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

    can't get bitmap shader work correctly

    Scheduled Pinned Locked Moved PYTHON Development
    3 Posts 0 Posters 581 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 01/02/2018 at 11:11, xxxxxxxx wrote:

      HI
      It's my first post here.
      I script a bit for a while, but it's my first try to write a plugin, so there could be  many dirty things.

      I'm currently trying to write a ShaderData plugin to manipulate textures.
      As I didn't find any example in python, for texturing/bitmap part, I try to "port" the sample from microbion site  (bmFlip), but which is in C++.
      The workfow is a bit different. I try my own "version" and it has worked for a while,  but it's pretty buggy. Sometime I get it in viewport, sometime in render, and now just bug the other modes (World or Local, who just display World position color) and no more render succes. If I clear the bitmap channel, all return fine.
      I'm obviously doing something wrong with my bitmap part "implentation".
      In output the shader call is in the "Espace UV" part.

      Somebody could put me in the right direction ?
      I can join the complete folder if necessary.

      And a second question I try to access different members of volumeData.
      it work, but I all time get this message : "UnboundLocalError: local variable 'raypos' referenced before assignment".

      And in case  I don't see anything to put an attachment, it must be extern ?

        
      import os  
      import math  
        
      import c4d  
      from c4d import plugins, bitmaps, utils  
        
        
      PLUGIN_ID = 1040539  
        
      FPLUGTWO_TEXTURE = 1000  
      FPLUGTWO_FLIPX = 1010  
      FPLUGTWO_FLIPY = 1020  
      FPLUGTWO_MODE  = 1030  
      FPLUGTWO_UV    = 0  
      FPLUGTWO_WORLD = 1  
      FPLUGTWO_LOCAL = 2  
      FPLUGTWO_PREVIEW = 1040  
      FPLUGTWO_TOTO = 1050  
        
      class FPlugTwo(c4d.plugins.ShaderData) :  
        
        print "FPlugTwo ok"  
              
        def __init__(self) :  
            #debug color  
            self.ape = True  
            self.mode = 0  
            self.shader = None  
            self.flipx = False  
            self.flipy = False  
            self.mode = 1  
            self.preview = True  
            self.toto = 0.5  
              
            self.SetExceptionColor(c4d.Vector(1,0,0))  
          
        def Init(self, node) :  
            donnees = node.GetDataInstance()  
            donnees.SetBool(FPLUGTWO_FLIPX, self.flipx)  
            donnees.SetBool(FPLUGTWO_FLIPY, self.flipy)  
            donnees.SetLong(FPLUGTWO_MODE, self.mode)  
            donnees.SetBool(FPLUGTWO_PREVIEW, self.preview)  
            donnees.SetReal(FPLUGTWO_TOTO, self.toto)  
            return True  
              
        def InitRender(self, sh, irs) :  
            donnees = sh.GetDataInstance()  
            self.shader = donnees.GetLink(FPLUGTWO_TEXTURE, irs.doc)  
            print self.shader  
            self.flipx = donnees.GetBool(FPLUGTWO_FLIPX)  
            self.flipy = donnees.GetBool(FPLUGTWO_FLIPY)  
            self.mode = donnees.GetLong(FPLUGTWO_MODE)  
            self.preview = donnees.GetBool(FPLUGTWO_PREVIEW, self.preview)  
            self.toto = donnees.GetReal(FPLUGTWO_TOTO)  
            self.irs = irs  
            if self.shader :  
                result = self.shader.InitRender(irs);  
                if result == c4d.INITRENDERRESULT_OK :  
                    print "INITRENDERRESULT_OK"  
                else :  
                    print "something Wrong in InitRender"                  
                return result  
            return 0  
          
        #This method seem not used, or not relevant  
        def Message(self, node, type, msgdat) :  
            donnees = node.GetDataInstance()  
            if type == c4d.MSG_INITIALCHANNEL:  
                print "MSG_INITIALCHANNEL"              
            #data = ((PluginShader* )node)->GetDataInstance();  
            #HandleInitialChannel(node, BMFLIPSHADER_TEXTURE, type, msgdat);  
            #HandleShaderMessage(node, (PluginShader* )data->GetLink(BMFLIPSHADER_TEXTURE, node->GetDocument(), Xbase), type, msgdat);  
            return True  
          
        def Output(self, sh, cd) :  
            pos = c4d.Vector()  
            nor = c4d.Vector()  
          
            if self.mode == FPLUGTWO_WORLD : # Espace Monde  
                if cd.vd : # 3D  
                    #just some tests  
                    pos  = cd.vd.p  
                    nor  = cd.vd.orign  
                    uvPos= cd.vd.uvw  
                    #print uvPos  
                    aRay = cd.vd.ray  
                    #print aRay  
                    raypos = aRay.p  
                    rayDir = aRay.v  
                    rayIOR = aRay.ior/4.0  
                    rayLength = cd.vd.dist #The distance between p and ray->p, i.e. the ray length.   
                    rayAngle = (cd.vd.cosc  \+ 1) /2.0 #The angle between ray vector and unbumped normal.  
                    mapVal = self.rangeMapper( rayAngle, 0.6, 1.0, 0.0, 1.0)  
                    print mapVal  
                    linVal = math.pow(mapVal, 2.2) #0.45454  
                    colVal = c4d.Vector(linVal,linVal/2.0,linVal)            
                else : # Aperçu  
                    if self.ape : pos = (cd.p - 0.5) * 100.0  
                    else : return pos              
                color = colVal  
              
            elif self.mode == FPLUGTWO_UV : # Espace UV  
                #color = cd.p  
                color = self.shader.Sample(cd)  
              
            elif self.mode == FPLUGTWO_LOCAL : # Espace Objet  
                if cd.vd : # 3D  
                    pos = cd.vd.p  
                else : # Aperçu  
                    if self.ape : pos = (cd.p - 0.5) * 100.0  
                    else : return pos  
                color = pos  
          
        def FreeRender(self, sh) :  
            #Free any resources used for the precalculated data from InitRender().  
            return  
          
          
        
      def registerThePlug() :  
        #c4d.plugins.RegisterShaderPlugin(id, str, info, g, description[, disklevel][, res])  
          
        IDS_FPLUGTWO=10000  
        name = plugins.GeLoadString(IDS_FPLUGTWO);  
        return plugins.RegisterShaderPlugin(PLUGIN_ID, name, 0, FPlugTwo, "FPlugTwo", 0)  
          
      if __name__ == "__main__":  
        registerThePlug()  
      
      1 Reply Last reply Reply Quote 0
      • H Offline
        Helper
        last edited by

        On 02/02/2018 at 04:02, xxxxxxxx wrote:

        Hello and Welcome to Plugin Café f_lcc !

        First of all I would like to remind you[URL-REMOVED] that we are not suppose to develop your plugin or even debug it.
        Please help us to help you. Instead of telling it's not working, tell us what you want to achieve.
        Moreover keep your example simple, one problem, one example (it will also help you to debug your code).

        With that said, there are few issues in your code.

        Output function:

        1. This function as it's written in the SDK, should return a c4d.Vector, then make sure all your conditions return a vector.
        2. Variable scope, if you create a variable within an indentation, this variable will only be available in this indentation scope or children one. (cf color variable)
        3. self.rangeMapper did not exist, so I replaced by c4d.utils.RangeMap(rayAngle, 0.6, 1.0, 0.0, 1.0, True). Use Clamp value to True since you are using pow.
        4. Always check for variable(cf self.shader)

        While I know you are currently learning, in python you can do MyVariable = 10 if x < y else 20

        	def Output(self, sh, cd) :
        		pos = c4d.Vector()
        		nor = c4d.Vector()
        		color = c4d.Vector()
          
        		if self.mode == FPLUGTWO_WORLD : # Espace Monde
        			colVal = c4d.Vector()
          
        			if cd.vd : # 3D
        				#just some tests
        				pos  = cd.vd.p
        				nor  = cd.vd.orign
        				uvPos= cd.vd.uvw
        				#print uvPos
        				aRay = cd.vd.ray
        				#print aRay
        				raypos = aRay.p
        				rayDir = aRay.v
        				rayIOR = aRay.ior/4.0
        				rayLength = cd.vd.dist #The distance between p and ray->p, i.e. the ray length. 
        				rayAngle = (cd.vd.cosc  \+ 1) /2.0 #The angle between ray vector and unbumped normal.
        				mapVal = c4d.utils.RangeMap(rayAngle, 0.6, 1.0, 0.0, 1.0, True) 
        				linVal = math.pow(mapVal, 2.2) #0.45454
        				colVal = c4d.Vector(linVal, linVal/2.0, linVal)
          
        			else : # Aperçu
        				pos = (cd.p - 0.5) * 100.0 if self.ape else pos
        				return pos
          
        			color = colVal
        		
        		elif self.mode == FPLUGTWO_UV : # Espace UV
        			#color = cd.p
        			color = self.shader.Sample(cd) if self.shader else cd.p
          
        		
        		elif self.mode == FPLUGTWO_LOCAL : # Espace Objet
        			if cd.vd : # 3D
        				pos = cd.vd.p
        			else : # Aperçu
        				if self.ape : pos = (cd.p - 0.5) * 100.0
        				else : return pos
        			color = pos
          
        		return color
        

        FreeRender:

        1. In your InitRender you initialize a shader, Free this one when the render is finnish or you have some memory leaks.
            def FreeRender(self, sh) :
                #Free any resources used for the precalculated data from InitRender().
                if self.shader:
                    self.shader.FreeRender()
                return
        

        If you have any others questions feel free to ask 🙂


        [URL-REMOVED] @maxon: This section contained a non-resolving link which has been removed.

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

          On 02/02/2018 at 07:58, xxxxxxxx wrote:

          Thank for the quick response.

          ok i will be more secifique next time.

          Work perfectly now.

          And true I hardly forgot the importance of scope 🙂

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