public static bool TestOBBOBB(CollisionOBB a, CollisionOBB b, CollisionParms parms)
 {
     if (MO.DoLog)
     MO.Log("TestOBBOBB Entering: a {0} b {1}", a, b);
     if (TestOBBOBBInternal(a, b)) {
     Vector3 n = b.center - a.center;
     // ??? Not right
     parms.SetNormPart(n);
     parms.SetNormObstacle(-n);
     if (MO.DoLog)
     MO.Log("TestOBBOBB Collided: n {0}", n);
     return true;
     }
     else
     return false;
 }
 public static bool TestCollisionSphereOBB(CollisionShape s1, CollisionShape s2,
                                   CollisionParms parms)
 {
     CollisionSphere x1 = (CollisionSphere)s1;
     CollisionOBB x2 = (CollisionOBB)s2;
     Vector3 closest;
     if (TestSphereOBB(x1, x2, out closest)) {
     Vector3 n = s1.center - closest;
     parms.SetNormPart(n);
     // ??? This isn't the correct value of the normal
     parms.SetNormObstacle(-n);
     return true;
     }
     else
     return false;
 }
 //////////////////////////////////////////////////////////////////////
 //
 // The per-shape-pair collision predicates.  Since collisions
 // themselves are much less frequent than the tests for
 // collisions, all the effort is in making the tests fast, and
 // if we have to repeat the same calculations in the event of
 // a collision, it's still a net savings if it makes the tests
 // cheaper
 //
 //////////////////////////////////////////////////////////////////////
 public static bool TestCollisionSphereSphere(CollisionShape s1, CollisionShape s2,
                                      CollisionParms parms)
 {
     CollisionSphere x1 = (CollisionSphere)s1;
     CollisionSphere x2 = (CollisionSphere)s2;
     Vector3 nS2 = s2.center - s1.center;
     if (x1.radius + x2.radius > nS2.Length) {
     Vector3 n = s2.center - s1.center;
     parms.SetNormPart(n);
     parms.SetNormObstacle(-n);
     return true;
     }
     else
     return false;
 }
 public static bool TestCollisionSphereCapsule(CollisionShape s1, CollisionShape s2,
                                       CollisionParms parms)
 {
     CollisionSphere x1 = (CollisionSphere)s1;
     CollisionCapsule x2 = (CollisionCapsule)s2;
     float rSum = x1.radius + x2.capRadius;
     if (SqDistPointSegment(x2.bottomcenter, x2.topcenter, x1.center) < rSum * rSum)
     {
     float t;
     Vector3 d;
     ClosestPtPointSegment(x1.center, x2.bottomcenter, x2.topcenter, out t, out d);
     Vector3 n = d - x1.center;
     parms.SetNormPart(n);
     parms.SetNormObstacle(-n);
     return true;
     }
     else
     return false;
 }
 public static bool TestCollisionSphereAABB(CollisionShape s1, CollisionShape s2,
                                     CollisionParms parms)
 {
     CollisionSphere x1 = (CollisionSphere)s1;
     CollisionAABB x2 = (CollisionAABB)s2;
     float d = SqDistPointAABB(x1.center, x2);
     if (d < Square(x1.radius)) {
     Vector3 n;
     ClosestPtPointAABB(x1.center, x2, out n);
     n -= x1.center;
     parms.SetNormPart(n);
     // ??? This isn't the correct value of the normal
     parms.SetNormObstacle(-n);
     return true;
     }
     else
     return false;
 }
 public static bool TestCollisionAABBAABB(CollisionShape s1, CollisionShape s2,
                                   CollisionParms parms)
 {
     CollisionAABB x1 = (CollisionAABB)s1;
     CollisionAABB x2 = (CollisionAABB)s2;
     if (TestAABBAABB(x1, x2)) {
     Vector3 n = x2.center - x1.center;
     parms.SetNormPart(n);
     // ??? This isn't the correct value of the normal
     parms.SetNormObstacle(-n);
     return true;
     }
     else
     return false;
 }
        public static bool TestCapsuleOBB(CollisionCapsule a, CollisionOBB b, CollisionParms parms)
        {
            SegOBBParams obbParms = new SegOBBParams(true);
            Segment s = Segment.SegmentFromStartAndEnd(a.bottomcenter, a.topcenter);
            if (SqrDistSegOBB(s, b, obbParms) < a.capRadius * a.capRadius) {
            // If parms.pfLParam == 0, closest is bottomcenter; if == 1,
            // closest is topcenter.

            Vector3 d = a.bottomcenter + obbParms.pfLParam * s.direction;
            // pfBVec is relative to the center of the box, but in box
            // coords.
            Vector3 f = b.center;
            for (int i=0; i<3; i++)
            f += obbParms.pfBVec[i] * b.axes[i];
            Vector3 n = f - d;
            parms.SetNormPart(n);
            parms.SetNormObstacle(-n);
            if (MO.DoLog) {
            MO.Log(" TestCapsuleOBB: pfLParam {0}, pfBVec {1}", obbParms.pfLParam, obbParms.pfBVec);
            MO.Log(" TestCapsuleOBB: d {0}, f {1}", f, d);
            MO.Log(" -n {0}", -n);
            }
            return true;
            }
            else
            return false;
        }
 public static bool TestCapsuleCapsule(CollisionCapsule c1, CollisionCapsule c2,
                               CollisionParms parms)
 {
     // Compute (squared) distance between the inner structures of the capsules
     float s, t;
     Vector3 p1, p2;
     float d = ClosestPtSegmentSegment(c1.bottomcenter, c1.topcenter,
                               c2.bottomcenter, c2.topcenter,
                               out s, out t, out p1, out p2);
     float r = c1.capRadius + c2.capRadius;
     Vector3 n = p2 - p1;
     parms.SetNormPart(n);
     parms.SetNormObstacle(-n);
     return d < r * r;
 }