Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

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.

Osy - Základy 3D grafiky a tvorba enginu

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.

3D kamera - Základy 3D grafiky a tvorba enginu

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.

osy otáčení - Základy 3D grafiky a tvorba enginu

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ínkami

Staženo 636x (99.53 kB)

 

Předchozí článek
XNA tvorba ve 3D - textury
Všechny články v sekci
Základy 3D grafiky a tvorba enginu
Přeskočit článek
(nedoporučujeme)
XNA tvorba ve 3D - Modely
Článek pro vás napsal vodacek
Avatar
Uživatelské hodnocení:
3 hlasů
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