Каркас Windows-приложения. Особенности нового каркаса. Перемещение в пространстве (с текстурированными стенами), страница 22

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.