00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00019
00020
00021 #include "btConvexConvexAlgorithm.h"
00022
00023
00024 #include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h"
00025 #include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
00026 #include "BulletCollision/CollisionDispatch/btCollisionObject.h"
00027 #include "BulletCollision/CollisionShapes/btConvexShape.h"
00028 #include "BulletCollision/CollisionShapes/btCapsuleShape.h"
00029
00030
00031 #include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h"
00032 #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
00033 #include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
00034 #include "BulletCollision/CollisionShapes/btBoxShape.h"
00035 #include "BulletCollision/CollisionDispatch/btManifoldResult.h"
00036
00037 #include "BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h"
00038 #include "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h"
00039 #include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
00040 #include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h"
00041
00042
00043
00044 #include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
00045 #include "BulletCollision/CollisionShapes/btSphereShape.h"
00046
00047 #include "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h"
00048
00049 #include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h"
00050 #include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h"
00051
00052
00053
00055
00056
00057
00058 static SIMD_FORCE_INLINE void segmentsClosestPoints(
00059 btVector3& ptsVector,
00060 btVector3& offsetA,
00061 btVector3& offsetB,
00062 btScalar& tA, btScalar& tB,
00063 const btVector3& translation,
00064 const btVector3& dirA, btScalar hlenA,
00065 const btVector3& dirB, btScalar hlenB )
00066 {
00067
00068
00069 btScalar dirA_dot_dirB = btDot(dirA,dirB);
00070 btScalar dirA_dot_trans = btDot(dirA,translation);
00071 btScalar dirB_dot_trans = btDot(dirB,translation);
00072
00073 btScalar denom = 1.0f - dirA_dot_dirB * dirA_dot_dirB;
00074
00075 if ( denom == 0.0f ) {
00076 tA = 0.0f;
00077 } else {
00078 tA = ( dirA_dot_trans - dirB_dot_trans * dirA_dot_dirB ) / denom;
00079 if ( tA < -hlenA )
00080 tA = -hlenA;
00081 else if ( tA > hlenA )
00082 tA = hlenA;
00083 }
00084
00085 tB = tA * dirA_dot_dirB - dirB_dot_trans;
00086
00087 if ( tB < -hlenB ) {
00088 tB = -hlenB;
00089 tA = tB * dirA_dot_dirB + dirA_dot_trans;
00090
00091 if ( tA < -hlenA )
00092 tA = -hlenA;
00093 else if ( tA > hlenA )
00094 tA = hlenA;
00095 } else if ( tB > hlenB ) {
00096 tB = hlenB;
00097 tA = tB * dirA_dot_dirB + dirA_dot_trans;
00098
00099 if ( tA < -hlenA )
00100 tA = -hlenA;
00101 else if ( tA > hlenA )
00102 tA = hlenA;
00103 }
00104
00105
00106
00107 offsetA = dirA * tA;
00108 offsetB = dirB * tB;
00109
00110 ptsVector = translation - offsetA + offsetB;
00111 }
00112
00113
00114 static SIMD_FORCE_INLINE btScalar capsuleCapsuleDistance(
00115 btVector3& normalOnB,
00116 btVector3& pointOnB,
00117 btScalar capsuleLengthA,
00118 btScalar capsuleRadiusA,
00119 btScalar capsuleLengthB,
00120 btScalar capsuleRadiusB,
00121 int capsuleAxisA,
00122 int capsuleAxisB,
00123 const btTransform& transformA,
00124 const btTransform& transformB,
00125 btScalar distanceThreshold )
00126 {
00127 btVector3 directionA = transformA.getBasis().getColumn(capsuleAxisA);
00128 btVector3 translationA = transformA.getOrigin();
00129 btVector3 directionB = transformB.getBasis().getColumn(capsuleAxisB);
00130 btVector3 translationB = transformB.getOrigin();
00131
00132
00133
00134 btVector3 translation = translationB - translationA;
00135
00136
00137
00138 btVector3 ptsVector;
00139
00140 btVector3 offsetA, offsetB;
00141 btScalar tA, tB;
00142
00143 segmentsClosestPoints( ptsVector, offsetA, offsetB, tA, tB, translation,
00144 directionA, capsuleLengthA, directionB, capsuleLengthB );
00145
00146 btScalar distance = ptsVector.length() - capsuleRadiusA - capsuleRadiusB;
00147
00148 if ( distance > distanceThreshold )
00149 return distance;
00150
00151 btScalar lenSqr = ptsVector.length2();
00152 if (lenSqr<= (SIMD_EPSILON*SIMD_EPSILON))
00153 {
00154
00155 btVector3 q;
00156 btPlaneSpace1(directionA,normalOnB,q);
00157 } else
00158 {
00159
00160 normalOnB = ptsVector*-btRecipSqrt(lenSqr);
00161 }
00162 pointOnB = transformB.getOrigin()+offsetB + normalOnB * capsuleRadiusB;
00163
00164 return distance;
00165 }
00166
00167
00168
00169
00170
00171
00172
00174
00175
00176
00177
00178
00179 btConvexConvexAlgorithm::CreateFunc::CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver)
00180 {
00181 m_numPerturbationIterations = 0;
00182 m_minimumPointsPerturbationThreshold = 3;
00183 m_simplexSolver = simplexSolver;
00184 m_pdSolver = pdSolver;
00185 }
00186
00187 btConvexConvexAlgorithm::CreateFunc::~CreateFunc()
00188 {
00189 }
00190
00191 btConvexConvexAlgorithm::btConvexConvexAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver,int numPerturbationIterations, int minimumPointsPerturbationThreshold)
00192 : btActivatingCollisionAlgorithm(ci,body0,body1),
00193 m_simplexSolver(simplexSolver),
00194 m_pdSolver(pdSolver),
00195 m_ownManifold (false),
00196 m_manifoldPtr(mf),
00197 m_lowLevelOfDetail(false),
00198 #ifdef USE_SEPDISTANCE_UTIL2
00199 m_sepDistance((static_cast<btConvexShape*>(body0->getCollisionShape()))->getAngularMotionDisc(),
00200 (static_cast<btConvexShape*>(body1->getCollisionShape()))->getAngularMotionDisc()),
00201 #endif
00202 m_numPerturbationIterations(numPerturbationIterations),
00203 m_minimumPointsPerturbationThreshold(minimumPointsPerturbationThreshold)
00204 {
00205 (void)body0;
00206 (void)body1;
00207 }
00208
00209
00210
00211
00212 btConvexConvexAlgorithm::~btConvexConvexAlgorithm()
00213 {
00214 if (m_ownManifold)
00215 {
00216 if (m_manifoldPtr)
00217 m_dispatcher->releaseManifold(m_manifoldPtr);
00218 }
00219 }
00220
00221 void btConvexConvexAlgorithm ::setLowLevelOfDetail(bool useLowLevel)
00222 {
00223 m_lowLevelOfDetail = useLowLevel;
00224 }
00225
00226
00227 struct btPerturbedContactResult : public btManifoldResult
00228 {
00229 btManifoldResult* m_originalManifoldResult;
00230 btTransform m_transformA;
00231 btTransform m_transformB;
00232 btTransform m_unPerturbedTransform;
00233 bool m_perturbA;
00234 btIDebugDraw* m_debugDrawer;
00235
00236
00237 btPerturbedContactResult(btManifoldResult* originalResult,const btTransform& transformA,const btTransform& transformB,const btTransform& unPerturbedTransform,bool perturbA,btIDebugDraw* debugDrawer)
00238 :m_originalManifoldResult(originalResult),
00239 m_transformA(transformA),
00240 m_transformB(transformB),
00241 m_unPerturbedTransform(unPerturbedTransform),
00242 m_perturbA(perturbA),
00243 m_debugDrawer(debugDrawer)
00244 {
00245 }
00246 virtual ~ btPerturbedContactResult()
00247 {
00248 }
00249
00250 virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar orgDepth)
00251 {
00252 btVector3 endPt,startPt;
00253 btScalar newDepth;
00254 btVector3 newNormal;
00255
00256 if (m_perturbA)
00257 {
00258 btVector3 endPtOrg = pointInWorld + normalOnBInWorld*orgDepth;
00259 endPt = (m_unPerturbedTransform*m_transformA.inverse())(endPtOrg);
00260 newDepth = (endPt - pointInWorld).dot(normalOnBInWorld);
00261 startPt = endPt+normalOnBInWorld*newDepth;
00262 } else
00263 {
00264 endPt = pointInWorld + normalOnBInWorld*orgDepth;
00265 startPt = (m_unPerturbedTransform*m_transformB.inverse())(pointInWorld);
00266 newDepth = (endPt - startPt).dot(normalOnBInWorld);
00267
00268 }
00269
00270
00271 #ifdef DEBUG_CONTACTS
00272 m_debugDrawer->drawLine(startPt,endPt,btVector3(1,0,0));
00273 m_debugDrawer->drawSphere(startPt,0.05,btVector3(0,1,0));
00274 m_debugDrawer->drawSphere(endPt,0.05,btVector3(0,0,1));
00275 #endif //DEBUG_CONTACTS
00276
00277
00278 m_originalManifoldResult->addContactPoint(normalOnBInWorld,startPt,newDepth);
00279 }
00280
00281 };
00282
00283 extern btScalar gContactBreakingThreshold;
00284
00285
00286
00287
00288
00289 void btConvexConvexAlgorithm ::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
00290 {
00291
00292 if (!m_manifoldPtr)
00293 {
00294
00295 m_manifoldPtr = m_dispatcher->getNewManifold(body0,body1);
00296 m_ownManifold = true;
00297 }
00298 resultOut->setPersistentManifold(m_manifoldPtr);
00299
00300
00301
00302
00303
00304 btConvexShape* min0 = static_cast<btConvexShape*>(body0->getCollisionShape());
00305 btConvexShape* min1 = static_cast<btConvexShape*>(body1->getCollisionShape());
00306
00307 btVector3 normalOnB;
00308 btVector3 pointOnBWorld;
00309 #ifndef BT_DISABLE_CAPSULE_CAPSULE_COLLIDER
00310 if ((min0->getShapeType() == CAPSULE_SHAPE_PROXYTYPE) && (min1->getShapeType() == CAPSULE_SHAPE_PROXYTYPE))
00311 {
00312 btCapsuleShape* capsuleA = (btCapsuleShape*) min0;
00313 btCapsuleShape* capsuleB = (btCapsuleShape*) min1;
00314 btVector3 localScalingA = capsuleA->getLocalScaling();
00315 btVector3 localScalingB = capsuleB->getLocalScaling();
00316
00317 btScalar threshold = m_manifoldPtr->getContactBreakingThreshold();
00318
00319 btScalar dist = capsuleCapsuleDistance(normalOnB, pointOnBWorld,capsuleA->getHalfHeight(),capsuleA->getRadius(),
00320 capsuleB->getHalfHeight(),capsuleB->getRadius(),capsuleA->getUpAxis(),capsuleB->getUpAxis(),
00321 body0->getWorldTransform(),body1->getWorldTransform(),threshold);
00322
00323 if (dist<threshold)
00324 {
00325 btAssert(normalOnB.length2()>=(SIMD_EPSILON*SIMD_EPSILON));
00326 resultOut->addContactPoint(normalOnB,pointOnBWorld,dist);
00327 }
00328 resultOut->refreshContactPoints();
00329 return;
00330 }
00331 #endif //BT_DISABLE_CAPSULE_CAPSULE_COLLIDER
00332
00333
00334 #ifdef USE_SEPDISTANCE_UTIL2
00335 if (dispatchInfo.m_useConvexConservativeDistanceUtil)
00336 {
00337 m_sepDistance.updateSeparatingDistance(body0->getWorldTransform(),body1->getWorldTransform());
00338 }
00339
00340 if (!dispatchInfo.m_useConvexConservativeDistanceUtil || m_sepDistance.getConservativeSeparatingDistance()<=0.f)
00341 #endif
00342
00343 {
00344
00345
00346 btGjkPairDetector::ClosestPointInput input;
00347
00348 btGjkPairDetector gjkPairDetector(min0,min1,m_simplexSolver,m_pdSolver);
00349
00350 gjkPairDetector.setMinkowskiA(min0);
00351 gjkPairDetector.setMinkowskiB(min1);
00352
00353 #ifdef USE_SEPDISTANCE_UTIL2
00354 if (dispatchInfo.m_useConvexConservativeDistanceUtil)
00355 {
00356 input.m_maximumDistanceSquared = BT_LARGE_FLOAT;
00357 } else
00358 #endif //USE_SEPDISTANCE_UTIL2
00359 {
00360 input.m_maximumDistanceSquared = min0->getMargin() + min1->getMargin() + m_manifoldPtr->getContactBreakingThreshold();
00361 input.m_maximumDistanceSquared*= input.m_maximumDistanceSquared;
00362 }
00363
00364 input.m_stackAlloc = dispatchInfo.m_stackAllocator;
00365 input.m_transformA = body0->getWorldTransform();
00366 input.m_transformB = body1->getWorldTransform();
00367
00368 gjkPairDetector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw);
00369
00370
00371
00372 #ifdef USE_SEPDISTANCE_UTIL2
00373 btScalar sepDist = 0.f;
00374 if (dispatchInfo.m_useConvexConservativeDistanceUtil)
00375 {
00376 sepDist = gjkPairDetector.getCachedSeparatingDistance();
00377 if (sepDist>SIMD_EPSILON)
00378 {
00379 sepDist += dispatchInfo.m_convexConservativeDistanceThreshold;
00380
00381
00382 }
00383 }
00384 #endif //USE_SEPDISTANCE_UTIL2
00385
00386
00387
00388
00389 if (m_numPerturbationIterations && resultOut->getPersistentManifold()->getNumContacts() < m_minimumPointsPerturbationThreshold)
00390 {
00391
00392 int i;
00393 btVector3 v0,v1;
00394 btVector3 sepNormalWorldSpace;
00395
00396 sepNormalWorldSpace = gjkPairDetector.getCachedSeparatingAxis().normalized();
00397 btPlaneSpace1(sepNormalWorldSpace,v0,v1);
00398
00399
00400 bool perturbeA = true;
00401 const btScalar angleLimit = 0.125f * SIMD_PI;
00402 btScalar perturbeAngle;
00403 btScalar radiusA = min0->getAngularMotionDisc();
00404 btScalar radiusB = min1->getAngularMotionDisc();
00405 if (radiusA < radiusB)
00406 {
00407 perturbeAngle = gContactBreakingThreshold /radiusA;
00408 perturbeA = true;
00409 } else
00410 {
00411 perturbeAngle = gContactBreakingThreshold / radiusB;
00412 perturbeA = false;
00413 }
00414 if ( perturbeAngle > angleLimit )
00415 perturbeAngle = angleLimit;
00416
00417 btTransform unPerturbedTransform;
00418 if (perturbeA)
00419 {
00420 unPerturbedTransform = input.m_transformA;
00421 } else
00422 {
00423 unPerturbedTransform = input.m_transformB;
00424 }
00425
00426 for ( i=0;i<m_numPerturbationIterations;i++)
00427 {
00428 if (v0.length2()>SIMD_EPSILON)
00429 {
00430 btQuaternion perturbeRot(v0,perturbeAngle);
00431 btScalar iterationAngle = i*(SIMD_2_PI/btScalar(m_numPerturbationIterations));
00432 btQuaternion rotq(sepNormalWorldSpace,iterationAngle);
00433
00434
00435 if (perturbeA)
00436 {
00437 input.m_transformA.setBasis( btMatrix3x3(rotq.inverse()*perturbeRot*rotq)*body0->getWorldTransform().getBasis());
00438 input.m_transformB = body1->getWorldTransform();
00439 #ifdef DEBUG_CONTACTS
00440 dispatchInfo.m_debugDraw->drawTransform(input.m_transformA,10.0);
00441 #endif //DEBUG_CONTACTS
00442 } else
00443 {
00444 input.m_transformA = body0->getWorldTransform();
00445 input.m_transformB.setBasis( btMatrix3x3(rotq.inverse()*perturbeRot*rotq)*body1->getWorldTransform().getBasis());
00446 #ifdef DEBUG_CONTACTS
00447 dispatchInfo.m_debugDraw->drawTransform(input.m_transformB,10.0);
00448 #endif
00449 }
00450
00451 btPerturbedContactResult perturbedResultOut(resultOut,input.m_transformA,input.m_transformB,unPerturbedTransform,perturbeA,dispatchInfo.m_debugDraw);
00452 gjkPairDetector.getClosestPoints(input,perturbedResultOut,dispatchInfo.m_debugDraw);
00453 }
00454
00455 }
00456 }
00457
00458
00459
00460 #ifdef USE_SEPDISTANCE_UTIL2
00461 if (dispatchInfo.m_useConvexConservativeDistanceUtil && (sepDist>SIMD_EPSILON))
00462 {
00463 m_sepDistance.initSeparatingDistance(gjkPairDetector.getCachedSeparatingAxis(),sepDist,body0->getWorldTransform(),body1->getWorldTransform());
00464 }
00465 #endif //USE_SEPDISTANCE_UTIL2
00466
00467
00468 }
00469
00470 if (m_ownManifold)
00471 {
00472 resultOut->refreshContactPoints();
00473 }
00474
00475 }
00476
00477
00478
00479 bool disableCcd = false;
00480 btScalar btConvexConvexAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
00481 {
00482 (void)resultOut;
00483 (void)dispatchInfo;
00485
00488 btScalar resultFraction = btScalar(1.);
00489
00490
00491 btScalar squareMot0 = (col0->getInterpolationWorldTransform().getOrigin() - col0->getWorldTransform().getOrigin()).length2();
00492 btScalar squareMot1 = (col1->getInterpolationWorldTransform().getOrigin() - col1->getWorldTransform().getOrigin()).length2();
00493
00494 if (squareMot0 < col0->getCcdSquareMotionThreshold() &&
00495 squareMot1 < col1->getCcdSquareMotionThreshold())
00496 return resultFraction;
00497
00498 if (disableCcd)
00499 return btScalar(1.);
00500
00501
00502
00503
00504
00505
00506
00507
00508
00510 {
00511 btConvexShape* convex0 = static_cast<btConvexShape*>(col0->getCollisionShape());
00512
00513 btSphereShape sphere1(col1->getCcdSweptSphereRadius());
00514 btConvexCast::CastResult result;
00515 btVoronoiSimplexSolver voronoiSimplex;
00516
00518 btGjkConvexCast ccd1( convex0 ,&sphere1,&voronoiSimplex);
00519
00520 if (ccd1.calcTimeOfImpact(col0->getWorldTransform(),col0->getInterpolationWorldTransform(),
00521 col1->getWorldTransform(),col1->getInterpolationWorldTransform(),result))
00522 {
00523
00524
00525
00526 if (col0->getHitFraction()> result.m_fraction)
00527 col0->setHitFraction( result.m_fraction );
00528
00529 if (col1->getHitFraction() > result.m_fraction)
00530 col1->setHitFraction( result.m_fraction);
00531
00532 if (resultFraction > result.m_fraction)
00533 resultFraction = result.m_fraction;
00534
00535 }
00536
00537
00538
00539
00540 }
00541
00543 {
00544 btConvexShape* convex1 = static_cast<btConvexShape*>(col1->getCollisionShape());
00545
00546 btSphereShape sphere0(col0->getCcdSweptSphereRadius());
00547 btConvexCast::CastResult result;
00548 btVoronoiSimplexSolver voronoiSimplex;
00549
00551 btGjkConvexCast ccd1(&sphere0,convex1,&voronoiSimplex);
00552
00553 if (ccd1.calcTimeOfImpact(col0->getWorldTransform(),col0->getInterpolationWorldTransform(),
00554 col1->getWorldTransform(),col1->getInterpolationWorldTransform(),result))
00555 {
00556
00557
00558
00559 if (col0->getHitFraction() > result.m_fraction)
00560 col0->setHitFraction( result.m_fraction);
00561
00562 if (col1->getHitFraction() > result.m_fraction)
00563 col1->setHitFraction( result.m_fraction);
00564
00565 if (resultFraction > result.m_fraction)
00566 resultFraction = result.m_fraction;
00567
00568 }
00569 }
00570
00571 return resultFraction;
00572
00573 }
00574