Fix in some degenerate GJK configuration: once a degenerate GJK case is detected, without valid EPA penetration, use a second GJK run without margin.

Thanks to Jacob Langford for the report:http://code.google.com/p/bullet/issues/detail?id=250
This commit is contained in:
erwin.coumans
2009-07-09 22:10:27 +00:00
parent dc4180f1ce
commit d9ad88aa7a
2 changed files with 36 additions and 0 deletions

View File

@@ -36,6 +36,8 @@ bool btGjkEpaPenetrationDepthSolver::calcPenDepth( btSimplexSolverInterface& sim
btVector3 guessVector(transformA.getOrigin()-transformB.getOrigin());
btGjkEpaSolver2::sResults results;
if(btGjkEpaSolver2::Penetration(pConvexA,transformA,
pConvexB,transformB,
guessVector,results))
@@ -46,7 +48,15 @@ bool btGjkEpaPenetrationDepthSolver::calcPenDepth( btSimplexSolverInterface& sim
wWitnessOnA = results.witnesses[0];
wWitnessOnB = results.witnesses[1];
return true;
} else
{
if(btGjkEpaSolver2::Distance(pConvexA,transformA,pConvexB,transformB,guessVector,results))
{
wWitnessOnA = results.witnesses[0];
wWitnessOnB = results.witnesses[1];
return false;
}
}
return false;
}

View File

@@ -324,6 +324,32 @@ void btGjkPairDetector::getClosestPoints(const ClosestPointInput& input,Result&
}
} else
{
///this is another degenerate case, where the initial GJK calculation reports a degenerate case
///EPA reports no penetration, and the second GJK (using the supporting vector without margin)
///reports a valid positive distance. Use the results of the second GJK instead of failing.
///thanks to Jacob.Langford for the reproduction case
///http://code.google.com/p/bullet/issues/detail?id=250
btVector3 tmpNormalInB = tmpPointOnA - tmpPointOnB;
btScalar lenSqr = tmpNormalInB.length2();
if (lenSqr > (SIMD_EPSILON*SIMD_EPSILON))
{
tmpNormalInB /= btSqrt(lenSqr);
btScalar distance2 = (tmpPointOnA-tmpPointOnB).length();
//only replace valid distances when the distance is less
if (!isValid || (distance2 < distance))
{
distance = distance2;
pointOnA = tmpPointOnA;
pointOnB = tmpPointOnB;
normalInB = tmpNormalInB;
isValid = true;
m_lastUsedMethod = 6;
} else
{
}
}
m_lastUsedMethod = 5;
}