Sign in to follow this  
JD

box falling thru a triangle mesh in ODE (solved)

Recommended Posts

Maybe someone can take a look and see if I forgot something. For the life of me I can't figure out why I'm having such problems with the tri mesh. The box vs. box works fine, it's just that box vs. tri mesh that I have problems with figuring out. This code shows a box falling down onto a triangle and thru it. I use opengl default coordinate basis ie. +y is up, +z is out of screen. The triangle has 3 verts, 3 indices, normal points up and has CCW winding order. Right now I'm using ODE space but I tried w/o it and same problem. My collision callback isn't called for weird reason. Had it at non-quick step, same thing. Running simulation at 60hz. Frames are like 500fps. Ask me questions if something is not clear. I cut off lots of code that is not relevant I think, it's tied to my libs as well. Thanks all. (triangle doesn't have a body and it had one but still problems even if not influenced by gravity)
struct UserData
{
	dWorldID world;
	dJointGroupID jointGroup;
	dBodyID boxBody;
};
	
int WinMain(...)
{					
	vector<Mesh*> meshes;

	meshes.push_back(new Mesh(object_level.meshes[0], 0.02f, 0.02f, 0.02f, "Textures\\checkers.tga"));
	meshes[0]->Offset(0, 1.5f, 0);
	
	float boxWidth=0.2f, boxHeight=0.2f, boxDepth=0.2f;
	meshes.push_back(new Mesh(boxWidth, boxHeight, boxDepth, Color(0, 200, 0), false));// box
	meshes[1]->Offset(0, 2, 0);

	// create physics for our world
	dWorldID world = dWorldCreate();
	assert(world);
	dWorldSetGravity(world, 0, -0.2, 0);
	dWorldSetAutoDisableFlag(world, 1);// auto disable bodies after some time or steps to speed up simulation
	
	// space
	dSpaceID space = dSimpleSpaceCreate(0);
	assert(space);

	// bodies
	dBodyID boxBody = dBodyCreate(world);
	assert(boxBody);
	dBodySetPosition(boxBody, meshes[1]->GetPosition().x, meshes[1]->GetPosition().y, meshes[1]->GetPosition().z); 
	
	dMass boxMass;
	dMassSetZero(&boxMass);
	dMassSetBoxTotal(&boxMass, 1, boxWidth, boxHeight, boxDepth);
	dBodySetMass(boxBody, &boxMass);
	
	// geoms
	dGeomID boxGeom = dCreateBox(space, boxWidth, boxHeight, boxDepth);
	assert(boxGeom);
	dGeomSetBody(boxGeom, boxBody);

	dTriMeshDataID levelData = dGeomTriMeshDataCreate();
	assert(levelData);
	
	dGeomTriMeshDataBuildSingle1(levelData,
		object_level.meshes[0]->coordinates,
		3 * sizeof(dReal),// vert stride
		object_level.meshes[0]->nVertices,
		
		object_level.meshes[0]->indices,
		object_level.meshes[0]->nIndices,
		3 * sizeof(int),// tri stride

		object_level.meshes[0]->normals);

	dGeomID levelGeom = dCreateTriMesh(space, levelData, 0, 0, 0);// last three params are callbacks
	assert(levelGeom);
	dGeomSetBody(levelGeom, 0);// level becomes static object

	// must reset position of geom because dGeomSetBody(geom, 0) moves it back to the center
	dGeomSetPosition(levelGeom, meshes[0]->GetPosition().x, meshes[0]->GetPosition().y, meshes[0]->GetPosition().z); 

	// joint group
	dJointGroupID jointGroup = dJointGroupCreate(0);
	assert(jointGroup);
	
	UserData userData;
	userData.world = world;
	userData.jointGroup = jointGroup;
	userData.boxBody = boxBody;

	struct CB
	{
		static void dNearCallback(void *userData, dGeomID geom1, dGeomID geom2)
		{
			const int nMaxContacts = 4;// number of contact points to generate
			dContactGeom contacts[nMaxContacts];
				
			int nContacts = 0;
			nContacts = dCollide(geom1, geom2, nContacts, contacts, sizeof(dContactGeom));
				
			// create contact joint for every collision point and put it into joint group
			for(int i = 0; i < nContacts; ++i)
			{
				static dSurfaceParameters surface;
				surface.mode = dContactBounce | dContactSoftCFM;
				surface.mu = dInfinity;
				surface.mu2 = 0;
				surface.bounce = 0.1f;
				surface.bounce_vel = 0.1f;
				surface.soft_cfm = 0.01f;
										
				dContact contact;
				contact.surface = surface;
				contact.geom = contacts[i];
				contact.fdir1[0] =  0;
				contact.fdir1[1] = -1;
				contact.fdir1[2] =  0;
				contact.fdir1[3] =  0;

				dJointID joint = dJointCreateContact(((UserData*)userData)->world,
					((UserData*)userData)->jointGroup, &contact);
				assert(joint);
					
				// attach a joint only to non-static body					
				dJointAttach(joint, ((UserData*)userData)->boxBody, 0);			
			}
		}
	};
	
	CTimer t;	
	float deltaTime = 0;	
	float accumFrameTime = 0;
	
	// denominator is how many times per second you want physics to update
	const float stepTime = 1.0f/60.0f;
	
	// Main message loop:
	while(msg.message != WM_QUIT)
	{
		t.Start();						
			
		if(!DrawWorld(meshes, deltaTime))			
			break;
						
		t.Stop();	

		deltaTime = t.GetTimeNum();			
		accumFrameTime += deltaTime;
						
		while(accumFrameTime >= stepTime)
		{				
			accumFrameTime -= stepTime;

			// PHYSICS				
				         				
			// call collision detection
			dSpaceCollide(space, &userData, CB::dNearCallback);

			// take a simulation step
			dWorldQuickStep(world, stepTime);				

			// remove all joints in the contact joint group	
			dJointGroupEmpty(jointGroup);	
				
			// move box's mesh in world
			rad::Vec3 pos(*(rad::Vec3*)dGeomGetPosition(boxGeom));						
			meshes[1]->MoveTo(pos);
		}						
	}
}


[Edited by - JD on May 25, 2005 3:07:06 AM]

Share this post


Link to post
Share on other sites
Quote:
Original post by JD
The triangle has 3 verts, 3 indices, normal points up and has CCW winding order.


*Disclaimer* I'm still learning ODE though another wrapper.

In the wrapper for Ode I am using, OgreOde, it has this comment:

TriangleMeshGeometry* EntityInformer::createStaticTriangleMesh(Space* space)
{
assert(_vertex_count && (_index_count >= 6) && "Mesh must have some vertices and at least 6 indices (2 triangles)");
...
}


Perhaps you should try that - having at least 6 indices instead? Sorry, I don't know much else. Good luck!

Share this post


Link to post
Share on other sites
That's probably ogre's requirement. I had a box, a largish mesh and a tri and they all failed. When I used ODE plane, collision with the box sort of worked in that the box went thru the tri but was stopped on the other side. Sort of hanging off the bottom like that. The body and mesh are in synch. Very strange. I took a look at the ODE's tri mesh example and other than they having z-up I haven't noticed anything else. I should mention that the box is a box geom, not another triangle based mesh. Thanks for your help.

Share this post


Link to post
Share on other sites
Problem solved :) Just a bug in the following:

int nContacts = 0;
nContacts = dCollide(geom1, geom2, nContacts, contacts, sizeof(dContactGeom));

nContacts param in dCollide() should have been MaxContacts possible not zero as I have set it to. Thus I wasn't getting any actual contacts made.

Now, things work fine. I have a box bouncing inside a room and it's quite fun. Seems to be pretty stable so far but only time will tell how it handles game levels.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this