The best used for these collision objects are in general very simplistic demos, and also they are good for understanding how to implement user defines collision for more complex objects.
The following code is a implementation of such collision primitive using a user define mesh
- Code: Select all
class PlaneCollision
{
public:
PlaneCollision(NewtonWorld* nWorld, const dVector& plane)
{
int j;
dVector m_minBox (-1000.0f, -1000.0f, -1000.0f);
dVector m_maxBox ( 1000.0f, 1000.0f, 1000.0f);
// get the transformation matrix that takes the plane to the world local space
m_rotation = dgGrammSchmidt(plane);
// build a unit grid in local space (this will be the shadow at projection of the collision aabb)
m_sphape[0] = dVector (0.0f, 1.0f, 1.0f);
m_sphape[1] = dVector (0.0f, -1.0f, 1.0f);
m_sphape[2] = dVector (0.0f, -1.0f, -1.0f);
m_sphape[3] = dVector (0.0f, 1.0f, -1.0f);
// save the plane
m_plane = plane;
m_attribute = 0;
m_faceIndices = 4;
for (j = 0; j < 4; j ++) {
m_indexArray[j] = j;
}
// create a Newton user collision
m_collision = NewtonCreateUserMeshCollision (nWorld, &m_minBox[0], &m_maxBox[0], this,
PlaneCollisionCollideCallback, PlaneMeshCollisionRayHitCallback,
PlaneCollisionDestroyCallback);
}
~PlaneCollision(void)
{
}
static void PlaneCollisionDestroyCallback(void* userData)
{
PlaneCollision* me;
me = (PlaneCollision*) userData;
delete me;
}
static void PlaneCollisionCollideCallback (NewtonUserMeshCollisionCollideDesc* collideDesc)
{
float t;
float s;
dInt32 i;
dFloat dist;
PlaneCollision* me;
me = (PlaneCollision*) collideDesc->m_userData;
// get bounding bos of teh collidong objects
dVector p0 (collideDesc->m_boxP0[0], collideDesc->m_boxP0[1], collideDesc->m_boxP0[2]);
dVector p1 (collideDesc->m_boxP1[0], collideDesc->m_boxP1[1], collideDesc->m_boxP1[2]);
// if the support vetexs of the aabb is not intesection the plane teh there is not collision
dVector suportVertex ((me->m_plane.m_x > 0.0f) ? p0.m_x : p1.m_x,
(me->m_plane.m_y > 0.0f) ? p0.m_y : p1.m_y,
(me->m_plane.m_z > 0.0f) ? p0.m_z : p1.m_z);
dist = me->m_plane % suportVertex + me->m_plane.m_w;
// if support the lower support vertex is close enought to the plane the report
// a single grid on eteh plane below the AABB and porpostional of the size of the AABB
if (dist < 0.25f) {
// calculate the aabb center
dVector centre ((p1 + p0).Scale (0.5f));
//find the projection of center point over the plane
t = - (me->m_plane % centre + me->m_plane.m_w);
centre += me->m_plane.Scale (t);
//know calculate the scale factor
dVector size (p1 - p0);
s = max (size.m_x, max (size.m_y, size.m_z));
// initialize the callback data structure
collideDesc->m_faceCount = 1;
collideDesc->m_vertexStrideInBytes = sizeof (dVector);
collideDesc->m_userAttribute = &me->m_attribute;
collideDesc->m_faceIndexCount = &me->m_faceIndices;
collideDesc->m_faceVertexIndex = &me->m_indexArray[0];
collideDesc->m_vertex = &me->m_collisionVertex[0][0];
for (i = 0; i < 4; i ++) {
me->m_collisionVertex[i] = centre + me->m_rotation.RotateVector(me->m_sphape[i].Scale (s));
}
/*
if (debugLinesMode) {
dInt32 i;
if (hightMap_debugCount < (MAX_DEBUG_CONTACTS - 256)) {
dVector p0 (me->m_collisionVertex[threadNumber][3]);
for (i = 0; i < 4; i ++) {
hightMap_debugLines[hightMap_debugCount].p0 = p0;
hightMap_debugLines[hightMap_debugCount].p1 = dVector (me->m_collisionVertex[threadNumber][i]);
hightMap_debugLines[hightMap_debugCount].isContact = 0;
p0 = hightMap_debugLines[hightMap_debugCount].p1;
hightMap_debugCount ++;
}
}
}
*/
}
}
static dFloat PlaneMeshCollisionRayHitCallback (NewtonUserMeshCollisionRayHitDesc* rayDesc)
{
dFloat t;
PlaneCollision* me;
dVector q0 (rayDesc->m_p0[0], rayDesc->m_p0[1], rayDesc->m_p0[2]);
dVector q1 (rayDesc->m_p1[0], rayDesc->m_p1[1], rayDesc->m_p1[2]);
dVector dq (q1 - q0);
// calculate intersection between point lien a plane and return intesetion parameter
me = (PlaneCollision*) rayDesc->m_userData;
t = -(me->m_plane % q0 + me->m_plane.m_w) / (me->m_plane % dq);
if ((t > 0.0f) && (t < 1.0f)) {
rayDesc->m_normalOut[0] = me->m_plane[0];
rayDesc->m_normalOut[1] = me->m_plane[1];
rayDesc->m_normalOut[2] = me->m_plane[2];
} else {
t = -1.0f;
}
return t;
}
static void PlaneCollisionGetFacesInAABB (
void* me,
const dFloat* p0,
const dFloat* p1,
const dFloat** vertexArray,
int* vertexCount,
int* vertexStrideInBytes,
const int* indexList,
int maxIndexCount)
{
_ASSERTE (0);
}
dVector m_sphape[4];
dVector m_plane;
dMatrix m_rotation;
NewtonCollision* m_collision;
dInt32 m_attribute;
dInt32 m_faceIndices;
dInt32 m_indexArray[4];
dVector m_collisionVertex[4];
};
NewtonCollision* CreatePlaneCollidion (NewtonWorld* nWorld, const dVector& Plane)
{
PlaneCollision* plane;
plane = new PlaneCollision (nWorld, Plane);
return plane->m_collision;
}
here is how to use it
- Code: Select all
dVector plane (0, 1, 0, 0);
collision = CreatePlaneCollidion (nWorld, plane);
// create the level rigid body
m_level = NewtonCreateBody(nWorld, collision);
// release the collision tree (this way the application does not have to do book keeping of Newton objects
NewtonReleaseCollision (nWorld, collision);
.......