[ODE] Trimesh/trimesh collision code
Jeffrey Smith
jeffreys at Softimage.com
Mon Feb 9 16:44:04 MST 2004
A few months ago, I wrote some servicable Trimesh/Trimesh collision
code. I've tested it extensively, and it appears to perform quite
well. There are three minor caveats:
1) The stepsize you use will, in general, have to be reduced for
accurate collision resolution. Non-convex shape collision is much
more dependent on the collision geometry than primitive collisions.
Further, the local contact geometry will change more rapidly (and
in a more complex fashion) for non-convex polytopes than it does
for simple, convex polytopes such as spheres and cubes.
2) I have changed dGeomTriMeshDataBuildSingle to accept (but not
require) a new argument: the normals of the faces of each trimesh
object, e.g.
dTriMeshDataID TriMeshData;
TriMeshData = dGeomTriMeshGetTriMeshDataID( Bodies[ BodyIndex ].GeomID );
// as long as dReal == floats
dGeomTriMeshDataBuildSingle(TriMeshData,
// Vertices
Bodies[BodyIndex].VertexPositions,
3*sizeof(dReal), (int) numVertices,
// Faces
Bodies[BodyIndex].TriangleIndices,
(int) NumTriangles, 3*sizeof(unsigned int),
// Normals
Bodies[BodyIndex].FaceNormals);
This pre-calculation saves some time during evaulation of the
conacts, but isn't necessary. If you don't want to calculate
the face normals before construction (or if you have enormous
trimeshes and know that only very few faces will be touching
and want to save time), just pass a "NULL" for the last argument,
and dCollideTTL will take care of the normal calcuations itself.
3) In order to efficiently resolve collisions, dCollideTTL needs
the positions of the colliding trimeshes in the previous timestep.
I use this to calculate an estimated velocity of each colliding
triangle, which is used to find the direction of impact, contact
normals, etc. This requires changes to a few files, as well as
requiring the user to update these variables at every timestep.
Personally, I do this update outside of ODE, so it is not included
in ODE itself. The code to do this looks something like this:
const double *DoubleArrayPtr = Bodies[BodyIndex].TransformationMatrix->GetArray();
dGeomTriMeshDataSet( TriMeshData,
TRIMESH_LAST_TRANSFORMATION,
(void *) DoubleArrayPtr );
The transformation matrix is the standard 4x4 homogenous transform
matrix, and the "DoubleArray" is the standard flattened array of
the 16 matrix values.
I've sent the files that this new feature affects:
collision_kernel.cpp
collision_trimesh.cpp
collision_trimesh_internal.h
collision_trimesh_trimesh.cpp
collision_trimesh.h
Makefile
to Martin Martin for testing, etc.
I haven't merged these with the latest CVS drop, so there will need
to be some minor merging by the ODE maintainers. Please let me know
if there are conflicts that you need me to resolve. (I also added
some code to the Makefile to make a shared object version of libode;
feel free to remove this if it's unwanted).
Finally, I also have new Trimesh/Bbox collision code which fixes the
(significant) bugs I've mentioned in other emails. However, I'm not
as happy with the quality of this code so I'll hold back on
contributing it until I've fixed it up a bit. If the ODE community
really wants this (working, but ugly) implementation, let me know and
I'll contribute it.
-Jeff
More information about the ODE
mailing list