# Ogre 3d and bullet physics interaction

I have been playing around with Ogre3d and trying to integrate bullet physics. I have previously somewhat successfully got this functionality working with irrlicht and bullet and I am trying to base this on what I had done there, but modifying it to fit with Ogre. It is working but not correctly and I would like some help to understand what it is I am doing wrong.

I have a state system and when I enter the "gamestate" I call some functions such as setting up a basic scene, creating the physics simulation. I am doing that as follows.

void GameState::enter() {
...
// Setup Physics
btDefaultCollisionConfiguration *CollisionConfiguration = new btDefaultCollisionConfiguration();
btCollisionDispatcher *Dispatcher = new btCollisionDispatcher(CollisionConfiguration);
btSequentialImpulseConstraintSolver *Solver = new btSequentialImpulseConstraintSolver();
World = new btDiscreteDynamicsWorld(Dispatcher, BroadPhase, Solver, CollisionConfiguration);
...
createScene();
}


In the createScene method I add a light and try to setup a "ground" plane to act as the ground for things to collide with.. as follows. I expect there is issues with this as I get objects colliding with the ground but half way through it and they glitch around like crazy on collision.

void GameState::createScene() {
m_pSceneMgr->createLight("Light")->setPosition(75,75,75);

// Physics

// As a test we want a floor plane for things to collide with
Ogre::Entity *ent;
Ogre::Plane p;
p.normal = Ogre::Vector3(0,1,0); p.d = 0;
Ogre::MeshManager::getSingleton().createPlane(
"FloorPlane", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
p, 200000, 200000, 20, 20, true, 1, 9000,9000,Ogre::Vector3::UNIT_Z);
ent = m_pSceneMgr->createEntity("floor", "FloorPlane");
ent->setMaterialName("Test/Floor");
Ogre::SceneNode *node = m_pSceneMgr->getRootSceneNode()->createChildSceneNode();
node->attachObject(ent);

btTransform Transform;
Transform.setIdentity();
Transform.setOrigin(btVector3(0,1,0));

// Give it to the motion state
btDefaultMotionState *MotionState = new btDefaultMotionState(Transform);

btCollisionShape *Shape = new btStaticPlaneShape(btVector3(0,1,0),0);

btVector3 LocalInertia;
Shape->calculateLocalInertia(0, LocalInertia);

// CReate the rigid body object
btRigidBody *RigidBody = new btRigidBody(0, MotionState, Shape, LocalInertia);

// Store a pointer to the Ogre Node so we can update it later
RigidBody->setUserPointer((void *) (node));

// Add it to the physics world
Objects.push_back(RigidBody);
m_pNumEntities++;

// End Physics
}


I then have a method to create a cube and give it rigid body physics properties. I know there will be errors here as I get the items colliding with the ground but not with each other properly. So I would appreciate some input on what I am doing wrong.

void GameState::CreateBox(const btVector3 &TPosition, const btVector3 &TScale, btScalar TMass)
{
Ogre::Vector3 size = Ogre::Vector3::ZERO;
Ogre::Vector3 pos = Ogre::Vector3::ZERO;
Ogre::Vector3 scale = Ogre::Vector3::ZERO;

pos.x = TPosition.getX();
pos.y = TPosition.getY();
pos.z = TPosition.getZ();

scale.x = TScale.getX();
scale.y = TScale.getY();
scale.z = TScale.getZ();

Ogre::Entity *entity = m_pSceneMgr->createEntity(
"Box" + Ogre::StringConverter::toString(m_pNumEntities),
"cube.mesh");

Ogre::AxisAlignedBox boundingB = entity->getBoundingBox();

size = boundingB.getSize(); //size /= 2.0f; // Only the half needed?
//size *= 0.96f;    // Bullet margin is a bit bigger so we need a smaller size

entity->setMaterialName("Test/Cube");

Ogre::SceneNode *node = m_pSceneMgr->getRootSceneNode()->createChildSceneNode();
node->attachObject(entity);
node->setPosition(pos);
//node->scale(scale);

// Physics
btTransform Transform;
Transform.setIdentity();
Transform.setOrigin(TPosition);

// Give it to the motion state
btDefaultMotionState *MotionState = new btDefaultMotionState(Transform);

btVector3 HalfExtents(TScale.getX()*0.5f,TScale.getY()*0.5f,TScale.getZ()*0.5f);
btCollisionShape *Shape = new btBoxShape(HalfExtents);

btVector3 LocalInertia;
Shape->calculateLocalInertia(TMass, LocalInertia);

// CReate the rigid body object
btRigidBody *RigidBody = new btRigidBody(TMass, MotionState, Shape, LocalInertia);

// Store a pointer to the Ogre Node so we can update it later
RigidBody->setUserPointer((void *) (node));

// Add it to the physics world
Objects.push_back(RigidBody);
m_pNumEntities++;
}


Then in the GameState::update() method which which runs every frame to handle input and render etc I call an UpdatePhysics method to update the physics simulation.

void GameState::UpdatePhysics(unsigned int TDeltaTime)
{
World->stepSimulation(TDeltaTime * 0.001f, 60);

btRigidBody *TObject;

for(std::vector<btRigidBody *>::iterator it = Objects.begin(); it != Objects.end(); ++it) {
// Update renderer
Ogre::SceneNode *node = static_cast<Ogre::SceneNode *>((*it)->getUserPointer());
TObject = *it;

// Set position
btVector3 Point = TObject->getCenterOfMassPosition();
node->setPosition(Ogre::Vector3((float)Point[0], (float)Point[1], (float)Point[2]));

// set rotation
btVector3 EulerRotation;
QuaternionToEuler(TObject->getOrientation(), EulerRotation);
node->setOrientation(1,(Ogre::Real)EulerRotation[0], (Ogre::Real)EulerRotation[1], (Ogre::Real)EulerRotation[2]);
//node->rotate(Ogre::Vector3(EulerRotation[0], EulerRotation[1], EulerRotation[2]));
}
}

void GameState::QuaternionToEuler(const btQuaternion &TQuat, btVector3 &TEuler) {
btScalar W = TQuat.getW();
btScalar X = TQuat.getX();
btScalar Y = TQuat.getY();
btScalar Z = TQuat.getZ();
float WSquared = W * W;
float XSquared = X * X;
float YSquared = Y * Y;
float ZSquared = Z * Z;

TEuler.setX(atan2f(2.0f * (Y * Z + X * W), -XSquared - YSquared + ZSquared + WSquared));
TEuler.setY(asinf(-2.0f * (X * Z - Y * W)));
TEuler.setZ(atan2f(2.0f * (X * Y + Z * W), XSquared - YSquared - ZSquared + WSquared));

}


I seem to have issues with the cubes not colliding with each other and colliding strangely with the ground. I have tried to capture the effect with the attached image. I would appreciate any help in understanding what I have done wrong. Thanks.

EDIT : Solution

The following code shows the changes I made to get accurate physics.

void GameState::createScene()
{
m_pSceneMgr->createLight("Light")->setPosition(75,75,75);

// Physics

// As a test we want a floor plane for things to collide with
Ogre::Entity *ent;
Ogre::Plane p;
p.normal = Ogre::Vector3(0,1,0); p.d = 0;
Ogre::MeshManager::getSingleton().createPlane(
"FloorPlane", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
p, 200000, 200000, 20, 20, true, 1, 9000,9000,Ogre::Vector3::UNIT_Z);
ent = m_pSceneMgr->createEntity("floor", "FloorPlane");
ent->setMaterialName("Test/Floor");
Ogre::SceneNode *node = m_pSceneMgr->getRootSceneNode()->createChildSceneNode();
node->attachObject(ent);

btTransform Transform;
Transform.setIdentity();
// Fixed the transform vector here for y back to 0 to stop the objects sinking into the ground.
Transform.setOrigin(btVector3(0,0,0));

// Give it to the motion state
btDefaultMotionState *MotionState = new btDefaultMotionState(Transform);

btCollisionShape *Shape = new btStaticPlaneShape(btVector3(0,1,0),0);

btVector3 LocalInertia;
Shape->calculateLocalInertia(0, LocalInertia);

// CReate the rigid body object
btRigidBody *RigidBody = new btRigidBody(0, MotionState, Shape, LocalInertia);

// Store a pointer to the Ogre Node so we can update it later
RigidBody->setUserPointer((void *) (node));

// Add it to the physics world
Objects.push_back(RigidBody);
m_pNumEntities++;

// End Physics

}

void GameState::CreateBox(const btVector3 &TPosition, const btVector3 &TScale, btScalar TMass)
{
Ogre::Vector3 size = Ogre::Vector3::ZERO;
Ogre::Vector3 pos = Ogre::Vector3::ZERO;
Ogre::Vector3 scale = Ogre::Vector3::ZERO;

pos.x = TPosition.getX();
pos.y = TPosition.getY();
pos.z = TPosition.getZ();

scale.x = TScale.getX();
scale.y = TScale.getY();
scale.z = TScale.getZ();

Ogre::Entity *entity = m_pSceneMgr->createEntity(
"Box" + Ogre::StringConverter::toString(m_pNumEntities),
"cube.mesh");

Ogre::AxisAlignedBox boundingB = entity->getBoundingBox();
// The ogre bounding box is slightly bigger so I am reducing it for
// use with the rigid body.
size = boundingB.getSize()*0.95f;

entity->setMaterialName("Test/Cube");

Ogre::SceneNode *node = m_pSceneMgr->getRootSceneNode()->createChildSceneNode();
node->attachObject(entity);
node->setPosition(pos);
node->showBoundingBox(true);
//node->scale(scale);

// Physics
btTransform Transform;
Transform.setIdentity();
Transform.setOrigin(TPosition);

// Give it to the motion state
btDefaultMotionState *MotionState = new btDefaultMotionState(Transform);

// I got the size of the bounding box above but wasn't using it to set
// the size for the rigid body. This now does.
btVector3 HalfExtents(size.x*0.5f,size.y*0.5f,size.z*0.5f);
btCollisionShape *Shape = new btBoxShape(HalfExtents);

btVector3 LocalInertia;
Shape->calculateLocalInertia(TMass, LocalInertia);

// CReate the rigid body object
btRigidBody *RigidBody = new btRigidBody(TMass, MotionState, Shape, LocalInertia);

// Store a pointer to the Ogre Node so we can update it later
RigidBody->setUserPointer((void *) (node));

// Add it to the physics world
Objects.push_back(RigidBody);
m_pNumEntities++;
}

void GameState::UpdatePhysics(unsigned int TDeltaTime)
{
World->stepSimulation(TDeltaTime * 0.001f, 60);

btRigidBody *TObject;

for(std::vector<btRigidBody *>::iterator it = Objects.begin(); it != Objects.end(); ++it) {
// Update renderer
Ogre::SceneNode *node = static_cast<Ogre::SceneNode *>((*it)->getUserPointer());
TObject = *it;

// Set position
btVector3 Point = TObject->getCenterOfMassPosition();
node->setPosition(Ogre::Vector3((float)Point[0], (float)Point[1], (float)Point[2]));

// Convert the bullet Quaternion to an Ogre quaternion
btQuaternion btq = TObject->getOrientation();
Ogre::Quaternion quart = Ogre::Quaternion(btq.w(),btq.x(),btq.y(),btq.z());

// use the quaternion with setOrientation
node->setOrientation(quart);
}
}


The QuaternionToEuler function isn't needed so that was removed from code and header files. The objects now collide with the ground and each other appropriately.

• You could always use Gamekit's Ogrekit.
– user17002
Jun 11 '12 at 0:09

• The Ogre ground plane is at y=0, but the Bullet ground is at y=1, because the motion state transform has its position set to (0,1,0) by this line: Transform.setOrigin(btVector3(0,1,0)); This is why the boxes are sinking into the ground.
• Do the dimensions of cube.mesh match the TScale dimensions which are being used to create the rigid body? I'd guess the cube.mesh is bigger, which makes it look like the cubes are not colliding.
• The Ogre SceneNode::setOrientation function does not use Euler angles, it uses the quaternion components directly.
• Thank you. I appreciate the response. It is of course working now. I will edit the question with the changes I made in case it helps anyone else. :)
– Tim
Oct 26 '11 at 3:27