Direct 3D - Prvé zhrnutie: 3D Room
Určite ste už premýšľali nad vytvorením niečoho väčšieho a ucelenejšieho. Ak ste pozorne čítali predchádzajúce časti, nemal by to byť veľký problém. A práve o tom je toto prvé zhrnutie doterajších lekcií. Zároveň je to ukážka pre tých, ktorí neveria, že aj vo Visual Basicu sa dá vytvoriť rýchle a kvalitné 3D prostredie.
Projekt
Ako už samotný nadpis hovorí, projektom je 3D miestnosť. Nič veľké, iba jedna miestnosť so skriňami, dverami, oknom, lampou, obrazom, truhlicou a kobercom, medzi ktorými sa môžete voľne pohybovať. Je to iba 3D scéna a nie hra. Vychádzal som z doterajších lekcií, preto tam žiadnu detekciu kolízie nenájdete. Považujte to skôr za návrh, ako by to mohlo vyzerať. Jeden z možných algoritmov.

Riešené problémy
Základom všetkého je 3D engine. Máte možnosť počuť, že rôzne hry bežia na rovnakom 3D engine. Snáď najznámejší je engine Unrealu. Čo by taký engine mal robiť? V prvom rade by mal uľahčiť prácu programátora. Otrocky vypisovať kód pre každý trojuholník je neefektívne. Mal by vedieť pracovať s textúrami (organizovať ich, prideliť najvhodnejšie miesto v pamäti), ovládať pohyb, detekciu kolízie a používať rôzne urýchľovacie techniky ako napr. LOD algoritmus (Level Of Detail) alebo Quadtree.
1. objektový engine
V prípade tohto projektu je možné len veľmi ťažko hovoriť o 3D engine. Od toho má ešte ďaleko. Všetky objekty sa vypisujú do procedúry ZoznamObjektov. Po tom, čo som si vytvoril “objektový engine”, stačilo sem už iba podopisovať objekty a ich umiestnenie. Procedúra potom volá ďalšie procedúry s parametrami:
PridajStvorec (Bod1,Bod2,Bod3,Bod4,textura,prevrateny)
PridajModel (umiestnenie,subor)
Call PridajStvorec(Bod3D(0, 20, 0), Bod3D(0, 20, 27.5), Bod3D(22.5, 20, 0), Bod3D(22.5, 20, 27.5), "strop1.jpg") Call PridajModel(30, 0, 10, "truhlica.x")
Vidíte, že isté uľahčenie vypisovania tu je. Stenu potom môžete vytvoriť jednoduchým volaním procedúry PridajStvorec, zadaním štyrom rohov steny a mena textúry.
Posledný parameter je nepovinný. Udáva, ktorá strana steny má mať normálový vektor. Rozpisovať tu, čo všetko procedúry obsahujú nemá zmysel. Všetko nájdete v samotnom projekte.
2. pohyb
Pohybuje sa pomocou šípok na klávesnici a rozhliadať sa môžete za pomoci myši. Celý algoritmus pohybu je riešený úplne jednoducho. Výška kamery (súradnica KameraPoz.Y) sa nemení. Z toho vyplýva, že sa pohybujeme v 2D rovine XZ. Najprv sa pozrime na prípad, keď stojíte na mieste a iba sa rohliadate okolo seba. To, že sa nehýbete znamená, že kamera zostáva na jednom mieste, tedy pozícia kamery(KameraPoz) je konštantná. Není sa iba miesto, na ktoré sa pozerá(KameraKam).

Keď sa na tým trochu zamyslíte, zistíte, že KamerKam opisuje kružnicu. Pre lepšiu predstavu uvediem konkrétnu situáciu: Stojíte uprostred miestnosti ako pozorovateľ P a pozeráte sa smerom na bod K. Chcete si ale pozrieť celú miestnosť, preto sa začnete točiť. Tým sa točí bod K s vami a zároveň opisuje kružnicu. Pozn.: Ten obrázok treba brať akoby pohľad zhora na pozorovateľa P. Potom už vieme vypočítať súradnice ktoréhokoľvek bodu na jednotkovej kružnici, kde stred má súradnice [0,0]. X súradnica je kosínusom uhla a Y súradnica je jeho sínusom. Tak napr. keď sa pozeráte dopredu: KameraPoz je [0,0] a KameraKam [cos(90),sin(90)] tedy [0,1]. Z toho vyplýva, že to kam sme práve natočený závisí od uhlu. Ostáva len vytvoriť vzťah medzi polohou myši a uhlom. Z obrázka je jasné, že keď pohneme myšou doprava uhol sa zmenší. Pri pohybe doľava sa zväčší. Preto musíme detekovať zmenu pohybu myši v procedúre Form_MouseMove.
AktUhol = AktUhol - (X - Myspoz.X) '(1) If AktUhol > 360 Then AktUhol = AktUhol - 360 '(2) If AktUhol < 0 Then AktUhol = AktUhol + 360 Myspoz.X = X '(3) Myspoz.Y = Y If Myspoz.X > RozlisenieX - 95 Then '(4) Call SetCursorPos(100, Y + 22) Myspoz.X = 100 ElseIf Myspoz.X < 95 Then Call SetCursorPos(RozlisenieX - 100, Y + 22) Myspoz.X = RozlisenieX - 100 End If KameraKam.Y = 9 - Y / 100 RadUhol = AktUhol * Rad '(5) VektorPohybu = Vektor3D(Cos(RadUhol), 0, Sin(RadUhol)) D3DXMatrixLookAtLH matView, KameraPoz, Vektor3D(KameraPoz.X + VektorPohybu.X, KameraKam.Y, KameraPoz.Z + VektorPohybu.Z), Vektor3D(0, 1, 0) D3DDevice.SetTransform D3DTS_VIEW, matView DoEvents
Na to, aby sme vedeli, či sa poloha myši zmenila smerom doprava alebo doľava, potrebujeme vedieť jej pôvodnú polohu. Tá je uložená v premennej Myspoz. Pri každom ďaľšom volaní procedúry porovnáme aktuálnu pozíciu myši a tú predchádzajúcu. Ich rozdiel pričítame k uhlu (1). Uhol musí byť v intervale <0,360>. Ak prekročí túto hranicu, musíme ho zmeniť (2). Aktualizujeme pôvodnú polohu myši, aby bola pripravená na ďalšie porovnávanie (3). Ale čo ak prídeme s myšou na okraj obrazovky? Nebudeme sa môcť ďalej otáčať. Tu je výhodné použiť API funkciu, ktorá posunie kurzor naspäť v prípade, že sa priblíži ku okraju (4). VB funkcie Sin a Cos pracujú s radiánmi a nie uhlami. Po konvertovaní (5) už môžeme vypočítať vektor pohľadu (a aj pohybu, t.j vektor daný bodmi P a K) a dosadiť do matice pohľadu. Pohľad hore a dole ani nemusím vysvetľovať. Keď pohnete myšou hore, KameraKam.Y sa zväčší a naopak.
Druhý prípad, opäť veľmi jednoduchý, nastane vtedy, keď chceme hýbať kamerou (pozri proc. Form_KeyDown). Napr. dopredu, čiže v smere, kam sme práve natočený. A to už predsa vieme vďaka vypočítanému vektoru pohľadu. A tak sa posunieme v smere tohoto vektoru. Pre pohyb dozadu sa posunieme v smere opačného vektoru. Na jednu však nesmieme zabudnúť: V smere vektoru pohybu musíme posunúť aj miesto, kam sa pozeráme. Nebolo by to prirodzené, keby sa telo hýbalo, ale hlava pozeralo stále na to isté miesto :). A to je k zhrnutiu#1 všetko. V nasledujúcich lekciách si ukážeme ako robiť k tomuto projektu detekciu kolízie.
Pozn.: Oveľa lepšie by bolo použiť DirectInput8 ako VB detekciu kláves. Už len z toho dôvodu, že používa priamy prístup ku klávesnici (a nie API volania systému), a preto by sme nemuseli nastavovať rýchlosť opakovania kláves cez API. Celý pohyb by bol “jemnejší”. Ale na to by bola potrebná celá ďalšia lekcia.
FPS Výsledky
Scéna je dosť jednoduchá, tvorená niekoľkými objektmi. Nemala by robiť problémy aj slabším strojom. Možno u 4MB kariet bude problém s veľkosťou textúr. Aj na to som myslel. Pri nastavení nízkej kvality textúr sa ich veľkosť z pôvodných 256×256 zmenší na 64×64. Preto budem veľmi rád keď svoje výsledky zverejníte. Určite to bude zaujímať nielen mňa, ale aj ostatných, ktorý si chcú porovnať výsledky. Vo VB fóre na inspired.sk nájdete príspevok FPS výsledky, do ktorého môžete prispieť aj vy. Stačí udať konfiguráciu počítača a výsledky FPS. Ako testovať? FPS sa mení so zmenou pohľadu. Preto je dôležité nehýbať s myšou po štarte programu (kliknutí na RUN). Mali by ste vidieť to isté, čo je na obrázku vyššie. Nesmiete meniť úvodné nastavenia(800×600, vysoká kvalita textúr…). Pokiaľ by ste ich zmenili je potrebné presne udať ktoré. Nejaké tie komentáre k projektu sú tiež povolené. Ale nepíšte tam, že vám to nejde spustiť. Chcem tam iba výsledky. Potom radšej napíšte úplne nový príspevok. Ešte nezabudnite vypnúť u driverov vertikálnu synchronizáciu s monitorom. Keď budete mať napr. maximálne 75 FPS pri pohľade na celú miestnosť a aj pri stene, tak ju máte určite zapnutú. FPS sa prispôsobí obnovovacej frekvencii monitora - vypnúť !!!
A na záver môj výsledok: 96 FPS na Duron700 a TNT2 PRO. (úplnú konfiguráciu nájdete vo VB fórum)