1 /* 2 Bullet Continuous Collision Detection and Physics Library 3 Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ 4 5 This software is provided 'as-is', without any express or implied warranty. 6 In no event will the authors be held liable for any damages arising from the use of this software. 7 Permission is granted to anyone to use this software for any purpose, 8 including commercial applications, and to alter it and redistribute it freely, 9 subject to the following restrictions: 10 11 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 3. This notice may not be removed or altered from any source distribution. 14 */ 15 16 #include "btCollisionWorld.h" 17 #include "btCollisionDispatcher.h" 18 #include "BulletCollision/CollisionDispatch/btCollisionObject.h" 19 #include "BulletCollision/CollisionShapes/btCollisionShape.h" 20 #include "BulletCollision/CollisionShapes/btConvexShape.h" 21 #include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h" 22 #include "BulletCollision/CollisionShapes/btSphereShape.h" //for raycasting 23 #include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h" //for raycasting 24 #include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h" 25 #include "BulletCollision/CollisionShapes/btCompoundShape.h" 26 #include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h" 27 #include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h" 28 #include "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h" 29 #include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" 30 #include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h" 31 #include "BulletCollision/BroadphaseCollision/btDbvt.h" 32 #include "LinearMath/btAabbUtil2.h" 33 #include "LinearMath/btQuickprof.h" 34 #include "LinearMath/btSerializer.h" 35 #include "BulletCollision/CollisionShapes/btConvexPolyhedron.h" 36 #include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h" 37 38 //#define DISABLE_DBVT_COMPOUNDSHAPE_RAYCAST_ACCELERATION 39 40 41 //#define USE_BRUTEFORCE_RAYBROADPHASE 1 42 //RECALCULATE_AABB is slower, but benefit is that you don't need to call 'stepSimulation' or 'updateAabbs' before using a rayTest 43 //#define RECALCULATE_AABB_RAYCAST 1 44 45 //When the user doesn't provide dispatcher or broadphase, create basic versions (and delete them in destructor) 46 #include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" 47 #include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h" 48 #include "BulletCollision/CollisionDispatch/btCollisionConfiguration.h" 49 50 51 ///for debug drawing 52 53 //for debug rendering 54 #include "BulletCollision/CollisionShapes/btBoxShape.h" 55 #include "BulletCollision/CollisionShapes/btCapsuleShape.h" 56 #include "BulletCollision/CollisionShapes/btCompoundShape.h" 57 #include "BulletCollision/CollisionShapes/btConeShape.h" 58 #include "BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h" 59 #include "BulletCollision/CollisionShapes/btCylinderShape.h" 60 #include "BulletCollision/CollisionShapes/btMultiSphereShape.h" 61 #include "BulletCollision/CollisionShapes/btPolyhedralConvexShape.h" 62 #include "BulletCollision/CollisionShapes/btSphereShape.h" 63 #include "BulletCollision/CollisionShapes/btTriangleCallback.h" 64 #include "BulletCollision/CollisionShapes/btTriangleMeshShape.h" 65 #include "BulletCollision/CollisionShapes/btStaticPlaneShape.h" 66 67 68 69 btCollisionWorld::btCollisionWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache, btCollisionConfiguration* collisionConfiguration) 70 :m_dispatcher1(dispatcher), 71 m_broadphasePairCache(pairCache), 72 m_debugDrawer(0), 73 m_forceUpdateAllAabbs(true) 74 { 75 } 76 77 78 btCollisionWorld::~btCollisionWorld() 79 { 80 81 //clean up remaining objects 82 int i; 83 for (i=0;i<m_collisionObjects.size();i++) 84 { 85 btCollisionObject* collisionObject= m_collisionObjects[i]; 86 87 btBroadphaseProxy* bp = collisionObject->getBroadphaseHandle(); 88 if (bp) 89 { 90 // 91 // only clear the cached algorithms 92 // 93 getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(bp,m_dispatcher1); 94 getBroadphase()->destroyProxy(bp,m_dispatcher1); 95 collisionObject->setBroadphaseHandle(0); 96 } 97 } 98 99 100 } 101 102 103 104 105 106 107 108 109 110 111 void btCollisionWorld::addCollisionObject(btCollisionObject* collisionObject,short int collisionFilterGroup,short int collisionFilterMask) 112 { 113 114 btAssert(collisionObject); 115 116 //check that the object isn't already added 117 btAssert( m_collisionObjects.findLinearSearch(collisionObject) == m_collisionObjects.size()); 118 119 m_collisionObjects.push_back(collisionObject); 120 121 //calculate new AABB 122 btTransform trans = collisionObject->getWorldTransform(); 123 124 btVector3 minAabb; 125 btVector3 maxAabb; 126 collisionObject->getCollisionShape()->getAabb(trans,minAabb,maxAabb); 127 128 int type = collisionObject->getCollisionShape()->getShapeType(); 129 collisionObject->setBroadphaseHandle( getBroadphase()->createProxy( 130 minAabb, 131 maxAabb, 132 type, 133 collisionObject, 134 collisionFilterGroup, 135 collisionFilterMask, 136 m_dispatcher1,0 137 )) ; 138 139 140 141 142 143 } 144 145 146 147 void btCollisionWorld::updateSingleAabb(btCollisionObject* colObj) 148 { 149 btVector3 minAabb,maxAabb; 150 colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb,maxAabb); 151 //need to increase the aabb for contact thresholds 152 btVector3 contactThreshold(gContactBreakingThreshold,gContactBreakingThreshold,gContactBreakingThreshold); 153 minAabb -= contactThreshold; 154 maxAabb += contactThreshold; 155 156 if(getDispatchInfo().m_useContinuous && colObj->getInternalType()==btCollisionObject::CO_RIGID_BODY && !colObj->isStaticOrKinematicObject()) 157 { 158 btVector3 minAabb2,maxAabb2; 159 colObj->getCollisionShape()->getAabb(colObj->getInterpolationWorldTransform(),minAabb2,maxAabb2); 160 minAabb2 -= contactThreshold; 161 maxAabb2 += contactThreshold; 162 minAabb.setMin(minAabb2); 163 maxAabb.setMax(maxAabb2); 164 } 165 166 btBroadphaseInterface* bp = (btBroadphaseInterface*)m_broadphasePairCache; 167 168 //moving objects should be moderately sized, probably something wrong if not 169 if ( colObj->isStaticObject() || ((maxAabb-minAabb).length2() < btScalar(1e12))) 170 { 171 bp->setAabb(colObj->getBroadphaseHandle(),minAabb,maxAabb, m_dispatcher1); 172 } else 173 { 174 //something went wrong, investigate 175 //this assert is unwanted in 3D modelers (danger of loosing work) 176 colObj->setActivationState(DISABLE_SIMULATION); 177 178 static bool reportMe = true; 179 if (reportMe && m_debugDrawer) 180 { 181 reportMe = false; 182 m_debugDrawer->reportErrorWarning("Overflow in AABB, object removed from simulation"); 183 m_debugDrawer->reportErrorWarning("If you can reproduce this, please email bugs (at) continuousphysics.com\n"); 184 m_debugDrawer->reportErrorWarning("Please include above information, your Platform, version of OS.\n"); 185 m_debugDrawer->reportErrorWarning("Thanks.\n"); 186 } 187 } 188 } 189 190 void btCollisionWorld::updateAabbs() 191 { 192 BT_PROFILE("updateAabbs"); 193 194 btTransform predictedTrans; 195 for ( int i=0;i<m_collisionObjects.size();i++) 196 { 197 btCollisionObject* colObj = m_collisionObjects[i]; 198 199 //only update aabb of active objects 200 if (m_forceUpdateAllAabbs || colObj->isActive()) 201 { 202 updateSingleAabb(colObj); 203 } 204 } 205 } 206 207 208 void btCollisionWorld::computeOverlappingPairs() 209 { 210 BT_PROFILE("calculateOverlappingPairs"); 211 m_broadphasePairCache->calculateOverlappingPairs(m_dispatcher1); 212 } 213 214 void btCollisionWorld::performDiscreteCollisionDetection() 215 { 216 BT_PROFILE("performDiscreteCollisionDetection"); 217 218 btDispatcherInfo& dispatchInfo = getDispatchInfo(); 219 220 updateAabbs(); 221 222 computeOverlappingPairs(); 223 224 btDispatcher* dispatcher = getDispatcher(); 225 { 226 BT_PROFILE("dispatchAllCollisionPairs"); 227 if (dispatcher) 228 dispatcher->dispatchAllCollisionPairs(m_broadphasePairCache->getOverlappingPairCache(),dispatchInfo,m_dispatcher1); 229 } 230 231 } 232 233 234 235 void btCollisionWorld::removeCollisionObject(btCollisionObject* collisionObject) 236 { 237 238 239 //bool removeFromBroadphase = false; 240 241 { 242 243 btBroadphaseProxy* bp = collisionObject->getBroadphaseHandle(); 244 if (bp) 245 { 246 // 247 // only clear the cached algorithms 248 // 249 getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(bp,m_dispatcher1); 250 getBroadphase()->destroyProxy(bp,m_dispatcher1); 251 collisionObject->setBroadphaseHandle(0); 252 } 253 } 254 255 256 //swapremove 257 m_collisionObjects.remove(collisionObject); 258 259 } 260 261 262 void btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans,const btTransform& rayToTrans, 263 btCollisionObject* collisionObject, 264 const btCollisionShape* collisionShape, 265 const btTransform& colObjWorldTransform, 266 RayResultCallback& resultCallback) 267 { 268 btCollisionObjectWrapper colObWrap(0,collisionShape,collisionObject,colObjWorldTransform,-1,-1); 269 btCollisionWorld::rayTestSingleInternal(rayFromTrans,rayToTrans,&colObWrap,resultCallback); 270 } 271 272 void btCollisionWorld::rayTestSingleInternal(const btTransform& rayFromTrans,const btTransform& rayToTrans, 273 const btCollisionObjectWrapper* collisionObjectWrap, 274 RayResultCallback& resultCallback) 275 { 276 btSphereShape pointShape(btScalar(0.0)); 277 pointShape.setMargin(0.f); 278 const btConvexShape* castShape = &pointShape; 279 const btCollisionShape* collisionShape = collisionObjectWrap->getCollisionShape(); 280 const btTransform& colObjWorldTransform = collisionObjectWrap->getWorldTransform(); 281 282 if (collisionShape->isConvex()) 283 { 284 // BT_PROFILE("rayTestConvex"); 285 btConvexCast::CastResult castResult; 286 castResult.m_fraction = resultCallback.m_closestHitFraction; 287 288 btConvexShape* convexShape = (btConvexShape*) collisionShape; 289 btVoronoiSimplexSolver simplexSolver; 290 btSubsimplexConvexCast subSimplexConvexCaster(castShape,convexShape,&simplexSolver); 291 292 btGjkConvexCast gjkConvexCaster(castShape,convexShape,&simplexSolver); 293 294 //btContinuousConvexCollision convexCaster(castShape,convexShape,&simplexSolver,0); 295 296 btConvexCast* convexCasterPtr = 0; 297 //use kF_UseSubSimplexConvexCastRaytest by default 298 if (resultCallback.m_flags & btTriangleRaycastCallback::kF_UseGjkConvexCastRaytest) 299 convexCasterPtr = &gjkConvexCaster; 300 else 301 convexCasterPtr = &subSimplexConvexCaster; 302 303 btConvexCast& convexCaster = *convexCasterPtr; 304 305 if (convexCaster.calcTimeOfImpact(rayFromTrans,rayToTrans,colObjWorldTransform,colObjWorldTransform,castResult)) 306 { 307 //add hit 308 if (castResult.m_normal.length2() > btScalar(0.0001)) 309 { 310 if (castResult.m_fraction < resultCallback.m_closestHitFraction) 311 { 312 //todo: figure out what this is about. When is rayFromTest.getBasis() not identity? 313 #ifdef USE_SUBSIMPLEX_CONVEX_CAST 314 //rotate normal into worldspace 315 castResult.m_normal = rayFromTrans.getBasis() * castResult.m_normal; 316 #endif //USE_SUBSIMPLEX_CONVEX_CAST 317 318 castResult.m_normal.normalize(); 319 btCollisionWorld::LocalRayResult localRayResult 320 ( 321 collisionObjectWrap->getCollisionObject(), 322 0, 323 castResult.m_normal, 324 castResult.m_fraction 325 ); 326 327 bool normalInWorldSpace = true; 328 resultCallback.addSingleResult(localRayResult, normalInWorldSpace); 329 330 } 331 } 332 } 333 } else { 334 if (collisionShape->isConcave()) 335 { 336 337 //ConvexCast::CastResult 338 struct BridgeTriangleRaycastCallback : public btTriangleRaycastCallback 339 { 340 btCollisionWorld::RayResultCallback* m_resultCallback; 341 const btCollisionObject* m_collisionObject; 342 const btConcaveShape* m_triangleMesh; 343 344 btTransform m_colObjWorldTransform; 345 346 BridgeTriangleRaycastCallback( const btVector3& from,const btVector3& to, 347 btCollisionWorld::RayResultCallback* resultCallback, const btCollisionObject* collisionObject,const btConcaveShape* triangleMesh,const btTransform& colObjWorldTransform): 348 //@BP Mod 349 btTriangleRaycastCallback(from,to, resultCallback->m_flags), 350 m_resultCallback(resultCallback), 351 m_collisionObject(collisionObject), 352 m_triangleMesh(triangleMesh), 353 m_colObjWorldTransform(colObjWorldTransform) 354 { 355 } 356 357 358 virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex ) 359 { 360 btCollisionWorld::LocalShapeInfo shapeInfo; 361 shapeInfo.m_shapePart = partId; 362 shapeInfo.m_triangleIndex = triangleIndex; 363 364 btVector3 hitNormalWorld = m_colObjWorldTransform.getBasis() * hitNormalLocal; 365 366 btCollisionWorld::LocalRayResult rayResult 367 (m_collisionObject, 368 &shapeInfo, 369 hitNormalWorld, 370 hitFraction); 371 372 bool normalInWorldSpace = true; 373 return m_resultCallback->addSingleResult(rayResult,normalInWorldSpace); 374 } 375 376 }; 377 378 btTransform worldTocollisionObject = colObjWorldTransform.inverse(); 379 btVector3 rayFromLocal = worldTocollisionObject * rayFromTrans.getOrigin(); 380 btVector3 rayToLocal = worldTocollisionObject * rayToTrans.getOrigin(); 381 382 // BT_PROFILE("rayTestConcave"); 383 if (collisionShape->getShapeType()==TRIANGLE_MESH_SHAPE_PROXYTYPE) 384 { 385 ///optimized version for btBvhTriangleMeshShape 386 btBvhTriangleMeshShape* triangleMesh = (btBvhTriangleMeshShape*)collisionShape; 387 388 BridgeTriangleRaycastCallback rcb(rayFromLocal,rayToLocal,&resultCallback,collisionObjectWrap->getCollisionObject(),triangleMesh,colObjWorldTransform); 389 rcb.m_hitFraction = resultCallback.m_closestHitFraction; 390 triangleMesh->performRaycast(&rcb,rayFromLocal,rayToLocal); 391 } 392 else 393 { 394 //generic (slower) case 395 btConcaveShape* concaveShape = (btConcaveShape*)collisionShape; 396 397 btTransform worldTocollisionObject = colObjWorldTransform.inverse(); 398 399 btVector3 rayFromLocal = worldTocollisionObject * rayFromTrans.getOrigin(); 400 btVector3 rayToLocal = worldTocollisionObject * rayToTrans.getOrigin(); 401 402 //ConvexCast::CastResult 403 404 struct BridgeTriangleRaycastCallback : public btTriangleRaycastCallback 405 { 406 btCollisionWorld::RayResultCallback* m_resultCallback; 407 const btCollisionObject* m_collisionObject; 408 btConcaveShape* m_triangleMesh; 409 410 btTransform m_colObjWorldTransform; 411 412 BridgeTriangleRaycastCallback( const btVector3& from,const btVector3& to, 413 btCollisionWorld::RayResultCallback* resultCallback, const btCollisionObject* collisionObject,btConcaveShape* triangleMesh, const btTransform& colObjWorldTransform): 414 //@BP Mod 415 btTriangleRaycastCallback(from,to, resultCallback->m_flags), 416 m_resultCallback(resultCallback), 417 m_collisionObject(collisionObject), 418 m_triangleMesh(triangleMesh), 419 m_colObjWorldTransform(colObjWorldTransform) 420 { 421 } 422 423 424 virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex ) 425 { 426 btCollisionWorld::LocalShapeInfo shapeInfo; 427 shapeInfo.m_shapePart = partId; 428 shapeInfo.m_triangleIndex = triangleIndex; 429 430 btVector3 hitNormalWorld = m_colObjWorldTransform.getBasis() * hitNormalLocal; 431 432 btCollisionWorld::LocalRayResult rayResult 433 (m_collisionObject, 434 &shapeInfo, 435 hitNormalWorld, 436 hitFraction); 437 438 bool normalInWorldSpace = true; 439 return m_resultCallback->addSingleResult(rayResult,normalInWorldSpace); 440 } 441 442 }; 443 444 445 BridgeTriangleRaycastCallback rcb(rayFromLocal,rayToLocal,&resultCallback,collisionObjectWrap->getCollisionObject(),concaveShape, colObjWorldTransform); 446 rcb.m_hitFraction = resultCallback.m_closestHitFraction; 447 448 btVector3 rayAabbMinLocal = rayFromLocal; 449 rayAabbMinLocal.setMin(rayToLocal); 450 btVector3 rayAabbMaxLocal = rayFromLocal; 451 rayAabbMaxLocal.setMax(rayToLocal); 452 453 concaveShape->processAllTriangles(&rcb,rayAabbMinLocal,rayAabbMaxLocal); 454 } 455 } else { 456 // BT_PROFILE("rayTestCompound"); 457 if (collisionShape->isCompound()) 458 { 459 struct LocalInfoAdder2 : public RayResultCallback 460 { 461 RayResultCallback* m_userCallback; 462 int m_i; 463 464 LocalInfoAdder2 (int i, RayResultCallback *user) 465 : m_userCallback(user), m_i(i) 466 { 467 m_closestHitFraction = m_userCallback->m_closestHitFraction; 468 m_flags = m_userCallback->m_flags; 469 } 470 virtual bool needsCollision(btBroadphaseProxy* p) const 471 { 472 return m_userCallback->needsCollision(p); 473 } 474 475 virtual btScalar addSingleResult (btCollisionWorld::LocalRayResult &r, bool b) 476 { 477 btCollisionWorld::LocalShapeInfo shapeInfo; 478 shapeInfo.m_shapePart = -1; 479 shapeInfo.m_triangleIndex = m_i; 480 if (r.m_localShapeInfo == NULL) 481 r.m_localShapeInfo = &shapeInfo; 482 483 const btScalar result = m_userCallback->addSingleResult(r, b); 484 m_closestHitFraction = m_userCallback->m_closestHitFraction; 485 return result; 486 } 487 }; 488 489 struct RayTester : btDbvt::ICollide 490 { 491 const btCollisionObject* m_collisionObject; 492 const btCompoundShape* m_compoundShape; 493 const btTransform& m_colObjWorldTransform; 494 const btTransform& m_rayFromTrans; 495 const btTransform& m_rayToTrans; 496 RayResultCallback& m_resultCallback; 497 498 RayTester(const btCollisionObject* collisionObject, 499 const btCompoundShape* compoundShape, 500 const btTransform& colObjWorldTransform, 501 const btTransform& rayFromTrans, 502 const btTransform& rayToTrans, 503 RayResultCallback& resultCallback): 504 m_collisionObject(collisionObject), 505 m_compoundShape(compoundShape), 506 m_colObjWorldTransform(colObjWorldTransform), 507 m_rayFromTrans(rayFromTrans), 508 m_rayToTrans(rayToTrans), 509 m_resultCallback(resultCallback) 510 { 511 512 } 513 514 void ProcessLeaf(int i) 515 { 516 const btCollisionShape* childCollisionShape = m_compoundShape->getChildShape(i); 517 const btTransform& childTrans = m_compoundShape->getChildTransform(i); 518 btTransform childWorldTrans = m_colObjWorldTransform * childTrans; 519 520 btCollisionObjectWrapper tmpOb(0,childCollisionShape,m_collisionObject,childWorldTrans,-1,i); 521 // replace collision shape so that callback can determine the triangle 522 523 524 525 LocalInfoAdder2 my_cb(i, &m_resultCallback); 526 527 rayTestSingleInternal( 528 m_rayFromTrans, 529 m_rayToTrans, 530 &tmpOb, 531 my_cb); 532 533 } 534 535 void Process(const btDbvtNode* leaf) 536 { 537 ProcessLeaf(leaf->dataAsInt); 538 } 539 }; 540 541 const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(collisionShape); 542 const btDbvt* dbvt = compoundShape->getDynamicAabbTree(); 543 544 545 RayTester rayCB( 546 collisionObjectWrap->getCollisionObject(), 547 compoundShape, 548 colObjWorldTransform, 549 rayFromTrans, 550 rayToTrans, 551 resultCallback); 552 #ifndef DISABLE_DBVT_COMPOUNDSHAPE_RAYCAST_ACCELERATION 553 if (dbvt) 554 { 555 btVector3 localRayFrom = colObjWorldTransform.inverseTimes(rayFromTrans).getOrigin(); 556 btVector3 localRayTo = colObjWorldTransform.inverseTimes(rayToTrans).getOrigin(); 557 btDbvt::rayTest(dbvt->m_root, localRayFrom , localRayTo, rayCB); 558 } 559 else 560 #endif //DISABLE_DBVT_COMPOUNDSHAPE_RAYCAST_ACCELERATION 561 { 562 for (int i = 0, n = compoundShape->getNumChildShapes(); i < n; ++i) 563 { 564 rayCB.ProcessLeaf(i); 565 } 566 } 567 } 568 } 569 } 570 } 571 572 void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const btTransform& convexFromTrans,const btTransform& convexToTrans, 573 btCollisionObject* collisionObject, 574 const btCollisionShape* collisionShape, 575 const btTransform& colObjWorldTransform, 576 ConvexResultCallback& resultCallback, btScalar allowedPenetration) 577 { 578 btCollisionObjectWrapper tmpOb(0,collisionShape,collisionObject,colObjWorldTransform,-1,-1); 579 btCollisionWorld::objectQuerySingleInternal(castShape,convexFromTrans,convexToTrans,&tmpOb,resultCallback,allowedPenetration); 580 } 581 582 void btCollisionWorld::objectQuerySingleInternal(const btConvexShape* castShape,const btTransform& convexFromTrans,const btTransform& convexToTrans, 583 const btCollisionObjectWrapper* colObjWrap, 584 ConvexResultCallback& resultCallback, btScalar allowedPenetration) 585 { 586 const btCollisionShape* collisionShape = colObjWrap->getCollisionShape(); 587 const btTransform& colObjWorldTransform = colObjWrap->getWorldTransform(); 588 589 if (collisionShape->isConvex()) 590 { 591 //BT_PROFILE("convexSweepConvex"); 592 btConvexCast::CastResult castResult; 593 castResult.m_allowedPenetration = allowedPenetration; 594 castResult.m_fraction = resultCallback.m_closestHitFraction;//btScalar(1.);//?? 595 596 btConvexShape* convexShape = (btConvexShape*) collisionShape; 597 btVoronoiSimplexSolver simplexSolver; 598 btGjkEpaPenetrationDepthSolver gjkEpaPenetrationSolver; 599 600 btContinuousConvexCollision convexCaster1(castShape,convexShape,&simplexSolver,&gjkEpaPenetrationSolver); 601 //btGjkConvexCast convexCaster2(castShape,convexShape,&simplexSolver); 602 //btSubsimplexConvexCast convexCaster3(castShape,convexShape,&simplexSolver); 603 604 btConvexCast* castPtr = &convexCaster1; 605 606 607 608 if (castPtr->calcTimeOfImpact(convexFromTrans,convexToTrans,colObjWorldTransform,colObjWorldTransform,castResult)) 609 { 610 //add hit 611 if (castResult.m_normal.length2() > btScalar(0.0001)) 612 { 613 if (castResult.m_fraction < resultCallback.m_closestHitFraction) 614 { 615 castResult.m_normal.normalize(); 616 btCollisionWorld::LocalConvexResult localConvexResult 617 ( 618 colObjWrap->getCollisionObject(), 619 0, 620 castResult.m_normal, 621 castResult.m_hitPoint, 622 castResult.m_fraction 623 ); 624 625 bool normalInWorldSpace = true; 626 resultCallback.addSingleResult(localConvexResult, normalInWorldSpace); 627 628 } 629 } 630 } 631 } else { 632 if (collisionShape->isConcave()) 633 { 634 if (collisionShape->getShapeType()==TRIANGLE_MESH_SHAPE_PROXYTYPE) 635 { 636 //BT_PROFILE("convexSweepbtBvhTriangleMesh"); 637 btBvhTriangleMeshShape* triangleMesh = (btBvhTriangleMeshShape*)collisionShape; 638 btTransform worldTocollisionObject = colObjWorldTransform.inverse(); 639 btVector3 convexFromLocal = worldTocollisionObject * convexFromTrans.getOrigin(); 640 btVector3 convexToLocal = worldTocollisionObject * convexToTrans.getOrigin(); 641 // rotation of box in local mesh space = MeshRotation^-1 * ConvexToRotation 642 btTransform rotationXform = btTransform(worldTocollisionObject.getBasis() * convexToTrans.getBasis()); 643 644 //ConvexCast::CastResult 645 struct BridgeTriangleConvexcastCallback : public btTriangleConvexcastCallback 646 { 647 btCollisionWorld::ConvexResultCallback* m_resultCallback; 648 const btCollisionObject* m_collisionObject; 649 btTriangleMeshShape* m_triangleMesh; 650 651 BridgeTriangleConvexcastCallback(const btConvexShape* castShape, const btTransform& from,const btTransform& to, 652 btCollisionWorld::ConvexResultCallback* resultCallback, const btCollisionObject* collisionObject,btTriangleMeshShape* triangleMesh, const btTransform& triangleToWorld): 653 btTriangleConvexcastCallback(castShape, from,to, triangleToWorld, triangleMesh->getMargin()), 654 m_resultCallback(resultCallback), 655 m_collisionObject(collisionObject), 656 m_triangleMesh(triangleMesh) 657 { 658 } 659 660 661 virtual btScalar reportHit(const btVector3& hitNormalLocal, const btVector3& hitPointLocal, btScalar hitFraction, int partId, int triangleIndex ) 662 { 663 btCollisionWorld::LocalShapeInfo shapeInfo; 664 shapeInfo.m_shapePart = partId; 665 shapeInfo.m_triangleIndex = triangleIndex; 666 if (hitFraction <= m_resultCallback->m_closestHitFraction) 667 { 668 669 btCollisionWorld::LocalConvexResult convexResult 670 (m_collisionObject, 671 &shapeInfo, 672 hitNormalLocal, 673 hitPointLocal, 674 hitFraction); 675 676 bool normalInWorldSpace = true; 677 678 679 return m_resultCallback->addSingleResult(convexResult,normalInWorldSpace); 680 } 681 return hitFraction; 682 } 683 684 }; 685 686 BridgeTriangleConvexcastCallback tccb(castShape, convexFromTrans,convexToTrans,&resultCallback,colObjWrap->getCollisionObject(),triangleMesh, colObjWorldTransform); 687 tccb.m_hitFraction = resultCallback.m_closestHitFraction; 688 tccb.m_allowedPenetration = allowedPenetration; 689 btVector3 boxMinLocal, boxMaxLocal; 690 castShape->getAabb(rotationXform, boxMinLocal, boxMaxLocal); 691 triangleMesh->performConvexcast(&tccb,convexFromLocal,convexToLocal,boxMinLocal, boxMaxLocal); 692 } else 693 { 694 if (collisionShape->getShapeType()==STATIC_PLANE_PROXYTYPE) 695 { 696 btConvexCast::CastResult castResult; 697 castResult.m_allowedPenetration = allowedPenetration; 698 castResult.m_fraction = resultCallback.m_closestHitFraction; 699 btStaticPlaneShape* planeShape = (btStaticPlaneShape*) collisionShape; 700 btContinuousConvexCollision convexCaster1(castShape,planeShape); 701 btConvexCast* castPtr = &convexCaster1; 702 703 if (castPtr->calcTimeOfImpact(convexFromTrans,convexToTrans,colObjWorldTransform,colObjWorldTransform,castResult)) 704 { 705 //add hit 706 if (castResult.m_normal.length2() > btScalar(0.0001)) 707 { 708 if (castResult.m_fraction < resultCallback.m_closestHitFraction) 709 { 710 castResult.m_normal.normalize(); 711 btCollisionWorld::LocalConvexResult localConvexResult 712 ( 713 colObjWrap->getCollisionObject(), 714 0, 715 castResult.m_normal, 716 castResult.m_hitPoint, 717 castResult.m_fraction 718 ); 719 720 bool normalInWorldSpace = true; 721 resultCallback.addSingleResult(localConvexResult, normalInWorldSpace); 722 } 723 } 724 } 725 726 } else 727 { 728 //BT_PROFILE("convexSweepConcave"); 729 btConcaveShape* concaveShape = (btConcaveShape*)collisionShape; 730 btTransform worldTocollisionObject = colObjWorldTransform.inverse(); 731 btVector3 convexFromLocal = worldTocollisionObject * convexFromTrans.getOrigin(); 732 btVector3 convexToLocal = worldTocollisionObject * convexToTrans.getOrigin(); 733 // rotation of box in local mesh space = MeshRotation^-1 * ConvexToRotation 734 btTransform rotationXform = btTransform(worldTocollisionObject.getBasis() * convexToTrans.getBasis()); 735 736 //ConvexCast::CastResult 737 struct BridgeTriangleConvexcastCallback : public btTriangleConvexcastCallback 738 { 739 btCollisionWorld::ConvexResultCallback* m_resultCallback; 740 const btCollisionObject* m_collisionObject; 741 btConcaveShape* m_triangleMesh; 742 743 BridgeTriangleConvexcastCallback(const btConvexShape* castShape, const btTransform& from,const btTransform& to, 744 btCollisionWorld::ConvexResultCallback* resultCallback, const btCollisionObject* collisionObject,btConcaveShape* triangleMesh, const btTransform& triangleToWorld): 745 btTriangleConvexcastCallback(castShape, from,to, triangleToWorld, triangleMesh->getMargin()), 746 m_resultCallback(resultCallback), 747 m_collisionObject(collisionObject), 748 m_triangleMesh(triangleMesh) 749 { 750 } 751 752 753 virtual btScalar reportHit(const btVector3& hitNormalLocal, const btVector3& hitPointLocal, btScalar hitFraction, int partId, int triangleIndex ) 754 { 755 btCollisionWorld::LocalShapeInfo shapeInfo; 756 shapeInfo.m_shapePart = partId; 757 shapeInfo.m_triangleIndex = triangleIndex; 758 if (hitFraction <= m_resultCallback->m_closestHitFraction) 759 { 760 761 btCollisionWorld::LocalConvexResult convexResult 762 (m_collisionObject, 763 &shapeInfo, 764 hitNormalLocal, 765 hitPointLocal, 766 hitFraction); 767 768 bool normalInWorldSpace = true; 769 770 return m_resultCallback->addSingleResult(convexResult,normalInWorldSpace); 771 } 772 return hitFraction; 773 } 774 775 }; 776 777 BridgeTriangleConvexcastCallback tccb(castShape, convexFromTrans,convexToTrans,&resultCallback,colObjWrap->getCollisionObject(),concaveShape, colObjWorldTransform); 778 tccb.m_hitFraction = resultCallback.m_closestHitFraction; 779 tccb.m_allowedPenetration = allowedPenetration; 780 btVector3 boxMinLocal, boxMaxLocal; 781 castShape->getAabb(rotationXform, boxMinLocal, boxMaxLocal); 782 783 btVector3 rayAabbMinLocal = convexFromLocal; 784 rayAabbMinLocal.setMin(convexToLocal); 785 btVector3 rayAabbMaxLocal = convexFromLocal; 786 rayAabbMaxLocal.setMax(convexToLocal); 787 rayAabbMinLocal += boxMinLocal; 788 rayAabbMaxLocal += boxMaxLocal; 789 concaveShape->processAllTriangles(&tccb,rayAabbMinLocal,rayAabbMaxLocal); 790 } 791 } 792 } else { 793 ///@todo : use AABB tree or other BVH acceleration structure! 794 if (collisionShape->isCompound()) 795 { 796 BT_PROFILE("convexSweepCompound"); 797 const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(collisionShape); 798 int i=0; 799 for (i=0;i<compoundShape->getNumChildShapes();i++) 800 { 801 btTransform childTrans = compoundShape->getChildTransform(i); 802 const btCollisionShape* childCollisionShape = compoundShape->getChildShape(i); 803 btTransform childWorldTrans = colObjWorldTransform * childTrans; 804 805 struct LocalInfoAdder : public ConvexResultCallback { 806 ConvexResultCallback* m_userCallback; 807 int m_i; 808 809 LocalInfoAdder (int i, ConvexResultCallback *user) 810 : m_userCallback(user), m_i(i) 811 { 812 m_closestHitFraction = m_userCallback->m_closestHitFraction; 813 } 814 virtual bool needsCollision(btBroadphaseProxy* p) const 815 { 816 return m_userCallback->needsCollision(p); 817 } 818 virtual btScalar addSingleResult (btCollisionWorld::LocalConvexResult& r, bool b) 819 { 820 btCollisionWorld::LocalShapeInfo shapeInfo; 821 shapeInfo.m_shapePart = -1; 822 shapeInfo.m_triangleIndex = m_i; 823 if (r.m_localShapeInfo == NULL) 824 r.m_localShapeInfo = &shapeInfo; 825 const btScalar result = m_userCallback->addSingleResult(r, b); 826 m_closestHitFraction = m_userCallback->m_closestHitFraction; 827 return result; 828 829 } 830 }; 831 832 LocalInfoAdder my_cb(i, &resultCallback); 833 834 btCollisionObjectWrapper tmpObj(colObjWrap,childCollisionShape,colObjWrap->getCollisionObject(),childWorldTrans,-1,i); 835 836 objectQuerySingleInternal(castShape, convexFromTrans,convexToTrans, 837 &tmpObj,my_cb, allowedPenetration); 838 839 } 840 } 841 } 842 } 843 } 844 845 846 struct btSingleRayCallback : public btBroadphaseRayCallback 847 { 848 849 btVector3 m_rayFromWorld; 850 btVector3 m_rayToWorld; 851 btTransform m_rayFromTrans; 852 btTransform m_rayToTrans; 853 btVector3 m_hitNormal; 854 855 const btCollisionWorld* m_world; 856 btCollisionWorld::RayResultCallback& m_resultCallback; 857 858 btSingleRayCallback(const btVector3& rayFromWorld,const btVector3& rayToWorld,const btCollisionWorld* world,btCollisionWorld::RayResultCallback& resultCallback) 859 :m_rayFromWorld(rayFromWorld), 860 m_rayToWorld(rayToWorld), 861 m_world(world), 862 m_resultCallback(resultCallback) 863 { 864 m_rayFromTrans.setIdentity(); 865 m_rayFromTrans.setOrigin(m_rayFromWorld); 866 m_rayToTrans.setIdentity(); 867 m_rayToTrans.setOrigin(m_rayToWorld); 868 869 btVector3 rayDir = (rayToWorld-rayFromWorld); 870 871 rayDir.normalize (); 872 ///what about division by zero? --> just set rayDirection[i] to INF/BT_LARGE_FLOAT 873 m_rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[0]; 874 m_rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[1]; 875 m_rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[2]; 876 m_signs[0] = m_rayDirectionInverse[0] < 0.0; 877 m_signs[1] = m_rayDirectionInverse[1] < 0.0; 878 m_signs[2] = m_rayDirectionInverse[2] < 0.0; 879 880 m_lambda_max = rayDir.dot(m_rayToWorld-m_rayFromWorld); 881 882 } 883 884 885 886 virtual bool process(const btBroadphaseProxy* proxy) 887 { 888 ///terminate further ray tests, once the closestHitFraction reached zero 889 if (m_resultCallback.m_closestHitFraction == btScalar(0.f)) 890 return false; 891 892 btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject; 893 894 //only perform raycast if filterMask matches 895 if(m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle())) 896 { 897 //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject(); 898 //btVector3 collisionObjectAabbMin,collisionObjectAabbMax; 899 #if 0 900 #ifdef RECALCULATE_AABB 901 btVector3 collisionObjectAabbMin,collisionObjectAabbMax; 902 collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax); 903 #else 904 //getBroadphase()->getAabb(collisionObject->getBroadphaseHandle(),collisionObjectAabbMin,collisionObjectAabbMax); 905 const btVector3& collisionObjectAabbMin = collisionObject->getBroadphaseHandle()->m_aabbMin; 906 const btVector3& collisionObjectAabbMax = collisionObject->getBroadphaseHandle()->m_aabbMax; 907 #endif 908 #endif 909 //btScalar hitLambda = m_resultCallback.m_closestHitFraction; 910 //culling already done by broadphase 911 //if (btRayAabb(m_rayFromWorld,m_rayToWorld,collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,m_hitNormal)) 912 { 913 m_world->rayTestSingle(m_rayFromTrans,m_rayToTrans, 914 collisionObject, 915 collisionObject->getCollisionShape(), 916 collisionObject->getWorldTransform(), 917 m_resultCallback); 918 } 919 } 920 return true; 921 } 922 }; 923 924 void btCollisionWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const 925 { 926 //BT_PROFILE("rayTest"); 927 /// use the broadphase to accelerate the search for objects, based on their aabb 928 /// and for each object with ray-aabb overlap, perform an exact ray test 929 btSingleRayCallback rayCB(rayFromWorld,rayToWorld,this,resultCallback); 930 931 #ifndef USE_BRUTEFORCE_RAYBROADPHASE 932 m_broadphasePairCache->rayTest(rayFromWorld,rayToWorld,rayCB); 933 #else 934 for (int i=0;i<this->getNumCollisionObjects();i++) 935 { 936 rayCB.process(m_collisionObjects[i]->getBroadphaseHandle()); 937 } 938 #endif //USE_BRUTEFORCE_RAYBROADPHASE 939 940 } 941 942 943 struct btSingleSweepCallback : public btBroadphaseRayCallback 944 { 945 946 btTransform m_convexFromTrans; 947 btTransform m_convexToTrans; 948 btVector3 m_hitNormal; 949 const btCollisionWorld* m_world; 950 btCollisionWorld::ConvexResultCallback& m_resultCallback; 951 btScalar m_allowedCcdPenetration; 952 const btConvexShape* m_castShape; 953 954 955 btSingleSweepCallback(const btConvexShape* castShape, const btTransform& convexFromTrans,const btTransform& convexToTrans,const btCollisionWorld* world,btCollisionWorld::ConvexResultCallback& resultCallback,btScalar allowedPenetration) 956 :m_convexFromTrans(convexFromTrans), 957 m_convexToTrans(convexToTrans), 958 m_world(world), 959 m_resultCallback(resultCallback), 960 m_allowedCcdPenetration(allowedPenetration), 961 m_castShape(castShape) 962 { 963 btVector3 unnormalizedRayDir = (m_convexToTrans.getOrigin()-m_convexFromTrans.getOrigin()); 964 btVector3 rayDir = unnormalizedRayDir.normalized(); 965 ///what about division by zero? --> just set rayDirection[i] to INF/BT_LARGE_FLOAT 966 m_rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[0]; 967 m_rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[1]; 968 m_rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[2]; 969 m_signs[0] = m_rayDirectionInverse[0] < 0.0; 970 m_signs[1] = m_rayDirectionInverse[1] < 0.0; 971 m_signs[2] = m_rayDirectionInverse[2] < 0.0; 972 973 m_lambda_max = rayDir.dot(unnormalizedRayDir); 974 975 } 976 977 virtual bool process(const btBroadphaseProxy* proxy) 978 { 979 ///terminate further convex sweep tests, once the closestHitFraction reached zero 980 if (m_resultCallback.m_closestHitFraction == btScalar(0.f)) 981 return false; 982 983 btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject; 984 985 //only perform raycast if filterMask matches 986 if(m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle())) { 987 //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject(); 988 m_world->objectQuerySingle(m_castShape, m_convexFromTrans,m_convexToTrans, 989 collisionObject, 990 collisionObject->getCollisionShape(), 991 collisionObject->getWorldTransform(), 992 m_resultCallback, 993 m_allowedCcdPenetration); 994 } 995 996 return true; 997 } 998 }; 999 1000 1001 1002 void btCollisionWorld::convexSweepTest(const btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, ConvexResultCallback& resultCallback, btScalar allowedCcdPenetration) const 1003 { 1004 1005 BT_PROFILE("convexSweepTest"); 1006 /// use the broadphase to accelerate the search for objects, based on their aabb 1007 /// and for each object with ray-aabb overlap, perform an exact ray test 1008 /// unfortunately the implementation for rayTest and convexSweepTest duplicated, albeit practically identical 1009 1010 1011 1012 btTransform convexFromTrans,convexToTrans; 1013 convexFromTrans = convexFromWorld; 1014 convexToTrans = convexToWorld; 1015 btVector3 castShapeAabbMin, castShapeAabbMax; 1016 /* Compute AABB that encompasses angular movement */ 1017 { 1018 btVector3 linVel, angVel; 1019 btTransformUtil::calculateVelocity (convexFromTrans, convexToTrans, 1.0f, linVel, angVel); 1020 btVector3 zeroLinVel; 1021 zeroLinVel.setValue(0,0,0); 1022 btTransform R; 1023 R.setIdentity (); 1024 R.setRotation (convexFromTrans.getRotation()); 1025 castShape->calculateTemporalAabb (R, zeroLinVel, angVel, 1.0f, castShapeAabbMin, castShapeAabbMax); 1026 } 1027 1028 #ifndef USE_BRUTEFORCE_RAYBROADPHASE 1029 1030 btSingleSweepCallback convexCB(castShape,convexFromWorld,convexToWorld,this,resultCallback,allowedCcdPenetration); 1031 1032 m_broadphasePairCache->rayTest(convexFromTrans.getOrigin(),convexToTrans.getOrigin(),convexCB,castShapeAabbMin,castShapeAabbMax); 1033 1034 #else 1035 /// go over all objects, and if the ray intersects their aabb + cast shape aabb, 1036 // do a ray-shape query using convexCaster (CCD) 1037 int i; 1038 for (i=0;i<m_collisionObjects.size();i++) 1039 { 1040 btCollisionObject* collisionObject= m_collisionObjects[i]; 1041 //only perform raycast if filterMask matches 1042 if(resultCallback.needsCollision(collisionObject->getBroadphaseHandle())) { 1043 //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject(); 1044 btVector3 collisionObjectAabbMin,collisionObjectAabbMax; 1045 collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax); 1046 AabbExpand (collisionObjectAabbMin, collisionObjectAabbMax, castShapeAabbMin, castShapeAabbMax); 1047 btScalar hitLambda = btScalar(1.); //could use resultCallback.m_closestHitFraction, but needs testing 1048 btVector3 hitNormal; 1049 if (btRayAabb(convexFromWorld.getOrigin(),convexToWorld.getOrigin(),collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,hitNormal)) 1050 { 1051 objectQuerySingle(castShape, convexFromTrans,convexToTrans, 1052 collisionObject, 1053 collisionObject->getCollisionShape(), 1054 collisionObject->getWorldTransform(), 1055 resultCallback, 1056 allowedCcdPenetration); 1057 } 1058 } 1059 } 1060 #endif //USE_BRUTEFORCE_RAYBROADPHASE 1061 } 1062 1063 1064 1065 struct btBridgedManifoldResult : public btManifoldResult 1066 { 1067 1068 btCollisionWorld::ContactResultCallback& m_resultCallback; 1069 1070 btBridgedManifoldResult( const btCollisionObjectWrapper* obj0Wrap,const btCollisionObjectWrapper* obj1Wrap,btCollisionWorld::ContactResultCallback& resultCallback ) 1071 :btManifoldResult(obj0Wrap,obj1Wrap), 1072 m_resultCallback(resultCallback) 1073 { 1074 } 1075 1076 virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth) 1077 { 1078 bool isSwapped = m_manifoldPtr->getBody0() != m_body0Wrap->getCollisionObject(); 1079 btVector3 pointA = pointInWorld + normalOnBInWorld * depth; 1080 btVector3 localA; 1081 btVector3 localB; 1082 if (isSwapped) 1083 { 1084 localA = m_body1Wrap->getCollisionObject()->getWorldTransform().invXform(pointA ); 1085 localB = m_body0Wrap->getCollisionObject()->getWorldTransform().invXform(pointInWorld); 1086 } else 1087 { 1088 localA = m_body0Wrap->getCollisionObject()->getWorldTransform().invXform(pointA ); 1089 localB = m_body1Wrap->getCollisionObject()->getWorldTransform().invXform(pointInWorld); 1090 } 1091 1092 btManifoldPoint newPt(localA,localB,normalOnBInWorld,depth); 1093 newPt.m_positionWorldOnA = pointA; 1094 newPt.m_positionWorldOnB = pointInWorld; 1095 1096 //BP mod, store contact triangles. 1097 if (isSwapped) 1098 { 1099 newPt.m_partId0 = m_partId1; 1100 newPt.m_partId1 = m_partId0; 1101 newPt.m_index0 = m_index1; 1102 newPt.m_index1 = m_index0; 1103 } else 1104 { 1105 newPt.m_partId0 = m_partId0; 1106 newPt.m_partId1 = m_partId1; 1107 newPt.m_index0 = m_index0; 1108 newPt.m_index1 = m_index1; 1109 } 1110 1111 //experimental feature info, for per-triangle material etc. 1112 const btCollisionObjectWrapper* obj0Wrap = isSwapped? m_body1Wrap : m_body0Wrap; 1113 const btCollisionObjectWrapper* obj1Wrap = isSwapped? m_body0Wrap : m_body1Wrap; 1114 m_resultCallback.addSingleResult(newPt,obj0Wrap,newPt.m_partId0,newPt.m_index0,obj1Wrap,newPt.m_partId1,newPt.m_index1); 1115 1116 } 1117 1118 }; 1119 1120 1121 1122 struct btSingleContactCallback : public btBroadphaseAabbCallback 1123 { 1124 1125 btCollisionObject* m_collisionObject; 1126 btCollisionWorld* m_world; 1127 btCollisionWorld::ContactResultCallback& m_resultCallback; 1128 1129 1130 btSingleContactCallback(btCollisionObject* collisionObject, btCollisionWorld* world,btCollisionWorld::ContactResultCallback& resultCallback) 1131 :m_collisionObject(collisionObject), 1132 m_world(world), 1133 m_resultCallback(resultCallback) 1134 { 1135 } 1136 1137 virtual bool process(const btBroadphaseProxy* proxy) 1138 { 1139 btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject; 1140 if (collisionObject == m_collisionObject) 1141 return true; 1142 1143 //only perform raycast if filterMask matches 1144 if(m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle())) 1145 { 1146 btCollisionObjectWrapper ob0(0,m_collisionObject->getCollisionShape(),m_collisionObject,m_collisionObject->getWorldTransform(),-1,-1); 1147 btCollisionObjectWrapper ob1(0,collisionObject->getCollisionShape(),collisionObject,collisionObject->getWorldTransform(),-1,-1); 1148 1149 btCollisionAlgorithm* algorithm = m_world->getDispatcher()->findAlgorithm(&ob0,&ob1); 1150 if (algorithm) 1151 { 1152 btBridgedManifoldResult contactPointResult(&ob0,&ob1, m_resultCallback); 1153 //discrete collision detection query 1154 1155 algorithm->processCollision(&ob0,&ob1, m_world->getDispatchInfo(),&contactPointResult); 1156 1157 algorithm->~btCollisionAlgorithm(); 1158 m_world->getDispatcher()->freeCollisionAlgorithm(algorithm); 1159 } 1160 } 1161 return true; 1162 } 1163 }; 1164 1165 1166 ///contactTest performs a discrete collision test against all objects in the btCollisionWorld, and calls the resultCallback. 1167 ///it reports one or more contact points for every overlapping object (including the one with deepest penetration) 1168 void btCollisionWorld::contactTest( btCollisionObject* colObj, ContactResultCallback& resultCallback) 1169 { 1170 btVector3 aabbMin,aabbMax; 1171 colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(),aabbMin,aabbMax); 1172 btSingleContactCallback contactCB(colObj,this,resultCallback); 1173 1174 m_broadphasePairCache->aabbTest(aabbMin,aabbMax,contactCB); 1175 } 1176 1177 1178 ///contactTest performs a discrete collision test between two collision objects and calls the resultCallback if overlap if detected. 1179 ///it reports one or more contact points (including the one with deepest penetration) 1180 void btCollisionWorld::contactPairTest(btCollisionObject* colObjA, btCollisionObject* colObjB, ContactResultCallback& resultCallback) 1181 { 1182 btCollisionObjectWrapper obA(0,colObjA->getCollisionShape(),colObjA,colObjA->getWorldTransform(),-1,-1); 1183 btCollisionObjectWrapper obB(0,colObjB->getCollisionShape(),colObjB,colObjB->getWorldTransform(),-1,-1); 1184 1185 btCollisionAlgorithm* algorithm = getDispatcher()->findAlgorithm(&obA,&obB); 1186 if (algorithm) 1187 { 1188 btBridgedManifoldResult contactPointResult(&obA,&obB, resultCallback); 1189 //discrete collision detection query 1190 algorithm->processCollision(&obA,&obB, getDispatchInfo(),&contactPointResult); 1191 1192 algorithm->~btCollisionAlgorithm(); 1193 getDispatcher()->freeCollisionAlgorithm(algorithm); 1194 } 1195 1196 } 1197 1198 1199 1200 1201 class DebugDrawcallback : public btTriangleCallback, public btInternalTriangleIndexCallback 1202 { 1203 btIDebugDraw* m_debugDrawer; 1204 btVector3 m_color; 1205 btTransform m_worldTrans; 1206 1207 public: 1208 1209 DebugDrawcallback(btIDebugDraw* debugDrawer,const btTransform& worldTrans,const btVector3& color) : 1210 m_debugDrawer(debugDrawer), 1211 m_color(color), 1212 m_worldTrans(worldTrans) 1213 { 1214 } 1215 1216 virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex) 1217 { 1218 processTriangle(triangle,partId,triangleIndex); 1219 } 1220 1221 virtual void processTriangle(btVector3* triangle,int partId, int triangleIndex) 1222 { 1223 (void)partId; 1224 (void)triangleIndex; 1225 1226 btVector3 wv0,wv1,wv2; 1227 wv0 = m_worldTrans*triangle[0]; 1228 wv1 = m_worldTrans*triangle[1]; 1229 wv2 = m_worldTrans*triangle[2]; 1230 btVector3 center = (wv0+wv1+wv2)*btScalar(1./3.); 1231 1232 if (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawNormals ) 1233 { 1234 btVector3 normal = (wv1-wv0).cross(wv2-wv0); 1235 normal.normalize(); 1236 btVector3 normalColor(1,1,0); 1237 m_debugDrawer->drawLine(center,center+normal,normalColor); 1238 } 1239 m_debugDrawer->drawLine(wv0,wv1,m_color); 1240 m_debugDrawer->drawLine(wv1,wv2,m_color); 1241 m_debugDrawer->drawLine(wv2,wv0,m_color); 1242 } 1243 }; 1244 1245 1246 void btCollisionWorld::debugDrawObject(const btTransform& worldTransform, const btCollisionShape* shape, const btVector3& color) 1247 { 1248 // Draw a small simplex at the center of the object 1249 if (getDebugDrawer() && getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawFrames) 1250 { 1251 getDebugDrawer()->drawTransform(worldTransform,1); 1252 } 1253 1254 if (shape->getShapeType() == COMPOUND_SHAPE_PROXYTYPE) 1255 { 1256 const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(shape); 1257 for (int i=compoundShape->getNumChildShapes()-1;i>=0;i--) 1258 { 1259 btTransform childTrans = compoundShape->getChildTransform(i); 1260 const btCollisionShape* colShape = compoundShape->getChildShape(i); 1261 debugDrawObject(worldTransform*childTrans,colShape,color); 1262 } 1263 1264 } else 1265 { 1266 1267 switch (shape->getShapeType()) 1268 { 1269 1270 case BOX_SHAPE_PROXYTYPE: 1271 { 1272 const btBoxShape* boxShape = static_cast<const btBoxShape*>(shape); 1273 btVector3 halfExtents = boxShape->getHalfExtentsWithMargin(); 1274 getDebugDrawer()->drawBox(-halfExtents,halfExtents,worldTransform,color); 1275 break; 1276 } 1277 1278 case SPHERE_SHAPE_PROXYTYPE: 1279 { 1280 const btSphereShape* sphereShape = static_cast<const btSphereShape*>(shape); 1281 btScalar radius = sphereShape->getMargin();//radius doesn't include the margin, so draw with margin 1282 1283 getDebugDrawer()->drawSphere(radius, worldTransform, color); 1284 break; 1285 } 1286 case MULTI_SPHERE_SHAPE_PROXYTYPE: 1287 { 1288 const btMultiSphereShape* multiSphereShape = static_cast<const btMultiSphereShape*>(shape); 1289 1290 btTransform childTransform; 1291 childTransform.setIdentity(); 1292 1293 for (int i = multiSphereShape->getSphereCount()-1; i>=0;i--) 1294 { 1295 childTransform.setOrigin(multiSphereShape->getSpherePosition(i)); 1296 getDebugDrawer()->drawSphere(multiSphereShape->getSphereRadius(i), worldTransform*childTransform, color); 1297 } 1298 1299 break; 1300 } 1301 case CAPSULE_SHAPE_PROXYTYPE: 1302 { 1303 const btCapsuleShape* capsuleShape = static_cast<const btCapsuleShape*>(shape); 1304 1305 btScalar radius = capsuleShape->getRadius(); 1306 btScalar halfHeight = capsuleShape->getHalfHeight(); 1307 1308 int upAxis = capsuleShape->getUpAxis(); 1309 getDebugDrawer()->drawCapsule(radius, halfHeight, upAxis, worldTransform, color); 1310 break; 1311 } 1312 case CONE_SHAPE_PROXYTYPE: 1313 { 1314 const btConeShape* coneShape = static_cast<const btConeShape*>(shape); 1315 btScalar radius = coneShape->getRadius();//+coneShape->getMargin(); 1316 btScalar height = coneShape->getHeight();//+coneShape->getMargin(); 1317 1318 int upAxis= coneShape->getConeUpIndex(); 1319 getDebugDrawer()->drawCone(radius, height, upAxis, worldTransform, color); 1320 break; 1321 1322 } 1323 case CYLINDER_SHAPE_PROXYTYPE: 1324 { 1325 const btCylinderShape* cylinder = static_cast<const btCylinderShape*>(shape); 1326 int upAxis = cylinder->getUpAxis(); 1327 btScalar radius = cylinder->getRadius(); 1328 btScalar halfHeight = cylinder->getHalfExtentsWithMargin()[upAxis]; 1329 getDebugDrawer()->drawCylinder(radius, halfHeight, upAxis, worldTransform, color); 1330 break; 1331 } 1332 1333 case STATIC_PLANE_PROXYTYPE: 1334 { 1335 const btStaticPlaneShape* staticPlaneShape = static_cast<const btStaticPlaneShape*>(shape); 1336 btScalar planeConst = staticPlaneShape->getPlaneConstant(); 1337 const btVector3& planeNormal = staticPlaneShape->getPlaneNormal(); 1338 getDebugDrawer()->drawPlane(planeNormal, planeConst,worldTransform, color); 1339 break; 1340 1341 } 1342 default: 1343 { 1344 1345 /// for polyhedral shapes 1346 if (shape->isPolyhedral()) 1347 { 1348 btPolyhedralConvexShape* polyshape = (btPolyhedralConvexShape*) shape; 1349 1350 int i; 1351 if (polyshape->getConvexPolyhedron()) 1352 { 1353 const btConvexPolyhedron* poly = polyshape->getConvexPolyhedron(); 1354 for (i=0;i<poly->m_faces.size();i++) 1355 { 1356 btVector3 centroid(0,0,0); 1357 int numVerts = poly->m_faces[i].m_indices.size(); 1358 if (numVerts) 1359 { 1360 int lastV = poly->m_faces[i].m_indices[numVerts-1]; 1361 for (int v=0;v<poly->m_faces[i].m_indices.size();v++) 1362 { 1363 int curVert = poly->m_faces[i].m_indices[v]; 1364 centroid+=poly->m_vertices[curVert]; 1365 getDebugDrawer()->drawLine(worldTransform*poly->m_vertices[lastV],worldTransform*poly->m_vertices[curVert],color); 1366 lastV = curVert; 1367 } 1368 } 1369 centroid*= btScalar(1.f)/btScalar(numVerts); 1370 if (getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawNormals) 1371 { 1372 btVector3 normalColor(1,1,0); 1373 btVector3 faceNormal(poly->m_faces[i].m_plane[0],poly->m_faces[i].m_plane[1],poly->m_faces[i].m_plane[2]); 1374 getDebugDrawer()->drawLine(worldTransform*centroid,worldTransform*(centroid+faceNormal),normalColor); 1375 } 1376 1377 } 1378 1379 1380 } else 1381 { 1382 for (i=0;i<polyshape->getNumEdges();i++) 1383 { 1384 btVector3 a,b; 1385 polyshape->getEdge(i,a,b); 1386 btVector3 wa = worldTransform * a; 1387 btVector3 wb = worldTransform * b; 1388 getDebugDrawer()->drawLine(wa,wb,color); 1389 } 1390 } 1391 1392 1393 } 1394 1395 if (shape->isConcave()) 1396 { 1397 btConcaveShape* concaveMesh = (btConcaveShape*) shape; 1398 1399 ///@todo pass camera, for some culling? no -> we are not a graphics lib 1400 btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT)); 1401 btVector3 aabbMin(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT)); 1402 1403 DebugDrawcallback drawCallback(getDebugDrawer(),worldTransform,color); 1404 concaveMesh->processAllTriangles(&drawCallback,aabbMin,aabbMax); 1405 1406 } 1407 1408 if (shape->getShapeType() == CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE) 1409 { 1410 btConvexTriangleMeshShape* convexMesh = (btConvexTriangleMeshShape*) shape; 1411 //todo: pass camera for some culling 1412 btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT)); 1413 btVector3 aabbMin(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT)); 1414 //DebugDrawcallback drawCallback; 1415 DebugDrawcallback drawCallback(getDebugDrawer(),worldTransform,color); 1416 convexMesh->getMeshInterface()->InternalProcessAllTriangles(&drawCallback,aabbMin,aabbMax); 1417 } 1418 1419 1420 1421 } 1422 1423 } 1424 } 1425 } 1426 1427 1428 void btCollisionWorld::debugDrawWorld() 1429 { 1430 if (getDebugDrawer()) 1431 { 1432 btIDebugDraw::DefaultColors defaultColors = getDebugDrawer()->getDefaultColors(); 1433 1434 if ( getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawContactPoints) 1435 { 1436 1437 1438 if (getDispatcher()) 1439 { 1440 int numManifolds = getDispatcher()->getNumManifolds(); 1441 1442 for (int i=0;i<numManifolds;i++) 1443 { 1444 btPersistentManifold* contactManifold = getDispatcher()->getManifoldByIndexInternal(i); 1445 //btCollisionObject* obA = static_cast<btCollisionObject*>(contactManifold->getBody0()); 1446 //btCollisionObject* obB = static_cast<btCollisionObject*>(contactManifold->getBody1()); 1447 1448 int numContacts = contactManifold->getNumContacts(); 1449 for (int j=0;j<numContacts;j++) 1450 { 1451 btManifoldPoint& cp = contactManifold->getContactPoint(j); 1452 getDebugDrawer()->drawContactPoint(cp.m_positionWorldOnB,cp.m_normalWorldOnB,cp.getDistance(),cp.getLifeTime(),defaultColors.m_contactPoint); 1453 } 1454 } 1455 } 1456 } 1457 1458 if ((getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe | btIDebugDraw::DBG_DrawAabb))) 1459 { 1460 int i; 1461 1462 for ( i=0;i<m_collisionObjects.size();i++) 1463 { 1464 btCollisionObject* colObj = m_collisionObjects[i]; 1465 if ((colObj->getCollisionFlags() & btCollisionObject::CF_DISABLE_VISUALIZE_OBJECT)==0) 1466 { 1467 if (getDebugDrawer() && (getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawWireframe)) 1468 { 1469 btVector3 color(btScalar(0.4),btScalar(0.4),btScalar(0.4)); 1470 1471 switch(colObj->getActivationState()) 1472 { 1473 case ACTIVE_TAG: 1474 color = defaultColors.m_activeObject; break; 1475 case ISLAND_SLEEPING: 1476 color = defaultColors.m_deactivatedObject;break; 1477 case WANTS_DEACTIVATION: 1478 color = defaultColors.m_wantsDeactivationObject;break; 1479 case DISABLE_DEACTIVATION: 1480 color = defaultColors.m_disabledDeactivationObject;break; 1481 case DISABLE_SIMULATION: 1482 color = defaultColors.m_disabledSimulationObject;break; 1483 default: 1484 { 1485 color = btVector3(btScalar(.3),btScalar(0.3),btScalar(0.3)); 1486 } 1487 }; 1488 1489 debugDrawObject(colObj->getWorldTransform(),colObj->getCollisionShape(),color); 1490 } 1491 if (m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawAabb)) 1492 { 1493 btVector3 minAabb,maxAabb; 1494 btVector3 colorvec = defaultColors.m_aabb; 1495 colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb,maxAabb); 1496 btVector3 contactThreshold(gContactBreakingThreshold,gContactBreakingThreshold,gContactBreakingThreshold); 1497 minAabb -= contactThreshold; 1498 maxAabb += contactThreshold; 1499 1500 btVector3 minAabb2,maxAabb2; 1501 1502 if(getDispatchInfo().m_useContinuous && colObj->getInternalType()==btCollisionObject::CO_RIGID_BODY && !colObj->isStaticOrKinematicObject()) 1503 { 1504 colObj->getCollisionShape()->getAabb(colObj->getInterpolationWorldTransform(),minAabb2,maxAabb2); 1505 minAabb2 -= contactThreshold; 1506 maxAabb2 += contactThreshold; 1507 minAabb.setMin(minAabb2); 1508 maxAabb.setMax(maxAabb2); 1509 } 1510 1511 m_debugDrawer->drawAabb(minAabb,maxAabb,colorvec); 1512 } 1513 } 1514 } 1515 } 1516 } 1517 } 1518 1519 1520 void btCollisionWorld::serializeCollisionObjects(btSerializer* serializer) 1521 { 1522 int i; 1523 1524 ///keep track of shapes already serialized 1525 btHashMap<btHashPtr,btCollisionShape*> serializedShapes; 1526 1527 for (i=0;i<m_collisionObjects.size();i++) 1528 { 1529 btCollisionObject* colObj = m_collisionObjects[i]; 1530 btCollisionShape* shape = colObj->getCollisionShape(); 1531 1532 if (!serializedShapes.find(shape)) 1533 { 1534 serializedShapes.insert(shape,shape); 1535 shape->serializeSingleShape(serializer); 1536 } 1537 } 1538 1539 //serialize all collision objects 1540 for (i=0;i<m_collisionObjects.size();i++) 1541 { 1542 btCollisionObject* colObj = m_collisionObjects[i]; 1543 if ((colObj->getInternalType() == btCollisionObject::CO_COLLISION_OBJECT) || (colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK)) 1544 { 1545 colObj->serializeSingleObject(serializer); 1546 } 1547 } 1548 } 1549 1550 1551 void btCollisionWorld::serialize(btSerializer* serializer) 1552 { 1553 1554 serializer->startSerialization(); 1555 1556 serializeCollisionObjects(serializer); 1557 1558 serializer->finishSerialization(); 1559 } 1560 1561