IT rekvalifikácia. Seniorní programátori zarábajú až 6 000 €/mesiac a rekvalifikácia je prvým krokom. Zisti, ako na to!

4. diel - XNA tvorba v 3D - Modely

Vitajte piatykrát, minule sme prebrali súradnice a matice 3D sveta. V tomto diele sa pozrieme na vykresľovanie modelu. Áno, už konečne model. Vedú ma k tomu neodkladnej skutočnosti posunúť sa od jednoduchých objektov, na ktorých sa síce všetko dobre vysvetľuje a názorne ukazuje, ale model je predsa model.

Model je v XNA reprezentovaný triedou Model. Ako by sa dalo čakať. Model nie je nič iné, než sústava trojuholníkov. Sú to tie jedny a isté trojuholníky, s ktorými sme si v predchádzajúcich dieloch hrali. XNA dovedie nahrať modely vo formáte .x, čo je akýsi DirectX formát, ale ja skôr odporúčam formát fbx. Do neho dovedú exportovať všetky bežne používané modelovacie programy. (iz sketch-upu sa nám to podarilo!) Len pozor, musí byť export do FBX verzie 2010. Odporúčam tiež ukladať v ASCII režimu a nie v binárnom, ako sa napokon presvedčíte nižšie. Často je potrebné do modelu siahnuť a upraviť adresy pre textúry na relatívna. Zaujímavý, no anglický článok o možných úskaliach exporte z obľúbeného 3dsmax nájdete tu, ďakujem zmijozelákovi za poskytnutie. Pre naše skúšanie som náhodne vybral jeden z modelov z projektu ŽvB2. Je to perzský koberček. Nájdete ho dole v archíve. Do projektu ho dostaneme rovnako ako textúru. Projekt som opäť vyčistil, aby sa nám tam naše predošlé výtvory neplietli. Vytvoríme si premennú pre model:

Model model;

V metóde LoadContent model nahráme:

model = Content.Load<Model>("koberec1");

Teraz skúsime projekt skompilovať. Všetko bez problémov. Že nie? No isteže nie, inak by som to predsa po vás nechcel. Dostali sme túto chybu:

Missing asset "C:\Documents and Settings\Prokop\Dokumenty\PVR\Textury\koberec1_uvw mapa_3.png"

Nemôže sa nájsť textúra nášho koberca. Áno, to je pochopiteľné, nie na všetkých počítačoch sa volá účet Prokop a nie na všetkých počítačoch budeme mať textúru v tejto zložke. Tu práve prichádza na rad to, prečo je dobré mať model v ASCII formáte. Ak by súbor bol uložený binárne, tak sa samozrejme nič nedeje. Možno ho prekonvertovať treba týmto nástrojom priamo od Autodesku. Opäť pozor na verziu, tá musí byť opäť 2010. Možno ho ľahko otvoriť v ľubovoľnom textovom editore (myslený nie Word) a mierne upraviť k obrazu nášmu. V súbore potom stačí nájsť miesta, kde sa všade nachádza Prokop alebo prípadne PRV alebo iná význačná časť z existujúcej adresy súboru. Väčšinu adresy zašpiníme a necháme iba:

koberec1_uvw mapa_3.png

Zmenu je u tohto súboru nutné vykonať celkom na štyroch riadkoch (1848,1849,18­74,1875). Túto činnosť možno určite automatizovať potrebné nejakým plug-inom do Visual Studia. Ak by mal niekto záujem pomôcť a treba u toho rovno napísať, ako sa mu podarilo ten plug-in urobiť, má tu príležitosť. Ďalej musíme súbor s textúrou nahrať do zložky Content. Textúru tiež nájdete v archíve, ale tentokrát už na svojom mieste v priečinku Content. Nemusíme ju vkladať cez Visual Studio, pretože je na neho odkaz má náš model a XNA si ho vyzdvihne samo. Ak teraz projekt skompilujeme, všetko sa už podarí bez chýb a my môžeme pokračovať ďalej. Vytvoríme si pole typu Matrix, kde budeme skladovať transformácie danej priamo modelovacím programom.

Matrix[] transforms;

Áno počujete dobre, transformácia, nie je to nič iné ako matice World, ktorá je však v tomto prípade daná priamo z modelovacieho programu. Ide opäť o natočenie modeli, zmenu mierky a podobne, ale tentoraz nie od nás, ale od modelovacieho programu. Presunieme sa do metódy LoadContent, kde práve vytvorené pole inicializujeme a naplníme hodnotami:

transforms=new Matrix[model.Bones.Count];
model.CopyAbsoluteBoneTransformsTo(transforms);

Ďalej si pripravíme objekt pre samotné vykreslenie. Rovnako ako u trojuholníka aj tu musíme nastaviť parametre efektu (shader, zvykajte si aj na tento pojem) a to konkrétne všetky tri matice. Lenže model nie je tak jednoduchá záležitosť ako jeden trojuholník. Iste, skladá sa z nich tiež, ale jeho štruktúra je zložitejšia. XNA rozlišuje takzvané meshe, reprezentované triedou ModelMesh. Pod týmto pojmom si možno predstaviť jeden súvislý povrch modelu. Trebárs hlavu postavy. Ďalej každý / á mesh má svoje časti. Tu nazvanej meshpart, a to v triede ModelMeshPart. Poväčšine má každá mesh iba jednu časť. Záleží ale na jej komplikovanosti. Práve tieto časti v sebe obsahujú už pripravené efekty, ktoré čakajú na nastavenie hodnôt. Nastavíme teda všade hodnoty matíc View, Projection a World a povolíme akési základné osvetlenie:

foreach (ModelMesh mesh in model.Meshes){
  foreach (ModelMeshPart part in mesh.MeshParts){
    BasicEffect ef = part.Effect as BasicEffect;
    ef.View = Matrix.CreateLookAt(new Vector3(100, 150, 0), new Vector3(0, 0, 0), Vector3.Up);
    ef.Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver2, GraphicsDevice.DisplayMode.AspectRatio, 1, 1000);
    ef.World = transforms[mesh.ParentBone.Index];
    ef.EnableDefaultLighting();
  }
}

Iste, nie je to optimálne riešenie. Matica je možné vypočítať aj mimo cyklus a potom len nastavovať. Všimnite si nastavenie matice World. Tu používame hodnoty z pripraveného poľa. Teraz sa premiestnime do metódy Draw. Ako vykresliť model? Máme hneď niekoľko možností. Je ale dobré sa už teraz naučiť túto, pretože sa nám bude v neskorších dielach viac hodiť:

foreach (ModelMesh mesh in model.Meshes){
  mesh.Draw();
}

To je všetko. Nič moc ťažkého alebo náročného. Ak teraz program spustíte, mali by ste vidieť nádherný perzský koberec od JUnit (týmto ďakujem, že mi ten model požičal, pamätaj na trojku !!).

koberec z rozprávky o lietajúcom koberci ako model v XNA - Základy 3D grafiky a tvorba enginu

Skvele. A keďže sa toho zdá byť málo tak pridáme jednoduchú animáciu. Vytvoríme si premennú s maticou pre rotáciu:

Matrix rotace;

V metóde Initialize ju nastavíme na východiskovú hodnotu:

rotace = Matrix.Identity;

Matica Identity (slovensky jednotková) je taká matica, ktorá má na svoje hlavné diagonále samé jednotky. Je to jediná matice, s ktorou keď vynásobíme maticu inú, tak výsledok je rovnaký ako predtým. V metóde Update pridáme zväčšenie rotácie o nejaký malý uhol. Otáčame okolo osi Y:

rotace *= Matrix.CreateRotationY(0.01f);

Násobíme predošlú maticu maticou novú, tým dosiahneme to, že sa uhly spočítajú. Potom už len v metóde Draw nastavíme nový parameter do World matice a môžeme model opäť vykresliť:

foreach (ModelMesh mesh in model.Meshes){
  foreach (ModelMeshPart part in mesh.MeshParts){
    BasicEffect ef = part.Effect as BasicEffect;
    ef.World = transforms[mesh.ParentBone.Index]*rotace;
  }
  mesh.Draw();
}

Všimnite si, že násobíme maticu World z editora a maticou našej. Nie naopak. Inak by výsledok nebol ten, ktorý požadujeme. Schválne si to skúste. Násobenie matíc nie je komutatívna teda A * B nie je to isté ako B * A. Uvedený spôsob animácií nie je však optimálna. Veľa záleží na FPS, ako sa z tohto problému vymaniť si ukážeme zase niekedy nabudúce.

Tak a to je pre dnešok všetko. Opäť sa teším na reakcie a komentáre, ktoré zatiaľ prichádzajú len keď si o ne poviem. Ako úlohu si skúste s pomocou návodov z 2D série napísať jednoduché ovládanie otáčania modelu pomocou treba šípok. Nabudúce sa pozrieme na ... a viete čo nechajte sa prekvapiť.


 

Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.

Stiahnuť

Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami

Stiahnuté 394x (1.58 MB)
Aplikácia je vrátane zdrojových kódov v jazyku C#

 

Predchádzajúci článok
XNA tvorba v 3D - súradnice a matice 3D sveta
Všetky články v sekcii
Základy 3D grafiky a tvorba enginu
Preskočiť článok
(neodporúčame)
XNA tvorba v 3D - Engine prvýkrát
Článok pre vás napísal vodacek
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
Vodáček dělá že umí C#, naplno se již pět let angažuje v projektu ŽvB. Nyní studuje na FEI Upa informatiku, ikdyž si připadá spíš na ekonomice. Není mu také cizí PHP a SQL. Naopak cizí mu je Java a Python.
Aktivity