Physics simulation using Bullet

After setting up the Bullet library in previous post, now we will move onto the first program of Bullet. In this program I will create a plane and will add some rigid bodies to the scene. Rigid bodies are such objects which do not get deformed when they collide with something else. Most of the trees, building, stones, etc will be rigit bodies in a 3D scene. Bullet provides a class btRigidBody for defining rigid bodies. For our program we are going to use spheres as our rigid bodies, the reason for choosing spheres is, they are the easiest objects when it comes to calculating collision detections. You need only two pieces of information when you want to detect the collision detection, the radius and the position. bound2 What I have done is created a class called bullet inside my tools library, this will take care of all the physics that I will deal with throughout the project.

class bullet 
{
public:
    bullet();
    ~bullet();
    btStaticPlaneShape* plane;                    //infinite plane for tests
    std::vector<btRigidBody*> bodies;            //all the rigid bodies
    
    btClock m_clock;
    btDynamicsWorld* world;                        //every physical object go to the world
    btDispatcher* dispatcher;                    //what collision algorithm to use?
    btCollisionConfiguration* collisionConfig;    //what collision algorithm to use?
    btBroadphaseInterface* broadphase;            //should Bullet examine every object, or just what close to each other
    btConstraintSolver* solver;                    //solve collisions, apply forces, impulses
    
    void createInfinitePlaneAtOrigin();

    void bullet_stepSimulation();
    btRigidBody* addSphere(float ,float ,float ,float ,float );
};

The main program can be divided into four different parts for simplicity. Here are the parts of our first Bullet physics program- 1- initializations : all the bullet initializations will be done here. 2- creating a plane : create a plane shape. (i will explain what it actually means below in detail) 3- adding spheres. 4- rendering spheres & plane. Explaining adding spheres & planes: When you run your graphics engine without any physics all you’re concerned about is the 3D world that you’re rendering your things in. You’re not bothered about the collisions of the objects in your scene. All you care about is the shading of your objects i.e. how your object looks. The moment you add some physics library in your scene, you create another world. Think of it as a parallal universe to the 3D world that you’re building. This parallal universe will be responsible for all the calculations of the positions of your objects based on the physics. This world, lets call it PHYSICS world, is not bothered about HOW your objects are shaded. In this world we are strictly concerned with the position of the object, mass, and inertia of the object. In our application we will maintain a vector (btRigidBody) of all the shapes that we have in the 3D. We will use this vector for all the collision detections in the scene. So when you add a plane or spheres, you’re actually adding that to the vector. Bullet provides us with different shapes that we can add to our scene. In our program we will use two shapes provided by bullet, plane and sphere. When we add any shape to the vector i mentioned above, we also specify its position, mass, inertia into btMotionState object which is then passed to btRigidBody and then its finally added to the vector. Here is a sample code to add a rigid body for your physics.

btRigidBody* bullet::addSphere(float rad, float x,float y,float z,float mass)
{
    btTransform t;    //position and rotation
    t.setIdentity();
    t.setOrigin(btVector3(x,y,z));    //put it to x,y,z coordinates
    btSphereShape* sphere=new btSphereShape(rad);    //it's a sphere, so use sphereshape
    btVector3 inertia(0,0,0);    //inertia is 0,0,0 for static object, else
    if(mass!=0.0)
        sphere->calculateLocalInertia(mass,inertia);    //it can be determined by this function (for all kind of shapes)
    
    btMotionState* motion=new btDefaultMotionState(t);    //set the position (and motion)
    btRigidBody::btRigidBodyConstructionInfo info(mass,motion,sphere,inertia);    //create the constructioninfo, you can create multiple bodies with the same info
    btRigidBody* body=new btRigidBody(info);    //let's create the body itself
    world->addRigidBody(body);    //and let the world know about it
    bodies.push_back(body);    //to be easier to clean, I store them a vector
    return body;
}
// code: https://www.youtube.com/user/thecplusplusguy

Once you add a shape, you can finally go onto rendering your object. Rendering a shape is not at all different from earlier, but with bullet, you need to ask the physics engine about the position of the shape. Because it is the bullet lib which is going to calculate new positions of your object based on the physics interactions. Speaking in terms of matrices, bullet library will give you the translation matrix for your object.

    float mat[16]={0};
    btTransform t;
    body->getMotionState()->getWorldTransform(t);
    t.getOpenGLMatrix(mat);

You get the btTransform object of the shape (body) that you want to query using getWorldTransform(). The btTransform has a method to get a matrix of the object in OpenGL format. You send an empty matrix to this function, the function will fill up the matrix and then you can use it in your program. If you’re working on fixed functionality pipeline you can simply use the matrix returned like this->

    glPushMatrix();
        glMultMatrixf(mat);    //translation,rotation
        // render the shape
    glPopMatrix();

But if you’re working in programmable pipeline like myself, you will need to get transpose of the matrix, you then multiply the new matrix with view and projection and then send it to shaders. (MVPs are usually send to shaders using uniforms) After this you can render your object like you were doing before and there will be proper collosion detection between different objects. You can call addSphere method on a keypress, this will give the effect of firing a bullet. In my scene I am adding a new shape where my camera is placed, I am also giving some initial velocity to the object.

PS: This program is based on a bullet physics tutorial by The CplusPlus guy. All the documentation for the bullet classes and functions is provided on documentation section on bullet webpage.

I would also like to add a couple of mistakes which I did, which ‘rendered’ my code useless-
1- I was adding spheres inside the display loop which caused program to slow down.
2- I was not resetting the model matrix when I was calculating positions of a new sphere.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s