views:

757

answers:

3

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.

+2  A: 

Often you will want a physics object with no graphics, a physics object with multiple graphics, or a graphics object represented by multiple physics objects.

Because of this (and other reasons, such as being able to swap different physics/graphics engines in and out), most engines keep the two systems fairly separate, just using references/links between the graphics and physics system (so that the physics objects can update the graphics entities after you have performed a simulation step)

Jason Williams
+1  A: 

As soon as I read your question I was going to point you to OgreODE, which provides a nice bridge between Ogre3D and ODE. If you may not use ODE, maybe you should nevertheless have a look at it, to get some hints on how to do it? There is also OgreNewt, a similar engine.

I think you need to install a FrameListener, it is called after a Frame has been rendered. Then you can access the SceneManager and its SceneNodes, and read and alter their positions.

However, the Meshes, unless they are basic shapes, are not very viable as model for collision detection, if you want to get a decent performance. This is why I think you should couple your Entities with a few basic shapes (cube, sphere, etc) and work with these instead of the Entity meshes. Subclass the Ogre3D entities and give them a collection of basic shapes and an accessor to them. Your FrameListener then gets the basic shapes of every SceneNode and does its calculations.

Ozan
Ozan, your comment makes a lot of sense and has helped me greatly :) I have done what you have said, however I have one more question. How can I ensure I am processing just the relevant nodes without checking collisions against everything? Ie is there some way to access nodes in a certain part of OGRE's quad tree? +1
Brock Woolf
I'm not sure if that is possible, plus you would get a problem when two objects meet at the border of those parts.I suggest you take your question to the ogre forums http://www.ogre3d.org/forums/
Ozan
Subclassing Ogre::Entity is not a good idea IMHO. It doesn't make sense from an OO perspective, the relationship between en entity and its shape is not is_a. Also Entity has a massive interface that should be kept separate.
haffax
+4  A: 

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 Ogre::Singleton
{
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.

haffax
Thanks for your answer, quite a lot of good info in your answer I will get back to you on this one in the next couple of days while I try to implement it. Thanks +1
Brock Woolf