Kollisionsdetektion
Irrlicht als reine Grafikengine hat keine eingebaute Physik - die Kollisionsbehandlung
ist daher recht rudimentär, dafür aber einfach zu bedienen. Das Einzige, das hier erreicht werden soll, ist, dass man beim
Laufen nicht durch den Boden fällt und man nicht durch Wände laufen kann. Dafür reicht es gerade noch...
Um das Problem des Treppensteigens muss man sich als Irrlichtnutzer übrigens keine Gedanken machen -
wenn man nichts falsch macht funktioniert das automatisch.
Aber zuerst zu dem Terrain.
Irrlicht verwendet zur Kollisionsabfrage Triangle Selectors. Für den Terrain gibt es - wer
hätte es gedacht - eine eigene Klasse davon: den TerrainTriangleSelector.
Der 2. Parameter der create-Methode bestimmt das LOD, wobei der Standardwert 0 sogleich
der Maximalwert ist.
//create triangle selector for the terrain
ITriangleSelector* selector = irrSceneMgr->createTerrainTriangleSelector(
terrain->setTriangleSelector(selector);
selector->drop();
Das Gleiche wird für das Tempelmodell gemacht.
Aber diesmal mit Oct-Tree-Triangle-Selector, der das Ganze noch ein wenig
optimiert. Das bringt zwar für dieses Modell nichts, da seine Polygonzahl zu niedrig
ist, aber zu Demonstrationszwecken kann es ja nicht schaden.
Wie man sieht, unterscheidet sich seine Anwendung so gut wie gar nicht von der Anwendung
eines anderen Triangle Selectors.
//create oct-tree-triangle selector for the object sariHan
ITriangleSelector* selector2 =
- irrSceneMgr->createOctTreeTriangleSelector(sariMesh->getMesh(0), sariHan);
sariHan->setTriangleSelector(selector2);
selector2->drop();
Jetzt muss noch ein Meta Triangle Selector erstellt werden, der die
verschiedenen Triangle Selectors verwaltet. Tut man das nicht, wird man sich später über
komisches Verhalten des Programms wundern müssen. So wird man z.B. springen können, wenn man auf dem Boden steht, nicht aber wenn man sich auf einem Objekt befindet.
//create meta triangle selector
IMetaTriangleSelector* meta = irrSceneMgr->createMetaTriangleSelector();
//add selectors to meta triangle selector
meta->addTriangleSelector(selector);
meta->addTriangleSelector(selector2);
Was wir jetzt haben, ist ein Meta Triangle Selector, in dem sämtliche Polygons
gespeichert sind, mit denen ein Objekt möglicherweise kollidieren könnte. Was wir nicht haben, ist dieses potenziell kollidierende Objekt. Beziehungsweise wir haben es schon,
nämlich die Kamera, nur weiss noch niemand, dass diese zur Kollisionsabfrage benutzt
werden soll. Also sagen wir es jemandem: dem CollisionResponseAnimator,
der sich fortan automatisch um die Kollisionsbehandlung kümmern wird. Er braucht für seine create-Methode 5 Argumente:
Den Meta Triangle Selector (oder einen einfachen Triangle Selector, wenn nur ein Objekt
der Kollisionsabfrage unterzogen werden soll) als erstes,
den Knoten, der manipuliert werden soll, also jener Knoten, der nicht mehr durch den
Terrain fallen oder durch Wände laufen soll und auf den die Gravitation wirken soll, die
im Folgenden noch gesetzt wird, als zweites.
Der 3. Parameter definiert den Radius der Ellipse, die für die Kollisionsberechnung benutzt
wird. Dieser Parameter legt also fest, welchen Abstand der Knoten (die Kamera) von einer
Wand hat, bis seine Bewegung blockiert wird und auch, wie breit ein Gang sein muss, damit
der Knoten hindurch gehen kann.
Die Ellipse sollte dabei so breit wie möglich sein, denn auf Grund von Irrlichts primitiver Kollisionsdetektion bleibt man sonst ab und zu im Terrain stecken,
wenn dieser nicht vollständig gerade ist.
Der 4. Parameter gravityPerSecond wird benutzt, um die Gravitation festzulegen. Interessanterweise wird die Gravitation als Vektor angegeben, d.h. dass sie auch in andere Richtung als die y-Achse wirken kann.
Als 5. Parameter kommt ellipsoidTranslation, also die Position der Ellipse relativ
zur Mitte des Knotens. Standardmäßig hat die Ellipse ihren Mittelpunkt in der Mitte des
Knotens, es kann aber durchaus sinnvoll sein, dies zu ändern. Zum Beispiel wenn man
treppensteigen will. In diesem Fall sollte die Ellipse oberhalb der Knotenmitte positioniert
sein, so dass eine Lücke zwischen Boden und Ellipse entsteht. Treppenstufen, die in diese
Lücke passen, kollidieren nicht mit dem Knoten.
Der letzte Parameter slidingValue gibt die Präzision der Kollision an. Ist der Wert
sehr niedrig (Standard), wird die Bewegung an den Wänden blockiert. Ist er hoch, so kann
man an der Wand entlangrutschen. (Diese Erklärung ist allerdings mit Vorsicht zu genießen,
da dieser Parameter nicht dokumentiert ist. Sie basiert auf Beobachtung und einem Forumseintrag von einem der Entwickler, aber ich denke, es kommt soweit hin)
Umso länger der Text, desto kürzer der Code:
//create collision response animator and attach it to the camera
ISceneNodeAnimator* anim = irrSceneMgr->createCollisionResponseAnimator(
- meta, camera, vector3df(8,25,8), vector3df(0,-8.0,0), vector3df(0,30,0));
camera->addAnimator(anim);
anim->drop();
zurück
weiter