Sign In/My Account | View Cart  
advertisement


Listen Print Discuss

Building a 3D Engine in Perl, Part 4
by Geoff Broadwell | Pages: 1, 2, 3, 4, 5, 6, 7, 8

The OpenGL section begins by setting the current drawing color to white with a call to glColor. The next line sets the raster position, the window coordinates at which to place the origin of the next bitmap. After rendering each bitmap, the raster position is automatically updated using the bitmap's X and Y increments so that the bitmaps will not overlap each other. In this case, (10, 10, 0) sets the raster position ten pixels up and right from the lower-left corner of the window, with Z=0.

The next two lines together actually call the appropriate display list in our bitmap font for each character in the $fps string. glCallListsScalar breaks the string into individual characters and calls the display list with the same number as the codepoint of the character. For example, for the "5" character (at codepoint 53 decimal), glCallListsScalar calls display list 53. Unfortunately, there's no guarantee that display list 53 actually will display a "5," because the font's list base may not be 0. If the font had a list base of 1500, for example, the code would need to call display list 1500+53=1553 to display the "5."

Rather than make the programmer do this calculation manually every time, OpenGL provides the glListBase function, which sets the list base to use with glCallLists. After the glListBase call above, OpenGL will automatically offset every display list number specified with glCallLists by $base.

You may have noticed that in the code I use glCallListsScalar, but the previous paragraph referred to glCallLists instead. glCallListsScalar is actually an SDL_perl extension (not part of core OpenGL) that provides an alternate calling convention for glCallLists in Perl. Internally, SDL_perl implements both Perl routines using the same underlying C function in OpenGL (glCallLists). SDL_perl provides two different calling conventions because Perl treats a string and an array of numbers as two different things, while C treats them as essentially the same.

If you want to render a string, and all of the characters in the string have codepoints <= 255 decimal (single-byte character sets, and the ASCII subset of most variable-width character sets), you can use glCallListsScalar, and it will do the right thing for you:

glCallListsScalar($string);

If you simply want to render several display lists with a single call, and you're not trying to render a string, use the standard version of glCallLists:

glCallLists(@lists);

If you need to render a string, but it contains characters above codepoint 255, you have to use a more complex workaround:

glCallLists(map ord($_) =& split // =& $string);

Because the FPS counter merely renders ASCII digits, the first option works fine.

draw_frame now ends with a call to draw_fps, like so:

sub draw_frame
{
    my $self = shift;

    $self->set_projection_3d;
    $self->set_eye_lights;
    $self->set_view_3d;
    $self->set_world_lights;
    $self->draw_view;
    $self->draw_fps;
}

For now, I decided to turn off benchmark mode by changing the config setting in init_config to 0:

    benchmark =& 0,

With the font handling in place, and draw_fps called each frame to display the frame rate in white in the lower-left corner, everything should be grand, as Figure 1 shows.

drawing frame rate, take one
Figure 1. Drawing the frame rate

Oops. There's no frame rate display. Actually, it's there, just very faint. If you look very carefully (or turn your video card's gamma up very high), you can just make out the frame rate display near the top of the window, above the big white box on the right. There are (at least) two problems--the text is too dark and it's in the wrong place.

Pages: 1, 2, 3, 4, 5, 6, 7, 8

Next Pagearrow