logo

Irrlicht3D Tutoriál - Vlastní scénové uzly

Tento tutoriál je pro pokročilejší vývojáře pracující s Irrlicht3D Enginem a pokud si zatím jen tak s Irrlichtem spíše hrajete a zkoušíte jeho možnosti, podívejte se nejdříve na ostatní ukázky a návody. Ukážeme si, jak vytvořit vlastní druhy scénových uzlů a jak je používat v enginu. Ty jsou užitečné, pokud chceme implementovat nové renderovací techniky, které zatím Irrlicht Engine nepodporuje. Například, můžeme tak napsat indoor portálově-založené renderery nebo pokročilejší terénové scénové uzly. Vytvořením vlastních scénových uzlů můžeme jednoduše rozšířit možnosti Irrlichtu a adaptovat je na naše potřeby.

Ponecháme tutoriál jednodušší tím, že se zde nebudeme zabývat ostatními druhotnými věcmi kvůli zkrácení kódu, a také ho celý necháme jen v jednom .cpp souboru. Na konci tutoriálu bude výsledek vypadat stejně, jako obrázek níže. Nevypadá to nijak zázračně, ale je to kompletně customizovaný scénový uzel a je to dobrý bod, ze kterého se odrazit při pozdějším výtváření Vašich vlastních.

Výsledný program
Výsledný program

Na začátku kódu, stejně jako i v ostatních tutoriálech, si includneme hlavičkové soubory Irrlichtu, použijeme zkrácení pro práci s kódem v namespacu irr, a nastavíme linkování statické knihovny.

Kód:
#include <irrlicht.h>
using namespace irr;
#pragma comment(lib, "Irrlicht.lib")

Zde přicházi nejsložitější část celého tutoriálu: Třída našeho vlastního druhu scénového uzlu. Pro jednoduchost, nebude to indoor portálový renderer a ani terénový scénový uzel, ale čtyřstěnný, pravidelný jehlan, skládající se z 4 propojených vrcholů, který se pouze sám vykreslí a nedělá nic dalšího speciálního.

Abychom mohli použít náš scénový uzel v Irrlichtu, bude potřeba, aby daná třída byla odvozená ze třídy IsceneNode a přepisovala některé její metody.

Kód:
class CSampleSceneNode : public scene::ISceneNode
{

Nejprve deklarujeme některé členské proměnné, které budou obsahovat data našeho jehlanu: bounding box (box ohraničující geometrii uzlu, používá se například pro automatický culling v Irrlichtu a mnohé další věci), 4 vrcholy a jeho materiál.

Kód:
core::aabbox3d<f32> Box;
video::S3DVertex Vertices[4];
video::SMaterial Material;

Parametry konstruktoru specifikují rodičovský scénový uzel, ukazatel na scénového managera a scénové id uzlu. V konstruktoru samotném pak volámě konstruktor bázové třídy, nastavíme některé vlastnosti materiálu, kterého používáme pro vykreslování uzlu a vytvoříme 4 vrcholy jehlanu.

Kód:
public:
CSampleSceneNode(scene::ISceneNode* parent, scene::ISceneManager* mgr, s32 id)

 : scene::ISceneNode(parent, mgr, id)

{ 

  Material.Wireframe = false;
  Material.Lighting = false;
  Vertices[0] = video::S3DVertex(0,0,10, 1,1,0,video::SColor(255,0,255,255),0,1);
  Vertices[1] = video::S3DVertex(10,0,-10, 1,0,0,video::SColor(255,255,0,255),1,1);
  Vertices[2] = video::S3DVertex(0,20,0, 0,1,1,video::SColor(255,255,255,0),1,0);
  Vertices[3] = video::S3DVertex(-10,0,-10, 0,0,1,video::SColor(255,0,255,0),0,0);

Irrlicht Engine potřebuje znát bounding box našeho uzlu, aby pomocí něj mohl provádět automatický culling a některé další věci. Vytvoříme tedy bounding box z námi nadefinovaných vrcholů. Pokud bychom nechtěli, aby engine prováděl culling, nebo vytvářet bounding box vůbec, můžeme taktéř napsat
AutomaticCullingEnabled = false;.

Kód:
Box.reset(Vertices[0].Pos);
  for (s32 i=1; i<4; ++i)
  Box.addInternalPoint(Vertices[i].Pos);
}

Před jakámkoli renderováním je zavolána metoda OnRegisterSceneNode() každého scénovéh uzlu. Pokud si scénový uzel přeje být vykreslen, registruje se ve scénovém managerovi. To je nezbytné, aby manager vědel, kdy zavolat metodu render. Pro příklad, normální scénové uzly renderují jejich obsah jeden po druhém, oproti tomu takový stencil buffer potřebuje být vykreslen až po všech ostatních uzlech, a kamery a světla zase před. Zde tedy jednoduše registrujeme uzel aby byl renderován normálně, pokud bychom ale chtěli, aby byl renderován jak kamery nebo světla, zavolali bychom SceneManager-&amp;gt;registerNodeForRendering(this, SNRT_LIGHT_AND_CAMERA); . Po tomto kroku zavoláme metodu OnRegisterSceneNode bázové třídy ISceneNode, která nechá také všechny potomky uzlu se registrovat.

Kód:
virtual void OnRegisterSceneNode()
{
  if (IsVisible)
    SceneManager->registerNodeForRendering(this);

  ISceneNode::OnPreRender();
}

Nakonec vytvoříme tři malé metody: getBoundingBox() vrací BB daného scénového uzlu, getMaterialCount() vrací množství materiálů, a getMaterial() vrací materál na daném indexu (vzhledem k tomu, že zde máme pouze jeden materiál, tak můžeme vrátit rovnou jej).

Kód:
virtual void render()
{
  u16 indices[] = { 0,2,3, 2,1,3, 1,0,3, 2,0,1 };

  video::IVideoDriver* driver = SceneManager->getVideoDriver();
  driver->setMaterial(Material);
  driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
  driver->drawIndexedTriangleList(&Vertices[0], 4, &indices[0], 4);
}

Hotovo. Scénový uzel je hotov. Nyní už pouze klasicky spustíme engine, vytvoříme scénový uzel a kameru.

Kód:
int main()
{
  IrrlichtDevice *device =
       createDevice(video::EDT_OPENGL, core::dimension2d<s32>(640, 480), 16, false);
  device->setWindowCaption(L"Custom Scene Node - Irrlicht Engine Demo");
  video::IVideoDriver* driver = device->getVideoDriver();
           scene::ISceneManager* smgr = device->getSceneManager();
  smgr->addCameraSceneNode(0, core::vector3df(0,-40,0), core::vector3df(0,0,0));

Vytvoříme náš scénový uzel. Všimněte si, že je dropnut ihned poté, co ho vytvoříme. Toto je možné protože se o něj scénový manager sám postará. Není to ale nutné, a mohlo by to být provedeno až na konci programu.

Kód:
CSampleSceneNode *myNode = 
  new CSampleSceneNode(smgr->getRootSceneNode(), smgr, 666);

myNode->drop();

Pro rozpohybování této jinak nudné scény obsahující pouze jeden jehlan, a také pro názornou ukázku toho, že nyní můžeme používat náš scénový uzel jako jakýkoli jiný v enginu, mu přidáme animátor, který jím bude rotovat.

Kód:
scene::ISceneNodeAnimator* anim = 
   smgr->createRotationAnimator(core::vector3df(0.8f, 0, 0.8f));

myNode->addAnimator(anim);

anim->drop();

Nyní vše vykreslíme a dofinishujeme kód.

Kód:
while(device->run())
{
    driver->beginScene(true, true, video::SColor(0,100,100,100));

    smgr->drawAll();

    driver->endScene();
}


device->drop();

return 0;
}

Hotovo, to je celé. Zkompilujte a pohrajte si s tím. :-)

PS: Tento tutoriál je překladem oficiálního Irrlicht Engine tutoriálu Custom Scene Nodes. Můžete ho také nalézt na portálu Irrlicht3D.cz, jehož jsem spoluautorem.
 
Přidat do:

Komentáře:


U článku zatím nejsou žádné komentáře.
Buďte první!

Nový komentář

Nick:
E-mail:
Web:

Text komentáře:

Smajlíci: :-) :D :-)) ;) 8-) :-| :o ]:-> :P :( :O
Opište kód z obrázku prosím:
Captcha =>
(Je obrázek nečitelný ? Jednoduše na něj klikněte pravým tlačítkem a dejte načíst znovu!)

(HTML není povoleno, můžete však využít základních formátovacích BBCode značek)
Pro pohodlnější odesílání příspěvků je nutný zapnutý JavaScript.


Uživ. jméno:
Heslo:
Nemáte účet?
Zapomenuté heslo ?


V databázi není žádná aktivní anketa, sorry.

Webdesign, kódování a grafické návrhy

Výběr jazyka:
-

Stav na Jabberu:
Zjišťování ..

RSS výstupy:
Články RSS 2.0
Komentáře RSS 2.0


Running on rDragCZ CMS vers. 1.50 .. page generation took 128.65ms; generated on 20/05/12 .. Dostupnost měří: ServiceUptime.com .. Copyright 2009