Tokamak Physics Engine with OpenGL

November 19th, 2009


With graphics technologies being able to display realistic images, there is a bigger need for more realistic behaviour of items in the scene. This may mean simple things like just a ball bouncing on the floor to anything one can imagine of.

While experimenting initially, bouncing a ball on a surface was easy.. then came adding gravity… then walls.. then more balls… then it became more and more difficult while adding some unsual shaped objects in the scene. This is when I felt the need of using some physics engine. A friend of mine suggested using the Tokamak Physics Engine.

You can see the license info and download the SDK from www.tokamakphysics.com The SDK can be used for Commercial and Non-commercial purposes free of charge. One thing lacking in the SDK is in depth documentation and easy to understand samples. Here is a brief introduction on how to begin using the engine with some simple samples.

Physics for the Virtual World

This article assumes that you would know the basics of GLUT (Will be adding articles on this soon). Lets start with how a simulation works in Tokamak. The basic flow for a simple simulation would be the following -

Creating a simulation world
Setting up Enviroment (Gravity etc)
Setting up the Animated and Rigid Bodies (Bounding, Type, Inertia etc)
Advancing the Simulator based on a timer
Drawing objects on scene based on the simulation
Killing the Simulation world
Lets see each of this in detail and try to simulate a ball bouncing on the floor.

Setting Up

The first setp is to set up the enviroment for Visual Studio .Net, Do the following

Click on Tools > Options
Under the Projects folder Select VC++ Directories
Under Show Directories for Select ‘Include Files’
Add the ‘Includes’ Directory from the Tokamak SDK
Once the pre-requisits are setup lets see the main code. The first step is to setup the Simulation world.

The Code

We start off by including the Tokamak header file and then the library file using the #pragma directive.

#include <tokamak.h>
#pragma comment (lib, "tokamak.lib")

Then we set up the variables for the simulation and make the simulation object.

neSimulator *simTok = NULL; // Simulation Object
neAllocatorDefault all; // Memory Allocator
neRigidBody *rgdBall;    // Rigid Body for the ball
neAnimatedBody *aniFloor;    // Animated body for the Floor

simTok is the simulator object and the others are the actors in the simulation, the ball and the floor.

Next we need to initialize the simulation world variables(Gravity, Number of Objects, etc), we write a function called initSim() which does this for us.

bool initSim(void){
neV3 gravity; gravity.Set(0.0f, -9.8f, 0.0f);
neSimulatorSizeInfo sizeInfo;
sizeInfo.rigidBodiesCount = 1;
sizeInfo.animatedBodiesCount = 1;
sizeInfo.overlappedPairsCount = 2;
sizeInfo.geometriesCount = 2;
simTok = neSimulator::CreateSimulator(sizeInfo, &all, &gravity);
return true;
}

Here we first create a Tokamak Vector gravity and set the gravity to -9.8 in the Y axis, this is the only natural force that will affect the objects in the simulation, next we need to set the size parameters for the simulator, this is done by the following lines in the code… here we create a sizeInfo object and set the count of Rigid Bodies, Animated bodies, Overlapped Pairs count (colliding) and the number of geometries. Then we set all of these parameters to the simTok object which is our simulator.

Next thing to do is to set up the objects in the simulator. For this we write a initBodies() function. Here we define the various properties of the objects in the simulation, in our case a Ball(Sphere) and a Floor(Box)

bool initBodies(void){
// Setup Ball
neV3 ballPos; // varaible for placing ball
rgdBall = simTok->CreateRigidBody();
neGeometry *geoBall = rgdBall->AddGeometry();
geoBall->SetSphereDiameter(1.5f);
rgdBall->UpdateBoundingInfo();
rgdBall->SetMass(2.0f);
rgdBall->SetInertiaTensor(neSphereInertiaTensor(1.5f,2.0f));
ballPos.Set(0.0f,5.0f,0.0f);
rgdBall->SetPos(ballPos);

Above we have set up the ball parameters, first we have created a RigidBody called rgdBall and then defined its geometry using SetSphereDiameter, Once this is done we update the Bounding information for the Rigid Body. Then comes other features of the Rigid Body like Mass and then the Inertia information and Position. Once this is done we move on to defining the Floor parameters…

//Setup Floor
neV3 floorPos;
aniFloor = simTok->CreateAnimatedBody();
neGeometry *geoFloor = aniFloor->AddGeometry();
geoFloor->SetBoxSize(30.0f, 1.0f, 30.0f);
aniFloor->UpdateBoundingInfo();
floorPos.Set(0.0f, 1.0f, 0.0f);
aniFloor->SetPos(floorPos);
return true;
}

Here the code is slightly different to the previous rigid body. Animated bodies are non moving or are controlled by the user in the scene. Here we set up the Size of the floor and then set the position to it.

Now that we have the Items Set up, Lets see how the rendering is done. In the display routine of the GLUT we can draw a sphere and a cube and transform it to look like the floor. Here is the code.

glPushMatrix();
glPushMatrix();
neT3 ballPos = rgdBall->GetTransform(); // Get the Ball Position
glMultMatrixf((GLfloat*)&ballPos); // Multiply the matrix
glutSolidSphere(1.5f,30.0f,30.0f);
glPopMatrix();
glPushMatrix();
glScalef(30.0f,1.0f,30.0f);
glutSolidCube(1.0f);
glPopMatrix();
glPopMatrix();

Thats it. Now all we need to do is advance the simulation. This can be done with the following code.

simTok->Advance(0.01);

In this example, I have added the code in the display routine. So when the frame is rendered, the simulation is advanced and re-rendered. This is not the best way to do this but it lets you see results instantly. Play around with the placement of the sphere and probably mass etc and see the results. Download the code for this project and play around with it.

In the next article we will see how to work with more complex simulations and different shaped objects.