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