How can I make a plane collision?

A place to discuss everything related to Newton Dynamics.

Moderators: Sascha Willems, walaber

How can I make a plane collision?

Postby Julio Jerez » Thu Mar 29, 2007 2:21 am

Plane collision are collision primitive with very little practical value, as such we do not spend time implementation such usesless objects.
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);
              .......

Julio Jerez
Moderator
Moderator
 
Posts: 11147
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Return to General Discussion

Who is online

Users browsing this forum: No registered users and 2 guests