2009-08-16 5 views
1

Ich muss OGRE3D für ein Universitätsprojekt verwenden, aber wir dürfen keine Bibliotheken von Drittanbietern für Physik oder Kollisionserkennung verwenden. Dies beinhaltet die Verwendung der integrierten Kollisionserkennung von OGRE.Integrieren Sie benutzerdefinierte Physikklassen mit OGRE 3D?

Ich habe einige Schwierigkeiten mit dem richtigen Weg zu nähern, meine eigenen benutzerdefinierten Physik-Routinen zu OGRE eingebauten Einheiten hinzuzufügen.

OGRE verwendet "Entity" -Objekte als grundlegendste Bausteine, und für die Physik benötigen Sie Objekte mit Massen-, Geschwindigkeits- usw. Attributen.

Die Sache, über die ich verwirrt bin, ist, dass OGREs Render/Logik Loops vom Benutzer innerhalb der OGRE-Engine versteckt sind. Dies ist ein Problem, weil ich jede Entität in OGRE abrufen und Kollisionserkennung und Physikberechnungen mit meiner benutzerdefinierten Physik-Engine durchführen muss, die ich erstelle.

Wie kann ich meine eigenen Physik/Kollisions-Engine-Klassen mit OGRE integrieren?

Update: Unter den Rat unten Ich habe subclassed OGRE :: Entity, das heißt:

class PhysicsEntity : public Ogre::Entity; 

PhysicsEntity *ent1 = (PhysicsEntity*)mSceneMgr->createEntity("PhysicsNinja", "ninja.mesh");; 
SceneNode *node1 = mSceneMgr->getRootSceneNode()->createChildSceneNode("NinjaNode1"); 
node2->attachObject((Ogre::Entity*)ent1); 

Die Kommentare Staat dies nicht der beste Weg ist, um OO comform, und ich stimme aber ich kann nicht besser sehen Weg in diesem Stadium? Was denkst du und hast bessere Ideen, weil ich nicht total glücklich damit bin?

Antwort

4

Jason Williams 'Antwort zeigt die richtige Spur. Eine Möglichkeit besteht darin, eine unabhängige Klasse für Ihr GameObject einzuführen. (Lass es uns so für den Rest der Antwort nennen, auch wenn du kein Spiel erstellst)

Diese GameObject-Klasse kapselt alle relevanten Aspekte deiner Ninja und Boxen und was auch immer und verbirgt die physischen und grafischen Aspekte durch die Zusammensetzung von andere Klassen, die sie repräsentieren. Z.B. GrafischesObjekt, PhysikalischesObjekt.

ist hier ein stark vereinfachtes Beispiel:

class GameObject 
{ 
public: 
    void setPosition(Vector3 pos) 
    { 
     m_position = pos; 
     m_graphical->setPosition(pos); 
     m_physical->setPosition(pos); 
    } 

private: 
    GraphicalObject m_graphical; 
    PhysicalObject m_physical; 
    Vector3 m_position; 
} 

Jetzt GraphicalObject kapselt einen Ogre :: SceneNode mit seinem Ogre :: Entity angebracht. PhysicalObject kapselt Ihre physische Körperklasse ein. Sowohl PhysicalObject als auch GraphicalObjects können eine gemeinsame Basisklasse verwenden, die die Schnittstelle zur GameObject-Klasse definiert. Oben habe ich tatsächliche Funktionen wie setPosition verwendet, aber normalerweise würde ich eine allgemeinere Nachrichtenschnittstelle empfehlen, aber in Ihrem Fall muss es wahrscheinlich nicht zu kompliziert sein.

Ein Problem ist immer noch, dass die GameObject-Position auf Änderungen in Ihrem physischen Simulationsschritt reagieren soll. Dies hängt stark davon ab, wie Ihre Physik-Engine entworfen ist. Wenn Sie jedoch über ein Callback-System verfügen, registrieren Sie Ihr PhysicalObject als Listener für alle Ereignisse, die sich auf dieses Ereignis beziehen, und ändern Sie die Position von ihren. Dasselbe gilt für die Orientierung oder Transformation im Allgemeinen, wenn Sie nicht speziell zwischen Position und Ausrichtung unterscheiden.

Wahrscheinlich möchten Sie die Eigenschaften des physischen Körpers (nennen wir es Body für diese Antwort) aus dem Netz ableiten, das die Grafiken darstellt. Im Falle des Ninja sollte seine Form der des Ninja-Netzes ähneln. Ich würde dies mit einer einfachen Hilfsklasse außerhalb der Klassenhierarchie tun. Zum Beispiel eine BodyFactory.

class BodyFactory 
{ 
public: 
    static Body* createEllipsoidBody(MeshPtr mesh); 
    static Body* createCuboidBody(MeshPtr mesh); 
    static Body* createConvexHullBody(MeshPtr mesh); 
} 

Diese Funktionen erstellen eine passende physische Darstellung Ihrer Physik-Engine aus den Mesh-Daten. Im einfachen Fall verwenden sie nur die Begrenzungsbox, oder für anspruchsvollere Körper, die sie die tatsächlichen Eckpunktdaten auswerten, spielt keine Rolle. Vielleicht können Sie die Schnittstelle für physische Attribute erweitern, die nicht im Mesh gespeichert sind (spezifisches Gewicht, Trägheitsmodifikatoren (hohl, massiv, etc.))

Ein allgemeiner Hinweis bei der Verwendung von Ogre (oder einer anderen Grafik-Engine): Verwenden Sie es nur für Grafiken. Ich verstehe, dass die SceneGraph-Implementierung von Ogre für das eigene Szenenmanagement gedacht ist, aber Sie binden sich so sehr an die Engine, überlasten Ihre Schnittstellen mit Dingen, die sie nicht brauchen, und Sie wollen nicht, dass sie davon abhängen. (Interface Segregation Principle) Es ist einfach nicht die Mühe wert. Dinge wirklich zu trennen ist einfacher zu verwalten und zu pflegen.

+0

Vielen Dank für Ihre Antwort, eine ganze Reihe von guten Informationen in Ihrer Antwort werde ich in den nächsten Tagen auf Sie zurückkommen, während ich versuche, es zu implementieren. Danke +1 –

2

Oft möchten Sie ein Physikobjekt ohne Grafiken, ein Physikobjekt mit mehreren Grafiken oder ein Grafikobjekt, das durch mehrere Physikobjekte repräsentiert wird.

Aus diesem Grund (und anderen Gründen, wie verschiedene Physics/Graphics Engines ein- und auslagern zu können) halten die meisten Engines die beiden Systeme ziemlich getrennt, indem sie nur Referenzen/Links zwischen dem Grafik- und Physiksystem verwenden dass die Physikobjekte die Grafikelemente aktualisieren können, nachdem Sie einen Simulationsschritt durchgeführt haben)

1

Sobald ich Ihre Frage gelesen habe, wollte ich Sie auf OgreODE verweisen, was eine nette Brücke zwischen Ogre3D und ODE darstellt. Wenn Sie ODE nicht benutzen sollten, sollten Sie es sich trotzdem ansehen, um ein paar Tipps zu bekommen. Es gibt auch OgreNewt, eine ähnliche Engine.

Ich denke, dass Sie einen FrameListener installieren müssen, wird es aufgerufen, nachdem ein Frame gerendert wurde. Dann können Sie auf den SceneManager und seine SceneNodes zugreifen und deren Positionen lesen und ändern.

Allerdings sind die Meshes, wenn sie keine grundlegenden Formen sind, nicht sehr brauchbar als Modell für die Kollisionserkennung, wenn Sie eine anständige Leistung erhalten möchten. Deshalb denke ich, dass du deine Entitäten mit ein paar Grundformen (Würfel, Kugel usw.) koppeln solltest und mit diesen anstelle der Entity Meshes arbeiten solltest. Unterklasse die Ogre3D-Objekte und gebe ihnen eine Sammlung von Grundformen und einen Accessor zu ihnen. Ihr FrameListener erhält dann die Grundformen jedes SceneNodes und berechnet seine Berechnungen.

+0

Ozan, Ihr Kommentar macht viel Sinn und hat mir sehr geholfen :) Ich habe getan, was Sie gesagt haben, aber ich habe noch eine Frage. Wie kann ich sicherstellen, dass ich nur die relevanten Knoten verarbeite, ohne Kollisionen mit allem zu prüfen? Dh gibt es eine Möglichkeit, auf Knoten in einem bestimmten Teil des OGRE-Quadbaums zuzugreifen? +1 –

+0

Ich bin nicht sicher, ob das möglich ist, und Sie würden ein Problem bekommen, wenn sich zwei Objekte an der Grenze dieser Teile treffen. Ich schlage vor, Sie nehmen Ihre Frage zu den Oger-Foren http://www.ogre3d.org/forums/ – Ozan

+0

Subclassing Ogre :: Entity ist keine gute Idee IMHO. Es macht keinen Sinn aus einer OO Perspektive, die Beziehung zwischen en entity und seiner Form ist nicht is_a. Auch Entity hat eine massive Schnittstelle, die getrennt gehalten werden sollte. – haffax