[ODE] Space additions for dRay

David McClurg dmcclurg at pandemicstudios.com.au
Tue Aug 20 23:51:02 2002


Found a problem with the AABB setup.  Here's the fix...

int dcTriListCollider::CollideRay(dxGeom* RayGeom, int Flags, dContactGeom* Contacts, int Stride){
  dcAABBTreeCollider& Collider = AABBCollider;

  /* Get ray */
  dVector3 o, d;
  dGeomRayGet(RayGeom, o, d);
  dcVector3 RayOrigin(o), RayDirection(d);
  dReal RayLength = dGeomRayGetLength(RayGeom);

  /* Make AABB */
  dReal tempAABB[6];
  dAABBRay(RayGeom, tempAABB);
  Opcode::CollisionAABB Box;
  Box.mExtents.x = (tempAABB[1]-tempAABB[0])/2;
  Box.mExtents.y = (tempAABB[3]-tempAABB[2])/2;
  Box.mExtents.z = (tempAABB[5]-tempAABB[4])/2;
  Box.mCenter.x = tempAABB[0] + Box.mExtents.x;
  Box.mCenter.y = tempAABB[2] + Box.mExtents.y;
  Box.mCenter.z = tempAABB[4] + Box.mExtents.z;

  /* Intersect */
  Collider.Collide((Opcode::AABBNoLeafTree*)BVTree.GetTree(), Box);

  /* Retrieve data */
  int TriangleIDCount = Collider.Contacts.size();

  if (TriangleIDCount != 0){
    dArray<int>& TriangleIDs = Collider.Contacts;

    Callback(RayGeom, TriangleIDs);

    /* Creating minimum contacts */
    int OutTriCount = 0;
    for (int i = 0; i < TriangleIDCount; i++){
      const int& TriIndex = TriangleIDs[i];

      if (!Valid(RayGeom, TriIndex)) continue;

      const dcVector3& v0 = Vertices[Indices[TriIndex * 3 + 0]];
      const dcVector3& v1 = Vertices[Indices[TriIndex * 3 + 1]];
      const dcVector3& v2 = Vertices[Indices[TriIndex * 3 + 2]];

      dcPlane TriPlane(v0, v1, v2);
      const dcVector3& ContactNormal = TriPlane.Normal;

      dReal Denom = ContactNormal.DotProduct(RayDirection);
      if (dFabs(Denom) < 0.00001f){
        continue;	// Ray never hits
      }

      dReal ContactDepth = ContactNormal.DotProduct(RayOrigin);
      ContactDepth = (TriPlane.Distance - ContactDepth) / Denom;
      if (ContactDepth < 0 || ContactDepth > RayLength){
        continue;	// Ray hits but not within boundaries
      }

      const dcVector3 ContactPos = RayOrigin + RayDirection * ContactDepth;

      // Inside triangle?
      int Index;
      for (Index = 0; Index < 3; Index++){
        const dcVector3& v0 = Vertices[Indices[TriIndex * 3 + Index]];
        const dcVector3& v1 = Vertices[Indices[TriIndex * 3 + (Index + 1) % 3]];
        dcPlane Plane(v0, v1, v1 - TriPlane.Normal);

        if (!Plane.Contains(ContactPos)){
          break;
        }
      }
      if (Index == 3){
        dContactGeom& OutContact = *Contacts;
        if (OutTriCount == 0 || ContactDepth < OutContact.depth) {
          ((dcVector3&)OutContact.pos) = ContactPos;
          ((dcVector3&)OutContact.normal) = ContactNormal;
          OutContact.depth = ContactDepth;
          OutTriCount = 1;
        }
      }
    }

    if (OutTriCount != 0){
      dContactGeom& OutContact = *Contacts;
      OutContact.g1 = RayGeom;
      OutContact.g2 = Geometry;
#ifdef GENERATEBODIES
      OutContact.b1 = dGeomGetBody(RayGeom);
      OutContact.b2 = dGeomGetBody(Geometry);
#endif	//GENERATEBODIES
      return 1;
    }
    else return 0;
  }
  else return 0;
}