Loading external scene / no materials problem



  • 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])



  • 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..



  • 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



  • 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()



  • 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



  • 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



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

    Hurahhh! Thank you!



  • 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.



  • 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.



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

    yeah that worked 👏



  • 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



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

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



  • 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)



  • 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



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

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


Log in to reply