PageRenderTime 28ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 1ms

/ExtLibs/bullet/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp

https://bitbucket.org/lennonchan/cafu
C++ | 846 lines | 595 code | 164 blank | 87 comment | 50 complexity | f088159983aa73f3f4ee7c315bc14b00 MD5 | raw file
  1. /*
  2. Bullet Continuous Collision Detection and Physics Library
  3. Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
  4. This software is provided 'as-is', without any express or implied warranty.
  5. In no event will the authors be held liable for any damages arising from the use of this software.
  6. Permission is granted to anyone to use this software for any purpose,
  7. including commercial applications, and to alter it and redistribute it freely,
  8. subject to the following restrictions:
  9. 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.
  10. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
  11. 3. This notice may not be removed or altered from any source distribution.
  12. */
  13. #include "btCollisionWorld.h"
  14. #include "btCollisionDispatcher.h"
  15. #include "BulletCollision/CollisionDispatch/btCollisionObject.h"
  16. #include "BulletCollision/CollisionShapes/btCollisionShape.h"
  17. #include "BulletCollision/CollisionShapes/btConvexShape.h"
  18. #include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h"
  19. #include "BulletCollision/CollisionShapes/btSphereShape.h" //for raycasting
  20. #include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h" //for raycasting
  21. #include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h"
  22. #include "BulletCollision/CollisionShapes/btCompoundShape.h"
  23. #include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
  24. #include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h"
  25. #include "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h"
  26. #include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
  27. #include "LinearMath/btAabbUtil2.h"
  28. #include "LinearMath/btQuickprof.h"
  29. #include "LinearMath/btStackAlloc.h"
  30. //#define USE_BRUTEFORCE_RAYBROADPHASE 1
  31. //RECALCULATE_AABB is slower, but benefit is that you don't need to call 'stepSimulation' or 'updateAabbs' before using a rayTest
  32. //#define RECALCULATE_AABB_RAYCAST 1
  33. //When the user doesn't provide dispatcher or broadphase, create basic versions (and delete them in destructor)
  34. #include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
  35. #include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h"
  36. #include "BulletCollision/CollisionDispatch/btCollisionConfiguration.h"
  37. btCollisionWorld::btCollisionWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache, btCollisionConfiguration* collisionConfiguration)
  38. :m_dispatcher1(dispatcher),
  39. m_broadphasePairCache(pairCache),
  40. m_debugDrawer(0),
  41. m_forceUpdateAllAabbs(true)
  42. {
  43. m_stackAlloc = collisionConfiguration->getStackAllocator();
  44. m_dispatchInfo.m_stackAllocator = m_stackAlloc;
  45. }
  46. btCollisionWorld::~btCollisionWorld()
  47. {
  48. //clean up remaining objects
  49. int i;
  50. for (i=0;i<m_collisionObjects.size();i++)
  51. {
  52. btCollisionObject* collisionObject= m_collisionObjects[i];
  53. btBroadphaseProxy* bp = collisionObject->getBroadphaseHandle();
  54. if (bp)
  55. {
  56. //
  57. // only clear the cached algorithms
  58. //
  59. getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(bp,m_dispatcher1);
  60. getBroadphase()->destroyProxy(bp,m_dispatcher1);
  61. collisionObject->setBroadphaseHandle(0);
  62. }
  63. }
  64. }
  65. void btCollisionWorld::addCollisionObject(btCollisionObject* collisionObject,short int collisionFilterGroup,short int collisionFilterMask)
  66. {
  67. btAssert(collisionObject);
  68. //check that the object isn't already added
  69. btAssert( m_collisionObjects.findLinearSearch(collisionObject) == m_collisionObjects.size());
  70. m_collisionObjects.push_back(collisionObject);
  71. //calculate new AABB
  72. btTransform trans = collisionObject->getWorldTransform();
  73. btVector3 minAabb;
  74. btVector3 maxAabb;
  75. collisionObject->getCollisionShape()->getAabb(trans,minAabb,maxAabb);
  76. int type = collisionObject->getCollisionShape()->getShapeType();
  77. collisionObject->setBroadphaseHandle( getBroadphase()->createProxy(
  78. minAabb,
  79. maxAabb,
  80. type,
  81. collisionObject,
  82. collisionFilterGroup,
  83. collisionFilterMask,
  84. m_dispatcher1,0
  85. )) ;
  86. }
  87. void btCollisionWorld::updateSingleAabb(btCollisionObject* colObj)
  88. {
  89. btVector3 minAabb,maxAabb;
  90. colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb,maxAabb);
  91. //need to increase the aabb for contact thresholds
  92. btVector3 contactThreshold(gContactBreakingThreshold,gContactBreakingThreshold,gContactBreakingThreshold);
  93. minAabb -= contactThreshold;
  94. maxAabb += contactThreshold;
  95. btBroadphaseInterface* bp = (btBroadphaseInterface*)m_broadphasePairCache;
  96. //moving objects should be moderately sized, probably something wrong if not
  97. if ( colObj->isStaticObject() || ((maxAabb-minAabb).length2() < btScalar(1e12)))
  98. {
  99. bp->setAabb(colObj->getBroadphaseHandle(),minAabb,maxAabb, m_dispatcher1);
  100. } else
  101. {
  102. //something went wrong, investigate
  103. //this assert is unwanted in 3D modelers (danger of loosing work)
  104. colObj->setActivationState(DISABLE_SIMULATION);
  105. static bool reportMe = true;
  106. if (reportMe && m_debugDrawer)
  107. {
  108. reportMe = false;
  109. m_debugDrawer->reportErrorWarning("Overflow in AABB, object removed from simulation");
  110. m_debugDrawer->reportErrorWarning("If you can reproduce this, please email bugs@continuousphysics.com\n");
  111. m_debugDrawer->reportErrorWarning("Please include above information, your Platform, version of OS.\n");
  112. m_debugDrawer->reportErrorWarning("Thanks.\n");
  113. }
  114. }
  115. }
  116. void btCollisionWorld::updateAabbs()
  117. {
  118. BT_PROFILE("updateAabbs");
  119. btTransform predictedTrans;
  120. for ( int i=0;i<m_collisionObjects.size();i++)
  121. {
  122. btCollisionObject* colObj = m_collisionObjects[i];
  123. //only update aabb of active objects
  124. if (m_forceUpdateAllAabbs || colObj->isActive())
  125. {
  126. updateSingleAabb(colObj);
  127. }
  128. }
  129. }
  130. void btCollisionWorld::performDiscreteCollisionDetection()
  131. {
  132. BT_PROFILE("performDiscreteCollisionDetection");
  133. btDispatcherInfo& dispatchInfo = getDispatchInfo();
  134. updateAabbs();
  135. {
  136. BT_PROFILE("calculateOverlappingPairs");
  137. m_broadphasePairCache->calculateOverlappingPairs(m_dispatcher1);
  138. }
  139. btDispatcher* dispatcher = getDispatcher();
  140. {
  141. BT_PROFILE("dispatchAllCollisionPairs");
  142. if (dispatcher)
  143. dispatcher->dispatchAllCollisionPairs(m_broadphasePairCache->getOverlappingPairCache(),dispatchInfo,m_dispatcher1);
  144. }
  145. }
  146. void btCollisionWorld::removeCollisionObject(btCollisionObject* collisionObject)
  147. {
  148. //bool removeFromBroadphase = false;
  149. {
  150. btBroadphaseProxy* bp = collisionObject->getBroadphaseHandle();
  151. if (bp)
  152. {
  153. //
  154. // only clear the cached algorithms
  155. //
  156. getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(bp,m_dispatcher1);
  157. getBroadphase()->destroyProxy(bp,m_dispatcher1);
  158. collisionObject->setBroadphaseHandle(0);
  159. }
  160. }
  161. //swapremove
  162. m_collisionObjects.remove(collisionObject);
  163. }
  164. void btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans,const btTransform& rayToTrans,
  165. btCollisionObject* collisionObject,
  166. const btCollisionShape* collisionShape,
  167. const btTransform& colObjWorldTransform,
  168. RayResultCallback& resultCallback)
  169. {
  170. btSphereShape pointShape(btScalar(0.0));
  171. pointShape.setMargin(0.f);
  172. const btConvexShape* castShape = &pointShape;
  173. if (collisionShape->isConvex())
  174. {
  175. // BT_PROFILE("rayTestConvex");
  176. btConvexCast::CastResult castResult;
  177. castResult.m_fraction = resultCallback.m_closestHitFraction;
  178. btConvexShape* convexShape = (btConvexShape*) collisionShape;
  179. btVoronoiSimplexSolver simplexSolver;
  180. #define USE_SUBSIMPLEX_CONVEX_CAST 1
  181. #ifdef USE_SUBSIMPLEX_CONVEX_CAST
  182. btSubsimplexConvexCast convexCaster(castShape,convexShape,&simplexSolver);
  183. #else
  184. //btGjkConvexCast convexCaster(castShape,convexShape,&simplexSolver);
  185. //btContinuousConvexCollision convexCaster(castShape,convexShape,&simplexSolver,0);
  186. #endif //#USE_SUBSIMPLEX_CONVEX_CAST
  187. if (convexCaster.calcTimeOfImpact(rayFromTrans,rayToTrans,colObjWorldTransform,colObjWorldTransform,castResult))
  188. {
  189. //add hit
  190. if (castResult.m_normal.length2() > btScalar(0.0001))
  191. {
  192. if (castResult.m_fraction < resultCallback.m_closestHitFraction)
  193. {
  194. #ifdef USE_SUBSIMPLEX_CONVEX_CAST
  195. //rotate normal into worldspace
  196. castResult.m_normal = rayFromTrans.getBasis() * castResult.m_normal;
  197. #endif //USE_SUBSIMPLEX_CONVEX_CAST
  198. castResult.m_normal.normalize();
  199. btCollisionWorld::LocalRayResult localRayResult
  200. (
  201. collisionObject,
  202. 0,
  203. castResult.m_normal,
  204. castResult.m_fraction
  205. );
  206. bool normalInWorldSpace = true;
  207. resultCallback.addSingleResult(localRayResult, normalInWorldSpace);
  208. }
  209. }
  210. }
  211. } else {
  212. if (collisionShape->isConcave())
  213. {
  214. // BT_PROFILE("rayTestConcave");
  215. if (collisionShape->getShapeType()==TRIANGLE_MESH_SHAPE_PROXYTYPE)
  216. {
  217. ///optimized version for btBvhTriangleMeshShape
  218. btBvhTriangleMeshShape* triangleMesh = (btBvhTriangleMeshShape*)collisionShape;
  219. btTransform worldTocollisionObject = colObjWorldTransform.inverse();
  220. btVector3 rayFromLocal = worldTocollisionObject * rayFromTrans.getOrigin();
  221. btVector3 rayToLocal = worldTocollisionObject * rayToTrans.getOrigin();
  222. //ConvexCast::CastResult
  223. struct BridgeTriangleRaycastCallback : public btTriangleRaycastCallback
  224. {
  225. btCollisionWorld::RayResultCallback* m_resultCallback;
  226. btCollisionObject* m_collisionObject;
  227. btTriangleMeshShape* m_triangleMesh;
  228. btTransform m_colObjWorldTransform;
  229. BridgeTriangleRaycastCallback( const btVector3& from,const btVector3& to,
  230. btCollisionWorld::RayResultCallback* resultCallback, btCollisionObject* collisionObject,btTriangleMeshShape* triangleMesh,const btTransform& colObjWorldTransform):
  231. //@BP Mod
  232. btTriangleRaycastCallback(from,to, resultCallback->m_flags),
  233. m_resultCallback(resultCallback),
  234. m_collisionObject(collisionObject),
  235. m_triangleMesh(triangleMesh),
  236. m_colObjWorldTransform(colObjWorldTransform)
  237. {
  238. }
  239. virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex )
  240. {
  241. btCollisionWorld::LocalShapeInfo shapeInfo;
  242. shapeInfo.m_shapePart = partId;
  243. shapeInfo.m_triangleIndex = triangleIndex;
  244. btVector3 hitNormalWorld = m_colObjWorldTransform.getBasis() * hitNormalLocal;
  245. btCollisionWorld::LocalRayResult rayResult
  246. (m_collisionObject,
  247. &shapeInfo,
  248. hitNormalWorld,
  249. hitFraction);
  250. bool normalInWorldSpace = true;
  251. return m_resultCallback->addSingleResult(rayResult,normalInWorldSpace);
  252. }
  253. };
  254. BridgeTriangleRaycastCallback rcb(rayFromLocal,rayToLocal,&resultCallback,collisionObject,triangleMesh,colObjWorldTransform);
  255. rcb.m_hitFraction = resultCallback.m_closestHitFraction;
  256. triangleMesh->performRaycast(&rcb,rayFromLocal,rayToLocal);
  257. } else
  258. {
  259. //generic (slower) case
  260. btConcaveShape* concaveShape = (btConcaveShape*)collisionShape;
  261. btTransform worldTocollisionObject = colObjWorldTransform.inverse();
  262. btVector3 rayFromLocal = worldTocollisionObject * rayFromTrans.getOrigin();
  263. btVector3 rayToLocal = worldTocollisionObject * rayToTrans.getOrigin();
  264. //ConvexCast::CastResult
  265. struct BridgeTriangleRaycastCallback : public btTriangleRaycastCallback
  266. {
  267. btCollisionWorld::RayResultCallback* m_resultCallback;
  268. btCollisionObject* m_collisionObject;
  269. btConcaveShape* m_triangleMesh;
  270. btTransform m_colObjWorldTransform;
  271. BridgeTriangleRaycastCallback( const btVector3& from,const btVector3& to,
  272. btCollisionWorld::RayResultCallback* resultCallback, btCollisionObject* collisionObject,btConcaveShape* triangleMesh, const btTransform& colObjWorldTransform):
  273. //@BP Mod
  274. btTriangleRaycastCallback(from,to, resultCallback->m_flags),
  275. m_resultCallback(resultCallback),
  276. m_collisionObject(collisionObject),
  277. m_triangleMesh(triangleMesh),
  278. m_colObjWorldTransform(colObjWorldTransform)
  279. {
  280. }
  281. virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex )
  282. {
  283. btCollisionWorld::LocalShapeInfo shapeInfo;
  284. shapeInfo.m_shapePart = partId;
  285. shapeInfo.m_triangleIndex = triangleIndex;
  286. btVector3 hitNormalWorld = m_colObjWorldTransform.getBasis() * hitNormalLocal;
  287. btCollisionWorld::LocalRayResult rayResult
  288. (m_collisionObject,
  289. &shapeInfo,
  290. hitNormalWorld,
  291. hitFraction);
  292. bool normalInWorldSpace = true;
  293. return m_resultCallback->addSingleResult(rayResult,normalInWorldSpace);
  294. }
  295. };
  296. BridgeTriangleRaycastCallback rcb(rayFromLocal,rayToLocal,&resultCallback,collisionObject,concaveShape, colObjWorldTransform);
  297. rcb.m_hitFraction = resultCallback.m_closestHitFraction;
  298. btVector3 rayAabbMinLocal = rayFromLocal;
  299. rayAabbMinLocal.setMin(rayToLocal);
  300. btVector3 rayAabbMaxLocal = rayFromLocal;
  301. rayAabbMaxLocal.setMax(rayToLocal);
  302. concaveShape->processAllTriangles(&rcb,rayAabbMinLocal,rayAabbMaxLocal);
  303. }
  304. } else {
  305. // BT_PROFILE("rayTestCompound");
  306. ///@todo: use AABB tree or other BVH acceleration structure, see btDbvt
  307. if (collisionShape->isCompound())
  308. {
  309. const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(collisionShape);
  310. int i=0;
  311. for (i=0;i<compoundShape->getNumChildShapes();i++)
  312. {
  313. btTransform childTrans = compoundShape->getChildTransform(i);
  314. const btCollisionShape* childCollisionShape = compoundShape->getChildShape(i);
  315. btTransform childWorldTrans = colObjWorldTransform * childTrans;
  316. // replace collision shape so that callback can determine the triangle
  317. btCollisionShape* saveCollisionShape = collisionObject->getCollisionShape();
  318. collisionObject->internalSetTemporaryCollisionShape((btCollisionShape*)childCollisionShape);
  319. rayTestSingle(rayFromTrans,rayToTrans,
  320. collisionObject,
  321. childCollisionShape,
  322. childWorldTrans,
  323. resultCallback);
  324. // restore
  325. collisionObject->internalSetTemporaryCollisionShape(saveCollisionShape);
  326. }
  327. }
  328. }
  329. }
  330. }
  331. void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const btTransform& convexFromTrans,const btTransform& convexToTrans,
  332. btCollisionObject* collisionObject,
  333. const btCollisionShape* collisionShape,
  334. const btTransform& colObjWorldTransform,
  335. ConvexResultCallback& resultCallback, btScalar allowedPenetration)
  336. {
  337. if (collisionShape->isConvex())
  338. {
  339. //BT_PROFILE("convexSweepConvex");
  340. btConvexCast::CastResult castResult;
  341. castResult.m_allowedPenetration = allowedPenetration;
  342. castResult.m_fraction = resultCallback.m_closestHitFraction;//btScalar(1.);//??
  343. btConvexShape* convexShape = (btConvexShape*) collisionShape;
  344. btVoronoiSimplexSolver simplexSolver;
  345. btGjkEpaPenetrationDepthSolver gjkEpaPenetrationSolver;
  346. btContinuousConvexCollision convexCaster1(castShape,convexShape,&simplexSolver,&gjkEpaPenetrationSolver);
  347. //btGjkConvexCast convexCaster2(castShape,convexShape,&simplexSolver);
  348. //btSubsimplexConvexCast convexCaster3(castShape,convexShape,&simplexSolver);
  349. btConvexCast* castPtr = &convexCaster1;
  350. if (castPtr->calcTimeOfImpact(convexFromTrans,convexToTrans,colObjWorldTransform,colObjWorldTransform,castResult))
  351. {
  352. //add hit
  353. if (castResult.m_normal.length2() > btScalar(0.0001))
  354. {
  355. if (castResult.m_fraction < resultCallback.m_closestHitFraction)
  356. {
  357. castResult.m_normal.normalize();
  358. btCollisionWorld::LocalConvexResult localConvexResult
  359. (
  360. collisionObject,
  361. 0,
  362. castResult.m_normal,
  363. castResult.m_hitPoint,
  364. castResult.m_fraction
  365. );
  366. bool normalInWorldSpace = true;
  367. resultCallback.addSingleResult(localConvexResult, normalInWorldSpace);
  368. }
  369. }
  370. }
  371. } else {
  372. if (collisionShape->isConcave())
  373. {
  374. if (collisionShape->getShapeType()==TRIANGLE_MESH_SHAPE_PROXYTYPE)
  375. {
  376. //BT_PROFILE("convexSweepbtBvhTriangleMesh");
  377. btBvhTriangleMeshShape* triangleMesh = (btBvhTriangleMeshShape*)collisionShape;
  378. btTransform worldTocollisionObject = colObjWorldTransform.inverse();
  379. btVector3 convexFromLocal = worldTocollisionObject * convexFromTrans.getOrigin();
  380. btVector3 convexToLocal = worldTocollisionObject * convexToTrans.getOrigin();
  381. // rotation of box in local mesh space = MeshRotation^-1 * ConvexToRotation
  382. btTransform rotationXform = btTransform(worldTocollisionObject.getBasis() * convexToTrans.getBasis());
  383. //ConvexCast::CastResult
  384. struct BridgeTriangleConvexcastCallback : public btTriangleConvexcastCallback
  385. {
  386. btCollisionWorld::ConvexResultCallback* m_resultCallback;
  387. btCollisionObject* m_collisionObject;
  388. btTriangleMeshShape* m_triangleMesh;
  389. BridgeTriangleConvexcastCallback(const btConvexShape* castShape, const btTransform& from,const btTransform& to,
  390. btCollisionWorld::ConvexResultCallback* resultCallback, btCollisionObject* collisionObject,btTriangleMeshShape* triangleMesh, const btTransform& triangleToWorld):
  391. btTriangleConvexcastCallback(castShape, from,to, triangleToWorld, triangleMesh->getMargin()),
  392. m_resultCallback(resultCallback),
  393. m_collisionObject(collisionObject),
  394. m_triangleMesh(triangleMesh)
  395. {
  396. }
  397. virtual btScalar reportHit(const btVector3& hitNormalLocal, const btVector3& hitPointLocal, btScalar hitFraction, int partId, int triangleIndex )
  398. {
  399. btCollisionWorld::LocalShapeInfo shapeInfo;
  400. shapeInfo.m_shapePart = partId;
  401. shapeInfo.m_triangleIndex = triangleIndex;
  402. if (hitFraction <= m_resultCallback->m_closestHitFraction)
  403. {
  404. btCollisionWorld::LocalConvexResult convexResult
  405. (m_collisionObject,
  406. &shapeInfo,
  407. hitNormalLocal,
  408. hitPointLocal,
  409. hitFraction);
  410. bool normalInWorldSpace = true;
  411. return m_resultCallback->addSingleResult(convexResult,normalInWorldSpace);
  412. }
  413. return hitFraction;
  414. }
  415. };
  416. BridgeTriangleConvexcastCallback tccb(castShape, convexFromTrans,convexToTrans,&resultCallback,collisionObject,triangleMesh, colObjWorldTransform);
  417. tccb.m_hitFraction = resultCallback.m_closestHitFraction;
  418. btVector3 boxMinLocal, boxMaxLocal;
  419. castShape->getAabb(rotationXform, boxMinLocal, boxMaxLocal);
  420. triangleMesh->performConvexcast(&tccb,convexFromLocal,convexToLocal,boxMinLocal, boxMaxLocal);
  421. } else
  422. {
  423. //BT_PROFILE("convexSweepConcave");
  424. btConcaveShape* concaveShape = (btConcaveShape*)collisionShape;
  425. btTransform worldTocollisionObject = colObjWorldTransform.inverse();
  426. btVector3 convexFromLocal = worldTocollisionObject * convexFromTrans.getOrigin();
  427. btVector3 convexToLocal = worldTocollisionObject * convexToTrans.getOrigin();
  428. // rotation of box in local mesh space = MeshRotation^-1 * ConvexToRotation
  429. btTransform rotationXform = btTransform(worldTocollisionObject.getBasis() * convexToTrans.getBasis());
  430. //ConvexCast::CastResult
  431. struct BridgeTriangleConvexcastCallback : public btTriangleConvexcastCallback
  432. {
  433. btCollisionWorld::ConvexResultCallback* m_resultCallback;
  434. btCollisionObject* m_collisionObject;
  435. btConcaveShape* m_triangleMesh;
  436. BridgeTriangleConvexcastCallback(const btConvexShape* castShape, const btTransform& from,const btTransform& to,
  437. btCollisionWorld::ConvexResultCallback* resultCallback, btCollisionObject* collisionObject,btConcaveShape* triangleMesh, const btTransform& triangleToWorld):
  438. btTriangleConvexcastCallback(castShape, from,to, triangleToWorld, triangleMesh->getMargin()),
  439. m_resultCallback(resultCallback),
  440. m_collisionObject(collisionObject),
  441. m_triangleMesh(triangleMesh)
  442. {
  443. }
  444. virtual btScalar reportHit(const btVector3& hitNormalLocal, const btVector3& hitPointLocal, btScalar hitFraction, int partId, int triangleIndex )
  445. {
  446. btCollisionWorld::LocalShapeInfo shapeInfo;
  447. shapeInfo.m_shapePart = partId;
  448. shapeInfo.m_triangleIndex = triangleIndex;
  449. if (hitFraction <= m_resultCallback->m_closestHitFraction)
  450. {
  451. btCollisionWorld::LocalConvexResult convexResult
  452. (m_collisionObject,
  453. &shapeInfo,
  454. hitNormalLocal,
  455. hitPointLocal,
  456. hitFraction);
  457. bool normalInWorldSpace = false;
  458. return m_resultCallback->addSingleResult(convexResult,normalInWorldSpace);
  459. }
  460. return hitFraction;
  461. }
  462. };
  463. BridgeTriangleConvexcastCallback tccb(castShape, convexFromTrans,convexToTrans,&resultCallback,collisionObject,concaveShape, colObjWorldTransform);
  464. tccb.m_hitFraction = resultCallback.m_closestHitFraction;
  465. btVector3 boxMinLocal, boxMaxLocal;
  466. castShape->getAabb(rotationXform, boxMinLocal, boxMaxLocal);
  467. btVector3 rayAabbMinLocal = convexFromLocal;
  468. rayAabbMinLocal.setMin(convexToLocal);
  469. btVector3 rayAabbMaxLocal = convexFromLocal;
  470. rayAabbMaxLocal.setMax(convexToLocal);
  471. rayAabbMinLocal += boxMinLocal;
  472. rayAabbMaxLocal += boxMaxLocal;
  473. concaveShape->processAllTriangles(&tccb,rayAabbMinLocal,rayAabbMaxLocal);
  474. }
  475. } else {
  476. ///@todo : use AABB tree or other BVH acceleration structure!
  477. if (collisionShape->isCompound())
  478. {
  479. BT_PROFILE("convexSweepCompound");
  480. const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(collisionShape);
  481. int i=0;
  482. for (i=0;i<compoundShape->getNumChildShapes();i++)
  483. {
  484. btTransform childTrans = compoundShape->getChildTransform(i);
  485. const btCollisionShape* childCollisionShape = compoundShape->getChildShape(i);
  486. btTransform childWorldTrans = colObjWorldTransform * childTrans;
  487. // replace collision shape so that callback can determine the triangle
  488. btCollisionShape* saveCollisionShape = collisionObject->getCollisionShape();
  489. collisionObject->internalSetTemporaryCollisionShape((btCollisionShape*)childCollisionShape);
  490. objectQuerySingle(castShape, convexFromTrans,convexToTrans,
  491. collisionObject,
  492. childCollisionShape,
  493. childWorldTrans,
  494. resultCallback, allowedPenetration);
  495. // restore
  496. collisionObject->internalSetTemporaryCollisionShape(saveCollisionShape);
  497. }
  498. }
  499. }
  500. }
  501. }
  502. struct btSingleRayCallback : public btBroadphaseRayCallback
  503. {
  504. btVector3 m_rayFromWorld;
  505. btVector3 m_rayToWorld;
  506. btTransform m_rayFromTrans;
  507. btTransform m_rayToTrans;
  508. btVector3 m_hitNormal;
  509. const btCollisionWorld* m_world;
  510. btCollisionWorld::RayResultCallback& m_resultCallback;
  511. btSingleRayCallback(const btVector3& rayFromWorld,const btVector3& rayToWorld,const btCollisionWorld* world,btCollisionWorld::RayResultCallback& resultCallback)
  512. :m_rayFromWorld(rayFromWorld),
  513. m_rayToWorld(rayToWorld),
  514. m_world(world),
  515. m_resultCallback(resultCallback)
  516. {
  517. m_rayFromTrans.setIdentity();
  518. m_rayFromTrans.setOrigin(m_rayFromWorld);
  519. m_rayToTrans.setIdentity();
  520. m_rayToTrans.setOrigin(m_rayToWorld);
  521. btVector3 rayDir = (rayToWorld-rayFromWorld);
  522. rayDir.normalize ();
  523. ///what about division by zero? --> just set rayDirection[i] to INF/BT_LARGE_FLOAT
  524. m_rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[0];
  525. m_rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[1];
  526. m_rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[2];
  527. m_signs[0] = m_rayDirectionInverse[0] < 0.0;
  528. m_signs[1] = m_rayDirectionInverse[1] < 0.0;
  529. m_signs[2] = m_rayDirectionInverse[2] < 0.0;
  530. m_lambda_max = rayDir.dot(m_rayToWorld-m_rayFromWorld);
  531. }
  532. virtual bool process(const btBroadphaseProxy* proxy)
  533. {
  534. ///terminate further ray tests, once the closestHitFraction reached zero
  535. if (m_resultCallback.m_closestHitFraction == btScalar(0.f))
  536. return false;
  537. btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject;
  538. //only perform raycast if filterMask matches
  539. if(m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
  540. {
  541. //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
  542. //btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
  543. #if 0
  544. #ifdef RECALCULATE_AABB
  545. btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
  546. collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax);
  547. #else
  548. //getBroadphase()->getAabb(collisionObject->getBroadphaseHandle(),collisionObjectAabbMin,collisionObjectAabbMax);
  549. const btVector3& collisionObjectAabbMin = collisionObject->getBroadphaseHandle()->m_aabbMin;
  550. const btVector3& collisionObjectAabbMax = collisionObject->getBroadphaseHandle()->m_aabbMax;
  551. #endif
  552. #endif
  553. //btScalar hitLambda = m_resultCallback.m_closestHitFraction;
  554. //culling already done by broadphase
  555. //if (btRayAabb(m_rayFromWorld,m_rayToWorld,collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,m_hitNormal))
  556. {
  557. m_world->rayTestSingle(m_rayFromTrans,m_rayToTrans,
  558. collisionObject,
  559. collisionObject->getCollisionShape(),
  560. collisionObject->getWorldTransform(),
  561. m_resultCallback);
  562. }
  563. }
  564. return true;
  565. }
  566. };
  567. void btCollisionWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const
  568. {
  569. //BT_PROFILE("rayTest");
  570. /// use the broadphase to accelerate the search for objects, based on their aabb
  571. /// and for each object with ray-aabb overlap, perform an exact ray test
  572. btSingleRayCallback rayCB(rayFromWorld,rayToWorld,this,resultCallback);
  573. #ifndef USE_BRUTEFORCE_RAYBROADPHASE
  574. m_broadphasePairCache->rayTest(rayFromWorld,rayToWorld,rayCB);
  575. #else
  576. for (int i=0;i<this->getNumCollisionObjects();i++)
  577. {
  578. rayCB.process(m_collisionObjects[i]->getBroadphaseHandle());
  579. }
  580. #endif //USE_BRUTEFORCE_RAYBROADPHASE
  581. }
  582. struct btSingleSweepCallback : public btBroadphaseRayCallback
  583. {
  584. btTransform m_convexFromTrans;
  585. btTransform m_convexToTrans;
  586. btVector3 m_hitNormal;
  587. const btCollisionWorld* m_world;
  588. btCollisionWorld::ConvexResultCallback& m_resultCallback;
  589. btScalar m_allowedCcdPenetration;
  590. const btConvexShape* m_castShape;
  591. btSingleSweepCallback(const btConvexShape* castShape, const btTransform& convexFromTrans,const btTransform& convexToTrans,const btCollisionWorld* world,btCollisionWorld::ConvexResultCallback& resultCallback,btScalar allowedPenetration)
  592. :m_convexFromTrans(convexFromTrans),
  593. m_convexToTrans(convexToTrans),
  594. m_world(world),
  595. m_resultCallback(resultCallback),
  596. m_allowedCcdPenetration(allowedPenetration),
  597. m_castShape(castShape)
  598. {
  599. btVector3 unnormalizedRayDir = (m_convexToTrans.getOrigin()-m_convexFromTrans.getOrigin());
  600. btVector3 rayDir = unnormalizedRayDir.normalized();
  601. ///what about division by zero? --> just set rayDirection[i] to INF/BT_LARGE_FLOAT
  602. m_rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[0];
  603. m_rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[1];
  604. m_rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[2];
  605. m_signs[0] = m_rayDirectionInverse[0] < 0.0;
  606. m_signs[1] = m_rayDirectionInverse[1] < 0.0;
  607. m_signs[2] = m_rayDirectionInverse[2] < 0.0;
  608. m_lambda_max = rayDir.dot(unnormalizedRayDir);
  609. }
  610. virtual bool process(const btBroadphaseProxy* proxy)
  611. {
  612. ///terminate further convex sweep tests, once the closestHitFraction reached zero
  613. if (m_resultCallback.m_closestHitFraction == btScalar(0.f))
  614. return false;
  615. btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject;
  616. //only perform raycast if filterMask matches
  617. if(m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle())) {
  618. //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
  619. m_world->objectQuerySingle(m_castShape, m_convexFromTrans,m_convexToTrans,
  620. collisionObject,
  621. collisionObject->getCollisionShape(),
  622. collisionObject->getWorldTransform(),
  623. m_resultCallback,
  624. m_allowedCcdPenetration);
  625. }
  626. return true;
  627. }
  628. };
  629. void btCollisionWorld::convexSweepTest(const btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, ConvexResultCallback& resultCallback, btScalar allowedCcdPenetration) const
  630. {
  631. BT_PROFILE("convexSweepTest");
  632. /// use the broadphase to accelerate the search for objects, based on their aabb
  633. /// and for each object with ray-aabb overlap, perform an exact ray test
  634. /// unfortunately the implementation for rayTest and convexSweepTest duplicated, albeit practically identical
  635. btTransform convexFromTrans,convexToTrans;
  636. convexFromTrans = convexFromWorld;
  637. convexToTrans = convexToWorld;
  638. btVector3 castShapeAabbMin, castShapeAabbMax;
  639. /* Compute AABB that encompasses angular movement */
  640. {
  641. btVector3 linVel, angVel;
  642. btTransformUtil::calculateVelocity (convexFromTrans, convexToTrans, 1.0, linVel, angVel);
  643. btVector3 zeroLinVel;
  644. zeroLinVel.setValue(0,0,0);
  645. btTransform R;
  646. R.setIdentity ();
  647. R.setRotation (convexFromTrans.getRotation());
  648. castShape->calculateTemporalAabb (R, zeroLinVel, angVel, 1.0, castShapeAabbMin, castShapeAabbMax);
  649. }
  650. #ifndef USE_BRUTEFORCE_RAYBROADPHASE
  651. btSingleSweepCallback convexCB(castShape,convexFromWorld,convexToWorld,this,resultCallback,allowedCcdPenetration);
  652. m_broadphasePairCache->rayTest(convexFromTrans.getOrigin(),convexToTrans.getOrigin(),convexCB,castShapeAabbMin,castShapeAabbMax);
  653. #else
  654. /// go over all objects, and if the ray intersects their aabb + cast shape aabb,
  655. // do a ray-shape query using convexCaster (CCD)
  656. int i;
  657. for (i=0;i<m_collisionObjects.size();i++)
  658. {
  659. btCollisionObject* collisionObject= m_collisionObjects[i];
  660. //only perform raycast if filterMask matches
  661. if(resultCallback.needsCollision(collisionObject->getBroadphaseHandle())) {
  662. //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
  663. btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
  664. collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax);
  665. AabbExpand (collisionObjectAabbMin, collisionObjectAabbMax, castShapeAabbMin, castShapeAabbMax);
  666. btScalar hitLambda = btScalar(1.); //could use resultCallback.m_closestHitFraction, but needs testing
  667. btVector3 hitNormal;
  668. if (btRayAabb(convexFromWorld.getOrigin(),convexToWorld.getOrigin(),collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,hitNormal))
  669. {
  670. objectQuerySingle(castShape, convexFromTrans,convexToTrans,
  671. collisionObject,
  672. collisionObject->getCollisionShape(),
  673. collisionObject->getWorldTransform(),
  674. resultCallback,
  675. allowedCcdPenetration);
  676. }
  677. }
  678. }
  679. #endif //USE_BRUTEFORCE_RAYBROADPHASE
  680. }