public bool GenerateContactCandidate(out ContactData contact)
{
//Generate contacts. This will just find one closest point using general supportmapping based systems like MPR and GJK.
//The collision system moves through a state machine depending on the latest collision generation result.
//At first, assume that the pair is completely separating. This is almost always the correct guess for new pairs.
//An extremely fast, warm-startable boolean GJK test can be performed. If it returns with nonintersection, we can quit and do nothing.
//If the initial boolean GJK test finds intersection, move onto a shallow contact test.
//The shallow contact test is a different kind of GJK test that finds the closest points between the shape pair. It's not as speedy as the boolean version.
//The algorithm is run between the marginless versions of the shapes, so that the closest points will form a contact somewhere in the space separating the cores.
//If the closest point system finds no intersection and returns the closest points, the state is changed to ShallowContact.
//If the closest point system finds intersection of the core shapes, then the state is changed to DeepContact, and MPR is run to determine contact information.
//The system tries to escape from deep contact to shallow contact, and from shallow contact to separated whenever possible.
//Here's the state flow:
//On Separated: BooleanGJK
// -Intersecting -> Go to ShallowContact.
// -Nonintersecting -> Do nothing.
//On ShallowContact: ClosestPointsGJK
// -Intersecting -> Go to DeepContact.
// -Nonintersecting: Go to Separated (without test) if squared distance > margin squared, otherwise use closest points to make contact.
//On DeepContact: MPR
// -Intersecting -> Go to ShallowContact if penetration depth < margin
// -Nonintersecting -> This case is rare, but not impossible. Go to Separated (without test).
previousState = state;
switch (state)
{
case CollisionState.Separated:
if (GJKToolbox.AreShapesIntersecting(collidableA.Shape, collidableB.Shape, ref collidableA.worldTransform, ref collidableB.worldTransform, ref localSeparatingAxis))
{
state = CollisionState.ShallowContact;
return DoShallowContact(out contact);
}
contact = new ContactData();
return false;
case CollisionState.ShallowContact:
return DoShallowContact(out contact);
case CollisionState.DeepContact:
return DoDeepContact(out contact);
}
contact = new ContactData();
return false;
}