tutorial 9

This tutorial is a bit more of a comparison with using different methods for using fonts. Again, we will be using the NSGLFont class. We will look at the four different types of NSGLFont that are now available, as well as see the kinds of changes that are made for each of them to work

First, a bit of extra code that I created. In Tutorial 7, I mentioned that I didn't know how to get the size of a letter. This led to an evenly spaced font, even when the font should have been variable width. Here is how you can find the width of each character:


x_offset[i] = (unsigned int)[font widthOfString: [NSString stringWithCString: jstr]] +1;

Now, let's look at bitmapFont. This font was covered in the last tutorial, and is made by using the glBitmap command. It's a quick font to create, and is generally easy to work with. On the other hand, a glBitmap can't really be scaled, moved, rotated, translated, or have any really interesting thing done to it.


glNewList( base+i,GL_COMPILE); glBitmap(width[i],height[i],0,0,x_offset[i],0,data[i]); glEndList();

This next one is very similar to the bitmapFont, and is a pixmapFont. Instead of using the glBitmap command, this uses glDrawPixels. Using this font means that we can have antialiased text, but this font isn't as easy to work with. Changing the color of a font using the pixmapFont format is much more difficult than for glBitmap, since we have to change the color of the actual pixels and not just the raster color. We can zoom in or out by using glZoomPixels. This font looks nicer than the bitmapFont, but has a bit more set up.


//setting up the CGContext: we need to use an RGB colorspace
//with an alpha value last in order to get antialiasing
//this is the only supported combination
colorspace = CGColorSpaceCreateDeviceRGB(); alphaInfo = kCGImageAlphaPremultipliedLast;
//compiling the list requires both drawing the pixels as well as
//moving the raster position so that we don't draw directly on top of anything
//while not required to draw, blending should also be enabled
//in order to have transparency of the black area
//(this is NOT required in a bitmap font)
glNewList( base+i,GL_COMPILE); glDrawPixels(width[i],height[i],GL_RGBA,GL_UNSIGNED_BYTE,data[i]); glBitmap(0,0,0,0,x_offset[i],0,NULL); glEndList();

Finally we start on extruded fonts. Extruded fonts can be easily rotated, translated, colored, scaled or any other OpenGL operation you might like to use. Unfortunately, they are made of polygons, so they eat your polygon count. First, we look at cheapOutlineFont. This font type limits the number of polygons used in any one character, however, this can mean that the character is simply not rendered properly. The colorspace is gray scale again. We try to determine the lowest number of vertices by a simple scan across a row. We then extrude the font using this scan. We scale these down, and we the translate so that we aren't writing everything on top of itself.

One of the worst aspects of this font is that you cannot use any color you want, because it will not necessarily look good. Most of the time, transparency will make the fonts looks plain wierd, with lines going through them.


glNewList( base+i,GL_COMPILE); glBegin(GL_QUADS); for( n = 0; n < nVertices*4; n += 4 ) { glVertex3f(vertex[n+0]*xdiff, vertex[n+1]*ydiff, 0); glVertex3f(vertex[n+2]*xdiff, vertex[n+1]*ydiff, 0); glVertex3f(vertex[n+2]*xdiff, vertex[n+3]*ydiff, 0); glVertex3f(vertex[n+0]*xdiff, vertex[n+3]*ydiff, 0); }
//(omitted a large number of the vertices)
glEnd(); glTranslatef(x_offset[i]*xdiff, 0, 0); glEndList();

Last, we look at outlineFont. This is the most costly in terms of setup of all the fonts. This is the nicest of the fonts as well. There are no color restrictions with this font. This font type has all the previously mentioned benefits of an extruded font, but uses on average more polygons and on average takes more time to be set up.

This font is a height map of an antialiased font drawing. It does not look as nice as an antialiased pixel based font if there is no rotation or translation.


glNewList( base+i,GL_COMPILE); glBegin( GL_QUADS ); maxX = 0; for( x = 0; x < max_width - STEPSIZE; x += STEPSIZE ) { for( y = 0; y < max_height - STEPSIZE; y += STEPSIZE ) {
//if the whole area is 0, then we don't want to add a quad
if( [self getHeight:i atX:x atY:y] == 0 && [self getHeight:i atX:x atY:y+STEPSIZE] == 0 && [self getHeight:i atX:x+STEPSIZE atY:y+STEPSIZE] == 0 && [self getHeight:i atX:x+STEPSIZE atY:y] == 0); else {
//scale the x and y, then get the z at the correct point
//finally, scale the z value at that point to 0<=zpoint<=z
usex = (float)x*xdiff; usey = (float)y*ydiff; usez = (float)[self getHeight:i atX:x atY:y]*z/255; glVertex3f(usex, usey, usez);
//do the same thing at the lower corner
usex = (float)x*xdiff; usey = (float)(y+STEPSIZE)*ydiff; usez = (float)[self getHeight:i atX:x atY:y+STEPSIZE]*z/255; glVertex3f(usex, usey, usez);
//and again at the right corner
usex = (float)(x+STEPSIZE)*xdiff; usey = (float)(y+STEPSIZE)*ydiff; usez = (float)[self getHeight:i atX:x+STEPSIZE atY:y+STEPSIZE]*z/255; glVertex3f(usex, usey, usez);
//and finally at the upper-right corner
usex = (float)(x+STEPSIZE)*xdiff; usey = (float)y*ydiff; usez = (float)[self getHeight:i atX:x+STEPSIZE atY:y]*z/255; glVertex3f(usex, usey, usez); } } } glEnd();
//after the letter has been created, simply move the character over
glTranslatef(x_offset[i]*xdiff, 0, 0); glEndList();




     Download the project builder files

 

return to deep cocoa / cocoagl tutorials