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

    DrawTexture(): Alpha problem

    Scheduled Pinned Locked Moved PYTHON Development
    9 Posts 0 Posters 766 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

      THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

      On 29/08/2012 at 10:39, xxxxxxxx wrote:

      Here is the code for a tag plugin that will draw text onto the screen like a HUD display using the DrawTexture() function.
      I've converted this to python from my C++ plugin. But the SDK uses an unsigned short int (UWORD) in the alpha section that I do not know how to convert to python.
      So I'm hoping someone here will know how to convert that part from C++ to python.

      import c4d,os  
      from c4d import plugins, bitmaps, documents  
        
      PLUGIN_ID = 1000003  #TESTING ID# Only!!!  
        
      class DrawText(plugins.TagData) :  
        def Init(self, tag) :  
            return True  
        
        def Draw(self, tag, op, bd, bh) :  
          
        doc = documents.GetActiveDocument()  
        obj = tag.GetObject()                                       #The object the python tag is on  
        if obj.GetType() == 5100:  
            points = obj.GetAllPoints()              
            globalpnts = obj.GetMg() * points[4]   
        
      ##### There is an OpenGL bug that makes the text hide behind objects    #####  
      ##### This is a dummy 2D object with zero length which works around that bug #####  
        bd.SetPen(c4d.Vector(1.0, 1.0, 1.0))  
        bd.SetMatrix_Screen()                                       #Use the screen's matrix to draw on  
        bd.DrawLine2D(c4d.Vector(0, 0, 0), c4d.Vector(0, 0, 0))     #Draw a line with a zero length<---This is our dummy object  
        bd.SetDepth(True)                                           #This fixes drawing problems when using 2D functions  
      ###############################################################  
        
        text = "My Text"                            #The text that will display on the screen  
        
        cm = c4d.bitmaps.GeClipMap()  
        cm.Init(0, 0, 32)  
        cm.BeginDraw()                              #Start drawing the object. This must be used before drawing the text  
        width = cm.TextWidth(text)                  #Gets the width of the text  
        height = cm.TextHeight()                    #Gets the height of the text  
        cm.EndDraw()                                #Tell C4D we're done drawing the text  
        cm.Destroy()                                #Release any memory used by the GeClipMap class  
        
        cm.Init(width, height, 32)                  #Dynamically sets the size of the virtual plane the text is on  
        cm.BeginDraw()  
        cm.SetColor(255, 255, 255, 255)             #Sets the color of the text to white  
        cm.TextAt(0,0,text)  
        cm.EndDraw()          
        bd.SetMatrix_Screen()                       #We always need a matrix to draw things...In this case we'll use the screen's matrix  
        bd.SetLightList(c4d.BDRAW_SETLIGHTLIST_NOLIGHTS)#Use other options for different results if desired      
          
        xpos=255                                     #The X screen location of the left upper corner of the plane object the text bitmap is on  
        ypos=255                                     #The Y screen location of the left upper corner of the plane object the text bitmap is on  
        
        
        #Now we set the actual vector postions for the four point plane object that holds the text bitmap  
        padr = [  
        (c4d.Vector(xpos,ypos,0)),                          #upper left corner  
        (c4d.Vector(xpos+width,ypos,0)),                    #upper right corner  
        (c4d.Vector(xpos+width,ypos+height,0)),             #lower right corner  
        (c4d.Vector(xpos,ypos+height,0))                    #lower left corner  
        ]      
        
        #Now we set the color vector values for the plane object   
        cadr = [  
        (c4d.Vector(1,1,1)),                            
        (c4d.Vector(1,1,1)),                   
        (c4d.Vector(1,1,1)),            
        (c4d.Vector(1,1,1))                
        ]  
        
        
        #Now we set up the normals directions for the four point plane object that holds the text bitmap  
        vnadr = [  
        (c4d.Vector(0,0,1)),                            
        (c4d.Vector(0,0,1)),                   
        (c4d.Vector(0,0,1)),            
        (c4d.Vector(0,0,1))                
        ]      
        
        #Now we set up the UV's for the four point plane object that holds the text bitmap  
        uvadr = [  
        (c4d.Vector(0,0,0)),                            
        (c4d.Vector(1,0,0)),                   
        (c4d.Vector(1,1,0)),            
        (c4d.Vector(0,1,0))                
        ]          
        
        cmbmp = bitmaps.BaseBitmap()  
        cmbmp = cm.GetBitmap()  
              
        bmp = bitmaps.BaseBitmap()  
        bmp = cm.GetBitmap()  
          
        alpha = bmp.GetInternalChannel()               #Get at the RGBA channels of the bitmap copy  
        alpha = bmp.AddChannel(True, False)  
          
          
              
        ################## This is the C++ looop that needs to be converted to python########  
        ######## GetPixel() stores color data r,g,b in a UWORD variable that doesn't exist in python #######       
        
        #Apply the alpha bitmap to the solution so only the text is visible on the screen  
        #The alpha acts like a matte object. So if you find that your text is getting cut off..Your alpha might be too small  
        #You can increase the width and height of the alpha to fix that problem  
        
        # LONG x,y;  
            # for(y=0; y<height; y++)  
            # {  
              # for(x=0; x<width; x++)  
              # {  
                 # UWORD r;                                //An unsigned short int variable...Can hold absolute values between 0->65,535  
                 # bmp->GetPixel(x,y,&r,&r,&r);            //Get each pixel's X.Y coords and assign them to pointers (r,g,b) (0 <= r/g/b <= 255)   
                 # bmp->SetAlphaPixel(alpha, x, y, r);     //r is the opacity  
              # }  
            # }  
        ########################################################################################################  
          
          
        bd.DrawTexture(bmp,padr,cadr,vnadr,uvadr,4,c4d.DRAW_ALPHA_NORMAL,c4d.DRAW_TEXTUREFLAGS_0)  
        bd.SetDepth(True)      
          
              
        return True  
        
      if __name__ == "__main__":  
        path, file = os.path.split(__file__)  
        bmp = bitmaps.BaseBitmap()  
        bmp.InitWith(os.path.join(path, "res", "icon.tif"))  
        plugins.RegisterTagPlugin(id = PLUGIN_ID, str = "DrawText", g = DrawText, description = "drawtext", icon = bmp, info = c4d.TAG_EXPRESSION|c4d.TAG_VISIBLE)
      

      -ScottA

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

        THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

        On 30/08/2012 at 07:04, xxxxxxxx wrote:

        Hi,

        C++ uses more 'precise' types but don't worry about that in Python. You can use a Python int to hold the pixel color (returned by GetPixel()) without problem.

        This code is pretty interesting and not difficult to understand.

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

          THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

          On 30/08/2012 at 07:39, xxxxxxxx wrote:

          Originally posted by xxxxxxxx

           
          #The alpha acts like a matte object. So if you find that your text is getting cut off..Your alpha might be too small  
          #You can increase the width and height of the alpha to fix that problem  
          

          What do you mean by increasing the width and height of the alpha?

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

            THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

            On 30/08/2012 at 08:10, xxxxxxxx wrote:

            Hi Yannick,

            I'm having trouble with that loop. Because the C++ version is using pointers to insert three color values(I'm assuming vectors) into it. And I don't know how to create a python variable that is the right type to do that. I tried c4d.Vector but it didn't work.
            The sdk has a page listing color as a struct. I'm not sure if this is what I need to do. Or how to do it.

                for y in xrange(height) :  
                  for x in xrange(width) :  
                      r  <----------------------#How do I define this as a three value color variable?    
                      bmp.GetPixel(x,y,r,r,r)  
                      bmp.SetAlphaPixel(alpha, x, y, r)
            

            -Per your question about about the width and height of the alpha.
            If you scale the virtual plane by placing their vectors father apart(padr). I've found that the alpha will not always scale up enough. So the text can sometimes get chopped off.
            So adding something like width+5 and height+5 in the alpha loop will fix that problem by making the alpha bigger so it doesn't cut off the text.
            This also seems to stretch the text and make it blurrier the more it's scaled up. So I'm not sure if this is the proper way to scale the text. But it's the only way I've found to do it (But it's probably wrong).
            I probably should have written better notes about that one.

            *Edit- It just dawned on me that to scale the text. We might need to use the Font function to do that. But I haven't been able to figure out how to use it.
            The Blit() function is another very cool function that could be all kinds of fun to use for drawing animated things to the screen. But the SDK gives me no clue who how to use it.

            -ScottA

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

              THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

              On 30/08/2012 at 10:22, xxxxxxxx wrote:

              One other additional note about FontData in the python docs.
              It was added to the SDK. But what is there is very vague on how to use it.

              In C++ this is an example how we do it:

                  BaseContainer *data=((BaseList2D* )node)->GetDataInstance(); //Create a new Base Container and assign to a variable  
                if (!data) return FALSE;  
                
                GeData d2(FONTCHOOSER_DATA, DEFAULTVALUE);                       //Create a parameter container variable with font flags  
                FontData* fd = (FontData* )d2.GetCustomDataType(FONTCHOOSER_DATA); //Get the font data from above and assign it to a variable  
                if (!fd) return FALSE;  
                
                BaseContainer bc;                                      //Create a new Base Container and assign to a variable  
                GeClipMap::EnumerateFonts(&bc, GE_CM_FONTSORT_FLAT);   //Grab all the fonts and fill the BaseContainer(bc) with that list  
                
                LONG i=0;  
                while (TRUE)  
                {  
                    LONG id = bc.GetIndexId(i++); //Loop through the BaseContainer to get each individual element that currently holds font data   
                    if (id==NOTOK) break;         //Exit the while loop if there are no more container elements found  
                
                    BaseContainer *fbc = bc.GetContainerInstance(id); //Creates a new temporary Base Container holding the indexes of BaseContainer bc  
                    if (fbc)          //If there is an index found   
                    {  
                     String name;     //Create an empty string variable    
                     if (!GeClipMap::GetFontName(fbc, GE_FONT_NAME_DISPLAY, &name)) return FALSE;  //If no font names are found in the index. Exit the while loop  
                
                     if (name.Compare("Arial") == 0) //Compares the String object with another string   
                      {  
                       fd->SetFont(fbc);   //Set the font to the value of the variable fbc  
                       if (!data->SetData(MY_FONT,d2)->GetType()) return FALSE; //Error handling  
                
                       return TRUE;  
                      }  
                    }  
                }  
                
                //This code block sets the font to the default if the Arial font is not found  
                BaseContainer bc2;  
                if (!GeClipMap::GetDefaultFont(GE_FONT_DEFAULT_SYSTEM, &bc2)) return FALSE;  
                fd->SetFont(&bc2);  
                if (!data->SetData(MY_FONT,d2)->GetType()) return FALSE;
              

              In the python docs there is no information on how to do the same thing.
              -No information how to create a variable with FONTCHOOSER_DATA in it.
              -No information on how to iterate all the fonts and then store them in a container
              -No information on how to then use those stored fonts and set them as needed

              Without that information. I can't use any of the various font functions in the python SDK.

              -ScottA

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

                THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

                On 31/08/2012 at 01:05, xxxxxxxx wrote:

                Originally posted by xxxxxxxx

                I'm having trouble with that loop. Because the C++ version is using pointers to insert three color values(I'm assuming vectors) into it. And I don't know how to create a python variable that is the right type to do that. I tried c4d.Vector but it didn't work.
                The sdk has a page listing color as a struct. I'm not sure if this is what I need to do. Or how to do it.

                    for y in xrange(height) :  
                      for x in xrange(width) :  
                          r  <----------------------#How do I define this as a three value color variable?    
                          bmp.GetPixel(x,y,r,r,r)  
                          bmp.SetAlphaPixel(alpha, x, y, r)
                

                The current documentation of BaseBitmap.GetPixel() is confusing but you see that it says that it returns the pixel color as a list of integer values, so you can do this:

                r, g, b = bmp.GetPixel(x,y)
                

                And in C++, r isn't a three color variable but it works because r, g and b holds the same value in the bitmap (greyscale) so it assigns three times the same value to r.

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

                  THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

                  On 31/08/2012 at 01:29, xxxxxxxx wrote:

                  Originally posted by xxxxxxxx

                  -Per your question about about the width and height of the alpha.
                  If you scale the virtual plane by placing their vectors father apart(padr). I've found that the alpha will not always scale up enough. So the text can sometimes get chopped off.
                  So adding something like width+5 and height+5 in the alpha loop will fix that problem by making the alpha bigger so it doesn't cut off the text.
                  This also seems to stretch the text and make it blurrier the more it's scaled up. So I'm not sure if this is the proper way to scale the text. But it's the only way I've found to do it (But it's probably wrong).
                  I probably should have written better notes about that one.

                  What I've done is to have a minimum alpha so the text isn't chopped off:

                  r,g,b = bmp.GetPixel(x, y)
                  if r < 150:
                      r = 150
                  bmp.SetAlphaPixel(alpha, x, y, r)
                  
                  1 Reply Last reply Reply Quote 0
                  • H Offline
                    Helper
                    last edited by

                    THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

                    On 31/08/2012 at 01:51, xxxxxxxx wrote:

                    Originally posted by xxxxxxxx

                    -No information how to create a variable with FONTCHOOSER_DATA in it.

                    In Python you can get the default font container for FONTCHOOSER_DATA calling

                    ft = c4d.GetCustomDataTypeDefault(c4d.FONTCHOOSER_DATA)
                    

                    Or you can also create a default FontData with

                    fd = c4d.FontData()
                    

                    Originally posted by xxxxxxxx

                    -No information on how to iterate all the fonts and then store them in a container

                    It's currently not possible to enumerate all the fonts and get information on them because EnumerateFonts(), GetFontName(), GetFontDescription(), GetDefaultFont(), GetFontSize(), SetFontSize() are missing in the Python SDK.

                    Originally posted by xxxxxxxx

                    -No information on how to then use those stored fonts and set them as needed

                    FontData has SetFont()/GetFont() methods in Python too.

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

                      THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

                      On 31/08/2012 at 08:34, xxxxxxxx wrote:

                      Thanks a lot Yannick. That's got it working now.
                      I'm so bad at interpreting those little (semi-hidden) things in the SDKs.

                      I found another error in the code I posted. So here's the entire code again that should work properly:

                      import c4d,os  
                      from c4d import plugins, bitmaps, documents  
                        
                      PLUGIN_ID = 1000003  #TESTING ID# Only!!!  
                        
                      class DrawText(plugins.TagData) :  
                        def Init(self, tag) :  
                            return True  
                        
                        def Draw(self, tag, op, bd, bh) :  
                          
                        doc = documents.GetActiveDocument()  
                        obj = tag.GetObject()                                       #The object the python tag is on  
                        if obj.GetType() == 5100:  
                            points = obj.GetAllPoints()              
                            globalpnts = obj.GetMg() * points[4]   
                        
                        bd.SetPen(c4d.Vector(1.0, 1.0, 1.0))  
                        bd.SetMatrix_Screen()                                       #Use the screen's matrix to draw on  
                        bd.DrawLine2D(c4d.Vector(0, 0, 0), c4d.Vector(0, 0, 0))     #Draw a line with a zero length<---This is our dummy object  
                        bd.SetDepth(True)                                           #This fixes drawing problems when using 2D functions  
                        
                        text = "My Text"                            #The text that will display on the screen  
                        
                        cm = c4d.bitmaps.GeClipMap()  
                        cm.Init(0, 0, 32)  
                        cm.BeginDraw()                              #Start drawing the object. This must be used before drawing the text  
                        width = cm.TextWidth(text)                  #Gets the width of the text  
                        height = cm.TextHeight()                    #Gets the height of the text  
                        cm.EndDraw()                                #Tell C4D we're done drawing the text  
                        cm.Destroy()                                #Release any memory used by the GeClipMap class  
                        
                        cm.Init(width, height, 32)                  #Dynamically sets the size of the virtual plane the text is on  
                        cm.BeginDraw()  
                        cm.SetColor(255, 255, 255, 255)             #Sets the color of the text to white  
                        cm.TextAt(0,0,text)  
                        cm.EndDraw()          
                        bd.SetMatrix_Screen()                       #We always need a matrix to draw things...In this case we'll use the screen's matrix  
                        bd.SetLightList(c4d.BDRAW_SETLIGHTLIST_NOLIGHTS)#Use other options for different results if desired      
                          
                        xpos=255                                     #The X screen location of the left upper corner of the plane object the text bitmap is on  
                        ypos=255                                     #The Y screen location of the left upper corner of the plane object the text bitmap is on  
                        
                        
                        #Now we set the actual vector postions for the four point plane object that holds the text bitmap  
                        padr = [  
                        (c4d.Vector(xpos,ypos,0)),                          #upper left corner  
                        (c4d.Vector(xpos+width,ypos,0)),                    #upper right corner  
                        (c4d.Vector(xpos+width,ypos+height,0)),             #lower right corner  
                        (c4d.Vector(xpos,ypos+height,0))                    #lower left corner  
                        ]      
                        
                        #Now we set the color vector values for the plane object   
                        cadr = [  
                        (c4d.Vector(1,1,1)),                            
                        (c4d.Vector(1,1,1)),                   
                        (c4d.Vector(1,1,1)),            
                        (c4d.Vector(1,1,1))                
                        ]  
                        
                        
                        #Now we set up the normals directions for the four point plane object that holds the text bitmap  
                        vnadr = [  
                        (c4d.Vector(0,0,1)),                            
                        (c4d.Vector(0,0,1)),                   
                        (c4d.Vector(0,0,1)),            
                        (c4d.Vector(0,0,1))                
                        ]      
                        
                        #Now we set up the UV's for the four point plane object that holds the text bitmap  
                        uvadr = [  
                        (c4d.Vector(0,0,0)),                            
                        (c4d.Vector(1,0,0)),                   
                        (c4d.Vector(1,1,0)),            
                        (c4d.Vector(0,1,0))                
                        ]          
                        
                        cmbmp = bitmaps.BaseBitmap()                 #Get the bitmap image(the text) being displayed on the virtual plane  
                        cmbmp = cm.GetBitmap()  
                              
                        bmp = bitmaps.BaseBitmap()                   #Get a copy of that image(we'll use this to create an alpha background channel)   
                        bmp = cmbmp.GetClone()  
                          
                        alpha = bmp.GetInternalChannel()             #Get at the RGBA channels of the bitmap copy  
                        alpha = bmp.AddChannel(True, False)          #Add a channel and assign it to a variable so we can use it later on  
                          
                              
                        #Apply the alpha bitmap to the solution so only the text is visible on the screen  
                        #The alpha acts like a matte object. So if you find that your text is getting cut off..Your alpha might be too small  
                        #You can increase the width and height of the alpha to fix that problem by adding numbers to height+ and width+      
                          
                        for y in xrange(height) :  
                            for x in xrange(width) :  
                                r,g,b = bmp.GetPixel(x, y)   
                                bmp.SetAlphaPixel(alpha, x, y, r)  
                                  
                        
                        #Optionally....You can also hard code an alpha size to control the size of the alpha  
                        #r,g,b = bmp.GetPixel(x, y)  
                        #if r < 150:  
                        #    r = 150  
                        #bmp.SetAlphaPixel(alpha, x, y, r)              
                        
                          
                        bd.DrawTexture(bmp,padr,cadr,vnadr,uvadr,4,c4d.DRAW_ALPHA_NORMAL,c4d.DRAW_TEXTUREFLAGS_0)  
                        bd.SetDepth(True)      
                          
                              
                        return True  
                        
                      if __name__ == "__main__":  
                        path, file = os.path.split(__file__)  
                        bmp = bitmaps.BaseBitmap()  
                        bmp.InitWith(os.path.join(path, "res", "icon.tif"))  
                        plugins.RegisterTagPlugin(id = PLUGIN_ID, str = "DrawText", g = DrawText, description = "drawtext", icon = bmp, info = c4d.TAG_EXPRESSION|c4d.TAG_VISIBLE)
                      

                      As always...Thanks a ton for your help Yannick. 👍
                      -ScottA

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