Запустите приложение и убедитесь в том, что оно работает в режиме выполнения (Ctrl+F5). Замечу, что в моей системе функция wglUseFontOutlines по неизвестной мне причине отказывается работать (зависает) в режиме отладки (F5).
Текст, как и любой другой объект сцены OpenGL, можно текстурировать, управляя текстурными координатами, фильтрацией, а кроме того и возможностями генерировать текстуру. Любопытно взглянуть на трехмерные изображения специальных символов, которые имеются в таких экзотических фонтах, как Wingdings. Следующий пример, позволяет это сделать. Создайте новый файл Text3DTex.cpp, скопируйте в него старый и введите изменения, как показано ниже. Набор глобальных переменных будет таким.
TCHAR *pFile = 0; // Bitmap file name
UINT texture; // One Texture Map
UINT c; // Character code counter
bool up, dn; // Upm Down Pressed?
Кроме возможности изменить текстуру, пользователь сможет перемещаться по спискам изображений с помощью клавиш VK_UP и VK_DOWN. Теперь добавьте функцию FileDlg, которую мы использовали ранее. Затем вставьте код функции LoadTexture, она должна быть такой же простой, как и в файле Wave.cpp. Далее приведены изменения, которые в основном касаются работы с текстом и анимации изображения.
void BuildFont ()
{
GLYPHMETRICSFLOAT gmf[256];
HFONT font = CreateFont(-12, 0,0,0, FW_BOLD,FALSE,FALSE,FALSE,SYMBOL_CHARSET,
OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS,ANTIALIASED_QUALITY,
FF_DONTCARE | DEFAULT_PITCH, "Wingdings"); // Font Name
SelectObject (gInfo.hDC, font);
wglUseFontOutlines (gInfo.hDC,0,255,1,0.1f,0.2f, WGL_FONT_POLYGONS, gmf);
}
void glPrint (char *text) // Custom GL "Print" Routine
{
if (!text)
return;
glPushAttrib (GL_LIST_BIT); // Pushes The Display List Bits
glListBase (1);
glCallLists (int(strlen(text)), GL_UNSIGNED_BYTE, text);
glPopAttrib (); // Pops The Display List Bits
}
bool Init ()
{
if (pFile == 0)
pFile = gInfo.bFull ?
strcpy (new TCHAR[128],"Data/Lights.bmp") : FileDlg (true);
if (!LoadTexture (pFile))
return false;
BuildFont();
glClearColor (0, 0, 0, 0.5f);
glShadeModel (GL_SMOOTH);
glClearDepth (1);
glEnable (GL_DEPTH_TEST);
glDepthFunc (GL_LEQUAL);
glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
glEnable (GL_LIGHT0);
glEnable (GL_LIGHTING);
glEnable(GL_TEXTURE_2D);
glEnable (GL_TEXTURE_GEN_S);
glEnable (GL_TEXTURE_GEN_T);
glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
return true;
}
void Draw ()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
static float a;
float y = -0.3f + 0.2f * sin (a / 30);
glTranslatef (-0.55f, y, -2.5f);
glRotatef (180 * (y + 0.3f), 0, 1, 0);
if (-0.302f < y && y < -0.298f)
c = (c+1) % 224;
char ch = char(31 + c);
char s[] = { ch, 0 };
glPrint (s);
a += 1;
}
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);
if (gInfo.keys[VK_UP] && !up)
{
up = true;
c = (c+1) % 224;
}
if (!gInfo.keys[VK_UP])
up = false;
if (gInfo.keys[VK_DOWN] && !dn)
{
dn = true;
if (c > 0)
c = (c-1) % 224;
else
c = 223;
}
if (!gInfo.keys[VK_DOWN])
dn = false;
}
Код символа изменяется в функции Draw после того как прошел весь цикл проективных трансформаций текущего изображения. Смотрите строку кода:
c = (c+1) % 224;
Ограничение вызвано особенностями используемого фонта.
Следующий пример иллюстрирует возможности изображения двухмерного текста. Мы приводим его после трехмерного, так как здесь использован более сложный сценарий использования массива списков (глифов).
q Во-первых, алгоритм использует 2 массива для создания двух множеств глифов, соответствующих двум фонтам,
q Во-вторых, здесь создаются bitmap-изображения не всех символов, а только 96 из них.
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.