Added specialized capsule-capsule collider. Should improve ragdoll collision performance

See also http://bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=3930
To disable it, define BT_DISABLE_CAPSULE_CAPSULE_COLLIDER in the build system
This commit is contained in:
erwin.coumans
2009-08-20 21:08:38 +00:00
parent bbeac75d93
commit c6493bb049

View File

@@ -13,6 +13,11 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
///Specialized capsule-capsule collision algorithm has been added for Bullet 2.75 release to increase ragdoll performance
///If you experience problems with capsule-capsule collision, try to define BT_DISABLE_CAPSULE_CAPSULE_COLLIDER and report it in the Bullet forums
///with reproduction case
//define BT_DISABLE_CAPSULE_CAPSULE_COLLIDER 1
#include "btConvexConvexAlgorithm.h"
//#include <stdio.h>
@@ -20,6 +25,9 @@ subject to the following restrictions:
#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "BulletCollision/CollisionShapes/btConvexShape.h"
#include "BulletCollision/CollisionShapes/btCapsuleShape.h"
#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
@@ -43,9 +51,128 @@ subject to the following restrictions:
///////////
static SIMD_FORCE_INLINE void segmentsClosestPoints(
btVector3& ptsVector,
btVector3& offsetA,
btVector3& offsetB,
btScalar& tA, btScalar& tB,
const btVector3& translation,
const btVector3& dirA, btScalar hlenA,
const btVector3& dirB, btScalar hlenB )
{
// compute the parameters of the closest points on each line segment
btScalar dirA_dot_dirB = btDot(dirA,dirB);
btScalar dirA_dot_trans = btDot(dirA,translation);
btScalar dirB_dot_trans = btDot(dirB,translation);
btScalar denom = 1.0f - dirA_dot_dirB * dirA_dot_dirB;
if ( denom == 0.0f ) {
tA = 0.0f;
} else {
tA = ( dirA_dot_trans - dirB_dot_trans * dirA_dot_dirB ) / denom;
if ( tA < -hlenA )
tA = -hlenA;
else if ( tA > hlenA )
tA = hlenA;
}
tB = tA * dirA_dot_dirB - dirB_dot_trans;
if ( tB < -hlenB ) {
tB = -hlenB;
tA = tB * dirA_dot_dirB + dirA_dot_trans;
if ( tA < -hlenA )
tA = -hlenA;
else if ( tA > hlenA )
tA = hlenA;
} else if ( tB > hlenB ) {
tB = hlenB;
tA = tB * dirA_dot_dirB + dirA_dot_trans;
if ( tA < -hlenA )
tA = -hlenA;
else if ( tA > hlenA )
tA = hlenA;
}
// compute the closest points relative to segment centers.
offsetA = dirA * tA;
offsetB = dirB * tB;
ptsVector = translation - offsetA + offsetB;
}
static SIMD_FORCE_INLINE btScalar capsuleCapsuleDistance(
btVector3& normalOnB,
btVector3& pointOnB,
btScalar capsuleLengthA,
btScalar capsuleRadiusA,
btScalar capsuleLengthB,
btScalar capsuleRadiusB,
int capsuleAxisA,
int capsuleAxisB,
const btTransform& transformA,
const btTransform& transformB,
btScalar distanceThreshold )
{
btVector3 directionA = transformA.getBasis().getColumn(capsuleAxisA);
btVector3 translationA = transformA.getOrigin();
btVector3 directionB = transformB.getBasis().getColumn(capsuleAxisB);
btVector3 translationB = transformB.getOrigin();
// translation between centers
btVector3 translation = translationB - translationA;
// compute the closest points of the capsule line segments
btVector3 ptsVector; // the vector between the closest points
btVector3 offsetA, offsetB; // offsets from segment centers to their closest points
btScalar tA, tB; // parameters on line segment
segmentsClosestPoints( ptsVector, offsetA, offsetB, tA, tB, translation,
directionA, capsuleLengthA, directionB, capsuleLengthB );
btScalar distance = ptsVector.length() - capsuleRadiusA - capsuleRadiusB;
if ( distance > distanceThreshold )
return distance;
btScalar lenSqr = ptsVector.length2();
if (lenSqr<= (SIMD_EPSILON*SIMD_EPSILON))
{
//degenerate case where 2 capsules are likely at the same location: take a vector tangential to 'directionA'
btVector3 q;
btPlaneSpace1(directionA,normalOnB,q);
} else
{
// compute the contact normal
normalOnB = ptsVector*-btRecipSqrt(lenSqr);
}
pointOnB = transformB.getOrigin()+offsetB + normalOnB * capsuleRadiusB;
return distance;
}
//////////
@@ -155,6 +282,7 @@ struct btPerturbedContactResult : public btManifoldResult
extern btScalar gContactBreakingThreshold;
//
// Convex-Convex collision algorithm
//
@@ -176,6 +304,33 @@ void btConvexConvexAlgorithm ::processCollision (btCollisionObject* body0,btColl
btConvexShape* min0 = static_cast<btConvexShape*>(body0->getCollisionShape());
btConvexShape* min1 = static_cast<btConvexShape*>(body1->getCollisionShape());
btVector3 normalOnB;
btVector3 pointOnBWorld;
#ifndef BT_DISABLE_CAPSULE_CAPSULE_COLLIDER
if ((min0->getShapeType() == CAPSULE_SHAPE_PROXYTYPE) && (min1->getShapeType() == CAPSULE_SHAPE_PROXYTYPE))
{
btCapsuleShape* capsuleA = (btCapsuleShape*) min0;
btCapsuleShape* capsuleB = (btCapsuleShape*) min1;
btVector3 localScalingA = capsuleA->getLocalScaling();
btVector3 localScalingB = capsuleB->getLocalScaling();
btScalar threshold = m_manifoldPtr->getContactBreakingThreshold();
btScalar dist = capsuleCapsuleDistance(normalOnB, pointOnBWorld,capsuleA->getHalfHeight(),capsuleA->getRadius(),
capsuleB->getHalfHeight(),capsuleB->getRadius(),capsuleA->getUpAxis(),capsuleB->getUpAxis(),
body0->getWorldTransform(),body1->getWorldTransform(),threshold);
if (dist<threshold)
{
btAssert(normalOnB.length2()>=(SIMD_EPSILON*SIMD_EPSILON));
resultOut->addContactPoint(normalOnB,pointOnBWorld,dist);
}
resultOut->refreshContactPoints();
return;
}
#endif //BT_DISABLE_CAPSULE_CAPSULE_COLLIDER
#ifdef USE_SEPDISTANCE_UTIL2
m_sepDistance.updateSeparatingDistance(body0->getWorldTransform(),body1->getWorldTransform());
if (!dispatchInfo.m_useConvexConservativeDistanceUtil || m_sepDistance.getConservativeSeparatingDistance()<=0.f)