Go from "translation" Nehe OpenGL tutorial
Objective
Statement, this Nehe OpenGL tutorial series of articles by 51 blog yarin Translation (2010-08-19), this blog for reprint and a little collation and modification. Thank you for compiling Nehe's OpenGL pipeline tutorial, as well as yarn translation finishing.
Nehe OpenGL Lesson 14th: Graphic Fonts
Graphic font:
In a lesson we will teach you to draw 3D graphic fonts, which can be transformed like normal 3D models.
This class goes on to the last lesson. In the 13th lesson we learned how to use bitmap fonts, this lesson, we will learn how to use contour fonts.
The way to create outline fonts is similar to the way we create bitmap fonts in Lesson 13th. However, the outline font looks cool 100 times times! You can specify the size of the outline font. Contour fonts can be 3D in the screen movement, and the outline of the font can also have a certain thickness! Rather than a plane
The 2D character. Using the contour font, you can convert any font in your computer to 3D fonts in OpenGL, plus the proper normals, and the characters will be illuminated when there is light.
A small comment, this code is written specifically for Windows, it uses the Windows WGL function to create fonts, obviously, the Apple machine system has agl,x system has GLX to support the same thing, unfortunately, I can not guarantee that the code is also easy to use. If a person
There are platform-independent code that can display text on the screen, please let me know and I'll rewrite a tutorial about fonts.
We start with the typical code for the first lesson, add the stdio.h header file for standard input/output operations, and the Stdarg.h header file is used to parse the text and convert the variable to text. Finally add the MATH.H header file so that we can use the sin and COS functions on the screen
Move the text.
In addition, we will add 2 variables. Base will save the number of the first display list we created. Each character needs to have its own display list. For example, the character ' A ' is $67 in the display list, ' B ' is a. Therefore, the character ' A ' should be saved in the display list
The base + 65 location.
Let's add a variable called rot. Use it with the sin and COS functions to rotate the text on the screen. We also use it to change the color of the text.
Gluint Base; The starting position of the display list of the drawing font
Glfloat rot; Rotate Font
Glyphmetricsfloat gmf[256] used to save 256 outline fonts displays information about the location and orientation of each of the lists in a list. We use Gmf[num] to select letters. Num is the number of the display list we want to know. In a later code, I'll explain
How to check the width of each character so that text is automatically positioned in the center of the screen. Remember that the width of each character can be different. Glyphmetrics will greatly simplify our work.
Glyphmetricsfloat gmf[256]; Record 256 Characters of information
The code used to build a real font is similar to the way we create bitmap fonts. As with lesson 13, just replace the Wglusefontbitmaps function with the Wglusefontoutlines function.
base = Glgenlists (n); // Create 256 display list
Wglusefontoutlines ( hdc, //sets the handle to the current window's Device description table
0, //the ASCII value used to create the first character of a display list font
255, //number of characters
base, //the name of the first display list
0.0f, //the smoothness of the font, the smaller the smoother, the 0.0 is the smoothest state
0.2f, //the distance in the Z-direction
wgl_font_polygons, //uses polygons to generate characters, Each vertex has a separate normal
    GMF); //an array that receives glyph metric data, with each array element populated with its corresponding display list character data
}
Glvoid Killfont (glvoid) //Delete the display list
{
gldeletelists ( Base, //); Delete 256 display list
}
Here is my excellent GL writing program. You can call this code by calling Glprint ("text to write"). The text is stored in the string text[].
Glvoid glprint (const char *FMT, ...) Custom GL Output Font functions
{
The first line below defines a variable called length. We use this variable to query the length of the string. The second line creates an array of characters with a size of 256 characters, which holds the text string we want. The third line creates a pointer to a list of variables that we
The string is passed along with the list of variables. If we pass the text with a variable, the pointer will point to them.
float length=0; Length of query string
Char text[256]; Save the text string we want
Va_list ap; Pointer to a list of variables
The following two lines of code check if there is anything that needs to be displayed, and if there is nothing, there is nothing on the screen.
if (FMT = = NULL)//If no input is returned
Return
The next three lines of code convert all the symbols in the text to their character numbers. Finally, the text and the converted symbols are stored in a string called "text". I'll explain some more details about the characters in the future.
Va_start (AP, FMT); Analyzing variable parameters
vsprintf (text, FMT, AP); To write a parameter value to a string
Va_end (AP); End Analysis
Thanks to Jim Williams for his advice on the code below. I used to put the text in the center by hand, and his approach was much better.
We start with a loop, and it checks the characters in the text one after the other. We get the length of the text by strlen (text). After the loops are set, we will increase the length value by adding the lengths of each character. When the loop is finished, the value saved in length is
The length of the entire string. So, if we're going to write "Hello", assuming that each character has a length of 10 units, we first add the length of the first letter to the value of 10. Then we check the length of the second letter, which is also 10, so length becomes
10 + 10 (20). When we have checked all 5 letters, the value of length will be equal to 50 (5 *10).
The code that gives us the length of each character is gmf[text[loop]].gmfcellincx. Remember, GMF stores the information for each of our display lists. If Loop equals 0,text[loop] is the first character in our string. If Loop equals 1,text
[Loop] is the second character in our string. Gmfcellincx tells us the length of the selected character. Gmfcellincx represents the true distance that the display position moves from the previous character on the drawing to the right, so that the characters do not overlap. At the same time, this distance
The distance is the width of the character we want. You can also use the gmfcelllncy command to get the height of the character. This is handy if you are drawing text vertically instead of horizontally.
for (unsigned int loop=0;loop< (strlen (text)); loop++)//Find the length of the entire string
{
Length+=gmf[text[loop]].gmfcellincx;
}
Finally we take out the calculated length and turn it into a negative number (because we want to move the text from the center of the screen to the left so that the entire text is placed in the middle of the screen). Then we divide the length by 2. We don't want to move the entire length of the text, only half!
Gltranslatef (-length/2,0.0f,0.0f); Put the string on the far left
Then we push the gl_list_bit into the property stack, which prevents gllistbase from affecting other display lists in our program
Glpushattrib (Gl_list_bit); Pressing the display list property into the property stack
Gllistbase (base); Set the base value of the display list to 0
Now that OpenGL knows where the character is stored, we can let it display the text on the screen. Glcalllists will invoke multiple display lists to display the contents of the entire text on the screen at the same time.
The following code does the follow-up work. First, it tells OpenGL that we are going to display the contents of the display list on the screen. The Strlen (text) function is used to calculate the length of the text we are going to display on the screen. Then, OpenGL needs to know the maximum number of lists we allow to send to it
Value. We still can't send a string with a length greater than 255. So we use Unsigned_byte. (use 0-255 to indicate the character we need). Finally, we tell OpenGL what to display by passing string literals.
Maybe you want to know why characters don't stack up with each other. Because each character's display list knows where the right edge of the character is, after writing a character, OpenGL automatically moves to the right of the character you just wrote, and moves from GL when you write down a word or draw an object.
Move to the last position to start, that is, the last character to the right.
Finally, we'll gl_list_bit the property pop-up stack and restore GL to the state we had before we used Gllistbase (base) to set base.
Glcalllists (strlen (text), gl_unsigned_byte, text); Invoking the Display list drawing string
Glpopattrib (); Pop-up property stack
}
Here is the code for the drawing. We start by clearing the screen and the depth cache. We call Glloadidentity () to reset everything. Then we move the coordinate system to the screen 10 units. Contour fonts perform very well in perspective mode. The deeper you move the text into the screen, the text
The word is even smaller when it is opened up. The closer the text is to you, the more it looks.
You can also use the Glscalef (x, y, z) command to manipulate outline fonts. If you want to enlarge the font twice times, you can use Glscalef (1.0f,2.0f,1.0f). 2.0f acts on the y-axis, which tells OpenGL to draw the height of the display list to twice times the original. If the 2.0f function
On the x-axis, the width of the text becomes twice times the original.
int Drawglscene (glvoid)//This procedure includes all drawing codes
{
Glclear (Gl_color_buffer_bit | Gl_depth_buffer_bit); Clear screen and depth cache
Glloadidentity (); Resets the current model observation matrix
Gltranslatef (0.0f,0.0f,-10.0f); Move into a unit on the screen
After moving to the screen, we want the text to rotate. The following 3 lines of code are used to rotate the screen on 3 axes. I multiply the rot by different numbers so that the rotational speed is different in each direction.
Glrotatef (rot,1.0f,0.0f,0.0f); Rotate along the x axis
Glrotatef (rot*1.5f,0.0f,1.0f,0.0f); Rotate along the y axis
Glrotatef (rot*1.4f,0.0f,0.0f,1.0f); Rotate along the z axis
The following is an exciting color cycle. As usual, we use the only incrementing variable (ROT). Colors are recycled by using the Cos and sin. I divide the rot by different numbers so that each color is incremented at a different rate. The end result is very good.
Set color based on font position
glcolor3f (1.0f*float (cos (rot/20.0f)), 1.0f*float (sin (rot/25.0f)), 1.0f-0.5f*float (cos (rot/17.0f)));
My favorite part, write the text on the screen. I use the same function that writes the bitmap font to the screen. Write the text on the screen, all you have to do is Glprint ("The text you want to write"). Very simple.
In the following code, we're going to write nehe, spaces, dashes, spaces, and then the result of the rot's value divided by 50 (in order to slow down the counter). If this number is greater than 999.99, the fourth number on the left will be removed (we require only 3 digits to the left of the decimal point). Show only decimals
Two digits to the right of the dot.
Glprint ("Nehe-%3.2f", rot/50); Output Text to screen
Then increase the rotation variable to change the color and rotate the text.
rot+=0.5f; Increase rotation variable
return TRUE; Successful return
}
Original source code and version of the download:
Http://nehe.gamedev.net/data/lessons/lesson.asp?lesson=14
Nehe OpenGL Tutorial Lesson 14th: Graphic Fonts