[ODE] Convex Volume Geom (GJK)
Rodrigo Hernandez
kwizatz at aeongames.com
Wed Dec 21 12:58:00 MST 2005
ode at erwincoumans.com wrote:
>Rodrigo,
>
>I'm interested in your solution for convex for ODE. Can you describe the
>algorithms you use to compute the contact points?
>
>Thanks,
>Erwin
>
>
Well, Like I said before, I have convex-plane and convex-sphere already
coded, so I can descrive those.
First some context,
Convex shapes are defined in my implementation in a somewhat redundant
way, a convex shape consists of the collection
of planes describing a convex hull, each plane is a dVector4 containing
the plane equation (X,Y,Z represents the normal of the plane and W the
signed distance from the origin),
then there is a collection of points describing the hull, simple
dVector3 variables, and finally an index buffer to assign the points to
the planes in a counter-clockwise manner,
this buffer is an int array, arranged in the following way: first the
number of points in a face (poligon), then that many indexes into the
point collection, then the sequence is repeated,
the first group of indices matches the first plane, and so on.
ODE takes pointers to all these structures, ODE does NOT allocate any of
that memory, I made it this way because I think that that information is
needed by a rendering engine or similar,
so it must be computed and allocated in the "client" application anyway,
so ODE can simply reuse the data.
Here us the dxConvex Class definition:
struct dxConvex : public dxGeom
{
dReal *planes; /*!< An array of planes in the form:
normal X, normal Y, normal Z,Distance
*/
dReal *points; /*!< An array of points X,Y,Z */
unsigned int *polygons; /*! An array of indices to the points of each
polygon, it should be the number of vertices followed by that amount of
indices to "points" in counter clockwise order*/
unsigned int planecount; /*!< Amount of planes in planes */
unsigned int pointcount;/*!< Amount of points in points */
dReal saabb[6];/*!< Static AABB */
dxConvex(dSpaceID space,
dReal *planes,
unsigned int planecount,
dReal *points,
unsigned int pointcount,
unsigned int *polygons);
~dxConvex()
{
//fprintf(stdout,"dxConvex Destroy\n");
}
void computeAABB();
};
And here is the Sample Data I am using for my tests, the following
describes a cube, in case it is not obvious :)
dReal planes[]= // planes for a cube
{
1.0f ,0.0f ,0.0f ,0.25f,
0.0f ,1.0f ,0.0f ,0.25f,
0.0f ,0.0f ,1.0f ,0.25f,
0.0f ,0.0f ,-1.0f,0.25f,
0.0f ,-1.0f,0.0f ,0.25f,
-1.0f,0.0f ,0.0f ,0.25f
};
const unsigned int planecount=6;
dReal points[]= // points for a cube
{
0.25f,0.25f,0.25f, // point 0
-0.25f,0.25f,0.25f, // point 1
0.25f,-0.25f,0.25f, // point 2
-0.25f,-0.25f,0.25f,// point 3
0.25f,0.25f,-0.25f, // point 4
-0.25f,0.25f,-0.25f,// point 5
0.25f,-0.25f,-0.25f,// point 6
-0.25f,-0.25f,-0.25f,// point 7
};
const unsigned int pointcount=8;
unsigned int polygons[] = //Polygons for a cube (6 squares)
{
4,0,2,6,4, // positive X
4,1,0,4,5, // positive Y
4,0,1,3,2, // positive Z
4,3,1,5,7, // negative X
4,2,3,7,6, // negative Y
4,5,4,6,7, // negative Z
};
Ok, now the algorithms,
Plane-Convex is done by simply separating the points in two groups, the
ones in front of the plane and the ones behind the plane, if all of them
are on either side, there is no collision, if there are points on
both sides, there is a collision, take the ones BEHIND the plane and use
them as Contact Points, the contact normal is the Plane normal for all
of them, and the depth is the distance from the plane to each of the points.
Sphere-Convex is a bit more complicated, but not much. you just iterate
thru the planes first, checking if the sphere intersects the plane (if
the distance from the center of the shere to the plane is less
than the radius of the sphere, it intersects) if it does, find the point
on the plane closer to the center of the sphere, and check if said point
is inside the polygon descrived on the plane (face), if it is,
the contact point is the point in the sphere surface in the direction of
the point on the plane, the depth is the radius of the sphere minus the
distance to the plane and the collision normal is the normal of the face.
IF the point is NOT inside the polygon, then we need to check for
collision with a vertex or edge, so find the Voronoy region of the
polygon on which the point resides and check for collision between the
sphere and the closest feature that gives you (vertex or edge) if there
is a collision then the collision position is the point on the sphere
surface in direction (point_in_edge or vertex)-sphere_center, the depth
is the radius of the sphere minus the distance to the point in the
feature and the normal is the normalized vector
sphere_center-(point_in_edge or vertex).
I think I invented the sphere-convex collision check (I have a contiuous
one as well), but it may just be a form of Lin-Canny or V-Clip, but I am
not sure, I wrote all that by memory, so some details may not be 100%
acurate.
Cheers!
More information about the ODE
mailing list