Advertisement

Help with 3D text.

Started by May 15, 2003 09:58 PM
4 comments, last by TheOnlyCoolTim 21 years, 9 months ago
I have created, by modifying the 3D Text tutorial, a "fonter" class that, when constructed, sets up the font display lists, and has a Print function that prints the string passed to it. The Print function also takes a horizontal and vertical size, and scales the string so that if the Print function were called and the sizes were both 1.0, the string would be constrained to a square or if the x size was 3.0 and the vertical size was 1.0, the string would be three times as long as it is high. The problem is that my strings are appearing slightly too far to the right. This makes things look bad and means that I cannot implement rotation of the strings properly. Here''s the constructor for the "fonter" class:
  

fonter::fonter(char* fontname, bool italic, bool underline, bool strikeout, HDC &hDC)
{
	HFONT	font;										// Windows Font ID

										
	base = glGenLists(256);								//base is a private member of the fonter class


	font = CreateFont(	-24,							// Height Of Font

						0,								// Width Of Font

						0,								// Angle Of Escapement

						0,								// Orientation Angle

						FW_BOLD,						// Font Weight

						italic,							// Italic

						underline,							// Underline

						strikeout,							// Strikeout

						ANSI_CHARSET,					// Character Set Identifier

						OUT_TT_PRECIS,					// Output Precision

						CLIP_DEFAULT_PRECIS,			// Clipping Precision

						ANTIALIASED_QUALITY,			// Output Quality

						FF_DONTCARE|DEFAULT_PITCH,		// Family And Pitch

						fontname);					// Font Name



	SelectObject(hDC, font);							// Selects The Font We Want

	
	wglUseFontOutlines(	hDC,				// Select The Current DC

			0,				// Starting Character

			255,				// Number Of Display Lists To Build

			base,				// Starting Display Lists

			0.0f,				// Deviation From The True Outlines

			0.05f,				// Font Thickness In The Z Direction

			WGL_FONT_POLYGONS,		// Use Polygons, Not Lines

			gmf);				// Address Of Buffer To Recieve Data - gmf is a private member of the fonter class

}

  
Here''s the implementation of the Print function:
  

GLvoid fonter::Print(GLfloat xsiz, GLfloat ysiz, const char *text)					
{

	GLfloat length = 0.0f; //Length of the font, before scaling

	GLfloat height = 0.0f; //Height " "

	GLfloat xscl = 1.0f;   //Factors to scale by to get the desired size.

	GLfloat yscl = 1.0f;
	GLfloat thisheight;    //A temp variable

	
	
 
    if (text == NULL)									// If There''s No Text

		return;											// Do Nothing

	
	for (unsigned int wloop=0;wloop<(strlen(text));wloop++)	// Loop To Find Text Length

	{
		length+=gmf[text[wloop]].gmfBlackBoxX;		// Increase Length By Each Characters Width

	}
	
	for (unsigned int hloop=0;hloop<(strlen(text));hloop++)
	{
	    thisheight = gmf[text[hloop]].gmfBlackBoxY;
        if (height < thisheight)                      //It just bases the height off the tallest character in the string.

	    height = thisheight;                          //Later it might do something about drop characters (like "g".)

    }

	xscl = xsiz/length;                               //Finds the factor to scale by

	yscl = ysiz/height;
 
	glEnable(GL_COLOR_MATERIAL);

	glScalef(xscl, 1.0f, 1.0f);                       //Scales

	glScalef(1.0f, yscl, 1.0f);
	
	glPushAttrib(GL_LIST_BIT);							// Pushes The Display List Bits

	glListBase(base);								// Sets The Base Character to 32

	glCallLists(strlen(text), GL_UNSIGNED_BYTE, text);	// Draws The Display List Text

	glPopAttrib();										// Pops The Display List Bits

	
	glDisable(GL_COLOR_MATERIAL);
}
  
Here is a place my program creates a "fonter": settingsfont = new fonter("Impact", 0, 0, 0, hDC); Here is a place I call the Print function for text 2 units long and 0.4 units high: settingsfont->Print(2.0f, 0.4f, "TANK-(P)ONG"); See if you can guess what game I am making from the string! Thanks for your help, Tim
Bump... Any help?

Tim
Advertisement
Just a couple of thoughts..

when you are calling the print function, you don''t appear to be setting the x, y and z position for the text? what is the previous glTranslate() your doing? is this offsetting where you want the text displayed?

I have a similat routine, and have glLoadIdentity() followed by glTranslate() to set the text position.

you have two glScalef commands in the code, doesn''t the second one with the x value of 1.0f reset the first command?

would it be better to have glScalef(xsize, ysize, 1.0f)
I wrote a class to encapsulate it, you might want to check it out....
http://www.codeproject.com/useritems/PsiFontEngine.asp
"you have two glScalef commands in the code, doesn''t the second one with the x value of 1.0f reset the first command?

would it be better to have glScalef(xsize, ysize, 1.0f)"

I guess I was playing around with weird scaling or something, but I changed it to glScalef(xscl, yscl, 1.0f) and it looks exactly the same.

"when you are calling the print function, you don''t appear to be setting the x, y and z position for the text? what is the previous glTranslate() your doing? is this offsetting where you want the text displayed?

I have a similat routine, and have glLoadIdentity() followed by glTranslate() to set the text position."

I don''t think this is a problem... I do my glTranslate() to the lower left position of the text beforehand, just the way I prefer my code... Here''s another snippet where I call the fonter.Print() function.

glLoadIdentity();//Snip a few lighting and color commands...glTranslatef(-2.5f, 1.8f, -6.0f+0.1*sin(0.5*pulse)); //pulse is a variable I use to make the text float around a little on the screensettingsfont->Print(5.0f, 0.6f, "-SETTINGS-"); 


So that should make a string "-SETTINGS-" that is 5.0 units long and centered on the screen, but it is off center. I''m going to do some tests with quads to figure out exactly how far off it is. That might help track down the problem.

Tim
When you are performing the translate immediately before you print the text, is this position going to be the centre of your text or the left hand edge??

The translate you have is -2.5f along the x axis, which may not be half the length of the text, so the centre of the word will be offset from the x co-ord you specify.

In my code I set the text position x value as "xval-(length/2)", this centres the text over the specified co-ordinates.


  GLvoid glPrintCentre(float xVal, float yVal, float zVal, float red, float green, float blue, float alpha, const char *fmt, ...)					// Custom GL "Print" Routine{	float length = 0.0f;						// Used To Find The Length Of The Text	float height = 0.0f;						// Used to hold the text height	char text[256];								// Holds Our String	va_list ap;									// Pointer To List Of Arguments	va_start(ap, fmt);									// Parses The String For Variables	    vsprintf(text, fmt, ap);						// And Converts Symbols To Actual Numbers	va_end(ap);											// Results Are Stored In Text	for (unsigned int loop=0;loop<(strlen(text));loop++)	// Loop To Find Text Length	{		length+=gmf[text[loop]].gmfCellIncX;			// Increase Length By Each Characters Width	}	height = gmf[text[0]].gmfBlackBoxY;	glLoadIdentity();	glColor4f(red, green, blue, alpha);	glTranslatef(xVal - (length / 2), yVal - (height / 2), zVal);		// Center Our Text On The Screen	glPushAttrib(GL_LIST_BIT);							// Pushes The Display List Bits	glListBase(base);									// Sets The Base Character to 0	glCallLists(strlen(text), GL_UNSIGNED_BYTE, text);	// Draws The Display List Text	glPopAttrib();										// Pops The Display List Bits}  


many thanks to NeHe for this, as 99% of this is based on his tutorials (13 or 14 I think)

This topic is closed to new replies.

Advertisement