Home
Demo and Benchmark Documentation Engines
 
Demo and Benchmark Documentation Engines
Navigation
» Introduction » Install Instructions » Developer Documentation » Simple Example » Graphics Engine Integration Examples »»Getting started with Irrlicht and PAL (Terrain example) »»Getting started with Horde3D and PAL (Ragdoll example) »»»Setting up Horde3D with PAL »»»Initialising PAL »»»Binding Scene nodes to Physics objects »»»Simple Physics demo »»»Linking objects with Constraints (Physics + Ragdolls = AWESOME) » PAL Developer Documentation » PAL Publications

Setting up Horde3D with PAL

This tutorial was contributed by Jarryd Pinto.

The following tutorial will demonstrate how to integrate P.A.L with the Horde 3d graphics engine. A simple physics demo will show you how to associate a Mesh/Scene Node with a PAL shape. Using constraints, you will then link several of these shapes to create a basic Ragdoll.

It is assumed that you are already familiar with the nuts and bolts of Horde3D. Setting up the engine, loading resources and initiating the render loop will not be covered. It is also assumed that you have installed P.A.L and configured your chosen compiler to work with its libraries. If not, please refer to the Irrlicht tutorial which covers this area in detail.

^ top

Initialising PAL

Let’s begin by loading and initialising PAL as follows:

#include "palFactory.h" //PAL physics
...
//Load PAL from the .dll
PF->LoadPALfromDLL();
	
//Load your chosen Physics engine
//The appropriate PAL dll MUST be in the working directory. Eg: //libpal_bullet.dll
PF->SelectEngine("Bullet"); 
	
//Create the main physics class
pp = PF->CreatePhysics(); 

if (pp == NULL) 
{
		printf("Failed to create the physics engine. Check to see if you spelt the engine name correctly, and that the engine DLL is in the right location");
		return false;	
}

Succesfully instantiating the physics engine with "PF->CreatePhysics()" will return a pointer to it. The pointer can then be used to initialise the engine as follows:

//Initialize the engine and set the main gravity vector
pp->Init(0,-9.8f,0);

The next step is optional, but recommended if you don’t wish to have objects falling inifinitely! Create a flat terrain to stop objects falling below a set level.

palTerrainPlane *pt= PF->CreateTerrainPlane(); //create the ground
//initialize it, set its location to 0,0,0 and minimum size to 50	   
pt->Init(0,0,0,50.0f);

^ top

Binding Scene nodes to Physics objects

With the engine initialised you must now provide it information on the objects in the simulation. P.A.L has various means of approximating geometry (capsules, convex meshes etc) but for simplicity’s sake, let us begin with a box.
Initialising this shape is carried out as follows:

//Create a physics object
palBox *pb = PF->CreateBox();
//Obtain scene node properties
float tx,ty,tz,rx,ry,rz,sx,sy,sz;
Horde3D::getNodeTransform(object,&tx,&ty,&tz,&rx,&ry,&rz,&sx,&sy,&sz);
//Set position, dimensions and mass
pb->Init(tx,ty,tz,width*sx,height*sy,depth*sz,mass);

//Set orientation
//roll: rotation around z	pitch: rotation around x	yaw: rotation around y
pb->SetOrientation(rz*DegToRad,rx*DegToRad,ry*DegToRad);

The physics engine will now keep track of this object, updating it’s transformation matrix when necessary. As this is done independently of the game engine however, you will have to copy this information on every update. This process is shown below:

//Get updated position & orientation from physics engine
palMatrix4x4 mat = pb->GetLocationMatrix();

//Extract rotation
float rotX,rotY,rotZ;
mat_get_rotation(&mat,&rotX,&rotY,&rotZ);

const float PI = 22.0f/7.0f;
const float RadToDeg = 180/PI;

//Update scene node
Horde3D::setNodeTransform( object,  mat._41, mat._42, mat._43,  //Translation
                     rotX*RadToDeg, rotY*RadToDeg, rotZ*RadToDeg,//Rotation
                               scaleX, scaleY,  scaleZ);   //Scale

Be sure to maintain the scale of the object when applying the new transformation. All of the above code has been encapsulated into a “SceneObject” class that you can use or modify for your own work.

^ top

Simple Physics demo

We shall now test the “SceneObjects” class with a simple Physics demo. Begin by initialising the Physics engine as before. Load a simple mesh that we can approximate with a P.A.L box. For example:

//Load the mesh ‘resource’
ResHandle box = Horde3D::addResource(ResourceTypes::SceneGraph,"Box.scene.xml",0);

Using the “SceneObjects” class, create a new object and intialise it as follows:

//For convenience, you may wish to maintain references to all your objects in 
//an array or vector.
std::vector<sceneObject*> physicsObjects; 

//Create a new object
sceneObject *obj = new sceneObject;

//Add the new object to the scene graph 
obj->object = Horde3D::addNodes(RootNode,box);

//Set the location, scale and orientation of the object 
Horde3D::setNodeTransform(head->object,0.4,5.21783,0,0,0,0, 1, 1,1);

//Initialise the corresponding physics object by passing the dimensions and //mass of the object 
obj->init(bxWidth,bxHeight,bxDepth,2);

//Add the new object to the list
physicsObjects.push_back(obj);

With the Objects and Physiscs engine initialised, the simulation is ready to go! In order to update the physics simulation on every frame, place the following code in the game loop:

//Update the physics engine. Advance the simulation time by 0.02 on every //frame
pp->Update(0.02);
While this method will happily update the simluation, it is important to note that it is tied to the frame - rate. Fluctuations in the frame rate will result in the simulation slowing up or down. The following update method is therefore recommended:

const float timeStep = 1.0f/60.0f;
//Accumulate the time elapsed since the last frame
elapsedTime += timeSinceLastFrame;
//'Step' through the physics simulation until the ‘elapsed time’ is accounted //for
while(elapsedTime>=timeStep)
{
	pp->Update(timeStep);
	elapsedTime -= timeStep;
}

After updating the simulation, update the transformations of all objects in the scene as follows:


//Update scene objects
for(int i=0; i< physicsObjects.size(); i++)
{
	//Call the “SceneObjects” update method to update transformation
physicsObjects[i]->update();
}

^ top

Linking objects with Constraints (Physics + Ragdolls = AWESOME)

Now that you’re done with the boring details of setting up your simulation, let’s have some fun. By linking the aforementioned object to a string of new objects, we will create a simple ragdoll. Physics objects are linked together using Constraints - of which there are several types (Hinges, Spherical joints, Prismatic joints etc). The process of linking two existing objects is described below:


//Assuming two scene objects (“head” & “body”) are already defined
//Create a “Spherical Link”
palSphericalLink *psl = 
dynamic_cast(PF->CreateObject("palSphericalLink"));
//Initialise the constraint by specifying it’s location
//and the objects it connects
psl->Init(head->pb,chest->pb,0.4,4.96809,0);
//Optionally, limit the freedom of movement as follows:
psl->SetLimits(.4,.2); 

Creating a “Hinge” constraint is similar but requires the axis around which rotation occurs. An example connecting a “Leg” with a “Thigh” is shown below:

//Link left leg with left thigh
palRevoluteLink *prl = 
dynamic_cast(PF->CreateObject("palRevoluteLink"));
prl->Init(leftThigh->pb,leftLeg->pb,0.4,3.56816,0.2,0,0,1);
prl->SetLimits(-0.2,0.1);
For a more detailed and thorough example, please see the attached source code. PAL Physics with Horde3d