Ok,
sorry for the delay,
Rather than trying to explain the method I use, I decided to just
paste my entire physics handler below so there is no confusion
whatsoever :p
//Physics.c
//Handles integration of the ODE physics engine
#include "physics.h"
float GeomMatrix[12];
dWorldID World;
dSpaceID Space;
dObject Objects[MAX_OBJS];
dJointGroupID contactgroup;
int numObjs = 0;
dGeomID land;
dTriMeshDataID triMesh;
dVector3 triVert[40000];
int indexes[10000];
int k=0;
void wakeAll(void){
int i;
for(i=0; i<numObjs; i++){
dBodyEnable(Objects[i].Body);
}
}
//Add one user defined object
int addDObj(int numGs, int type){
dMatrix3 R;
size_t s = 0; //The user data
int j;
if(type != 2){
Objects[numObjs].Body = dBodyCreate(World);
dBodySetPosition(Objects[numObjs].Body, 0, 30, 0);
dBodySetLinearVel(Objects[numObjs].Body, .01, 0, 0);
//hdBodySetLinearVel(Objects[numObjs].Body, dRandReal() * 50 -
25, dRandReal() * 50 - 25, dRandReal() * 50 - 25);
dBodySetAngularVel(Objects[numObjs].Body, 0.0, 0.0, 0.0);
dRFromAxisAndAngle(R, dRandReal() * 2.0 - 1.0, dRandReal() * 2.0
- 1.0, dRandReal() * 2.0 - 1.0, dRandReal() * 10.0 - 5.0);
dBodySetRotation(Objects[numObjs].Body, R);
//Add user data (nothing)
dBodySetData(Objects[numObjs].Body, (void*)s);
}
//Add mass
switch(type){
case 0:{
//If Box
dMassSetBox(&Objects[numObjs].mass, 0.5, 2, 2, 2);
dBodySetMass(Objects[numObjs].Body, &Objects[numObjs].mass);
}break;
case 1:{
//If Sphere
dMassSetSphere(&Objects[numObjs].mass, 0.5, 2);
dBodySetMass(Objects[numObjs].Body, &Objects[numObjs].mass);
}break;
case 2:{
//Trimesh (does not link to an object, .: no mass
}break;
}
//Initalise object's geoms
for(j=0; j<numGs; j++){
switch(type){
case 0:{
//If Box
Objects[numObjs].geoms[j] = dCreateBox(Space, 2, 2, 2);
dGeomSetData(Objects[numObjs].geoms[j], "Box");
dGeomSetBody(Objects[numObjs].geoms[j],
Objects[numObjs].Body);
}break;
case 1:{
//If Sphere
Objects[numObjs].geoms[j] = dCreateSphere(Space, 2);
dGeomSetData(Objects[numObjs].geoms[j], "Sphere");
dGeomSetBody(Objects[numObjs].geoms[j],
Objects[numObjs].Body);
}break;
case 2:{
//Trimesh
Objects[numObjs].Body = (dBodyID)0;
triMesh = dGeomTriMeshDataCreate();
int i, j = 0;
for(i=0; i<objects[numObjs].vertices_qty; i++){
triVert[i][0] = (dReal)objects[numObjs].vertex[i].x;
triVert[i][1] = (dReal)objects[numObjs].vertex[i].y;
triVert[i][2] = (dReal)objects[numObjs].vertex[i].z;
triVert[i][3] = 0.0f;
}
for(i=0; i<objects[numObjs].polygons_qty; i++){
indexes[k] = objects[numObjs].triangle[j].a;
k++;
indexes[k] = objects[numObjs].triangle[j].b;
k++;
indexes[k] = objects[numObjs].triangle[j].c;
k++;
j++;
}
dGeomTriMeshDataBuildSimple(triMesh, (dReal*)triVert,
objects[numObjs].vertices_qty, indexes, k);
Objects[numObjs].geoms[j] = dCreateTriMesh(Space, triMesh,
NULL, NULL, NULL);
dGeomTriMeshSetData(Objects[numObjs].geoms[j], triMesh);
dGeomSetPosition(Objects[numObjs].geoms[j], 0, 10, 0);
dGeomSetData(Objects[numObjs].geoms[j], "TriMesh");
/*
int indexes[6];
dVector3 triVert[4];
indexes[0] = 2;
indexes[1] = 1;
indexes[2] = 0;
indexes[3] = 3;
indexes[4] = 2;
indexes[5] = 0;
triVert[0][0] = 100.0f;
triVert[0][1] = -5.0f;
triVert[0][2] = 100.0f;
triVert[0][3] = 0.0f;
triVert[1][0] = -100.0f;
triVert[1][1] = -5.0f;
triVert[1][2] = 100.0f;
triVert[0][3] = 0.0f;
triVert[2][0] = -100.0f;
triVert[2][1] = 5.0f;
triVert[2][2] = -100.0f;
triVert[0][3] = 0.0f;
triVert[3][0] = 100.0f;
triVert[3][1] = 5.0f;
triVert[3][2] = -100.0f;
triVert[0][3] = 0.0f;
dGeomTriMeshDataBuildSimple(triMesh, (dReal*)triVert, 4,
indexes, 6);
Objects[numObjs].geoms[j] = dCreateTriMesh(Space, triMesh,
NULL, NULL, NULL);
dGeomSetData(Objects[numObjs].geoms[j], "Plane");
dGeomSetPosition(Objects[numObjs].geoms[j], 0, 10.0, 0);
*/
/*
dVector3 v0, v1, v2;
dGeomTriMeshGetTriangle(Objects[numObjs].geoms[j], 0, &v0,
&v1, &v2);
printf("\n%f\t%f\t%f\n", (float)v0[0], (float)v0[1],
(float)v0[2]);
printf("%f\t%f\t%f\n", (float)v1[0], (float)v1[1],
(float)v1[2]);
printf("%f\t%f\t%f\n", (float)v2[0], (float)v2[1],
(float)v2[2]);
*/
//dGeomSetBody(Objects[numObjs].geoms[j],
Objects[numObjs].Body);
}break;
};
Objects[numObjs].numGeoms += 1;
}
Objects[numObjs].localID = numObjs;
numObjs += 1;
return(numObjs - 1);
}
//Initialise the ODE engine
void initODE(void){
World = dWorldCreate();
Space = dSimpleSpaceCreate(0);
contactgroup = dJointGroupCreate(0);
dCreatePlane(Space, 0, 1, 0, 0);
dWorldSetGravity(World, 0, -9.8, 0);
dWorldSetERP(World, 0.2);
dWorldSetCFM(World, 1e-5);
dWorldSetContactMaxCorrectingVel(World, 0.9);
dWorldSetContactSurfaceLayer(World, .002);
dWorldSetAutoDisableFlag(World, 1);
}
//Clean up the ODE engine
void closeODE(void){
dJointGroupDestroy(contactgroup);
dSpaceDestroy(Space);
dWorldDestroy(World);
}
//Check if two objects are colliding
//Note: Not allowed to modify collision space while it is being
processed with dSpaceCollide
static void nearCallback(void *data, dGeomID o1, dGeomID o2){
int i, numc;
dBodyID b1 = dGeomGetBody(o1);
dBodyID b2 = dGeomGetBody(o2);
dContact contact[MAX_CONTACTS];
for(i = 0; i < MAX_CONTACTS; i++){
contact[i].surface.mode = dContactBounce | dContactSoftCFM;
contact[i].
surface.mu = dInfinity;
contact[i].surface.mu2 = 0;
//contact[i].surface.bounce = 2.51;
contact[i].surface.bounce = 0.1;
contact[i].surface.soft_cfm = 0.0001;
}
numc = dCollide(o1, o2, MAX_CONTACTS, &contact[0].geom,
sizeof(dContact));
printf("numc is %d\n", numc);
if(numc){
for(i = 0; i < numc; i++){
dJointID c = dJointCreateContact(World, contactgroup, contact
+ i);
dJointAttach(c, b1, b2);
}
}
}
//Draw each geom object
//void drawgeoms(dgeomsID g, const dReal *pos, const dReal *R, int
show_aabb){
void drawGeom(dGeomID g, const dReal *pos, const dReal *R, int
show_aabb, int locID){
if(!g){
return;
}
if(!pos){
pos = dGeomGetPosition(g);
}
if(!R){
R = dGeomGetRotation(g);
}
int type = dGeomGetClass(g);
printf("%d", type);
system("pause");
if(type == dBoxClass){
drawObj((float *)pos, (float *)R, locID);
}else if(type == dSphereClass){
drawObj((float *)pos, (float *)R, locID);
}else if(type == dTriMeshClass){
drawObj((float *)pos, (float *)R, locID);
}
}
int type;
//Run one frame of the physics loop
void simLoop(void){
dSpaceCollide(Space, 0, &nearCallback);
//Advance the simulation
//float test = 70.0f / 1000.0f;
//dWorldQuickStep(World, 0.05);
dWorldQuickStep(World, 0.009);
dJointGroupEmpty(contactgroup);
//For each object + geoms
int i, j;
for(i=0; i<numObjs; i++){
for(j=0; j<Objects[i].numGeoms; j++){
drawGeom(Objects[i].geoms[j], 0, 0, 0, i);
}
}
}
OK, brief explanation of the functions,,,
(sorry for any random global variables, this code is the same code I
am working on, so it is till being de-bugged...)
wakeall just activates all geoms, a debugging function
addDObj adds one user-defined object, ignore the first variable, it
doesn't do anything, the second variable says what type of object to
add, 0 is a box, 1 is a sphere and 2 is a trimesh
initODE and closeODE just start and close everything,
nearCallback is my collision test function
drawgeoms draws each geometry
and simLoop steps the simulation every frame...
this isn't my latest version of the code, so if there are minor errors
with things like initialising ODE etc, i am probably allready aware of
them, however if anyone could check my trimesh creation code that
would be really appreciated,
thanks!