DrawTexture(): Alpha problem
-
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
-
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.
-
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?
-
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
-
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 neededWithout that information. I can't use any of the various font functions in the python SDK.
-ScottA
-
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.
-
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)
-
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.
-
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