CS409/CS809 Tutorial 2: Sprite Fonts

This tutorial will show you how to use sprite fonts, which are fonts represented as images.  Here the demonstration simply shows how to use functions from the Obj Library to accomplish this tasks; to see how they are done using OpenGL directly, please see the source code in the Obj Library.

Setting up an OpenGL Project with the Obj Library of Files

1.      Start Microsoft Visual Studio 2013.  Select File / New / Project.  Under “Project Type”, choose Templates / Visual C++. Then choose a Win32 Console Application.  Change the name to Tutorial2 or some suitable name and change the location to a hard drive located on the computer (typically C or D).  You will need to remember this location for steps 3 and 5.  Make sure the “Create folder for project” checkbox is not checked and that the “Add to source control” is not checked.  Click OK.

·         If the Chose Location window keeps popping up again, you aren’t allowed to save files at the location you chose.  Select a different location, such as the desktop.

·         Do not put your program on one of the external drives like H.  The connection is slow, and your program may not compile correctly.

2.      Click Next> or Application Settings (they go to the same place).  Check the “Empty Project” box.  Make sure the “Security development lifecycle check” is not checked.  Click Finish.

3.      Go to http://www2.cs.uregina.ca/~anima/409/Terms/201810/Tutorials/index.html and download the Tutorial2.zip and ObjLibrary.zip files to your project directory.

4.      Unzip the 2 zip files.  You will have a folder called ObjLibrary and 11 other files.

5.      In Visual C++, go to Project/Add Existing Item… and select main2.cpp (and holding control, continue to select), Sleep.h, Sleep.cpp, and GetGlut.h.

6.      Ensure that Solution Explorer is visible (View / Solution Explorer). In the Solution Explorer, select Tutorial2 (the project name) and right click it.  Choose Add / New Filter.  A new folder icon should appear in the Solution Explorer.  Name it ObjLibrary.  (This creates an imaginary folder in the project, but it would not create a Windows folder on the computer).

7.      In the Solution Explorer, right click on the ObjLibrary folder icon and select Add / Existing item.  Go into the ObjLibrary folder on Windows and select all files.  The files should appear in the Solution Explorer inside the ObjLibrary folder.  You should get 26 files, although you will not be using most of them for this tutorial.

8.      Compile and run the original program.  You should see 2 windows: a text console and a graphical window labeled “Sprite Fonts”.  There is a set of positive X/Y/Z axes and a brown sphere in the middle of this second window.  Exit the windows.  Closing the text window will close the graphical window, and usually vice versa.

9.      For the remainder of the instructions, it is assumed that you compile and run regularly so that you can see what each change does.

Displaying Text using a SpriteFont

10.  Add an #include for "ObjLibrary/SpriteFont.h"
#include "ObjLibrary/SpriteFont.h"
Add a
using directive for ObjLibrary after the using directive for std:
using namespace ObjLibrary;

11.  Declare a global variable (before the main function) of the SpriteFont type:
SpriteFont font;

12.  In the main function, between initDisplay and glutMainLoop, use the load function in the SpriteFont class to load the sprite font Font.bmp:
  font.load("Font.bmp");
This function can only be called after the glutInit and glutCreateWindow functions have been executed.  If you call it before, it will fail to load the texture and generate an incomprehensible error message referring to assert.

13.  Immediately before the glutSwapBuffers command at the end of the display function, use the setUp2dView function in the SpriteFont class to set up a flat 2D coordinate system 640 by 480 units in size
  SpriteFont::setUp2dView(640, 480);
Although the coordinate system for sprite fonts is 640x480 in size, it corresponds to your whole window, regardless of the window’s actual size; most importantly, if your window has different proportions than 4:3, then stretching will occur. After the drawing your text, restore the old view with the unsetUp2dView function in the SpriteFont class:
  SpriteFont::unsetUp2dView();
If you do not call unsetUp2dView before calling setUp2dView next time the screen is displayed, your program will crash.

14.  After calling setUp2dView, display the text "Hello World!" starting at (260, 220), which is about in the middle of the screen. You can use the draw function in the SpriteFont class:
  font.draw("Hello World!", 260, 220);
The text should appear in white.

15.  After drawing "Hello World!", pass additional parameters to the draw function to display messages in different colours (the last three numbers are RGB values from 0 to 255):
  font.draw("Red Text",     385, 250, 255, 0,   0);
  font.draw("Yellow Text",  375, 190, 255, 255, 0);
  font.draw("Green Text",   275, 150, 0,   255, 0);
  font.draw("Cyan Text",    165, 190, 0,   255, 255);
  font.draw("Blue Text",    165, 250, 0,   0,   255);
  font.draw("Purple Text",  275, 300, 255, 0,   255);

16.  Make sure that these calls to the draw function are between the calls to setUp2dView and unsetUp2dView.  Note if one message draws over another message, the last one drawn is the one that will be visible.

17.  Make the "Hello World!" message display in bold face by adding SpriteFont::BOLD as a parameter to end of the draw command.
     
font.draw("Hello World!", 250, 220, SpriteFont::BOLD);

18.  Make the "Purple Text" message display in italics by adding SpriteFont::ITALICS as a parameter to end of the draw command.
  font.draw("Purple Text",  275, 300, 255, 0,   255, SpriteFont::ITALICS);

Handling Changes to Window Size

19.  Add two global variables to represent the current window size:
int window_width  = 640;
int window_height = 480;

20.  In the display function, set up the 2D coordinate system using these variables:
  SpriteFont::setUp2dView(window_width, window_height);

21.  Change the main function to set the initial window size using these variables.
  glutInitWindowSize(window_width, window_height);
This will ensure that you won't accidentally change one and not the other.

22.  Add code at the beginning of the reshape function to update the window size:
  window_width  = w;
  window_height = h;
Now, if you resize the window, the position and scaling of the text should not change, although the rest of the image will.

Review of Converting Numbers to Text

23.  Add an #include for <sstream>
#include <sstream>

24.  In the display function, declare a variable of type stringstream:
  stringstream ss;

Write some values into the stringstream using the same notation as with cout:
     ss << "Black" << 14;
You don’t need an
endl. The result will be “Black14”.

25.  Use the .str() function in stringstream to extract your values as an std::string:
  string black_string = ss.str();

26.  The string can now be displayed using the draw function in SpriteFont:
  font.draw(black_string,    50, 400, 0,   0,   0);
Remember to call the
draw function between the calls to setUp2dView and unsetUp2dView.

27.  Change the statement from Step 22 to produce a left parenthesis, a number from a variable x, and a right parenthesis:
  float x = 5.9f;
  ss << "(" << x << ")";