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
    • Recent
    • Tags
    • Users
    • Login

    Loading external scene / no materials problem

    Scheduled Pinned Locked Moved PYTHON Development
    15 Posts 0 Posters 1.4k Views
    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 Offline
      Helper
      last edited by

      On 02/11/2014 at 05:45, xxxxxxxx wrote:

      Hi
      I'm currently trying to setup a way of having a low poly object in my scene replaced by a high poly version at render time.  Both the low and high poly objects are automatically generated by my code and saved to a temporary scene file for retrieval at render time.  I've got everything almost working except that the materials saved with the high poly object aren't showing in the render.  The materials are definitely there in the scene file as I can load independently and see.  I have a null object with a python tag that detects messages for external rendering - which loads up the high poly object.

      Heres the bones of the code.  It's messy and hacked I know - if anyone has a better suggestion to mimic the Xref process, would be great.

      > def message(id, data) :
      >
      >     if c4d.CheckIsRunning(c4d.CHECKISRUNNING_EXTERNALRENDERING) == True:
      >
      >         loadScene()
      >
      >     return
      >
      >     
      >
      >
      >
      >
      >
      >
      >
      > def loadScene() :
      >
      >
      >
      >
      >
      >
      >
      >     path = "/Applications/MAXON/tempScene.c4d"
      >
      >
      >
      >
      >     fO = LoadDocument(path, c4d.SCENEFILTER_OBJECTS)
      >
      >     fM = LoadDocument(path, c4d.SCENEFILTER_MATERIALS)
      >
      >     
      >
      >     #Find the specific object in the file
      >
      >     obj = fO.SearchObject("Vecfield Final")
      >
      >       #Make a copy of it in memory
      >
      >     clone = obj.GetClone()
      >
      >
      >
      >
      >     #Add the copy to your current open scene   
      >
      >     doc.InsertObject(clone,None,None) 
      >
      >
      >
      >
      >     mats = fM.GetMaterials()
      >
      >
      >
      >
      >     for m in range(0,len (mats)) :
      >
      >         doc.InsertMaterial(mats[m])

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

        On 02/11/2014 at 10:13, xxxxxxxx wrote:

        the texture tags on the loaded object have a question mark on them - if thats helpful info..

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

          On 02/11/2014 at 10:30, xxxxxxxx wrote:

          Hi Glenn,

          it seems to me, that you forgot to assign the materials to the corresponding texture tags:

          obj = your highpoly object
          mat = the corresponding material

            
            TexTag=obj.GetTag(c4d.Ttexture)  
            TexTag[c4d.TEXTURETAG_MATERIAL] = mat  
          

          Best wishes
          Martin

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

            On 02/11/2014 at 10:49, xxxxxxxx wrote:

            Hi Martin,
            Still having trouble - this is a script I'm running on a simple file with a single cube with 1 material on it.
            It loads the cube - but still the texture tag with question mark.

            def main() :
                path = "/Applications/MAXON/box.c4d"
                
                fO = LoadDocument(path, c4d.SCENEFILTER_OBJECTS)
                fM = LoadDocument(path, c4d.SCENEFILTER_MATERIALS)
                
                #Find the specific object in the file
                obj = fO.SearchObject("Cube")
                
                mats = fM.GetMaterials()
                mat = mats[0]
                
                TexTag=obj.GetTag(c4d.Ttexture)
                TexTag[c4d.TEXTURETAG_MATERIAL] = mat
                
                  #Make a copy of it in memory
                clone = obj.GetClone()  
                doc.InsertObject(clone, None, None)
                c4d.EventAdd()

            if __name__=='__main__':
                main()

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

              On 02/11/2014 at 10:55, xxxxxxxx wrote:

              here's the scene file if it helps
              https://drive.google.com/file/d/0B_WlfEtsbLpJQkFOUWIzellDUUU/view?usp=sharing

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

                On 02/11/2014 at 11:07, xxxxxxxx wrote:

                you need to insert the material, too and relink it to the object after insertion, like:

                  
                import c4d  
                  
                  
                def main() :  
                  path = "/Users/monkeytack/Desktop/box/box.c4d"  
                    
                  fO = c4d.documents.LoadDocument(path, c4d.SCENEFILTER_OBJECTS)  
                  fM = c4d.documents.LoadDocument(path, c4d.SCENEFILTER_MATERIALS)  
                    
                  #Find the specific object in the file  
                  obj = fO.SearchObject("Cube")  
                    
                  mats = fM.GetMaterials()  
                  mat = mats[0]  
                    
                  
                  
                  #Make a copy of it in memory  
                  clone = obj.GetClone()    
                  doc.InsertObject(clone, None, None)  
                  doc.InsertMaterial(mat, checknames=True)  
                    
                  TexTag=clone.GetTag(c4d.Ttexture)  
                  TexTag[c4d.TEXTURETAG_MATERIAL] = mat  
                    
                  c4d.EventAdd()  
                  
                if __name__=='__main__':  
                  main()  
                

                cheers,
                Martin

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

                  On 02/11/2014 at 11:21, xxxxxxxx wrote:

                  Hurahhh! Thank you!

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

                    On 02/11/2014 at 13:40, xxxxxxxx wrote:

                    ohhh there's always something else,

                    in my actual scene - there's hundreds of objects, differently coloured using several materials.  It seems when I load in the objects - they don't know which material was originally assigned to the texture tag.  It's just empty.  I could manually somehow write a function to fix all this and match them up again - but seems a lot of uncessary work.  I thought loading a scene would keep all the material and texture data intact.

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

                      On 02/11/2014 at 13:54, xxxxxxxx wrote:

                      i'm thinking - because it does load in the name of the texture tag name string - i could use this when creating and saving the scene to store the material name it belongs to - then write a function when loading which could search the scene materials and match each object up this way.

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

                        On 02/11/2014 at 14:24, xxxxxxxx wrote:

                        yeah that worked 👏

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

                          On 03/11/2014 at 08:39, xxxxxxxx wrote:

                          Hi Glenn,

                          a much simpler approach:
                          concatenate your material and object flags inside the load document function.
                          ask the object for it´s tag assignment and insert the corresponding material.
                          Be sure to ask the original object not the cloned one.

                            
                            
                          import c4d  
                            
                            
                          def main() :  
                            path = "/Users/monkeytack/Desktop/box/box.c4d"  
                              
                            fO = c4d.documents.LoadDocument(path, c4d.SCENEFILTER_OBJECTS|c4d.SCENEFILTER_MATERIALS)  
                            
                            obj = fO.SearchObject("Cube.1")  
                              
                            
                            TexTag=obj.GetTag(c4d.Ttexture)  
                            mat= TexTag[c4d.TEXTURETAG_MATERIAL]  
                            
                              
                            clone = obj.GetClone()  
                            doc.InsertObject(clone, None, None)  
                            doc.InsertMaterial(mat, checknames=True)  
                            
                            c4d.EventAdd()  
                            
                          if __name__=='__main__':  
                            main()  
                            
                          

                          Best wishes
                          Martin

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

                            On 03/11/2014 at 09:14, xxxxxxxx wrote:

                            Thanks Martin, that's a bit more elegant..

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

                              On 03/11/2014 at 13:44, xxxxxxxx wrote:

                              it's nearly working... I need to iterate through the list of objects - it seems to just manage as far as the number count of the materials - so if I have a hundred objects and 3 materials - it will only assign up to 3 objects..

                              fO = c4d.documents.LoadDocument(path, c4d.SCENEFILTER_OBJECTS|c4d.SCENEFILTER_MATERIALS)

                              olist = fO.SearchObject("Vecfield Final").GetChildren()

                              for obj in olist:

                              TexTag=obj.GetTag(c4d.Ttexture)
                                     
                                      mat = TexTag[c4d.TEXTURETAG_MATERIAL]

                              clone = obj.GetClone()
                                      doc.InsertObject(clone, None, None)
                                      doc.InsertMaterial(mat, checknames=True)

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

                                On 03/11/2014 at 15:37, xxxxxxxx wrote:

                                I see the problem now.
                                If you insert the material with only one linked object it remains in this status.

                                A maybe not that elegant but working solution is this:
                                store all connections in a list and assign it after insertion.

                                If someone has a better idea I´ll be interested.

                                  
                                import c4d  
                                  
                                  
                                def main() :  
                                    
                                  path = "/Users/monkeytack/Desktop/box/box.c4d"  
                                    
                                  fO = c4d.documents.LoadDocument(path, c4d.SCENEFILTER_OBJECTS|c4d.SCENEFILTER_MATERIALS)  
                                  olist = fO.SearchObject("Vectorfield").GetChildren()  
                                    
                                  #set up an assignment list to associate the object with the material  
                                  AssList=[]  
                                  for obj in olist:  
                                  
                                      TexTag=obj.GetTag(c4d.Ttexture)  
                                      mat= TexTag[c4d.TEXTURETAG_MATERIAL]  
                                      AssList.append([obj,mat])  
                                    
                                  #insert all materials  
                                  mats=fO.GetMaterials()  
                                  for mat in mats:  
                                  
                                      doc.InsertMaterial(mat, checknames=False)  
                                  
                                  
                                  #insert all objects and assign the corresponding material  
                                  for om in AssList:  
                                  
                                      clone = om[0].GetClone()  
                                      doc.InsertObject(clone, None, None)  
                                      TexTag=clone.GetTag(c4d.Ttexture)  
                                      TexTag[c4d.TEXTURETAG_MATERIAL] = om[1]  
                                        
                                  c4d.EventAdd()  
                                  
                                if __name__=='__main__':  
                                  main()  
                                

                                Best wishes
                                Martin

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

                                  On 03/11/2014 at 15:50, xxxxxxxx wrote:

                                  Thanks very much for this Martin, I'll try it out.

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