článek

Vytvoř si svou bludišťovku – 3

Vytvoř si svou bludišťovku – 3

V dnešním díle jsem si dal za úkol seznámit vás s vykreslováním objektů a jejich orientací v 3D prostoru. Výsledkem dnešního snažení tedy bude vykreslení modelu čajové konve do námi vytvořeného okna.

Ze všeho nejdříve je důležité pochopit orientaci v trojrozměrném světě. Představte si pouze jednoduchý bod, který chceme umístit někam v 3D prostoru. Určení pozice v trojrozměrném prostoru je prováděno pomocí tří os s názvy x, y a z. Zaměřte svou pozornost na váš kurzor a zkuste s ním libovolně zahýbat. Jistě jste si všimli skutečnosti, že s ním můžete pohybovat ve dvou osách – po ose x (horizontálně) a po ose y (vertikálně). Takto můžete kdykoliv určit jeho pozici na obrazovce, například (35;40). První hodnota je zde osa x, druhá y s tím, že zde by byl počátek souřadného systému v levém dolním rohu obrazu a souřadnice by nabývaly pouze kladných hodnot. Normálně mohou samozřejmě nabývat i hodnot záporných. To by bylo vysvětlení 2D prostoru. Trojrozměrný prostor má navíc třetí osu. Přidáme-li ji k předešlým osám, bude kolmá na váš monitor. Pomocí těchto tří os můžeme náš bod umísit na jakékoliv místo.


Nyní se vezměme krychli. Počítejme s tím, že veškeré její transformace provádíme kolem bodu, který leží v jejím středu. Můžeme jí tedy nastavit pozici na souřadnice třeba (10;20;30) a v tomto bodě se bude nacházet její střed. Ale to není zdaleka vše. S krychlí můžeme také rotovat, a to opět ve třech osách. Úhly se udávají ve stupních nebo radiánech a kombinací úhlů v daných třech osách můžeme dosáhnout libovolného natočení tělesa.


Poslední transformace již nemusí být tak zřejmá, ale kdo už někdy viděl modelovací program tak ví, že je to změna velikosti neboli měřítko. I to se udává ve třech osách. Pokud chceme těleso v původní velikosti, nastavíme měřítko na (1;1;1), pokud chceme těleso dvakrát větší, nastavíme (2;2;2), pokud poloviční (0.5;0.5;0.5) a pokud zadáme například (2;1;1), bude těleso roztažené v ose x.


Nyní, jak to vypadá v praxi. Tyto transformace se nazývají v D3D World Transformation. Než vykreslíme nějaké těleso, musíme D3D oznámit, jak má být těleso transformováno (pozice, rotace, měřítko). Potřebné informace se ukládají ve struktuře s názvem D3DXMATRIX. Právě tato struktura je jednou z klíčových součástí Direct3D. Ve stručnosti je matrix (česky matice) dvourozměrné pole čísel. V našem případě je to pole 4x4 proměnných typu float. Velkým přínosem je, že D3D obsahuje velké množství funkcí pro práci s matrixy, tudíž v podstatě vůbec není potřeba manuálně nastavovat jednotlivé prvky struktury.


Konečně nastal čas ukázat si nějaký kód pro nastavení World Transformation. V první řadě si musíme vytvořit potřebné matice. Potřebujeme jednu pro nastavení pozice, jednu pro nastavení měřítka a tři pro nastavení rotace (jednu pro každou osu).





D3DXMATRIX matTranslation;
D3DXMATRIX matRotationX;
D3DXMATRIX matRotationY;
D3DXMATRIX matRotationZ;
D3DXMATRIX matScale;





Nyní musíme dané matice naplnit daty. Pro větší přehlednost si vytvoříme funkci initMatrices.





void initMatrices()
{

}




Začneme nastavením pozice, tedy naplnění matice matTranslation. Je to tak jednoduché, jak to jen jde. Stačí použít funkci D3DXMatrixTranslation.





D3DXMatrixTranslation(&matTranslation, 0, 0, 0);




První parametr je ukazatel na naší matici a zbylé 3 parametry jsou proměnné typu float, představující pozici na osách x, y a z. V našem případě je nastavena pozice (0;0;0), tedy počátek souřadného systému. Stejným způsobem nastavíme měřítko na hodnotu (1;1;1), což je velikost 1:1 a rotaci pro všechny tři osy. Hodnota rotace se udává v radiánech, proto použijeme funkci pro převod stupňů na radiány D3DXToRadian.





D3DXMatrixRotationX(&matRotationX, D3DXToRadian(0));
D3DXMatrixRotationY(&matRotationY, D3DXToRadian(0));
D3DXMatrixRotationZ(&matRotationZ, D3DXToRadian(0));
D3DXMatrixScaling(&matScale, 1.0f, 1.0f, 1.0f);




A to je vše ohledně World Transformation. Pokud nyní chceme něco vykreslit, musíme to převést na dvourozměrný obraz, který se vykreslí na monitor. Mezi tím je však potřeba ještě jeden mezikrok. Potřebujeme nastavit jistý pohled, kterým se díváme na scénu. Dobře se to dá představit jako kamera. Tato kamera se nachází někde prostoru a někam směřuje. A právě to co kamera vidí, se převede na dvourozměrný obraz a vykreslí. Je to jako ve skutečnosti. Informace o naší kameře se nazývá View Transformation.


První co musíme udělat je vytvořit si potřebnou matici.





D3DXMATRIX matView;




Pro naplnění matView potřebnými daty nám opět stačí jedna funkce se jménem D3DXMatrixLookAtLH. Její první parametr je ukazatel na matici, dále následují tři struktury typu D3DXVECTOR3 pro určení pozice kamery, bodu, kam se kamera dívá a označení, která osa směřuje nahoru. Bude to osa y. Nyní krátká zastávka u struktury D3DXVECTOR3. Jedná se o strukturu, která obsahuje tři proměnné typu float s názvy x, y a z a spoustu užitečných funkcí a přetížených operátorů pro jejich násobení, porovnávání a podobně.


Zpět k naší funkci.





D3DXMatrixLookAtLH(&matView,
&D3DXVECTOR3(0.0f, 0.0f, -10.0f),
&D3DXVECTOR3(0.0f, 0.0f, 0.0f),
&D3DXVECTOR3(0.0f, 1.0f, 0.0f));




A protože v dnešním díle už matView měnit nebude, můžeme rovnou nastavit View Transformation pomocí funkce SetTransform.





d3ddev->SetTransform(D3DTS_VIEW, &matView);




Konečně se dostáváme k části poslední a tou je Projection Transformation, neboli vytvoření dvourozměrného obrazu naší scény, viděné kamerou. Nejprve si tradičně vytvoříme příslušnou matici.





D3DXMATRIX matProjection;




I pro tuto matici existuje funkce. Její název je D3DXMatrixPerspectiveFovLH. Tato funkce má na rozdíl od předchozích trochu víc parametrů, takže si je detailněji popíšeme.





D3DXMATRIX* D3DXMatrixPerspectiveFovLH( D3DXMATRIX *pOut, FLOAT fovy, FLOAT Aspect, FLOAT zn, FLOAT zf );





  • D3DXMATRIX *pOut – ukazatel na matici, se kterou bude funkce pracovat

  • FLOAT fovy – V podstatě úhel pohledu kamery.Tradičně se udává 45°. Pomocí tohoto parametru můžete dosáhnout efektů jako přiblížení nebo naopak jakési protažení obrazu, které můžete vidět například v některých závodních hrách při vysokých rychlostech.

  • FLOAT Aspect – Poměr stran obrazu.

  • FLOAT zn – Udává v jaké vzdálenosti od pozice kamery se začne obraz vykreslovat.

  • FLOAT zf – Udává naopak do jaké vzdálenosti se bude vykreslovat. Například v interierových lokacích nemusíte mít nastavenou vzdálenost vykreslování až kdoví kam.






Po naplnění matice nám už jen zbývá nastavit Projection transformation pomocí funkce SetTransform.





D3DXMatrixPerspectiveFovLH(&matProjection, D3DXToRadian(45), (float)4/3, 1.0f, 1000.0f);

d3ddev->SetTransform(D3DTS_PROJECTION, &matProjection);




Co nám ještě zbývá ke štěstí je vytvoření objektu, který budeme moci vykreslit. D3D nám poskytuje mocnou třídu pro uchování 3D geometrie s názvem ID3DXMesh. Pomocí této třídy můžeme například jednoduše načíst model ve formátu x. To vše v příštím díle. Dnes si ukážeme jak jednoduše vykreslit jeden z modelů, který má ID3DXMesh předdefinovaný. Je jím čajová konvice. Nejprve si tedy mesh vytvoříme.





LPD3DXMESH meshTeapot = 0;




Hlavně pro budoucí využití si vytvoříme funkci initMeshes a vložíme do ní velmi jednoduchou funkci D3DXCreateTeapot.





void initMeshes()
{
D3DXCreateTeapot(d3ddev, &meshTeapot, NULL);
}




Náš mesh obsahuje model čajové konvice a nastal čas ho vykreslit. Podívejte se ve zdrojovém kódu na funkci Render(). V předchozím díle bylo řečeno, že veškeré vykreslování probíhá mezi funkcemi d3ddev->BeginScene() a d3ddev->EndScene(). Co my potřebujeme zvládnout je nastavit World Transformation a vykreslit naší meshTeapot pomocí její funkce DrawSubset.





d3ddev->BeginScene();

d3ddev->SetTransform(D3DTS_WORLD, &(matRotationX * matRotationY * matRotationZ * matScale * matTranslation));
meshTeapot->DrawSubset(0);

d3ddev->EndScene();




V první řadě musíme naše matice s informacemi o pozici, rotaci a měřítku spojit. Ovšem pozor, nemůžete zde libovolně prohazovat pořadí matic.


Dále si řekněme něco o funkci DrawSubset a subsetech obecně. Subsety jsou části meshe. Nejčastěji to jsou části meshe, které mají rozdílnou texturu nebo materiál. O tom všem ještě bude podrobně řeč.


A nám už jen zbývá uvolnit mesh tradičně funkcí Release(). Naše konvice se bude vykreslovat černě, takže změníme barvu pozadí na modrou.





d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 255), 1.0f, 0);




Nyní je vše připraveno a v okně se nám objeví černá čajová konvice. Vypadá ploše, protože na ní není nanesená žádná textura a není ani nasvícená. Vy si můžete vyzkoušet měnit její pozici, rotaci nebo měnit pozici kamery a uvidíte, že těleso je opravdu trojrozměrné.








Tím bych ukončil dnešní díl. Příště se již začneme věnovat přímo tvorbě naší bludišťovky a načteme si ze souboru mapu bludiště, kterou jsem pro vás připravil.



Kompletní zdrojové kódy (všechny díly seriálu): bludistovka_zdroje.zip



Související odkazy:






pavlík_petr

autor
/ pavlík_petr

Publikováno: 25.11.2007


další články této kategorie





diskuze

odeslat

Nejsi automat? Napiš výsledek 4 + 3 =

Drticka

Drticka | 12.05.18 v 12:45

to mě musi někdo naučit