Material tag not rendering to picture viewer



  • On 10/04/2013 at 10:14, xxxxxxxx wrote:

    After taking time off from Python because of complaints from work that I was not simply acting busy when no 3D work was available, I've started sneaking time back into programming (there isn't enough 3D work to keep me busy).

    I'm creating an object plugin that creates lights and applies texture tags to image planes for GI lighting.

    Problem: When I preview render my scene in the scene frame it renders correctly with the materials showing as they should, but when I render to the picture viewer, my materials don't render.  When I break my plugin (press C), the materials render fine in the picture viewer.

    Here are snippets of my code that hopefully will show what I am doing wrong:

      
        def __init__(self) :
            self.SetOptimizeCache(True)
      
        def GetVirtualObjects(self, op, hierarchyhelp) :
            doc = c4d.documents.GetActiveDocument()
            myData = op.GetDataInstance()
            baseNull = c4d.BaseObject(c4d.Onull)
            giPlaneTop = c4d.BaseObject(c4d.Oplane)
            giPlaneTop.InsertUnder(baseNull)
      
            textureTagTop = giPlaneTop.MakeTag(c4d.Ttexture)
            giMatTop = c4d.BaseMaterial(5703)
            giMatTop[c4d.ID_BASELIST_NAME] = "GI Top"
      
            textureLinkTop = myData.GetData(11010) #Link to image FILENAME
      
            if textureLinkTop != None and textureLinkTop != "":
                bsbitTop = c4d.BaseList2D(c4d.Xbitmap)  #create a bitmap baseshader
                bsbitTop[c4d.BITMAPSHADER_FILENAME] = textureLinkTop
                giMatTop[c4d.MATERIAL_LUMINANCE_SHADER] = bsbitTop
                giMatTop.InsertShader(bsbitTop)#insert the shaders under the shader that uses it
                giMatTop.Message(c4d.MSG_UPDATE)#update
                giMatTop.Update(True, True)
                giMatTop[c4d.MATERIAL_USE_LUMINANCE] = 1
                textureTagTop[c4d.TEXTURETAG_MATERIAL] = giMatTop
                matList = doc.GetMaterials()
                for i in range(len(matList)) :
                    if matList[i].GetName() == "GI Top":
                        xTop = 1
                        myData = op.GetDataInstance()
                        giMatTop = matList[i]
                        textureTagTop[c4d.TEXTURETAG_MATERIAL] = giMatTop
                try:
                    if xTop != 1:
                        doc.InsertMaterial(giMatTop)
                except:
                    doc.InsertMaterial(giMatTop)
      
    
    

    For the coding god who decides to help me, let me know if you need any more of my completed code to make sense of this, or if you have any more questions that will help solve this for me.  I will also supply the code and a sample scene if needed.
    Thanks!
    -Dave



  • On 10/04/2013 at 10:51, xxxxxxxx wrote:

    i cannot pinpoint it 100% but the problem lies within using the object name as an identifier
    (generally a really bad idea) and rendering the document in the picture viewer which does
    rebuild the caches.

    possible solutions :

    1. boolean compare the basecontainers of your material. this approach is also a bit flawed, as
    __eq__ does not always work like you would expect it for basecontainers (nested gelistnodes).

    2. simply store a refererence to your material as a class member.

     def __init__(self) :
            self.SetOptimizeCache(True)
        	self.myMaterial = c4d.BaseMaterial(c4d.Mmaterial)
      
        def Init(self, node) :
            node.GetDocument().InsertMaterial(self.myMaterial)
      
        def GetVirtualObjects(self, op, hierarchyhelp) :
            giPlaneTop = c4d.BaseObject(c4d.Oplane)
            ttag       = c4d.TextureTag()
      
            ttag.SetMaterial(self.myMaterial)
            giPlaneTop.InsertTag(ttag)
            return giPlaneTop
    

    edit : you would have to add a method / some code to modify your material based on the
    node settings in GVO of course. you could also hide the material form the users view in the
    material manager, using the NBIT_OHIDE flag and prevent unwanted modifications of the 
    material by the user.



  • On 10/04/2013 at 11:14, xxxxxxxx wrote:

    Thanks a lot for your reply and suggestions Ferdinand!  This should get me on the right track... but to be greedy, and if it's not too much trouble, would you please point me to an example of storing a reference to a material as a class member, or something similar?  I haven't gotten my head completely wrapped around writing plugins yet. (I'm picturing my head actually wrapping around the word "plugin")



  • On 10/04/2013 at 11:48, xxxxxxxx wrote:

    my snippet was an example for that. here a commented version.

     def __init__(self) :
            self.SetOptimizeCache(True)
    	# the reference to your material
        	self.myMaterial = c4d.BaseMaterial(c4d.Mmaterial)
    # the gelistnode attached to your plugin class has been created.
    # we can now grab the bd to insert the material.
        def Init(self, node) :
            node.GetDocument().InsertMaterial(self.myMaterial)
    	
        def GetVirtualObjects(self, op, hierarchyhelp) :
            giPlaneTop = c4d.BaseObject(c4d.Oplane)
            ttag       = c4d.TextureTag()
    	# insert the material using the reference
            ttag.SetMaterial(self.myMaterial)
            giPlaneTop.InsertTag(ttag)
            return giPlaneTop
    

    one thing i forgot here is duplicating the document. __init__ and init() will be 
    executed each time the document is loaded/duplicated. while it would not change
    visually anything for you, a new material would be created and inserted into the 
    document each time.

    so when your object is initialized you have do basically the same as you were trying
    in gvo, but in init. i would hve to try this for myself, as this is a rather special subject.
    as i wrote comparing basecontainers could be a solution. another way could be to
    stoe some sort of hash-value with the material and object container. you have to try 
    here what does work best for you.



  • On 10/04/2013 at 11:49, xxxxxxxx wrote:

    _not sure if this is browser specific, but chrome does cut of half of my previous posting,  _
    so there is the rest:

    one thing i forgot here is duplicating the document. __init__ and init() will be 
    executed each time the document is loaded/duplicated. while it would not change
    visually anything for you, a new material would be created and inserted into the 
    document each time.

    so when your object is initialized you have do basically the same as you were trying
    in gvo, but in init. i would have to try this for myself, as this is a rather special subject.
    as i wrote comparing basecontainers could be a solution. another way could be to
    store some sort of hash-value with the material and object container. you have to try 
    here what does work best for you.



  • On 10/04/2013 at 12:11, xxxxxxxx wrote:

    Doh! (insert favorite image of someone covering face in embarrassment).  I glanced over your code snippet too fast thinking that you had just quoted mine.  This should give me what I need.  I'll also try storing a hash-value with the material.  Thanks!

    Also, thanks for the tip on hiding materials from the use with NBIT_OHIDE.

    -Dave


Log in to reply