Ogre 3d and bullet physics interaction

Tim
  • Ogre 3d and bullet physics interaction Tim

    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
    btBroadphaseInterface *BroadPhase = new btAxisSweep3(btVector3(-1000,-1000,-1000), btVector3(1000,1000,1000));
    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);
    
    // Add Mass
    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
    World->addRigidBody(RigidBody);
    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");
    entity->setCastShadows(true);
    
    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);
    
    // Add Mass
    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
    World->addRigidBody(RigidBody);
    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));
    TEuler *= RADTODEG;
    
    }
    

    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. weird physics

    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);
    
    // Add Mass
    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
    World->addRigidBody(RigidBody);
    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");
    entity->setCastShadows(true);
    
    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);
    
    // Add Mass
    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
    World->addRigidBody(RigidBody);
    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.

    • 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.

Tags
c++ ogre bullet-physics
Related questions and answers
  • }; // for the old/new screen command // Some nCurses setup int r = 0, c = 0; // current row and column (upper-left is (0,0)) const int nrows = 56, // number of rows in window ncols = 79... set_location(int X, int Y) { location[0] = X; location[1] = Y;}; bool Alive() {return alive;}; void SetLife(bool f) {alive= f;}; //////////////////////////////// Move //////////// bool move(int X, int Y) { location[0] += X; location[1] += Y; return true;}; };// end of sprite

  • shader in every node. Other option I was thinking was making some helper functions to deal with the simpler cases, which would set some default parameters and would ask only the most basic ones... don't want to find out in the end that I have to rewrite everything again, as a lot of other objects will be working with these data. Sorry if it's a too subjective matter, but I need some insight. I'm... I was thinking about making smaller structures with the fTime variable each so I can have attribute keyframes, light keyframes and buffer keyframes, then make the node structure look like

  • I have got some problem in my OpenGL game. I am using bullet physics and I want to achive quite simple effect - I want one object (a sphere) to roll and hit another (box) which will fall down. I...) initialization: dynamicsWorld-&gt;setGravity(btVector3(0,-10,0)); ballShape = new btSphereShape(1); fallMotionState = new btDefaultMotionState(btTransform(btQuaternion(0,0,0,1),btVector3...(mass2,fallMotionState2,pinShape,fallInertia2); pinRigidBody = new btRigidBody(fallRigidBodyCI2); dynamicsWorld-&gt;addRigidBody(pinRigidBody); and this is how I am setting the box position and rotation: btTransform

  • different objects in my game: plane, obstacle, player, bullet and I designed them like this: class Player : public GlObject{ private: std::string name; public: Player(); Bullet fire() const; //this method is unique to the class player void generate_mesh(); } Now in the game engine I want to have a general object list where I can check for example for collision, move objects, and so...I'm a beginner both in game developping and programming. I'm trying to learn some principle in the building of a game engine. I want to create a simple game, I'm at the point where I'm trying

  • (pBackBuffer, NULL, &amp;rtv); pBackBuffer-&gt;Release(); // set the back buffer as the render target device-&gt;OMSetRenderTargets(1, &amp;rtv, dsv); D3D10_VIEWPORT viewport; // create a struct to hold... be on the depth buffer is 0.0 viewport.MaxDepth = 1; // the farthest an object can be on the depth buffer is 1.0 device-&gt;RSSetViewports(1, &amp;viewport); // set the viewport...(&amp;PassDesc); // get the Transform effect variable pTransform = pEffect-&gt;GetVariableByName("Transform")-&gt;AsMatrix(); // create the input element descriptions D3D10_INPUT_ELEMENT_DESC Layout

  • I have got some problem implementing bullet physics into my opengl game. The thing is that it doesn't want to update my translatef value continously but only at the end. The code for bullet looks...,-10,0)); ballShape = new btSphereShape(1); pinShape = new btCylinderShape(btVector3(1,1,1)); pinShape-&gt;setMargin(0.04); fallMotionState = new btDefaultMotionState(btTransform(btQuaternion(0,0,0,1...); btDefaultMotionState* groundMotionState = new btDefaultMotionState(btTransform(btQuaternion(0,0,0,1),btVector3(0,-1,0))); btRigidBody::btRigidBodyConstructionInfo groundRigidBodyCI

  • in advance of first use. Here is a bit a sketch of the classes I am using: typedef unsigned int ResourceId; // Resource is an abstract data type. class Resource { Resource(); virtual... a soft target for the total memory used by all the game's resources combined. Other classes will create resource objects, which will be in an unloaded state, and pass them to the ResourceManager... * name,Resource *resource); // Get the uid of a resource. Returns 0 if it doesn't exist. ResourceId getResourceId(const char * name); // This is the call most likely to be used when

  • it up correctly.. heres the code: void BulletifyContinent(GLMmodel* mesh,float x,float y,float z,float scale) { btTriangleMesh* trimesh = new btTriangleMesh(); for(int t=0;t<mesh-&gt... btDefaultMotionState(btTransform(btQuaternion(0,0,0,0),btVector3(x,y,z))); btScalar Mass = 1; btVector3 FallInertia(0,0,0); btRigidBody::btRigidBodyConstructionInfo StillRigidCI(Mass... = new btRigidBody(StillRigidCI); PhysicsWorld-&gt;addRigidBody(ContiRigid); Edit 2: There is no need to create the bullet vertices on the heap with new: btVector3 v0( p0[0], p0[1], p0[2

  • , In); // Get The Current Line ( NEW ) shaderData[i][0] = shaderData[i][1] = shaderData[i][2] = float(atof (Line)); // Copy Over The Value ( NEW ) } fclose... ) glColor3fv (&amp;outlineColor[0]); // Set The Outline Color ( NEW ) // HERE I AM PARSING THE VERTICES AGAIN (NOT IN THE ORIGINAL FUNCTION) FOR THE OUTLINE AS PER... (1, &amp;shaderTexture[0]); // Get A Free Texture ID ( NEW ) glBindTexture (GL_TEXTURE_1D, shaderTexture[0]); // Bind This Texture. From Now On It Will Be 1D

Data information