Aktuelle Zeit: 22.12.2024, 06:03

Alle Zeiten sind UTC + 1 Stunde




Ein neues Thema erstellen Auf das Thema antworten  [ 1 Beitrag ] 
Autor Nachricht
BeitragVerfasst: 19.03.2007, 23:37 
Offline
Benutzeravatar

Registriert: 13.03.2007, 11:37
Beiträge: 7
Wohnort: Erfurt
Tutorial 3: Custom Scene Node (Benutzerdefinierter Szeneknoten)
(übersetzt von Ba'el, original eng. von irrlicht.sourceforge.net)
Dieses Tutorial ist für etwas Erfahrenere. Dieses Tutorial behandelt wie man „custom scene node“ herstellt und wie man sie in der engine benutzt. Eine „custom scene node“ wird benötigt um eine Render-Technik zu Implementieren, welche von der Irrlicht-Engine nicht unterstützt wird. Mit erstellten „custom scene nodes“ kannst du einfach die Irrlicht-Engine erweitern und deinen Anforderungen anpassen.

Auf geht's!
Zuerst wird die header file eingebunden, wir benutzen die irr namespace, und linken die .lib file.
Code:
#include <irrlicht.h>
using namespace irr;
#pragma comment(lib, "Irrlicht.lib")
Hier kommt nun der anspruchsvollste Teil dieses Tutorials: Die Klasse eurer eigenen „custom scene node“. Halten wir's einfach, eure „scene node“ wird keine “indoor portal renderer” und auch keine “terrain scene node”, sondern ein einfacher Tetraeder, ein 3d Objekt bestehend aus 4 verbundenen Vertikalen, welcher sich nur selbst zeichnet und sonst nix.
Last uns eure „scene node“ in die Irrlicht-Engine scene einfügen, die Klasse die wir erstellen benötigt nur die Herleitung von der „ISceneNode“ Klasse durch überschreiben einiger Methoden.
Code:
class CSampleSceneNode : public scene::ISceneNode
{

Als erstes, deklarieren wir einige Membervariabeln, zum speichern der Daten für euren Tetraeder: die Begrenzungsbox (bounding box), 4 Vertikale, und das Material des Tetraeders.
Code:
core::aabbox3d<f32> Box;
video::S3DVertex Vertices[4];
video::SMaterial Material;
Die Parameter der Konstruktionsspezifkationen der “parent” der „scene node“, ein Pointer auf den „scene manager“, und eine id der „scene node“. Im Konstruktor selbst, rufen wir den “parent class Konstruktor” auf, setzen einige Eigenschaften des Materials welches wir zum zeichnen der „scene node“ benötigen und erstellen die 4 Vertikalen des Tetraeders den wir später zeichnen wollen.
Code:
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);

Die Irrlicht-Engine braucht noch Infos über die „bounding box“ eurer „scene node“. Es wird genutzt zum automatischen „culling“ und anderen Dingen. Nun brauchen wir eine “bounding box” der 4 Vertikalen. Wenn du keine Box für's automatische “culling“, und/oder keine eigene schreiben willst kannst du auch schreiben
AutomaticCullingEnabled = false;.
Code:
Box.reset(Vertices[0].Pos);
for (s32 i=1; i<4; ++i)
        Box.addInternalPoint(Vertices[i].Pos);
}

Ehe es gezeichnet wird, muss die „OnPreRender()“-Methode jede “scene node“ in der „scene“ durch den „scene manager“ aufrufen. Wird gewünscht das sich die “scene node” selbst zeichnet, muss sie sich selbst beim “scene manager“ zum zeichnen registrieren. Dies ist notwendig um den „scene manager“ mitzuteilen wenn es die „::render“-Methode aufrufen soll. Z.b. Normale “scene nodes” Rendern ihren Inhalt eins nach dem andern, während „stencil buffer shadows“ nach allen anderen „scene nodes“ gezeichnet werden. Und „camera oder light scene nodes“ müssen vor allen anderen „scene nodes“ gerendert werden.
So hier Registrieren wir ganz einfach die „scene node“ um sie normal zu rendern. Wenn wir es wie Kameras oder Licht rendern wollen müssen wir „SceneManager-registerNodeForRendering“(this, SNRT_LIGHT_AND_CAMERA) aufrufen;
Danach rufen wir die „OnPreRender“-Methode der Klasse „ISceneNode“, welche ganz einfach alle „child scene nodes“ dieses „node register“ zulässt.
Code:
virtual void OnPreRender()
{
  if (IsVisible)
    SceneManager->registerNodeForRendering(this);

  ISceneNode::OnPreRender();
}
In der “render()”-Methode spielen sich die meisten der interessanten Dinge: der „scene node render“ selbst. Wir überschreiben diese Methode und zeichnen den Tetraeder.
Code:
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);
}
Wenigstens müssen wir drei kleine Hilfsmethoden. GetBoundingBox() gibt die „bounding box“ dieser „scene node“ zurück, GetMaterialCount() gibt die Anzahl der Materialien in dieser „scene node“ (euer Tetraeder hat nur ein Material) zurück, und getMaterial() gibt das Material durch einen Index zurück. Weil wir nur ein Material haben, können wir auch nur ein Material zurückgeben, so können wir annehmen das niemand getMaterial() mit einem Index größer 0 aufrufen wird.
Code:
virtual const core::aabbox3d<f32>& getBoundingBox() const
  {
    return Box;
  }
  virtual s32 getMaterialCount()

  {

    return 1;

  }
  virtual video::SMaterial& getMaterial(s32 i)
  {
    return Material;
  }

};
Das war's, die „scene node“ ist fertig. Nun müssen wir nur noch die Engine starten, erstelle die „scene node“ und eine Kamera, und schau dir das Resultat an ;).
Code:
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));
Erstelle deine „scene node“. Vergesse nicht es zu droppen (->drop()) nachdem du es erstellt hast. Das ist möglich, weil der “scene manager” sich jetzt darum kümmert. Das ist nicht unbedingt nötig es direkt danach zu machen, es kann auch am ende des Programms passieren.
Code:
CSampleSceneNode *myNode =
  new CSampleSceneNode(smgr->getRootSceneNode(), smgr, 666);

myNode->drop();
Die Animation besteht zwar nur aus dem Tetraeder, aber wir adden noch einen Animator zur „scene node“, um es wenigstens etwas rotieren zu lassen.
Code:
scene::ISceneNodeAnimator* anim =
   smgr->createRotationAnimator(core::vector3df(0.8f, 0, 0.8f));

myNode->addAnimator(anim);

anim->drop();
Nun zeichne alles und fertig.
Code:
while(device->run())
  {
    driver->beginScene(true, true, video::SColor(0,100,100,100));

    smgr->drawAll();

    driver->endScene();
  }


device->drop();

return 0;
}
Das war's, Kompiliere alles und probiere etwas rum.

_________________
"Die folgende Aussage ist falsch. Die vorherige Aussage ist richtig."


Nach oben
 Profil  
 
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 1 Beitrag ] 

Alle Zeiten sind UTC + 1 Stunde


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 2 Gäste


Du darfst keine neuen Themen in diesem Forum erstellen.
Du darfst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.
Du darfst keine Dateianhänge in diesem Forum erstellen.

Suche nach:
Gehe zu:  
Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de