Code: Select all
//
// sphere [P, v, r].
// convex object [].
// probe limit : tmax
// Collision result : [Ncoll, tcoll, dcoll]
// Ncoll : normal of collision
// tcoll : time of collision
// dcoll : distance between sphere and convex object (negative -> intersection).
//
bool Collide(const Vector& P, const Vector& V, const Vector& r, const ConvexObject& Convex, float tmax, Vector& Ncoll, float& tcoll, float& dcoll)
{
const float search_tolerance = 1.0E-8f;
const float contact_tolerance = 1.0E-5f;
while (1)
{
bool contained; // is the point contained in the convex shape (only of convex shape is a closed volume).
Vector Q = Convex.ClosestPoint(P, contained); // closest point on the convex object from sphere centre.
Vector PQ = (P - Q);
float d2 = (PQ * PQ);
// intersection
if (d2 <= (r*r))
{
float sign = (contained)? -1.0f : 1.0f;
float d = sqrt(d2) * sign;
tcoll = 0.0f;
Ncoll = PQ / d;
dcoll = (d - r); // distance of the sphere to convex shape (negative means intersection)
}
Vector N = PQ / sqrt(d2); // normal of plane (normalised)
float denom = (V * N);
if(denom < search_tolerance) return false; // sphere behind the plane -> no collision
float numer = (r - (PQ * N));
float t = numer / denom;
if (t < 0.0f || t > tmax) return false; // time to collision to the plane. out of bounds -> no collision
// point of contact on the plane
Vector C = (P + V * t) - (N * r);
// delta from the closest point
Vector H = (C - Q);
float delta_squared = (H * H);
// the closest point on the convex object is out collision point.
// we have found our contact.
if(delta_squared < (contact_tolerance * contact_tolerance))
{
tcoll = t;
Ncoll = N;
dcoll = (H * N); // distance of sphere to the convex shape surface (signed)
return true;
}
}
}
That algo should be quite similar to the swept GJK, only you'd be working with closest points for each iterations.
Also, the end condition isn't great, especially when the incident angle is very shallow. I think using the deviation from the plane normals between iterations should work better. Same problem as with GJK (working with tolerances).