Lekce 3 - XNA tvorba ve 3D - souřadnice a matice 3D světa
Vítám vás počtvrté u skromného seriálu jak na 3D v XNA. V minulé lekci, XNA tvorba ve 3D - textury, jsme se věnovali texturám.
Dnes se podíváme na 3D prostor jako takový. Je to nutné zlo, kterým si
musíme projít, aby bylo možné pokračovat dále k lepším věcem. Také se
podíváme znovu a více podrobně na všechny tři matice. Ale hlavně na
matici World
, kterou jsme prozatím ještě nijak nepoužívali a
přitom nám všem mohla ušetřit spoustu práce a počítání. Stále se
divím, že nikdo znalý se již dávno neozval.
Možná jste si všimli, že u všech příkladů, co jsem zde uváděl, jsme
pracovali pouze se dvěma souřadnicovými osami. Byly to X
a
Y
. Z
osu jsme ponechávali vždy na nule.
XNA
využívá pravotočivý souřadnicový systém. Osa
X
tedy vede vodorovně doprava, osa Y
vzhůru a osa
Z
směrem z obrazovky k nám.

Samozřejmě záleží na pohledu kamery (na matici View
a
Projection
) a jejím nastavení. V našich příkladech, které
jsme měli v předchozích dílech, byla kamera dobře narafičena A toto rozložení os platilo.
Podívejme se tedy na definici matice
View
, kterou jsme dosud
používali:
Matrix.CreateLookAt(new Vector3(0, 0, 30), new Vector3(0,0,0), Vector3.Up);
Znovu zopakuji, že matice View
slouží k definici pohledu
odkud (první parametr), kam (druhý parametr) se díváme. Třetí parametr
udává, kde a jakým směrem má kamera v jejím pohledu směr vzhůru. Jak
vidno tak máme kameru nastavenou o 30 jednotek jakoby k nám a dívá se
přímo do středu souřadnicového systému. V tomto chytře zvoleném
nastavení nám osy X
a Y
kopírují výšku a
šířku monitoru. Pokud by byla kamera nastavena jinak, tak by tomu tak
samozřejmě nebylo. Podívejme se také podrobněji na druhou matici. V prvním
díle jsem k ní moc faktů schválně neprozradil. Nyní již ale musím s
pravdou ven, takže vypadalo to takto:
effect.Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver2, GraphicsDevice.DisplayMode.AspectRatio, 1, 1000);
Opět by bylo asi dobré říct, že matice Projection
slouží
k definici toho, jak bude 3D prostor převeden do 2D na naší obrazovce.

Používá se zde obyčejná perspektiva. První parametr nám určuje jak
moc širokou výseč kamerou sledujeme a to v radiánech (na obrázku modrá
kostrbatá čára). Zde používáme 90°, já ale obvykle používám 45°, ale
je to opět závislé na účelu. Další parametr je poměr stran okna našeho
programu. Jednička je vzdálenost takzvané near plane
. Je to
jakási pomyslná plocha, od které se začnou objekty vykreslovat (na obrázku
označená jako near
). Vše co bude před ní nebude vidět. Tady
důsledně doporučuji vždy na toto místo dávat jedničku, ušetříte si
tím spoustu starostí s pozdějšími chybami v efektech. Poslední číslo je
takzvaná far plane
(na obrázku označena překvapivě jako
far
). Vše co bude za touto virtuální plochou opět nebude
vykresleno. Toto číslo volte podle potřeby, ale ne zas zbytečně moc
velké.
Aby byl výčet vlastností používaných matic kompletní, musíme si
říci také něco k matici World
, kterou jsme prozatím
nepoužili. Je to docela škoda, ale i jakýsi můj záměr. Matice
World
, jak již byste měli vědět, určuje s umístění objektu
ve světě. Jeho pozici, natočení, ale také třeba měřítko. Až do této
chvíle jsme všechny souřadnice počítali ručně a umísťovali objekty na
daná místa. Co když bychom ale chtěli ne jeden objekt, ale třeba deset
vedle sebe? Jistě můžeme využít nějakého rafinovaného cyklu, který by
za nás souřadnice vypočítal. Co kdybychom ale potřebovali objekt také o
nějaký úhel natočit. Zvládli byste to? Já ne Lepší je udělat si jen jakýsi
prototyp našeho objektu se středem na souřadnicích (0,0,0) a s ním jen
potom posouvat pomocí matice
World
. Umístit ho na dané
souřadnice, natočit ho a ještě změnit měřítko. Právě proto zde tato
matice je, aby nám pomohla řešit tyto problémy velmi snadno a elegantně.
Matice se skládají ne sčítáním, ale násobením, takže jediné úskalí,
které se tu skrývá, je správné pořadí při násobení matic. Jak známo
A*B není u matic stejné jako B*A. Výsledek je pokaždé jiný. Naštěstí to
není u těchto matic tak horké, ale je dobré naučit se určité pořadí,
abyste předešli možným chybám.
World = S * R * T
- písmenko S označuje Scale tedy změnu měřítka
- písmenko R označuje Rotation tedy natočení
- písmenko T označuje Translate a není to přeložit, ale posunout
Dá se to snadno zapamatovat jako srt
a to pokud se nepletu je
jedna z přípon souboru na titulky. To je jedno pro mě zatím vždy
fungujících pořadí. Zajímavé ovšem je, že zde
je uvedeno přesně opačné pořadí, než jsem dosud používal. Všechny
matice se v XNA
, jak jste si možná již povšimli, vytvářejí
skrze statické metody třídy Matrix
. Metody pokaždé začínají
na Create*
kde za hvězdičku dosadíte co přesně potřebujete.
Dalším výhodným poznatkem je, že pokaždé vyžaduje-li nějaký parametr
úhel, tak je v XNA
vždy v radiánech.
Matici pro měřítko vytvoříme velmi snadno:
Matrix.CreateScale(meritko)
Kde meritko je Vector3
. Origniální velikosti dosáhneme se
samými jedničkami (výhodné je taky použít Vector3.One
).
Velikostí větších většími čísly a velikostí s čísly mezi nulou a
jedničkou. Pokud by byla někdy použita 0, tak se nám nezobrazí vůbec nic a
pokud číslo záporné, těleso by se nám převrátilo.
Matici pro posun vytvoříme také velmi snadno:
Matrix.CreateTranslation(posun)
Kde opět posun je Vector3
a vyjadřuje o kolik se má se s
objektem ve světě hnout.
Poslední je matice pro rotaci, která je poměrně zrádná. Lze ji vytvořit několika způsoby, podle několika různých matematických představ. Pro určité operace se více hodí něco a pro jiné zas to druhé. Vždy jsem používal jen tuto nejjednodušší metodu, protože mi přišla nejvíce pochopitelná. Je to rotace kolem jednotlivých os objektu. Pokud by někdo měl větší zkušenosti a věděl více tak se prosím vyjádřete dole v komentářích.

Opět připomínám, že úhly musí být v radiánech. Na převod do nich
má XNA
vestavěnou metodu ToRadians
třídy
MathHelper
, které se o převod postará sama.
Asi je dobré napsat si na toto nějakou pomocnou metodu, která se nám o to
postará a v budoucnu se nebudeme muset zabývat nějakými pravidly. Vložíme
si tedy nový soubor s třídou Utility
, učiníme jí veřejnou
identifikátorem public
a dovnitř dáme sadu statických,
navzájem přetížených metod:
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); }
Přidal jsem také jednu metodu pro vytvoření matice pro rotaci. Bude se nám posléze hodit. A to je myslím vše, co jsem chtěl říci k tomuto tématu. Doufám, že jste pochopili k čemu je to vše dobré a že se bez tohoto nadále neobejdeme. Příště se zkusíme vrhnout na nějaký ten vysněný model. Opět čekám na komentáře pod článkem.
V příští lekci, XNA tvorba ve 3D - Modely, si představíme Modely.
Stáhnout
Stažením následujícího souboru souhlasíš s licenčními podmínkamiStaženo 737x (99.53 kB)