OpenGL v C++ Builderu (6.díl) - Builder.cz - Informacni server o programovani

Odběr fotomagazínu

Fotografický magazín "iZIN IDIF" každý týden ve Vašem e-mailu.
Co nového ve světě fotografie!

 

Zadejte Vaši e-mailovou adresu:

Kamarád fotí rád?

Přihlas ho k odběru fotomagazínu!

 

Zadejte e-mailovou adresu kamaráda:



C/C++

OpenGL v C++ Builderu (6.díl)

open gl

4. prosince 2001, 00.00 | Vítejte u dalšího dílu seriálu věnovanému OpenGL. V dnešním již šestém díle si povíme něco o tom, jak využívat fonty a tisknout řetězců do OpenGL okna.

Používání fontů

Vítejte u dalšího dílu seriálu věnovanému OpenGL. V dnešním šestém díle si povíme něco o tom, jak využívat fonty a tisknout řetězců do OpenGL okna. Myslím, že je pravý čas naučit se psát a využívat systémové fonty (Arial, Courier atd..).

O co půjde? Napadají mě dvě možnosti, jak pracovat s textem v OpenGL. Jedna možnost je mít připravený obrázek s písmem, všechny v řadě za sebou (nebo do řádků). Načíst tento obrázek do paměti a pak při tisku řetězce vybírat jednotlivé písmenka z obrázku a kreslit je do okna na správnou pozici. Druhý způsob je podobný, vytvoříme si tabulku znaků (0-255, ale může to být i jinak 32-128). Každý znak uložíme do listu (tabulky). A obdobně při tisku řetězce vyvoláváme jednotlivé znaky z listu (jako objekty). Princip je stejný v obou případech, rozdílem jsou zpracovávaná data, v prvém případě se jedná o obrázek BMP a v druhém jde o objekty z listu. My se budeme zabývat druhým způsobem.

Uvidíte, jak vám pěkně za chvíli do sebe zapadne to, co jsem vám napsal. Náš dnešní příklad bude opět jednoduchý. Vidíte jej na obrázku, ale navíc se text bude pohybovat v okně a měnit barvu. Tak se pusťme do díla.

Budeme k našemu programu potřebovat několik pomocných proměnných.

GLuint	base; // Display List pro první písmeno
GLfloat cnt1; // čítač pro posun textu
GLfloat cnt2; // čítač pro posun textu

Všechny znaky budou uložené v display listech od a až po ž v pořadí za sebou. Proměnná base nás bude informovat o indexu prvního znaku v display listu a za ním jsou naskládané ostatní písmenka. Tak například znak 'A' má v tabulce znaků pořadové číslo 65 a znak 'B' má pořadové číslo 66. Tak to pokračuje dál. No a my máme všechna písmenka uložené v display listu a písmeno 'A' budeme mít uloženo v display listu na pozici base + 65.

A teď si ukážeme, že proměnná base je opravdu potřeba. Vytvoříme si vlastní funkci, která zavede font do paměti a aktivuje ho.
Pro to nám poslouží naše vlastní funkce TForm1::BuildFont(GLvoid)

HFONT	font; // Windows Font ID
base = glGenLists(223); // 223 políček pro 223 znaku
 font = CreateFont(-20, // výška fontu
               0, // šířka fontu
               0, // úhel
               0, // úhel
               FW_BOLD, // typ písma (normální ,tučné)
               FALSE, // kurzíva
               FALSE, // podtržené
               FALSE, // přeškrtnuté
               DEFAULT_CHARSET, // kódování znaků
               OUT_TT_PRECIS,
               CLIP_DEFAULT_PRECIS,
               ANTIALIASED_QUALITY, // kvalita tisku
               FF_DONTCARE|DEFAULT_PITCH,
               "Arial"); // jméno fontu
 SelectObject(hDC, font); // označení používaného fontu
 wglUseFontBitmaps(hDC, 32, 223, base); // uložíme znaky od 32 do 255
             

Funkce glGenLists má za úkol vytvořit spojité pole display listů, a vrací nám index prvního display listu (uložíme do base). My potřebujeme 223 display listů a funkce glGenLists zajistí, aby šli po sobě.

Font vytvoříme pomocí funkce CreateFont. Komentář je v rámečku myslím výstižný, ale řekněme si některé další možné nastavení. V helpu je tato funkce popsána takto:
CreateFont(int Height,int Width,int Escapement, int Orientation, int Weight, DWORD Italic, DWORD Underline, DWORD StrikeOut, DWORD CharSet, DWORD OutputPrecision, DWORD ClipPrecision, DWORD Quality, DWORD PitchAndFamily, LPCTSTR Face);

Height - určuje výšku textu, pokud je hodnota 0, velikost písma bude implicitní. Pokud je hodnota kladná, zadáváme výšku buňky písma. Když je hodnota záporná, určujeme absolutní velikost písma (doporučuji vyzkoušet).
Width - šířka textu
Escapement - velmi zajímavý parametr, nastaví úhel natočení textu, zadáváme ho v desetinách stupně. Můžeme zadávat kladné a záporné hodnoty. Uspokojivých výsledků dosáhneme do hodnoty +250. Záporné hodnoty nedávají dobré výsledky.
CharSet - určí kódování písma, pokud si vystačíte pouze s anglickými znaky zadejte ANSI_CHARSET, k českým znakům se doberete přes DEFAULT_CHARSET a je zde i spoustu jiných možností (EASTEUROPE_CHARSET,RUSSIAN_CHARSET atd.)
OutputPrecision - je také užitečné nastavení, pokud je v systému nainstalovaných více fontů stejného jména, více verzí (true typové, rastrové). nejlepší je použít vždy true typovou verzi písma, takže nastavení OUT_TT_ONLY_PRECIS.
ClipPrecision - určí typ ořezání písma - CLIP_DEFAULT_PRECIS
Quality - definuje výstupní kvalitu. Pokud mohu mluvit za sebe, mám rád nejvyšší kvalitu a ta nese označení ANTIALIASED_QUALITY (vyhlazené písmo)
Face - jméno fontu, jak je známe například z WORDu a jiných aplikací (Arial, Courier . . .)

Další velice důležitou věcí je udělat si nějakou funkci, která se nám postará o výpis celého řetězce naráz. Uděláme funkci glPrint a není nikterak složitá.

char	text[256];	
va_list ap; // seznam argumentů
if (fmt == NULL)  // test na prázdný řetězec
 return;
va_start(ap, fmt); 
vsprintf(text, fmt, ap); // obdoba sprintf ale s proměnným počtem parametrů va_end(ap);
glPushAttrib(GL_LIST_BIT);
glListBase(base-32); // nastaví aktuální DisplayList na první písmeno
glCallLists(strlen(text), GL_UNSIGNED_BYTE, text); // zpracuje celý řetězec
glPopAttrib();

Řetězec do funkce vstupuje jako parametr fmt, a my ho potřebujeme trochu upravit. Připíšeme navíc ještě čítač (číslo, které se bude v průběhu měnit), k tomu nám poslouží výborně funkce vsprintf, která nám znovu řetězec přeformátuje a připíše číslo. Potom pomocí glListBase musíme nastavit základní (bázový) display list, protože potom funkce glCallLists vykresluje jednotlivé písmenka z pole text (řetězce), kde jsou číselně uložené kódy těchto písmen. A funkce glCallLists vyvolává postupně display listy od hodnoty, kterou nastavíme do glListBase. No to ale ještě nevysvětluje, proč je tam jako parametr
glListBase(base-32);
To je proto, že jsme při tvorbě naší tabulky znaků zanedbali 32 prvních znaků. Takže abychom se dostali vždy ke správnému písmenku, musíme tuto hodnotu báze ještě o 32 snížit.

No a to je už skoro celé, nyní akorát zaměříme svoji pozornost na funkci DrawScene a nastavíme pozici, kde chceme řetězec v okně zobrazit a pak zavoláme náš výtvor glPrint:
glRasterPos2f(-2.0f+2*cos(cnt1), sin(2*cnt2));
glPrint("Miškyn TEST Font - %7.2f", cnt1);

Čítače cnt1 a cnt2 zajistí pohyb v okně.

Celý program si můžete stáhnout ZDE (320KB).

Užitečné informace:

nehe.gamedev.net




Obsah seriálu (více o seriálu):

Tématické zařazení:

 » Rubriky  » C/C++  

 

 

 

Nejčtenější články
Nejlépe hodnocené články

 

Přihlášení k mému účtu

Uživatelské jméno:

Heslo: