physicscollision-detectionogre3d

Integrate Custom Physics Classes with OGRE 3D?


I have to use OGRE3D for a university project however, we are not allowed to use any third party libraries for Physics or collision detection. This includes using OGRE's built in collision detection.

I am having some difficulty with the correct way to approach adding my own custom physics routines to OGRE's built in entities.

OGRE uses "Entity" objects as the most basic of building blocks and for physics you need objects to have mass, velocity, etc attributes.

The thing I am confused about is that OGRE's render/logic loops seem to be hidden away from the user inside the OGRE engine. This is a problem because I need to be able to get every entity in OGRE and perform collision detection and physics calculations with my custom physics engine that I am building.

How can I integrate my own physics/collisions engine classes with OGRE?

Update: Taking the advice below I have subclassed OGRE::Entity, ie:

class PhysicsEntity : public Ogre::Entity;

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

The comments state this is not the best way to comform to OO, and I agree however I cannot see a better way at this stage? What do you think and do you have any better ideas because I'm not totally happy with doing this.


Solution

  • Jason Williams' answer shows the right track. One possible way is to introduce an independent class representing your GameObject. (Let's call it thus for the rest of the answer, even if you don't create a game)

    This GameObject class encapsulates all relevant aspects of your Ninja and boxes and whatever and hides the physical and graphical aspects by composition of other classes representing them. E.g. GraphicalObject, PhysicalObject.

    Here is a grossly simplified example:

    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;
    }
    

    Now GraphicalObject encapsulates an Ogre::SceneNode with its Ogre::Entity attached. PhysicalObject encapsulates your physical body class. Both PhysicalObject and GraphicalObjects may share a common base class that defines the interface to the GameObject class. Above I used actual functions like setPosition, but usually I'd recommend a more generic message interface, but it probably doesn't have to be too complicated in your case.

    One problem still is that you want the GameObject position to respond to changes in your physical simulation step. This greatly depends on how your physics engine is designed. But if you have some kind of callback system, then register your PhysicalObject as listener to any events regarding this and change position from their. Same for orientation or transform in general, if you don't distinguish between position and orientation specifically.

    You probably want to derive the properties of the physical body (let's call it Body for this answer) from the mesh representing the graphics. In case of the Ninja its shape should somehow resemble that of the ninja mesh. I'd do this with a simple helper class outside the class hierarchy. For instance a BodyFactory.

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

    These functions create a fitting physical representation of your physics engine from the mesh data. In the simple case they just use the bounding box, or for more sophisticated bodies they evaluate the actual vertex data, doesn't matter. Maybe you can extend interface for physical attributes not stored in the mesh (specific weight, inertia modifiers (hollow, solid, etc.))

    A general advice still when using Ogre (or any pure graphics engine): Use it only for graphics. I understand Ogre's SceneGraph implementation begs to be used for your own scene management, but you bind yourself to the engine so much, overload your interfaces with stuff they don't need and you don't want them to depend on. (Interface Segregation Principle) It is just not worth the hassle. Keeping things separate really is easier to manage and to maintain.