Open Inventor: Vesmírná scéna

5. 9. 2003
Doba čtení: 8 minut

Sdílet

Dnes si ukážeme, jak načítat modely ze souborů na disku, a postavíme si vesmírnou scénu v podobě naší Sluneční soustavy.

Dnes začínáme už pokročilejší sérii příkladů, ve kterých už snad budeme moci najít inspiraci pro vlastní jednoduchou hru. A protože se zajímavostí příkladů roste i složitost, stihneme v tomto dílu jen dva:

Tabulka č. 482
2.1 – Model Viewer prohlížeč modelů
2.2 – Solar System sluneční soustava

V prvním příkladu se vrhneme na načítání scén z disku, ve druhém to pak bude složitější scéna, kde se pohybuje více objektů. Nebude chybět ani teorie týkající se animace hierarchických soustav, ani detailnější popis toho, jak vlastně probíhá rendrování scény.

Ještě jedna poznámka: Rozhodl jsem se počeštit anglická slova render a rendering na rendrovat a rendrování, abychom i v češtině mohli psát, jak vyslovujeme.

Příklad 2.1: Model Viewer (Prohlížeč modelů)

Open Inventor má vestavěnou podporu pro načítání a ukládání scény do souborů. To nám může velmi usnadnit práci, neboť scénu můžeme vytvořit v našem oblíbeném modelovacím programu a uložit v některém z podporovaných formátů. Samotné načtení je již triviální záležitostí.

Paleta podporovaných formátů opravdu není příliš široká. Nejdůležitějším formátem, který snad podporují všechny rozšířenější modelovací programy, bude VRML. Dále inventorské formáty a na závěr 3ds, který je prozatím ve vývoji a není standardně aktivován. V následující tabulce je přesný popis:

Tabulka č. 483
formát přípona verze
Inventorská
rodina
.iv 2.0 a 2.1, textové i binární verze
VRML .wrl, .wrml podporovány novější verze VRML97/VRML2,
pro starou verzi VRML1 se pomalu připravuje podpora
3ds .3ds všechny verze 3ds, zatím ve vývoji

I já jsem byl zklamán omezenou paletou formátů, a protože většina modelů na internetu byla v 3ds, rozhodl jsem se napsat vlastní loader. Dnes už to chodí na většině modelů. A protože tento loader není v Coin standardně zapnutý (provádí se parametrem při configure), tak abych všem ulehčil práci, vyrobil jsem z něj malou utilitku 3ds2iv (čte se po anglicku: 3ds to iv), kterou si můžete stáhnout a zkompilovat. Pak stačí napsat 3ds2iv, volitelně můžeme zvolit -b, pokud chceme vygenerovat výsledný soubor v binárním formátu místo textového, a jméno souboru. Výsledný soubor se vygeneruje se stejným jménem, ale s příponou iv.

Jak tedy načíst a zobrazit nějaký model v Open Inventoru? K tomu máme třídu SoFile. Ta obsahuje jedinou datovou položku „name“, tedy jméno souboru. Kdykoliv ji modifikujeme, je načtena scéna z daného souboru. V našem příkladu budeme zobrazovat standardně soubor fighter1.iv nebo můžeme na příkazovém řádku specifikovat jiný soubor:

  SoFile *model = new SoFile;
  if (argc > 1) model->name.setValue(argv[1]);
  else model->name.setValue("fighter1.iv");
  root->addChild(model);

Zbytek kódu je téměř stejný jako v předchozím příkladu. Stahovat můžete verzi pro Linux a Windows. Příklady obsahují čtyři modely v 3ds formátu (staženy z 3D CAFE), přičemž fighter1 už máme i v inventorovském formátu (iv). Hned po spuštění se nám naskytne tento pohled:


Poté můžeme vyzkoušet i jiné modely. Nejprve zkompilujeme naši 3ds2iv utilitu. Pak ji spustíme se jménem 3ds souboru, který chceme zkonvertovat, coby parametrem. Nakonec můžeme opět spustit náš viewer, tentokrát již s parametrem jména tohoto nového modelu.

Pokud jste si vyzkoušeli a chtěli byste získat nějaké další modely, zde jsou linky, které jsem našel:

Nejlepším zdrojem, alespoň pro mě, bylo 3D CAFE. Nečekejte však, že vše, co tam najdete, bude skvěle vypadat a fungovat. Některé modely nejsou úplně dokončené, některé nejdou načíst nebo jsou příliš tmavé, jiné jsou vytvořené v příliš velkém detailu a to množství trojúhelníků nám neunese grafická karta bez poklesu FPS (snímků za sekundu).
Celkově to dá i kus práce najít si modely pro svou vlastní aplikaci. A pokud najdete na internetu nějaký jiný, zde neuvedený, dobrý zdroj modelů či textur, budu rád, když se o ně podělíte s námi ostatními v diskusi pod článkem (nebo mi pošlete mail a já časem možná vytvořím nějakou sbírku odkazů).

Příklad 2.2: Solar System (Sluneční soustava)

V tomto příkladu začneme se složitějšími scénami. Postavíme si model naší Sluneční soustavy. Textury, světla a další složitosti si necháme na později. Tentokrát nás čeká pouze nejjednodušší základ.

Naším cílem je výsledek podobný následujícímu obrázku.


Vidíme na něm Slunce, které je umístěno v počátku souřadnic, a kolem něj obíhají tři planety: Merkur, Venuše a Země. K realizaci Slunce nám stačí dva nody: SoMaterial a SoSphere. SoSphere je nod rendrující kouli na aktuálních souřadnicích. Kód bude vypadat takto:

  // Nastav difuzní složku materiálu na žlutou
  SoMaterial *sunMat = new SoMaterial;
  sunMat->diffuseColor.setValue(1.0f, 1.0f, 0.3f);
  root->addChild(sunMat);

  // Koule o poloměru 10
  SoSphere *sun = new SoSphere;
  sun->radius.setValue(10.f);
  root->addChild(sun);

Realizace planet je poněkud složitější. Oproti Slunci musíme navíc zařídit i pohyb. Použitý princip bude stejný jako v příkladu 1–2 s tím rozdílem, že tam se kužel točil kolem vlastní osy, kdežto tady budeme otáčet kolem osy procházející Sluncem. Celý problém je demonstrován na následujícím obrázku pro Zemi (modrá planeta):


Z obrázku je již víceméně patrno, které nody budeme používat. Bude to SoRotationXYZ pro rotaci a SoTranslation k translaci, tedy posunutí v prostoru. Vždy nejprve provedeme rotaci o úhel Alfa, který se s časem zvětšuje a způsobuje, že planeta obíhá kolem Slunce. Po rotaci následuje translace, která posune planetu z počátku souřadnic, tedy ze středu Slunce na její oběžnou dráhu. Tajemství celé operace je vysvětleno na následujících obrázcích pro planetu Zemi.


Na obrázku vidíme pohled do scény zhora. Vidíme pozici kamery, která se dívá směrem do Slunce. Nyní k počátečnímu nastavení souřadných os: Pokud se díváme z pozice pozorovatele, osa X směřuje doprava, osa Y nahoru (na obrázku není vidět, protože se díváme shora) a osa Z směřuje ke kameře. Vše je tedy tak, jak nám to zavedlo OpenGL.


Po provedení rotace se nám souřadný systém pootočí.


Na závěr provedeme translaci a vidíme, že souřadný systém má nyní počátek na pozici, kde by měla být vykreslena Země. Tu nám vykreslí nod SoSphere.

Jak ale teď vrátit souřadný systém zpět do středu Slunce, abychom mohli vykreslit další planetu, například Venuši, pokud ještě není vykreslená? To nám obstará SoSeparátor. Pojďme se podívat na graf scény jedné planety.


Vidíme separátor, materiál udávající barevné vlastnosti tělesa, rotaci, translaci a na závěr nod SoSphere, který způsobí vyrendrování koule. Nyní se můžeme mrknout na to, co se děje „za našimi zády“ při rendrování scény.


Na obrázku vidíme pět událostí. Vidíme, že proces rendrování začíná i končí u Separátoru a jeho děti jsou rendrovány zleva doprava. Mezi komentáři k jednotlivým událostem také vidíme podivné slovo „Element“. Elementy patří ke klíčovým designerským konceptům v Open Inventoru. Proto bychom si měli alespoň rámcově osvětlit jejich úlohu.

Elementy jsou něco jako vnitřní stavy v OpenGL. Jako příklad si můžeme uvést modelview transformační matici, která obyčejně v OpenGL uchovává aktuální souřadnicovou transformaci. V Open Inventoru je tato projekční matice zapouzdřena v SoModelMatri­xElement. A co nám toto zapouzdření přináší navíc? Například informace o modifikacích v elementech. Ty jsou důležité pro správnou funkci rendrovací cache, kdy se pro vyšší výkon předkompilovává kus grafu scény do displaylistu. Snad nejdůležitějšími funkcemi jsou však push a pop. Aktuální stav elementu je možno uložit na zásobník (push) a později jej obnovit (pop). Zde můžeme vidět podobnost s glPushMatrix a glPopMatrix z OpenGL. Avšak transformační matice jsou snad jediné vnitřní stavy OpenGL, které mají zásobníkovou funkcionalitu. Elementy nám toto zavádějí pro všechny stavové proměnné, dokonce i pro ty, které nemají s OpenGL nic společného. Do Open Inventoru totiž skrz podporu VRML přišla i podpora 3D zvuku, která si vyžádala svoje speciální elementy. V každém případě se do zvuku sami nepouštějte, je to zatím nová věc a určitě plná chyb. Ale časem se k tomuto tématu možná dostaneme i v našem tutoriálu.

Tímto jsme skončili s teoretickým výkladem a pojďme se ještě jednou podívat na náš obrázek. Následuje detailnější popis jednotlivých událostí:

  1. push state – Elementy jsou „uloženy“ do zásobníku. V praxi se většinou opravdové ukládání provádí teprve, až se element modifikuje – kvůli efektivitě.
  2. set material-related elements – SoMaterial nastavuje celkem šest elementů jako: SoDiffuseColo­rElement, SoAmbientColo­rElement a další. Nebudeme je ani vypisovat, neboť materiály budeme detailněji rozebírat až příště.
  3. set SoModelMatrixE­lement – SoRotation i SoTranslation modifikují aktuální souřadnicovou transformaci.
  4. render sphere – Všechny potřebné elementy jsou poslány do OpenGL a je vyrendrována koule.
  5. pop state – Jsou obnoveny stavy všech modifikovaných elementů – v našem případě stačí obnovit pouze SoModelMatrixE­lement a elementy modifikované SoMateriálem.

Již jsme tedy našli odpověď na naši otázku, jak po vykreslení Země vrátit aktuální transformaci zpět do středu Slunce, abychom mohli vykreslovat další planetu. Vše nám obstará SoSeparator, který při „pop state“ obnoví transformaci do podoby, v jaké byla, než jsme začali planetu rendrovat.

Pojďme se mrknout na celý graf scény. Nelekněte se jeho rozsáhlosti – jsou zde tři planety a každá je realizována čtyřmi nody a Separatorem. Graf už byl příliš složitý pro ruční kreslení, sehnal jsem si tedy automatický generátor obrázků grafů scény. Proto vypadá jinak, než jsme byli dosud zvyklí. Ikonky nodů jsou použity dle zvyklostí Inventoru. Pro přiblížení klikněte na obrázek.


bitcoin_skoleni


Zdrojáky stahujte ve verzi pro Linux a Windows.

Závěr

Doufám, že vás příklady příliš neunavily a že se líbily obrázky, které daly opravdu hodně práce. Příště budeme pokračovat se Sluneční soustavou. Ukážeme si, jak používat světla a co vše nám umožní plné využití možností materiálů, proletíme se scénou a možná i něco navíc.

Autor článku