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:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user