Keyframe-Driven Collision Shape?

Leezer
Posts: 22
Joined: Mon Nov 09, 2009 5:06 am

Keyframe-Driven Collision Shape?

Post by Leezer »

Hello there,

I just downloaded the Bullet API today, so I am very new to the library and its capabilities.

Summary of my issue/question:
- I am having trouble deciding which collision shape (or maybe a soft body would be better?) to use for approximating a trimesh human head with individually animated vertices (the head trimesh is not animated using transformation matrices)
- I don't want this collision shape to be affected by anything other than the movement of the head trimesh (i.e. it should not deform or move when hit)
- However, I do want to be able to throw objects at the head/shape and have them bounce off realistically (realistically in the sense that a cube collision shape would not do the trick, because it isn't very good at approximating the lumpy geometry of a human head)

Read on if you are interested...

Specific details:
I am interested in using a collision shape to approximate an animated trimesh (specifically a human head that will make nodding movements). Since each vertex in the animated head could potentially change positions between time steps, I think I would need to use a dynamic collision shape.

According to the Bullet wiki, my options are either:
- a compound collision shape comprised of multiple primitives (I would probably use spheres) or btConvexHulls
- a single btConvexHull
- a single btConvexTriangleMeshShape

But since the collision shape would have to be driven by the vertex positions of the trimesh head that it encapsulates, I am wondering where this leaves me in terms of options. I have read through the User Manual, but have not found any information pertaining to changing (at each time step) the individual vertices of a btConvexHull after it has been created (i.e. driving the shape of a collision shape with vertex keyframe data).

On the other hand, since I don't what the collision shape to be influenced by any external forces (I want to instead collide objects against it), perhaps I should make it a static collision shape and not a dynamic one.

Thank you so much for your help, even if it is just pointing me to the right class or to a different physics library altogether.

--Leezer :)
User avatar
Erwin Coumans
Site Admin
Posts: 4221
Joined: Sun Jun 26, 2005 6:43 pm
Location: California, USA

Re: Keyframe-Driven Collision Shape?

Post by Erwin Coumans »

It would be best to use a kinematic object with a btBvhTriangleMeshShape.

There is already an example doing deformation on such 'deforming' triangle mesh, check out Bullet/Demos/ConcaveDemo/ConcavePhysicsDemo.cpp

In a nutshell: you need to call

Code: Select all

trimeshShape->partialRefitTree(aabbMin,aabbMax); 
each time the triangle mesh deforms/changes vertex positions. Note that you need to flag the object kinematic. The aabbMin and aabbMax arguments specify the axis aligned bounding box around all deformed vertices. So if only the mouth or the nose of your face changes, it only needs to update the acceleration structures around the nose. In case your simulation suffers deep penetrations (due to vertex animation) try using a smaller internal timestep such as 1./240. instead of the defaula 1.60 (simulation->stepSimulation(actualDeltaTime,10,1./240.) for example).

Please check the ConcavePhysicsDemo.cpp for details, and let us know if you run into any problems.

Thanks,
Erwin
Leezer
Posts: 22
Joined: Mon Nov 09, 2009 5:06 am

Re: Keyframe-Driven Collision Shape?

Post by Leezer »

Erwin --

Thank you so much for your help - the btBvhTriangleMeshShape is definitely what I was looking for! I have modified the ConcavePhysicsDemo to include the trimesh head and I am rotating all if its vertices slightly (about the Y axis) at each simulation step in order to roughly simulate the kinds of nodding/shaking movements that it will eventually have.

I am, however, running into problems where you said I might - when I shoot cubes (the default DemoApplication feature) at the rotating trimesh, some bounce off while some pass right through (in fact, the majority pass through). I tried using a smaller timestep interval like you suggested, but the frequency of cubes passing through the trimesh did not change (only their shooting speed). So, I've currently set it back to what it was originally for the ConcavePhysicsDemo (getDeltaTimeMicroseconds() * 0.000001f). Thinking that my "animation" was too fast, I slowed the rotation down considerably, but this didn't change things either. In fact, if I don't animate the trimesh at all (and don't call partialRefitTree), I still have some cubes (though not as many) passing right through the head trimesh.

I'm wondering if there's something else that I can try tweaking, other than the simulation timestep interval, to try and produce a higher percentage of hit recognition.

Could relative size be a factor? The entire head trimesh (including neck) occupies a bounding box with maximum = (16.5, 12.9, 9.2) and minimum = (-16.5, -12.9, -9.2), while the shooting cubes are boxes with size 0.5 x 0.5 x 0.5. On the other hand, I'd like to be able to collide small shapes with the trimesh head because I eventually want to simulate hair on the head using colliding particles to do so, so simply chalking this up as a size problem would be disappointing.

Or maybe it's a problem with the new bounding box max and min that I'm feeding into partialRefitTree at every simulation step (after rotating the trimesh slightly).

Code: Select all

// This function rotates the trimesh's vertices and then returns the new bounding box max
// and min to feed into partialRefitTree()
// "trimesh head" is synonymous with "collider", by the way
btVector3* ConcaveDemo::rotateColliderVertices(float degreeInc) // degreeInc is set to 0.3
{
	// Calculate how much to rotate the collider (given by degreeInc)
	float radInc = degreeInc * 0.01745329251994329547; // radians per degree

	btQuaternion rot(btVector3(0,1,0), radInc); // a rotation radInc about the Y axis

	// Rotate each vertex in the collider!
	int totalColliderVerts = m_objParser->getNumParsedVertices(); // the trimesh head was an obj that I parsed in
	for (int i=0; i < totalColliderVerts; i++)
	{
		btVector3 vertAfterRot = btMatrix3x3(rot) * gColliderVertices[i];
		gColliderVertices[i].setValue(vertAfterRot[0], vertAfterRot[1], vertAfterRot[2]);
	}

	// Return the collider's new brute force AABB maximum/minimum
	btVector3* gNewAABB = new btVector3[2];
	m_colliderIndexVertexArrays->calculateAabbBruteForce(gNewAABB[0], gNewAABB[1]);

	return gNewAABB;
}
So really, I just use the trimesh's new brute force AABB as the AABB to feed into partialRefitTree (because I have the whole trimesh head rotating, not just a specific area). But maybe this is still too small, and that's why the shooting cube collisions aren't registering.

Thanks again :-)

--Leezer
Leezer
Posts: 22
Joined: Mon Nov 09, 2009 5:06 am

Re: Keyframe-Driven Collision Shape?

Post by Leezer »

Erwin, you there? Maybe I should re-post this as a new topic...
Leezer
Posts: 22
Joined: Mon Nov 09, 2009 5:06 am

Re: Keyframe-Driven Collision Shape?

Post by Leezer »