Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush Python API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Login

    What could hang BakeTexture? [SOLVED]

    SDK Help
    0
    15
    1.4k
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • H
      Helper
      last edited by

      On 27/05/2015 at 15:18, xxxxxxxx wrote:

      Found the problem and is the following:

      If my original object (the one that is placed in a new document with IsolateObjects) is using materials with bitmaps that have a full path, it works fine. If the bitmap has a name only (meaning that should be in a folder that Cinema 4D searches for) it will hang.

      I can understand why this is happening. The newly created document has no clue where the bitmaps are, if they are referenced just by name.
      But I thought that the IsolateObjects would deal with that, since it states clearly in the SDK:

        
      BaseDocument* IsolateObjects(BaseDocument* doc, const AtomArray& t_objects)   
        
      A helper routine to copy the objects t_objects of document doc to a new document (returned). All materials associated are also copied over and the links are corrected.   
      

      I guess the links are not really corrected. So, how can I make sure that the document returned by IsolateObjects knows where the bitmaps are?
      Is there any way for force all references to external bitmaps to become absolute paths in the document created by IsolateObjects?

      1 Reply Last reply Reply Quote 0
      • H
        Helper
        last edited by

        On 27/05/2015 at 15:35, xxxxxxxx wrote:

        Links are corrected but the references to images stored on disk (the 'bitmap') are not.  You may have to actually get the full path from the original materials and set it in the bake document materials.

        1 Reply Last reply Reply Quote 0
        • H
          Helper
          last edited by

          On 27/05/2015 at 15:48, xxxxxxxx wrote:

          So, I must run through all materials, through all channels, inside each shader and sub-shader to check if there are any bitmaps and change all materials from relative to absolute?

          1 Reply Last reply Reply Quote 0
          • H
            Helper
            last edited by

            On 27/05/2015 at 16:08, xxxxxxxx wrote:

            That is a bit of a conundrum there.  If the image files are all relative to the saved document (Save as Project), then that document can find all of the image files easily.  But since you are creating a new, temporary, unsaved document, that relationship no longer exists.  Interesting that this is not taken into account in their code to fill out the paths to absolute.

            In BaseDocument, there is GetAllTextures() which you can use on the original doc.  There is no SetAllTextures().  In code that I've created to resolve image file path issues for one of my plugins, it was only at the Channel texture level so shaders and sub-shaders were of no concern.  Code for this might get hairy.

            1 Reply Last reply Reply Quote 0
            • H
              Helper
              last edited by

              On 27/05/2015 at 16:11, xxxxxxxx wrote:

              Yes, I can see that it can 😞
              Maxon should really have included a way to turn all texture paths into absolute, on the documents created by IsolateObjects 😞

              1 Reply Last reply Reply Quote 0
              • H
                Helper
                last edited by

                On 27/05/2015 at 16:14, xxxxxxxx wrote:

                There is a command (CallCommand(1029820)) that performs "Globalize Filenames" but I guess it works on the active document, not on a virtual document 😞

                1 Reply Last reply Reply Quote 0
                • H
                  Helper
                  last edited by

                  On 27/05/2015 at 16:19, xxxxxxxx wrote:

                  One possibility, and this may be ill-advised, is to call BaseDocument's SetDocumentPath() on the temp doc with the path from the original document (using GetDocumentPath()) and see if that 'magically' lets your temp doc find the image files.  'Twould be much less work if it is fooled.

                  1 Reply Last reply Reply Quote 0
                  • H
                    Helper
                    last edited by

                    On 27/05/2015 at 16:20, xxxxxxxx wrote:

                    I will give it a shot 😉

                    1 Reply Last reply Reply Quote 0
                    • H
                      Helper
                      last edited by

                      On 27/05/2015 at 16:25, xxxxxxxx wrote:

                      Know what?

                      IT WORKED!!!! 😄

                      YES!!! Thank you, Robert.

                      1 Reply Last reply Reply Quote 0
                      • H
                        Helper
                        last edited by

                        On 27/05/2015 at 18:04, xxxxxxxx wrote:

                        One caveat: if the original document has not been saved with Save As Project, there may be issues using this methodology.  You have several alternatives: do that yourself (somewhere and probably with file cleanup thereafter), request the user to do it a priori, or have both methods available (the easy one and then fall into the more laborious one in that circumstance).  The first alternative is almost the easiest since it only requires that you track the original document path and do the file cleanup using the easy fix method.  Keep this approach in mind.  Always consider all possibilities!

                        1 Reply Last reply Reply Quote 0
                        • H
                          Helper
                          last edited by

                          On 28/05/2015 at 04:19, xxxxxxxx wrote:

                          I agree that we, programmers, must cover all possible situations that could go wrong 🙂
                          However, I don't thing there will be a problem with that.
                          Because, if the user try to use my plugin on a non-saved document, two things can happen:

                          - The bitmaps that he loads are on one of the default paths that Cinema4D searches for (the "tex" folders, the application folder, the preferences folder, the Texture Paths folders, etc). And, in that case, it all works fine. I tested it 😉

                          - The bitmaps that he loads are NOT on one of the default paths and in that case, Cinema 4D asks if the user wants to create a copy of the bitmap. It the user says NO, an absolute path is stored and, in that case, my plugin works fine. If it says yes, just the name is stored but the bitmap is copied to the "tex" folder inside the Preferences folder (since the document was not saved yet). And this takes us to the previous case 🙂

                          I already tested it. It works fine, even in non-saved documents.

                          However, I will advise the users to follow good working methods, in the manual 🙂

                          1 Reply Last reply Reply Quote 0
                          • H
                            Helper
                            last edited by

                            On 29/05/2015 at 03:18, xxxxxxxx wrote:

                            Hi,

                            I know, you already solved your problem and don't have a real need for it.
                            Nevertheless I want to add a small example, how to walk over all shaders in a document.
                            The code walks over all materials and looks for shaders of a given ID (shdId) and calls a given function (func) for each of these shaders. It takes care for shaders in shaders (like for example Layer Shader) and reflectance channel.

                            typedef maxon::BaseArray<BaseShader*> tArrShd;
                            typedef std::function<void (BaseDocument* const, Material* const, BaseShader* const)> tWalkShaderCallback;
                              
                            void WalkShaderTree(BaseDocument* const doc, const Int32 shdId, Material* const mat, BaseShader* const shd, tWalkShaderCallback func)
                            {
                            	if (!shd)
                            		return;
                            	if (shd->GetNodeID() == shdId)
                            		func(doc, mat, shd);
                            	WalkShaderTree(doc, mat, shd->GetDown(), func);
                            	WalkShaderTree(doc, mat, shd->GetNext(), func);
                            }
                              
                            void WalkAllShaders(BaseDocument* const doc, const Int32 shdId, tWalkShaderCallback func)
                            {
                              for (BaseMaterial* bm = doc->GetFirstMaterial(); bm; bm = bm->GetNext())
                              {
                                if (!bm->IsInstanceOf(Mmaterial))
                                  continue;
                                Material* mat = static_cast<Material*>(bm);
                                for (Int32 idChan = 0; idChan < MAX_MATERIALCHANNELS; ++idChan) // iterate over all material channels (except reflectance, see below)
                                {
                                  BaseChannel* chan = mat->GetChannel(idChan);
                                  if (!chan)
                                    continue;
                                  BaseShader* shd = chan->GetShader();
                                  if (!shd)
                                    continue;
                                  WalkShaderTree(doc, shdId, mat, shd, func);
                                }
                                tArrShd arrReflectanceShaders;
                                mat->GetAllReflectionShaders(arrReflectanceShaders);
                                for (tArrShd::ConstIterator iter = arrReflectanceShaders.Begin(); iter != arrReflectanceShaders.End(); ++iter)
                                {
                                  WalkShaderTree(doc, shdId, mat, *iter, func);
                                }
                              }
                            }
                            

                            You'd use it as follows:
                            Have a function to be called for every shader with the given ID:

                            void DoForShader(BaseDocument* const doc, Material* const mat, BaseShader* const shd)
                            {
                              // do something for every shader found
                            }
                            

                            Then for example call this to execute DoForShader() for all bitmap shaders in any material of a scene:

                            WalkAllShaders(doc, Xbitmap, DoForShader);
                            
                            1 Reply Last reply Reply Quote 0
                            • H
                              Helper
                              last edited by

                              On 29/05/2015 at 03:39, xxxxxxxx wrote:

                              WOW!!! Great piece of code. Very useful.
                              Thank you, Andreas.

                              1 Reply Last reply Reply Quote 0
                              • First post
                                Last post