3. diel - XNA tvorba v 3D - súradnice a matice 3D sveta
Vítam vás štvrtýkrát u skromného seriálu tak na 3D v XNA. Dnes sa
pozrieme na 3D priestor ako taký. Je to nutné zlo, ktorým si musíme prejsť,
aby bolo možné pokračovať ďalej k lepším veciam. Tiež sa pozrieme znova
a viac podrobne na všetky tri matice. Ale hlavne na maticu World
,
ktorú sme zatiaľ ešte nijako nepoužívali a pritom nám všetkým mohla
ušetriť veľa práce a počítanie. Stále sa čudujem, že nikto znalý sa
už dávno neozval.
Možno ste si všimli, že pri všetkých príkladov, čo som tu uvádzal,
sme pracovali iba s dvoma súradnicovými osami. Boli to X
a
Y
. Z
osu sme ponechávali vždy na nule.
XNA
využíva pravotočivý systém súradníc. Os X
teda vedie vodorovne doprava, os Y
hore a os Z
smerom
z obrazovky k nám.
Samozrejme záleží na pohľadu kamery (na maticu View
a
Projection
) a jej nastavení. V našich príkladoch, ktoré sme
mali v predchádzajúcich dieloch, bola kamera dobre narafičena A toto rozloženie os platilo.
Pozrime sa teda na definíciu matice View
, ktorú sme doteraz
používali:
Matrix.CreateLookAt(new Vector3(0, 0, 30), new Vector3(0,0,0), Vector3.Up);
Znovu zopakujem, že matica View
slúži k definícii pohľadu
odkiaľ (prvý parameter), kam (druhý parameter) sa pozeráme. Tretí parameter
udáva, kde a akým smerom má kamera v jej pohľade smer nahor. Ako vidno tak
máme kameru nastavenú o 30 jednotiek akoby k nám a pozerá sa priamo do
stredu súradnicového systému. V tomto chytro zvolenom nastavení nám osi
X
a Y
kopírujú výšku a šírku monitora. Ak by
bola kamera nastavená inak, tak by to tak samozrejme nebolo. Pozrime sa tiež
podrobnejšie na druhú maticu. V prvom diele som k nej moc faktov schválne
neprezradil. Teraz už ale musím s pravdou von, takže vyzeralo to takto:
effect.Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver2, GraphicsDevice.DisplayMode.AspectRatio, 1, 1000);
Opäť by bolo asi dobré povedať, že matica Projection
slúži k definíciu toho, ako bude 3D priestor prevedený do 2D na našej
obrazovke.
Používa sa tu obyčajná perspektíva. Prvý parameter nám určuje ako
veľmi širokú výseč kamerou sledujeme a to v radiánoch (na obrázku modrá
kostrbatá čiara). Tu používame 90 °, ja ale zvyčajne používam 45 °, ale
je to opäť závislé od účelu. Ďalšia parameter je pomer strán okna
nášho programu. Jednička je vzdialenosť takzvané near plane
.
Je to akási pomyselná plocha, od ktorej sa začnú objekty vykresľovať (na
obrázku označená ako near
). Všetko čo bude pred ňou nebude
vidieť. Tu dôsledne odporúčam vždy na toto miesto dávať jedničku,
ušetríte si tým veľa starostí s neskoršími chybami v efektoch. Posledné
číslo je takzvaná far plane
(na obrázku označená prekvapivo
ako far
). Všetko čo bude za touto virtuálny plochou opäť
nebude vykreslené. Toto číslo voľte podľa potreby, ale nie zas zbytočne
veľa veľké.
Aby bol výpočet vlastností používaných matíc kompletné, musíme si
povedať aj niečo k matici World
, ktorú sme zatiaľ nepoužili.
Je to celkom škoda, ale aj akýsi môj zámer. Matice World
, ako
už by ste mali vedieť, určuje s umiestnenia objektu vo svete. Jeho pozíciu,
natočenie, ale tiež treba meradlo. Až do tejto chvíle sme všetky súradnice
počítali ručne a umiestňovali objekty na dané miesta. Čo keď by sme ale
chceli nie jeden objekt, ale napríklad desať vedľa seba? Iste môžeme
využiť nejakého rafinovaného cyklu, ktorý by za nás súradnice
vypočítal. Čo keby sme ale potrebovali objekt aj o nejaký uhol natočiť.
Zvládli by ste to? ja nie
Lepšie je urobiť si len akýsi prototyp nášho objektu sa stredom na
súradniciach (0,0,0) as ním len potom posúvať pomocou matice
World
. Umiestniť ho na dané súradnice, natočiť ho a ešte
zmeniť mierku. Práve preto tu táto matica je, aby nám pomohla riešiť tieto
problémy veľmi ľahko a elegantne. Matica sa skladajú nie sčítaním, ale
násobením, takže jediné úskalia, ktoré sa tu skrýva, je správne poradie
pri násobenie matíc. Ako je známe A * B nie je u matíc rovnaké ako B * A.
Výsledok je zakaždým iný. Našťastie to nie je u týchto matíc tak
horúce, ale je dobré naučiť sa určité poradie, aby ste predišli možným
chybám.
World = S * R * T
- písmenko S označuje Scale teda zmenu mierky
- písmenko R označuje Rotation teda natočenie
- písmenko T označuje Translate a nie je to preložiť, ale posunúť
Dá sa to ľahko zapamätať ako srt
a to ak sa nemýlim je
jedna z prípon súboru na titulky. To je jedno pre mňa zatiaľ vždy
fungujúcich poradí. Zaujímavé však je, že tu
je uvedené presne opačné poradie, než som doteraz používal. Všetky matice
sa v XNA
, ako ste si možno už všimli, vytvárajú skrze
statickej metódy triedy Matrix
. Metódy zakaždým začínajú na
Create*
kde za hviezdičku dosadíte čo presne potrebujete.
Ďalším výhodným poznatkom je, že zakaždým ak vyžaduje nejaký parameter
uhol, tak je v XNA
vždy v radiánoch.
Maticu pre meradlo vytvoríme veľmi ľahko:
Matrix.CreateScale(meritko)
Kde meradle je Vector3
. Origniální veľkosti dosiahneme sa
samými jednotkami (výhodné je taky použiť Vector3.One
).
Veľkosťou väčších väčšími číslami a veľkostí s číslami medzi
nulou a jednotkou. Ak by bola niekedy použitá 0, tak sa nám nezobrazí vôbec
nič a ak číslo záporné, teleso by sa nám prevrátilo.
Maticu pre posun vytvoríme tiež veľmi ľahko:
Matrix.CreateTranslation(posun)
Kde opäť posun je Vector3
a vyjadruje o koľko sa má sa s
objektom vo svete hnúť.
Posledný je matica pre rotáciu, ktorá je pomerne zradná. Možno ju vytvoriť niekoľkými spôsobmi, podľa niekoľkých rôznych matematických predstáv. Pre určité operácie sa viac hodí niečo a pre iných zas to druhé. Vždy som používal len túto najjednoduchšiu metódu, pretože mi prišla najviac pochopiteľná. Je to rotácie okolo jednotlivých osí objektu. Ak by niekto mal väčšie skúsenosti a vedel viac tak sa prosím vyjadrite dole v komentároch.
Opäť pripomínam, že uhly musí byť v radiánoch. Na prevod do nich má
XNA
vstavanú metódu ToRadians
triedy
MathHelper
, ktoré sa o prevod postará sama.
Asi je dobré napísať si na toto nejakú pomocnú metódu, ktorá sa nám o
to postará a v budúcnosti sa nebudeme musieť zaoberať nejakými pravidlami.
Vložíme si teda nový súbor s triedou Utility
, urobíme jej
verejnú identifikátorom public
a dovnútra dáme sadu
statických, navzájom preťažených metód:
public static Matrix CreateWorld(Vector3 posun){ return Matrix.CreateTranslation(posun); } public static Matrix CreateWorld(Vector3 posun, Matrix rotace){ return rotace*Matrix.CreateTranslation(posun); } public static Matrix CreateWorld(Vector3 posun, Matrix rotace, Vector3 meritko){ return Matrix.CreateScale(meritko) * rotace * Matrix.CreateTranslation(posun); } public static Matrix CreateRotation(Vector3 rotace){ return Matrix.CreateFromYawPitchRoll(rotace.Y, rotace.X, rotace.Z); }
Pridal som tiež jednu metódu pre vytvorenie matice pre rotáciu. Bude sa nám neskôr hodiť. A to je myslím všetko, čo som chcel povedať k tejto téme. Dúfam, že ste pochopili k čomu je to všetko dobré a že sa bez tohto naďalej nezaobídeme. Nabudúce sa skúsime vrhnúť na nejaký ten vysnívaný model. Opäť čakám na komentáre pod článkom.
Stiahnuť
Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkamiStiahnuté 698x (99.53 kB)