Lekce 08 - Od každého trochu
Předmluva
Předem se všem neomlouvám za dobu kdy jsem nic nenapsal. Za prvé jsem měl nedostatek času a za druhé, vzhledem k nulovým reakcím na předchozí tvorbu jsem neměl ani motivaci něco psát. Pokud toto i po této lekci přetrvá, nebudu se již psaním článků dále zdržovat.
To bylo několik slov na úvod a teď už zpět k OGL.
Dám vám k dispozici svůj "debug" projekt a upozorním jen na některé jeho části. Popisovat zde veškeré použité fce. nebudu. Ty ostatně naleznete volně na internetu.
Takže - >
Vytvoření okna obstará funkce CreateWindow třídy Window. Pokud voláme bez parametrů, bude vytvořeno ogl okno o rozměrech a barevné hloubce která je momentálne nastavena na monitoru. Pokud použijeme parametry (šířka, výška a barevná hloubka) funkce změní nastavení dle vašeho zadání. Při uvolnění okna je vráceno zpět původní nastavení.
Dále ->
Kamera je kompletně předělaná. Nepoužívá už glTranslate, ale počítá si transformační matici sama. Ušetříme tak několik volání ogl a zároveň máme neustále přehled o stavu vektorů (to bude potřeba při počítání kolizí).
V neposlední řadě je tento kód i rychlejší. Pokud totiž použijeme glTranslate, musíme stejně počítat novou pozici (pouze trochu jednodušeji :) ) a ogl potom naše hodnoty stejně prepočítává pro transformační matici. Takhle dostane matici již spočítanou a jen ji použije. Třída kamery je z jedné části vytvořena díky pečlivému studiu zdrojových kódu pro C++ a Delphi a z druhé části díky probděným nocím u počítače (a nebyla to žádná sranda).
Několik odkazů které mi hodně pomohli:
http://wiki.delphigl.com/index.php/Matrix
http://programovani.net-mag.cz/?action=art&num=446
http://www.root.cz/clanky/opengl-5-transformacni-matice-a-linearni-transformace
http://www.ozone3d.net/opengl_direct3d_tutorials.php#tut11
http://nehe.gamedev.net/
DisplayList
Teď se vrátím zpátky k tomu co jsem již naznačil v poslední lekci a to je DisplayList. Vysvětlení trochu zjednodušším.
Představte si že si potřebujete s někým předávat několik klíčů. Pokud je předáváte po jednom trvá to příliš dlouho. Pokud je ale dáte do svazku a předáte celý svazek najednou, je výměna mnohem rychlejší. V ogl je to podobné. Pokud potřebujete vykreslit nějaké objekty, musíte je zadávat po jednom asi takhle
jeden bod
glBegin GL_POINT
glVertex3f atd.......
glEnd
jedna usecka
glBegin GL_LINE
glVertex3f atd.......
glEnd
atd....
Všechna tato volání můžeme jednoduše vtěsnat do jednoho "svazku"
Nejdříve si vyžádáme dostupný (volný) index pro nový DisplayList, nám stačí jeden list takže voláme s 1.
Dim IDList as integer
IDList = glGenLists(1)
Potom oznámíme že budeme vytvářet nový list, předáme volný index a chceme ho zkompilovat (pomocí tohoto indexu potom budeme náš list volat).
Začátek listu
glNewList IDWorld, GL_COMPILE
Teď definujeme vše co má list obsahovat
jeden bod
glBegin GL_POINT
glVertex3f atd.......
glEnd
jedna usecka
glBegin GL_LINE
glVertex3f atd.......
glEnd
atd...
a konec listu
glEndList
To je vše.
Volání potom provedeme jednoduše z naší funkce DrawScene s číslem indexu našeho listu
call glCallList(IDWorld)
List může obsahovat všechny příkazy které ogl podporuje. tedy včetně definice textur, světel atd. Pokud budete potřebovat některé z hodnot změnit, musíte si zkompilovat list nový!
Souboru zdrojů
Načtení bitmapy ze souboru zdrojů *.RES. Soubor zdrojů není vhodné používat pro nějaké velké obrázky, protože je zkompilován do našeho *,EXE a velikost je tudíž důležitá. Ideální využití je např. pro uložení kursoru myši, tabulky s písmem apod. . Je ovšem potřeba dodržet několik pravidel.
1.obrázek nesmíte vkládat jako obrázek, ale jako data. Tzn. v editoru souboru zdrojů klepněte na "AddCustomResource" a zvolte váš obrázek.
2.Načtení potom provedeme pomocí funkce VB LoadResData a načteme jej do pole bytů.
Dim Data() As Byte
Data = LoadResData("FONT", "CUSTOM")
Další zpracování obrázku je již stejné jako při načítání ze souboru. Já jsem si to trochu ulehčil. Následující kód načte obrázek s písmem (o tom později) a vytvoří texturu. Protože je obrázek uložen v *.exe souboru a nehodlám ho měnit za jiný, nemusím tedy programově zjišťovat jeho velikost atd. Prostě je rovnou zadám.
Vytvoření textury
glGenTextures 1, ID_TexPrint
glBindTexture glTexture2D, ID_TexPrint
glTexParameteri glTexture2D, tpnTextureMagFilter, GL_LINEAR
glTexParameteri glTexture2D, tpnTextureMinFilter, GL_LINEAR
glTexImage2D glTexture2D, 0, 3, 256, 256, 0, GL_BGR_EXT, GL_UNSIGNED_BYTE, Data(54)
Všimněte si že udávám jako první použitelný byte číslo 54. Protože je obrázek ve formátu BMP a jeho hlavička má velikost 54byte, znamená to tedy že data samotného obrázku jsou uložena od 54 pole.
Tabulka znaků

Výpis textu
Výpis textu na obrazovku. Základní myšlenka je z http://nehe.ceskehry.cz/tut_13.php a http://nehe.ceskehry.cz/tut_43.php Doporučuji přečíst, já to vezmu jen velice stručně.
Pokud potřebujete na obrazovku napsat nějaký znak tak nevezmete fixu, ale vytvoříte si jej ve vašem programu.
Ve skutečnosti jej nevytváříte od základu, ale jen použijete některý z fontů již obsažených v systému. Jsou tu dvě "ale".
1.zvolený font se nemusí nacházet na každém počítači
2.takto vytvořený text není nejostřejší
Řešení je jednoduché. Prostě si v nějakém graf. editoru vytvořte obrázek se znaky všech písmen a číslic.
Ten potom nahrajte, vytvořte texturu a vytvořte displaylisty, jejichž indexy budou představovat ascii hodnotu znaků.
Je tedy potřeba vytvořit sadu znaků jako první dokud jsou volné ID v rozsahu 1-256.
Potom si ještě napište fci která na základě zadaného textu bude volat pole display listů s indexy jež odpovídají ascii hodnotě zadaných znaků.
Podrobnější info naleznete na odkazech viz.Nehe. To co zde popisuji naleznete ve zdrojovém kódu třídy Utils.
Ukázka textu

Alpha blending
O co jde zjistíte na http://nehe.ceskehry.cz/tut_32.php takže zase stručně. Pokud máme kursor myši např. tento

nebudeme chtít aby se nám na monitoru zobrazovala černá barva, ale jen to co je nakreslené červeně. Postup je následující. Nejdříve vykreslíme scénu poté vykreslíme kursor. Pixely které mají hodnotu odpovídající černé barvě násobíme hodnotou barvy podkladu (scéna), černé pixely nastavíme na hodnotu která nám vyšla. Popravdě je to trochu složitější, podrobnější SUPR info naleznete na http://www.root.cz/clanky/opengl-28-blending/
Ukázku použití Alpha blendingu, naleznete ve zdrojovém kódu ve třídě utils fce LoadCursorBitmap()
Výsledek

Pozn. Alpha blending je použit rovněž pro zobrazení textu.
To je pro tentokrát vše.
Dodatek
Formát *,MAP jako zdroj uložení hodnot scény jsem zavrhl, zejména pro jeho nedostečný obsah. Teď mám rozpracovaný import formátu souboru *.ASE. Výsledek můžete posoudit v přiloženém příkladu, jenž ostatně obsahuje i vše dnes zmíněné. Převod ASE je teprve ve fázi debug, takže jsem zatím schopen převést pouze vertexy face a názvy a koordináty textur. Po převodu si vytvořím binární soubor z něhož potom načítám scénu. Tento postup je mnohem rychlejší než zpracovávat ASE formát (ascii export z 3D Max studia) .
Teď se chci podívat na kolize.
Zdrojové kódy zde.
Exkluzivně pro FreeGate.cz vytvořil SID
sid26@seznam.cz
|