Use of InitBakeTexture and BakeTexture?



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 20/06/2007 at 03:08, xxxxxxxx wrote:

    User Information:
    Cinema 4D Version:   10.102 
    Platform:   Windows  ;   
    Language(s) :     C++  ;

    ---------
    Hello there again!

    I'm having problems getting a grip of the InitBakeTexture(...) and BakeTexture(...) functions. The documentation isn't helping me that much in that case and the forum search did come up with nothing concerning BakeTexture, so I am again starting a new thread.

    The basic idea of what I want to do is the following:
    For an export into a real-time 3D-Engine I want to be able to also evaluate all the fancy shaders, noises and so on. To make that easy I thought I could just bake the result of one material channel into a bitmap, one for every channel. So I want to end up with a bitmap for the color channel of the material, one for the bump channel, one for the specular color channel and so on, if the respective channels used something else than just a basic bitmap in the first place.
    So I had a look at InitBakeTexture(...) and BakeTexture(...) and gave it a shot, but no success yet. The reason for that might be I don't understand some of the parameters too well. Normally I'm not that bad at playing around a bit with a function to get a grasp of its workings, but this time I think that's just too much guessing. These are the parameters that are not clear to me:

      
    InitBakeTexture(...) :  
    return value BaseDocument*:   
        I suppose this is a render document to use with  
        BakeTexture(...) later, which is what I do currently.  
        Please tell me if that is wrong.  
    params I don't understand:  
        The two UVWTag*: ideally I'd want to end up with a  
            bitmap containing UV from [0,0] to [1,1], like a   
            'normal' texture would.  
            Currently I use a UVWTag containing the  
            UV-coords for a simple quad, which I create  
            before calling the function for both UVWTag*.  
            What is 'destuvw' there for?  
        BaseThread* th (=NULL) : I assume this should be a  
            thread to perform the baking process. Where would  
            I get such a thread?  
      
    BakeTexture(...) :  
        BaseDocument* doc: I assume I should use the document  
            acquired through InitBakeTexture(...) here.  
            Correct?  
        BaseThread* th: Here the thread seems absolutely  
            necessary, but I don't have a clue how to get  
            one to use here?  
        BakeProgressHook* hook: do I absolutely need that one  
            or could I just wait until the state of 'info' is  
            BAKE_STATE_COMPLETE?  
            If I absolutely need it: What is that function  
            supposed to do (i.e. what should it handle)?  
        BakeProgressInfo* info : Seems to report the current  
            state of the baking process, so I should be able  
            to just do a  
            while(info.state != BAKE_STATE_COMPLETE);  
            to wait for the baking process to complete,   
            right?  
    

    It would be great if someone could clarify those parameters to me and how they interact. A simple example for a baking process would be great, too, but explanations are worth more to me normally.

    Thx for reading, your time and your help.

    PS: Currently, InitBakeTexture does not return an error code, but BakeTexture returns 3003, which is BAKE_TEX_ERR_NO_TEXTURE_TAG. So I guess something's wrong with my use of InitBakeTexture(...).



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 26/06/2007 at 01:40, xxxxxxxx wrote:

    *bump*
    Is there really nobody that knows how to use those functions and could explain it to me? I still haven't figured that out and it seems the cinema4dsdk samples don't use those functions, so no help from there.



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 02/07/2007 at 05:13, xxxxxxxx wrote:

    Quote: return value BaseDocument*:
    >
    > * * *
    >
    >     I suppose this is a render document to use with
    >     BakeTexture(...) later, which is what I do currently.
    >     Please tell me if that is wrong.
    >
    >
    > * * *

    that's correct

    > Quote: __
    >
    > * * *
    >
    >     The two UVWTag*: ideally I'd want to end up with a
    >         bitmap containing UV from [0,0] to [1,1], like a
    >         'normal' texture would.
    >         Currently I use a UVWTag containing the
    >         UV-coords for a simple quad, which I create
    >         before calling the function for both UVWTag*.
    >         What is 'destuvw' there for?
    >
    >
    > * * *

    the first UVW tag is the tag used in the texturetag.
    the second UVW tag is used if you have a different texture projection than UVW.

    > Quote: __
    >
    > * * *
    >
    >     BaseThread* th (=NULL) : I assume this should be a
    >         thread to perform the baking process. Where would
    >         I get such a thread?
    >
    >
    > * * *

    if you pass NULL Cinema's main thread will be used. Otherwise you have to start your own thread.

    > Quote: __
    >
    > * * *
    >
    > BakeTexture(...) :
    >     BaseDocument* doc: I assume I should use the document
    >         acquired through InitBakeTexture(...) here.
    >         Correct?
    >     BaseThread* th: Here the thread seems absolutely
    >         necessary, but I don't have a clue how to get
    >         one to use here?
    >     BakeProgressHook* hook: do I absolutely need that one
    >         or could I just wait until the state of 'info' is
    >         BAKE_STATE_COMPLETE?
    >         If I absolutely need it: What is that function
    >         supposed to do (i.e. what should it handle)?
    >     BakeProgressInfo* info : Seems to report the current
    >         state of the baking process, so I should be able
    >         to just do a
    >         while(info.state != BAKE_STATE_COMPLETE);
    >         to wait for the baking process to complete,
    >         right?
    >
    >
    > * * *

    if you don't need any progressbar you can pass NULL to BakeProgressHook and BakeProgressInfo.

    cheers,
    Matthias



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 02/07/2007 at 05:55, xxxxxxxx wrote:

    Great, thx for clearing some things up. Still, some questions remain:
    1. If I pass NULL as thread to InitBakeTexture(...), it will use the C4D's main thread. Do I pass NULL as thread to BakeTexture(...), too? What if I would want to use a different thread for the baking process? Where / how could I obtain such a thread?
    2. If I pass NULL as BaseThread, BakeProgressHook and BakeProgressInfo, how do I know when the baking process is finished? Will the use of the C4D's main thread mean my plugin will also wait until the baking progress is done?
    3. If I would want to implement a BaseProgessHook function, what should it do / handle? Could I implement a BaseProgressHook function that for example stores the result of the baking process in an image file when the process is done?

    Thx for your help so far, I will try to get those two functions to work now.



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 02/07/2007 at 07:55, xxxxxxxx wrote:

    1. You'll need to setup and start your own thread (derive your own class from class Thread). There is only the main thread and your own threads in this case. In some places, like ObjectData::ModifyObject(), a thread may be passed from Cinema 4D.



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 03/07/2007 at 02:28, xxxxxxxx wrote:

    Thx! I'll give that a try!



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 03/07/2007 at 03:49, xxxxxxxx wrote:

    Okay, I've implemented my own thread, which seems to work fine. It gets started and shut down and the Main is executed. Furthermore I get the same error as before (that was error# 3003 from BakeTexture(...), which means "texture is null or not in doc").
    My guess is I'm missing something in the bake settings (the BaseContainer I pass in with InitBakeTexture and BakeTexture). Currently I'm just using these settings:

      
    BaseContainer bakeSettings;  
    bakeSettings.InsData(BAKE_TEX_COLOR, GeData(TRUE));  
    bakeSettings.InsData(BAKE_TEX_WIDTH, GeData(512));  
    bakeSettings.InsData(BAKE_TEX_HEIGHT, GeData(512));  
    bakeSettings.InsData(BAKE_TEX_UV_LEFT, GeData(0.0));  
    bakeSettings.InsData(BAKE_TEX_UV_RIGHT, GeData(1.0));  
    bakeSettings.InsData(BAKE_TEX_UV_TOP, GeData(0.0));  
    bakeSettings.InsData(BAKE_TEX_UV_BOTTOM, GeData(1.0));  
    

    Until 10 minutes ago I only had BAKE_TEX_COLOR = TRUE in there, but I thought I should add a width and a height for the texture in there, and while I was at it I just added those UV-settings. Is there something I'm missing in these settings?

    Here is my baking code from the Main() of my thread:

      
    this->m_pBakeDoc = InitBakeTexture(m_pInputDoc, m_pTag, m_pInputUVs, m_pResultUVs, m_BakeSettings, &this-;>m_ErrorCode, this->Get());  
    if(m_ErrorCode)  
    {  
    //error output  
         return;  
    }  
    m_pResultBitmap = BaseBitmap::Alloc();  
    m_ErrorCode = BakeTexture(m_pBakeDoc, m_BakeSettings, m_pResultBitmap, this->Get(), NULL, NULL);  
    if(m_ErrorCode)  
    {  
    //error output  
    }  
    

    those m_... get set in the constructor for the thread, m_BakeSettings receives a copy of the bakeSettings from above.
    m_pInputUVs and m_pResultUVs should get set according to the projection used for the texture tag m_pTag. Currently I'm only baking if the projection of the tag is set to UVW, so m_pInputUVs is set to the UVWTag of the object and m_pResultUVs is NULL.
    m_pTag is definitely a valid texture tag, I use it right before those lines above to get the material itself and parse some parameters from that.

    Furthermore currently I'm running the thread synchronously to avoid anything stupid ;) (as you may have guessed I'm not experienced with multi-threading yet)

    It would be great if anybody could help me with that problem. I'm completely stumped. :(



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 13/12/2007 at 02:39, xxxxxxxx wrote:

    Hey Match,
    Did you ever get this figured out?  I'm getting ready to look into these functions for my Riptide .obj import/export plugin.  I haven't actually written any code yet, but maybe the following thoughts will help clear up some things...
    In my case, the issue I'm trying to resolve is not in producing new bitmap texture files, but instead it is producing the proper "Texture Tag - modified uv-mapping".  To get an idea of what I'm talking about, try this:
    1. in a new scene, add a Cube primitive object and make it editable (making it editable will create a UVW Tag on it, with default Cubic mapping).
    2. create a new Material, using some recognizable bitmap texture in the Color channel.
    3. drag the Material onto the Cube in the Object Manager to create a Texture Tag.
    ...at this point, with the Texture Tag selected, note that it has options that modify how the Material gets mapped onto the cube - Offset X/Y, Length X/Y, Tiles X/Y - these settings are applied on top of the UVW Mapping...
    4. with the Projection still set to UVW Mapping, change the Tiles X value to 10 (or Length X to 10% - same thing).
    5. switch to BodyPaint UV Edit mode, where you can see the mapping.
    6. alternately, click on the Texture Tag and then the UVW Tag and view the differences.
    ...note how the  uv-mapping (in the UVW Tag) gets stretched along the X/U axis by the Texture Tag (which is tiling it 10 times).  If you were to export this mesh to an .obj file using C4D's built-in exporter, the resulting uv-mapping will be the combined affect of the UVW Tag, modified by the Texture Tag settings.  Currently, my Riptide plugin only looks at the UVW Tag, so any Texture Tag adjustments get discarded.
    So, moving on...
    7. back in the modeller, select the Texture Tag and change the Projection from UVW Mapping to Cylindrical.
    8. activate the Texture Tool.
    9. activate the Rotation Tool and rotate the texture around some (note - the Rotation, Scaling and Translation tools don't have any affect on the UVW Mapping projection, but they do on other projection types).
    10. with the Projection still set to Cylindrical, switch back to the UV Editor and click back and forth on the Texture Tag and the UVW Tag.
    ...note that the uv-mapping (in the UVW Tag) is still set as a standard Cubic mapping (but currently being ignored by the editor/renderer), but when you are looking at the modified (Texture Tag) mapping, it's stretched, rotated and Cylindrically mapped.
    Again, exporting with the built-in .obj exporter would result in the Cylindrical mapping which is currently active, but my Riptide exporter just outputs the UVW Tag data, so you get incorrect results.
    So, obviously, the built-in exporter is 'baking' the uv-mapping, based on the Projection type, as well as any other Texture Tag settings, modified by the current texture matrix (rotation, scaling and translation if the Projection is set to something besides UVW Mapping).
    Of particular note, relative to your situation is...

    • the Texture Tag settings (Offset X/Y, Length X/Y, Tiles X/Y, etc) can/do affect UVW Mapping projection.
    • you're only baking if it's set to UVW Mapping and...
    • you're passing a NULL pointer for the result UVs (?)

    ...I'm thinking that the result UVs pointer needs to be a valid/allocated UVW Tag to hold the baked uv-mapping results - regardless of Projection type -  because those other Texture Tag settings can modify them.  So maybe the error code you're getting is actually due to InitBakeTexture() not getting things set up correctly for BakeTexture() ?
    I realize that my situation/goal is different than yours, but I hope my ramblings can help :).
    Keith



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 13/12/2007 at 02:55, xxxxxxxx wrote:

    And now for my own questions :)...
    1. BaseDocument* InitBakeTexture(BaseDocument* doc, TextureTag* textag, UVWTag* texuvw, UVWTag* destuvw)
    Ok, I assume I pass in the current BaseDocument pointer I'm using, but

    • what is being returned? A new document pointer?
    • Do I need to free that later?
    • I assume I need to pass it to BakeTexture() but... do I (ever) pass this back into InitBakeTexture() if I need to call that again? or should I pass my orginal basedoc pointer back in?
    • If I'm only interested in the adjusted/baked UVs, do I even need to call BakeTexture()?  Or are they baked by the Init call?

    2. LONG BakeTexture(BaseDocument* doc, const BaseContainer& data, BaseBitmap* bmp, BaseThread* th, ProgressHook* hook, void* priv_data)
    If I'm only interested in the baked UVs, but it turns out that I do need to call BakeTexture() anyway, ...

    • what should the Bake parameters be? (can it be empty?)
    • can I pass a NULL for the BaseBitmap ?

    ...a bit of sample code would sure help clear things up :).



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 13/12/2007 at 05:35, xxxxxxxx wrote:

    Hi there!
    Sry I haven't answered yet, have been away til just now. I'll look up how I managed to get texture baking working. Actually, exporting the proper UVs (meaning UVs generated by mappings other than UVW mapping) was one of the things to do on my list. I think I asked here in the forums for a way to do that. Will have to look that one up again, too. My exporter has been "asleep" for quite some time due to other stuff I have to do. Anyway: I'll check how I used InitBakeTexture and BakeTexture now and post some code snippets.



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 13/12/2007 at 06:05, xxxxxxxx wrote:

    Okay, I looked up how exactly I do my baking, and I suppose it won't help you much, because your main concern seem to be the UV coordinates, which I currently don't care for at all.
    My TextureBaker results in a new bitmap file for every unique shader, a single quad with the shader applied gets rendered and saved. I do that by creating a temporary plane object, converting that to a polygon object and using the resulting UVW-tag to bake the texture.
    I chose that way because I want to reuse those textures for every object that uses the material without relying on the UV-mapping (the BakeTexture process somehow only writes pixels for actually used areas on the texture, therefore relying on the UV-coordinates of the object).
    Furthermore, because I had problems with some of the material channels not getting baked properly (read: the way I wanted them, being just the clean result of the shader, not something with lighting or other "obscure" effects), I copy the requested material channel to a dummy material into the color channel. Pretty much a workaround, but it does the job.
    Once I get proper export of UV-coordinates running I should be fine.

    Here's the code I thought could be interesting for you, which is basically the complete main method of my TextureBaker thread:

    > _
    > BaseDocument* bakeDoc = NULL;
    >      BaseContainer bakeSettings;
    >      TextureTag* tTagToBake;
    >      Material* matToBake;
    >      
    >      // create plane
    >      BaseContainer planeData;
    >      planeData.InsData(PRIM_PLANE_SUBW, GeData(1));
    >      planeData.InsData(PRIM_PLANE_SUBH, GeData(1));
    >      BaseObject* plane = GeneratePrimitive(g_pDocument, Oplane, planeData,1.0, false, this->Get());
    >      
    >      // make plane editable
    >      ModelingCommandData mcData = ModelingCommandData();
    >      mcData.doc = g_pDocument;
    >      mcData.op = plane;
    >      if(!SendModelingCommand(MCOMMAND_CURRENTSTATETOOBJECT, mcData))
    >      {
    >           GeConsoleOut("ERROR: TextureBaker failed creating dummy plane!");
    >           BaseObject::Free(plane);
    >           return;
    >      }
    >      BaseObject::Free(plane);
    >      //get editable plane to get UVW set
    >      BaseObject* vPlane = static_cast<BaseObject*>(mcData.result->GetIndex(0));
    >      UVWTag* quadUV = (UVWTag* )vPlane->GetTag(Tuvw,0);
    >      //set texture tag for editable plane
    >      tTagToBake = TextureTag::Alloc();
    >      tTagToBake->SetParameter(DescID(TEXTURETAG_PROJECTION), TEXTURETAG_PROJECTION_UVW, 0);
    >      vPlane->InsertTag(tTagToBake);
    >      
    >      g_pDocument->InsertObject(vPlane, 0,0,0);
    >      
    >      //iterate through assigned jobs
    >      for(std::vector<BakerInstruction>::iterator i = this->m_vWorkList.begin(); i != this->m_vWorkList.end(); i++)
    >      {
    >           bakeDoc = NULL;
    >           //creates default settings in bakeSettings
    >           MakeDefaultBakeSettings(bakeSettings, *i);
    >           
    >           if(i->ChannelToBake != CHANNEL_BUMP)
    >           {
    >                //create copy of source material with desired channel copied to color channel of result material 'matToBake'
    >                Material* sourceMat = (Material* )i->TexTag->GetMaterial();
    >                //clone original material
    >                matToBake = (Material* )sourceMat->GetClone(0,0);
    >                //disable all channels
    >                for(LONG j = CHANNEL_COLOR; j < CHANNEL_NORMAL; j++)
    >                {
    >                     matToBake->SetChannelState(j, FALSE);
    >                }
    >                //enable color channel
    >                matToBake->SetChannelState(CHANNEL_COLOR, TRUE);
    >                //set temp material name and copy source channel from source material to color channel of temp material
    >                matToBake->SetName(i->TexTag->GetMaterial()->GetName()+String("_Copy"));
    >                CopyChannel(sourceMat, i->ChannelToBake, matToBake, CHANNEL_COLOR);
    >               
    >                //add material to document
    >                g_pDocument->InsertMaterial(matToBake);
    >                //enable color channel baking
    >                bakeSettings.SetData(BAKE_TEX_COLOR, GeData(TRUE));
    >                //set temp material in temp TextureTag
    >                tTagToBake->SetMaterial(matToBake);
    >           }
    >           else
    >           {
    >                // enable bumpmap baking
    >                bakeSettings.SetData(BAKE_TEX_NORMAL, GeData(TRUE));
    >                // set original material in temp TextureTag
    >                tTagToBake->SetMaterial(i->TexTag->GetMaterial());
    >           }
    >
    >           
    >           bakeDoc = InitBakeTexture(g_pDocument, tTagToBake, quadUV, i->ResultUVs, bakeSettings, &i-;>ResultError, this->Get());
    >           if(i->ResultError || !bakeDoc)
    >           {
    >                GeConsoleOut(i->ToString());
    >                continue;
    >           }
    >
    >           //create multipass bitmap (needed for bumpmap baking)
    >           MultipassBitmap* resultBitmap = MultipassBitmap::Alloc(i->TargetResX, i->TargetResY, MODE_RGB);
    >           
    >           i->ResultError = BakeTexture(bakeDoc, bakeSettings, resultBitmap, this->Get(), NULL, NULL);
    >           if(i->ResultError)
    >           {
    >                GeConsoleOut(i->ToString());
    >                continue;
    >           }
    >           //get valid version of materialname
    >           String matName = NameManager::GetInstance()->ReformatString(i->ExpMat->GetName());
    >           i->ResultFile = Filename(matName+String("_")+TexChannelToString(i->ChannelToBake));
    >           i->ResultFile.SetSuffix("tif");
    >
    >           switch(i->ChannelToBake)
    >           {
    >           case CHANNEL_COLOR: i->ExpMat->SetDiffuseTex(i->ResultFile); break;
    >           case CHANNEL_TRANSPARENCY: i->ExpMat->SetTransparencyTex(i->ResultFile); break;
    >           case CHANNEL_SPECULARCOLOR: i->ExpMat->SetSpecTex(i->ResultFile); break;
    >           case CHANNEL_BUMP: i->ExpMat->SetBumpTex(i->ResultFile); break;
    >           default: GeConsoleOut("Can't set new filename for exportmaterial"); break;
    >           }
    >           
    >           GeConsoleOut(i->ToString());
    >           if(!resultBitmap->Save(Filename(i->TargetFolder.GetString()+String("\")+i->ResultFile.GetFileString()), FILTER_TIF, 0, 0))
    >           {
    >                GeConsoleOut("ERROR: Failed writing texture to disc!");
    >           }
    >
    >           MultipassBitmap::Free(resultBitmap);
    >           if(i->ChannelToBake != CHANNEL_BUMP)
    >           {
    >                matToBake->Remove();
    >                Material::Free(matToBake);
    >           }
    >           BaseDocument::Free(bakeDoc);
    >      }
    >
    >      //clean up
    >      tTagToBake->Remove();
    >      TextureTag::Free(tTagToBake);
    >      quadUV = NULL;
    >      vPlane->Remove();
    >      BaseObject::Free(vPlane);
    >      vPlane = NULL;
    >
    >      bakeSettings.FlushAll();
    > _

    That 'BakerInstruction' is a struct I defined for this job. It contains everything needed to bake the material channel and also stores the results from a baking process. The names of its members should be pretty self-explanatory.
    I could also post the 'MakeDefaultBakeSettings(...)' and 'CopyChannel' functions, but they just do what their names imply, although copying the channel of a material to another was a bit tricky.
    If you got any questions, feel free to ask.
    Hope this helps.



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 13/12/2007 at 09:35, xxxxxxxx wrote:

    Hey Match,
    Thanks for the info!  My forum search was just on the titles, so I only saw this thread... but later (just before going to sleep) I did a search on the body and saw your other/later thread where you seemed to get some of the above working (but ultimately needed to switch to MultipassBitmap).  Thanks for the updated code snippet.  I may do something similar with the textures in the future, so this will come in handy.
    I still have some questions relative to the UV-baking, but I guess I'll do some experiments while I wait for more definative answers to my above questions.
    Thanks again,
    Keith



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 13/12/2007 at 18:28, xxxxxxxx wrote:

    No problem.
    It is quite possible that I get some time to work on that exporter some more in the next few days. So if you find out something about exporting the proper UV coordinates (I'm guessing you're also wanting to export the ones used for rendering by C4D?), please keep me updated. If I find something before that, I'll post my findings.

    Good luck!



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 13/12/2007 at 20:49, xxxxxxxx wrote:

    I tried some things out today and so far, no joy.  I'm currently working with the R9.1 SDK, but it looks like there were substantial changes made by R9.6, so later versions may work (or work differently).
    The current problem I'm seeing is that InitBakeTexture() is not filling in the destUVTag under any circumstances that I've tried so far.  I had the thought that maybe BakeTexture() is actually supposed to alter it, but so far, it's not either.
    The R9.1 c4d_tools.h file has the following comments...

        
        
        
        
        /*   
        textag : the texture tag you want to bake (must be assigned to an object)  
        data : bake parameters - see below  
        bmp : the destination bitmap  
        th : the current thread  
        texuvw : must be valid, if UVW pojection is selected in the tag, ignored otherwise  
        destuvw : if not NULL, the current projection is transformed into the uvw tag  
        */  
        
    

    ...but neither function is altering the destuvw tag as expected.



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 14/12/2007 at 11:04, xxxxxxxx wrote:

    Ok, I'm giving up on InitBakeTexture() and BakeTexture() for getting the UVs fixed... I'm just not having an luck getting them to work at all.
    Instead, I've developed a work-around by using GenerateUVW() (c4d_baseobject.h utility function).  It seems to handle the various Projection types and texture axis adjustments for me, but I still have to jump through some hoops to handle the Offset/Length/Tiles values of the Texture Tag, as well as account for the fact that there may be multiple Texture Tags on a mesh, each with different Projection types, but restricted to some subset of polygons.
    Fortunately, my exporter pre-parsing has already determined which texture tags affect which polygons and set up structures for easy access to everything.  Here's my current code (it uses many internal structures, but you should be able to follow along)...

        
        
        
        
        //------------------------------------------------------------------------------------------------------  
        //******************************************************************************************************  
        // BakeUVs() - create a consolidated and uv-mapping resolved UVWTag  
        //  
        // Because a mesh can have multiple Texture Tags on it (usually restricted to a subset of polygons of  
        // that mesh), with each potentially set to some different Projection type, this routine will loop  
        // through all the various Texture Tags on the mesh and create a consolidated UVWTag for the export  
        // code to use.  It also resolves all Offset and Scaling (tiling) adjustments of those tags.  
        //******************************************************************************************************  
        //------------------------------------------------------------------------------------------------------  
        Bool ObjSaver::BakeUVs(PolygonObject *op, UVWTag *pDstUVs)  
        {  
         Matrix mg = op->GetMg();  
         DWORD i,j;
        
        
        
        
         // start by grabbing the current UVWTag  
         UVWTag *pSrcUVs = (UVWTag* )(op->GetTag(Tuvw, 0));  
         if( !pSrcUVs )  
          return false;
        
        
        
        
         // create a working sand-box  
         UVWTag *pWrkUVs = UVWTag::Alloc(m_numFaces);  
         if( !pWrkUVs )  
          return false;
        
        
        
        
         // before we start, set the default state of caller's UVWTag to src  
         for(i=0; i<m_numFaces; i++)  
          pDstUVs->Cpy(i, pSrcUVs, i);
        
        
        
        
         objMaterial *pMat = &m_pMats[0];  
         for(i=0; i<m_numMaterials; i++)  
         {  
          // ==================================================================================  
          // if we have a pointer to a TextureTag for this material, we may need to adjust the  
          // uv values for the polygons assigned to it.  If we don't have a pointer, then the  
          // default values filled in above should be good.  
          // ==================================================================================  
          if( pMat->pTex )  
          {  
           // ==================================================================================  
           // if the texture tag projection is set to something besides UVW, then GenerateUVW()  
           // will resolve it into UVW format. This operation also includes any texture matrix  
           // adjustments, but does not include the offset and tiling values of the tag. If the  
           // call returns NULL, then it's already set to UVW, so we just copy the orginal UVs  
           // into our working tag.  
           // ==================================================================================  
           UVWTag *pGenUVs = GenerateUVW(op, mg, pMat->pTex, mg, NULL);  
           if( pGenUVs )  
           {  
            for(i=0; i<m_numFaces; i++)  
             pWrkUVs->Cpy(i, pGenUVs, i);  
            UVWTag::Free(pGenUVs);  
           }  
           else  
           {  
            for(i=0; i<m_numFaces; i++)  
             pWrkUVs->Cpy(i, pSrcUVs, i);  
           }
        
        
        
        
           // ==================================================================================  
           // next we need to get the offset and tiling (scaling) values from the tag...  
           // ==================================================================================  
           Real uScale = 1.0;  
           Real vScale = 1.0;
        
        
        
        
           BaseContainer tagvals = pMat->pTex->GetData();  
           Real uOffset = -tagvals.GetReal(TEXTURETAG_OFFSETX);  
           Real vOffset = -tagvals.GetReal(TEXTURETAG_OFFSETY);  
           Real lenX = tagvals.GetReal(TEXTURETAG_LENGTHX);  
           Real lenY = tagvals.GetReal(TEXTURETAG_LENGTHY);
        
        
        
        
           if( lenX )  
            uScale /= lenX;  
           if( lenY )  
            vScale /= lenY;
        
        
        
        
           // ==================================================================================  
           // and finally, we loop through all the polygons assigned to this particular Texture  
           // Tag and apply any offset and scaling, transfering the resulting UVs into the caller's  
           // UVWTag  
           // ==================================================================================  
           for(j=0; j<pMat->numFaces; j++)  
           {  
            objFacet *pFacet = &m_pFaces[pMat->pFaceIndices[j]];
        
        
        
        
            // get working uv values  
            UVWStruct uvw = pWrkUVs->Get(pFacet->iPolyNdx);
        
        
        
        
            // apply offset and scaling  
            uvw.a.x = (uvw.a.x * uScale) + uOffset;  
            uvw.b.x = (uvw.b.x * uScale) + uOffset;  
            uvw.c.x = (uvw.c.x * uScale) + uOffset;  
            uvw.d.x = (uvw.d.x * uScale) + uOffset;
        
        
        
        
            uvw.a.y = (uvw.a.y * vScale) + vOffset;  
            uvw.b.y = (uvw.b.y * vScale) + vOffset;  
            uvw.c.y = (uvw.c.y * vScale) + vOffset;  
            uvw.d.y = (uvw.d.y * vScale) + vOffset;
        
        
        
        
            // store adjusted values in caller's UVWTag  
            pDstUVs->Set(pFacet->iPolyNdx, uvw);  
           }  
          }  
          pMat++;  
         }  
         UVWTag::Free(pWrkUVs);  
         return true;  
        }  
        
    


  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 14/12/2007 at 18:09, xxxxxxxx wrote:

    wow, that looks much simpler than I was afraid of :) Thx for posting this, would have taken me quite a while to figure that out, I guess.
    I have something along the lines of your TextureTag->Polygons relation already implemented (I'm writing an Ogre export, so I have to work with submeshes anyway for multiple materials on one object), so I should be able to use that code 1:1 more or less. Thx again!



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 14/12/2007 at 18:46, xxxxxxxx wrote:

    Sure thing... after a bit of testing, it looks like it may not be fully cooked yet, but I haven't had a chance to look into it again yet. If I find/fix anything, I'll report back.



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 15/12/2007 at 02:05, xxxxxxxx wrote:

    Ahh.. ok, too much cutting and pasting... change this:

        
        
        
        
          
           if( pGenUVs )  
           {  
            for(i=0; i<m_numFaces; i++)  
             pWrkUVs->Cpy(i, pGenUVs, i);  
            UVWTag::Free(pGenUVs);  
           }  
           else  
           {  
            for(i=0; i<m_numFaces; i++)  
             pWrkUVs->Cpy(i, pSrcUVs, i);  
           }  
        
    

    ...to this...

        
        
        
        
          
           if( pGenUVs )  
           {  
            for(j=0; j<m_numFaces; j++)  
             pWrkUVs->Cpy(j, pGenUVs, j);  
            UVWTag::Free(pGenUVs);  
           }  
           else  
           {  
            for(j=0; j<m_numFaces; j++)  
             pWrkUVs->Cpy(j, pSrcUVs, j);  
           }  
        
    

    ...replace the 'i' variable with 'j'.  The original code above was re-using i inside an i loop, so it was blowing out of the outer loop early :).
    Aside from that typo, it looks like it's working now (barring any misunderstanding on my part about the order the math is applied).



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 22/12/2007 at 04:02, xxxxxxxx wrote:

    I implemented UV baking two days ago. Thx for your help. Although the structure I'm working in didn't allow to just copy & paste your method especially the pointer to GenerateUVW(...) was extremely helpful.



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 22/12/2007 at 09:09, xxxxxxxx wrote:

    Cool.. btw, you don;t happen to know where I can find the DTS file format specs (Torque engine) do you? :)


Log in to reply