Fix issues with GJK algorithm

This commit is contained in:
Daniel Chappuis 2017-09-09 15:37:55 +02:00
parent 8cb2ec7e17
commit 709bed3cec
2 changed files with 8 additions and 16 deletions

View File

@ -66,8 +66,6 @@ GJKAlgorithm::GJKResult GJKAlgorithm::testCollision(NarrowPhaseInfo* narrowPhase
const ConvexShape* shape1 = static_cast<const ConvexShape*>(narrowPhaseInfo->collisionShape1); const ConvexShape* shape1 = static_cast<const ConvexShape*>(narrowPhaseInfo->collisionShape1);
const ConvexShape* shape2 = static_cast<const ConvexShape*>(narrowPhaseInfo->collisionShape2); const ConvexShape* shape2 = static_cast<const ConvexShape*>(narrowPhaseInfo->collisionShape2);
bool isPolytopeShape = shape1->isPolyhedron() && shape2->isPolyhedron();
// Get the local-space to world-space transforms // Get the local-space to world-space transforms
const Transform& transform1 = narrowPhaseInfo->shape1ToWorldTransform; const Transform& transform1 = narrowPhaseInfo->shape1ToWorldTransform;
const Transform& transform2 = narrowPhaseInfo->shape2ToWorldTransform; const Transform& transform2 = narrowPhaseInfo->shape2ToWorldTransform;
@ -95,6 +93,7 @@ GJKAlgorithm::GJKResult GJKAlgorithm::testCollision(NarrowPhaseInfo* narrowPhase
LastFrameCollisionInfo& lastFrameInfo = narrowPhaseInfo->overlappingPair->getLastFrameCollisionInfo(); LastFrameCollisionInfo& lastFrameInfo = narrowPhaseInfo->overlappingPair->getLastFrameCollisionInfo();
if (lastFrameInfo.isValid && lastFrameInfo.wasUsingGJK) { if (lastFrameInfo.isValid && lastFrameInfo.wasUsingGJK) {
v = lastFrameInfo.gjkSeparatingAxis; v = lastFrameInfo.gjkSeparatingAxis;
assert(v.lengthSquare() > decimal(0.000001));
} }
else { else {
v.setAllValues(0, 1, 0); v.setAllValues(0, 1, 0);
@ -140,8 +139,7 @@ GJKAlgorithm::GJKResult GJKAlgorithm::testCollision(NarrowPhaseInfo* narrowPhase
// Contact point has been found // Contact point has been found
contactFound = true; contactFound = true;
break;
return GJKResult::INTERPENETRATE;
} }
// Compute the point of the simplex closest to the origin // Compute the point of the simplex closest to the origin
@ -150,14 +148,7 @@ GJKAlgorithm::GJKResult GJKAlgorithm::testCollision(NarrowPhaseInfo* narrowPhase
// Contact point has been found // Contact point has been found
contactFound = true; contactFound = true;
break;
return GJKResult::INTERPENETRATE;
}
// Closest point is almost the origin, go to EPA algorithm
// Vector v to small to continue computing support points
if (v.lengthSquare() < MACHINE_EPSILON) {
return GJKResult::INTERPENETRATE;
} }
// Store and update the squared distance of the closest point // Store and update the squared distance of the closest point
@ -177,8 +168,7 @@ GJKAlgorithm::GJKResult GJKAlgorithm::testCollision(NarrowPhaseInfo* narrowPhase
break; break;
} }
} while((isPolytopeShape && !simplex.isFull()) || (!isPolytopeShape && !simplex.isFull() && } while(!simplex.isFull() && distSquare > MACHINE_EPSILON * simplex.getMaxLengthSquareOfAPoint());
distSquare > MACHINE_EPSILON * simplex.getMaxLengthSquareOfAPoint()));
if (contactFound && distSquare > MACHINE_EPSILON) { if (contactFound && distSquare > MACHINE_EPSILON) {
@ -203,7 +193,7 @@ GJKAlgorithm::GJKResult GJKAlgorithm::testCollision(NarrowPhaseInfo* narrowPhase
// Do not generate a contact point with zero normal length // Do not generate a contact point with zero normal length
if (normal.lengthSquare() < MACHINE_EPSILON) { if (normal.lengthSquare() < MACHINE_EPSILON) {
return GJKResult::INTERPENETRATE; return GJKResult::SEPARATED;
} }
if (reportContacts) { if (reportContacts) {
@ -219,7 +209,7 @@ GJKAlgorithm::GJKResult GJKAlgorithm::testCollision(NarrowPhaseInfo* narrowPhase
return GJKResult::COLLIDE_IN_MARGIN; return GJKResult::COLLIDE_IN_MARGIN;
} }
return GJKResult::SEPARATED; return GJKResult::INTERPENETRATE;
} }

View File

@ -79,6 +79,8 @@ struct LastFrameCollisionInfo {
wasColliding = false; wasColliding = false;
wasUsingSAT = false; wasUsingSAT = false;
wasUsingGJK = false; wasUsingGJK = false;
gjkSeparatingAxis = Vector3(0, 1, 0);
} }
}; };