GLYPHMETRICSFLOAT gmf[256]; // Information About Font Characters Outline
bool BuildFont ()
{
HFONT font; // Windows Font ID
font = CreateFont(
12, // Font Height
0, // Font Width
0, // Angle Of Escapement
0, // Orientation Angle
FW_BOLD, // Font Weight
FALSE, // Italic
FALSE, // Underline
FALSE, // 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
"Comic Sans MS"); // Font Name
if (font == 0)
return false;
SelectObject (gInfo.hDC, font); // Selects The Font We Created
int res = wglUseFontOutlines(
gInfo.hDC, // Select The Current DC
0, // Starting Character
255, // Number Of Display Lists To Build
1, // Starting Display Lists
0.0f, // Deviation From The True Outlines
0.3f, // Font Thickness In The Z Direction
WGL_FONT_POLYGONS, // Use Polygons, Not Lines
gmf); // Address Of Buffer To Recieve Data
return res == TRUE;
}
void glPrint (int font, const char *fmt, ...) // Custom GL "Print" Routine
{
if (!fmt)
return;
char text[256]; // Holds Our String
va_list p; // Pointer To List Of Arguments
va_start (p, fmt); // Parses The String For Variables
vsprintf (text, fmt, p); // And Converts Symbols To Actual Numbers
va_end (p); // Results Are Stored In Text
size_t len = strlen(text);
float width = 0; // Width of the text
for (size_t i=0; i<len; i++)
width += gmf[text[i]].gmfCellIncX; // Increase by each characters width
glTranslatef (-width /2, 0, 0);// Center the text on the screen
glPushAttrib (GL_LIST_BIT); // Save the glListBase setting
glListBase (1);
glCallLists (int(len), GL_UNSIGNED_BYTE, text); // Draw the text
glPopAttrib (); // Restore the glListBase setting
}
bool Init ()
{
glClearColor (0, 0, 0, 0);
glShadeModel (GL_SMOOTH);
glEnable (GL_DEPTH_TEST);
glClearDepth (1);
glDepthFunc(GL_LEQUAL);
glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
glEnable (GL_LIGHT0);
glEnable (GL_LIGHTING);
glEnable (GL_COLOR_MATERIAL);
return BuildFont (); // Build The Font
}
void Draw ()
{
static bool grow = true;
static float angle, shift; // Used to rotate text & change color
angle += grow ? 0.5f : -0.5f;
if (angle < -60.f || 60.f < angle)
grow = !grow;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef (0, 0, angle/8 - 8);
glRotatef (angle, 1, 0, 0);
glRotatef (angle, 0, 0, 1);
float
a = (angle + shift) / 40, // Pulsing Colors Based On The Rotation
red = 0.5f + 0.5f * cos (a),
green = 0.5f + 0.5f * sin (a),
blue = 0.6f - 0.2f * cos (a);
glColor3f (red, green, blue);
glPrint (0, "Rotation Angle: %+05.1f", angle);
shift += 2;
}
void Update (DWORD ms)
{
if (gInfo.keys[VK_ESCAPE])
{
gInfo.bQuit = true;
PostMessage (gInfo.hWnd, WM_QUIT, 0, 0);
}
if (gInfo.keys[VK_F1])
PostMessage (gInfo.hWnd, WM_TOGGLEFULLSCREEN, 0, 0);
}
В этом примере мы не пользовались услугами функции glGenLists, так как нужен только один фонт и один список изображений, в который попали все 256 символов таблицы ASCII. В другом сценарии пришлось бы вызывать glGenLists. Отметьте, что:
q Код символа является индексом сдвига в массиве изображений глифов.
q Функция glPrint с переменным числом аргументов реализована с помощью макросов: va_list, va_start, va_end и особой функции vsprintf, которая умеет работать со списком аргументов произвольной длины.
q Вызовы функций glPushAttrib и glPopAttrib в нашем сценарии можно убрать, они приведены с учебной целью.
В других, более сложных сценариях использования списков изображений, обращения к стеку аттрибутов (то есть состояний конечного автомата OpenGL) могут понадобиться. Стек позволяет запомнить и восстановить многие состояния, в том числе и начальный сдвиг в массиве изображений. Он установлен при вызове функции glListBase.
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.