2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2006 Erwin Coumans https://bulletphysics.org
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:
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.
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/CollisionShapes/btScaledBvhTriangleMeshShape.h" //for raycasting
25 #include "BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h" //for raycasting
26 #include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h"
27 #include "BulletCollision/CollisionShapes/btCompoundShape.h"
28 #include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
29 #include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h"
30 #include "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h"
31 #include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
32 #include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
33 #include "BulletCollision/BroadphaseCollision/btDbvt.h"
34 #include "LinearMath/btAabbUtil2.h"
35 #include "LinearMath/btQuickprof.h"
36 #include "LinearMath/btSerializer.h"
37 #include "BulletCollision/CollisionShapes/btConvexPolyhedron.h"
38 #include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
40 //#define DISABLE_DBVT_COMPOUNDSHAPE_RAYCAST_ACCELERATION
42 //#define USE_BRUTEFORCE_RAYBROADPHASE 1
43 //RECALCULATE_AABB is slower, but benefit is that you don't need to call 'stepSimulation' or 'updateAabbs' before using a rayTest
44 //#define RECALCULATE_AABB_RAYCAST 1
46 //When the user doesn't provide dispatcher or broadphase, create basic versions (and delete them in destructor)
47 #include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
48 #include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h"
49 #include "BulletCollision/CollisionDispatch/btCollisionConfiguration.h"
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"
67 btCollisionWorld::btCollisionWorld(btDispatcher* dispatcher, btBroadphaseInterface* pairCache, btCollisionConfiguration* collisionConfiguration)
68 : m_dispatcher1(dispatcher),
69 m_broadphasePairCache(pairCache),
71 m_forceUpdateAllAabbs(true)
75 btCollisionWorld::~btCollisionWorld()
77 //clean up remaining objects
79 for (i = 0; i < m_collisionObjects.size(); i++)
81 btCollisionObject* collisionObject = m_collisionObjects[i];
83 btBroadphaseProxy* bp = collisionObject->getBroadphaseHandle();
87 // only clear the cached algorithms
89 getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(bp, m_dispatcher1);
90 getBroadphase()->destroyProxy(bp, m_dispatcher1);
91 collisionObject->setBroadphaseHandle(0);
96 void btCollisionWorld::refreshBroadphaseProxy(btCollisionObject* collisionObject)
98 if (collisionObject->getBroadphaseHandle())
100 int collisionFilterGroup = collisionObject->getBroadphaseHandle()->m_collisionFilterGroup;
101 int collisionFilterMask = collisionObject->getBroadphaseHandle()->m_collisionFilterMask;
103 getBroadphase()->destroyProxy(collisionObject->getBroadphaseHandle(), getDispatcher());
106 btTransform trans = collisionObject->getWorldTransform();
110 collisionObject->getCollisionShape()->getAabb(trans, minAabb, maxAabb);
112 int type = collisionObject->getCollisionShape()->getShapeType();
113 collisionObject->setBroadphaseHandle(getBroadphase()->createProxy(
118 collisionFilterGroup,
124 void btCollisionWorld::addCollisionObject(btCollisionObject* collisionObject, int collisionFilterGroup, int collisionFilterMask)
126 btAssert(collisionObject);
128 //check that the object isn't already added
129 btAssert(m_collisionObjects.findLinearSearch(collisionObject) == m_collisionObjects.size());
130 btAssert(collisionObject->getWorldArrayIndex() == -1); // do not add the same object to more than one collision world
132 collisionObject->setWorldArrayIndex(m_collisionObjects.size());
133 m_collisionObjects.push_back(collisionObject);
136 btTransform trans = collisionObject->getWorldTransform();
140 collisionObject->getCollisionShape()->getAabb(trans, minAabb, maxAabb);
142 int type = collisionObject->getCollisionShape()->getShapeType();
143 collisionObject->setBroadphaseHandle(getBroadphase()->createProxy(
148 collisionFilterGroup,
153 void btCollisionWorld::updateSingleAabb(btCollisionObject* colObj)
155 btVector3 minAabb, maxAabb;
156 colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb, maxAabb);
157 //need to increase the aabb for contact thresholds
158 btVector3 contactThreshold(gContactBreakingThreshold, gContactBreakingThreshold, gContactBreakingThreshold);
159 minAabb -= contactThreshold;
160 maxAabb += contactThreshold;
162 if (getDispatchInfo().m_useContinuous && colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY && !colObj->isStaticOrKinematicObject())
164 btVector3 minAabb2, maxAabb2;
165 colObj->getCollisionShape()->getAabb(colObj->getInterpolationWorldTransform(), minAabb2, maxAabb2);
166 minAabb2 -= contactThreshold;
167 maxAabb2 += contactThreshold;
168 minAabb.setMin(minAabb2);
169 maxAabb.setMax(maxAabb2);
172 btBroadphaseInterface* bp = (btBroadphaseInterface*)m_broadphasePairCache;
174 //moving objects should be moderately sized, probably something wrong if not
175 if (colObj->isStaticObject() || ((maxAabb - minAabb).length2() < btScalar(1e12)))
177 bp->setAabb(colObj->getBroadphaseHandle(), minAabb, maxAabb, m_dispatcher1);
181 //something went wrong, investigate
182 //this assert is unwanted in 3D modelers (danger of loosing work)
183 colObj->setActivationState(DISABLE_SIMULATION);
185 static bool reportMe = true;
186 if (reportMe && m_debugDrawer)
189 m_debugDrawer->reportErrorWarning("Overflow in AABB, object removed from simulation");
190 m_debugDrawer->reportErrorWarning("If you can reproduce this, please email bugs@continuousphysics.com\n");
191 m_debugDrawer->reportErrorWarning("Please include above information, your Platform, version of OS.\n");
192 m_debugDrawer->reportErrorWarning("Thanks.\n");
197 void btCollisionWorld::updateAabbs()
199 BT_PROFILE("updateAabbs");
201 for (int i = 0; i < m_collisionObjects.size(); i++)
203 btCollisionObject* colObj = m_collisionObjects[i];
204 btAssert(colObj->getWorldArrayIndex() == i);
206 //only update aabb of active objects
207 if (m_forceUpdateAllAabbs || colObj->isActive())
209 updateSingleAabb(colObj);
214 void btCollisionWorld::computeOverlappingPairs()
216 BT_PROFILE("calculateOverlappingPairs");
217 m_broadphasePairCache->calculateOverlappingPairs(m_dispatcher1);
220 void btCollisionWorld::performDiscreteCollisionDetection()
222 BT_PROFILE("performDiscreteCollisionDetection");
224 btDispatcherInfo& dispatchInfo = getDispatchInfo();
228 computeOverlappingPairs();
230 btDispatcher* dispatcher = getDispatcher();
232 BT_PROFILE("dispatchAllCollisionPairs");
234 dispatcher->dispatchAllCollisionPairs(m_broadphasePairCache->getOverlappingPairCache(), dispatchInfo, m_dispatcher1);
238 void btCollisionWorld::removeCollisionObject(btCollisionObject* collisionObject)
240 //bool removeFromBroadphase = false;
243 btBroadphaseProxy* bp = collisionObject->getBroadphaseHandle();
247 // only clear the cached algorithms
249 getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(bp, m_dispatcher1);
250 getBroadphase()->destroyProxy(bp, m_dispatcher1);
251 collisionObject->setBroadphaseHandle(0);
255 int iObj = collisionObject->getWorldArrayIndex();
256 // btAssert(iObj >= 0 && iObj < m_collisionObjects.size()); // trying to remove an object that was never added or already removed previously?
257 if (iObj >= 0 && iObj < m_collisionObjects.size())
259 btAssert(collisionObject == m_collisionObjects[iObj]);
260 m_collisionObjects.swap(iObj, m_collisionObjects.size() - 1);
261 m_collisionObjects.pop_back();
262 if (iObj < m_collisionObjects.size())
264 m_collisionObjects[iObj]->setWorldArrayIndex(iObj);
269 // slow linear search
271 m_collisionObjects.remove(collisionObject);
273 collisionObject->setWorldArrayIndex(-1);
276 void btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans, const btTransform& rayToTrans,
277 btCollisionObject* collisionObject,
278 const btCollisionShape* collisionShape,
279 const btTransform& colObjWorldTransform,
280 RayResultCallback& resultCallback)
282 btCollisionObjectWrapper colObWrap(0, collisionShape, collisionObject, colObjWorldTransform, -1, -1);
283 btCollisionWorld::rayTestSingleInternal(rayFromTrans, rayToTrans, &colObWrap, resultCallback);
286 void btCollisionWorld::rayTestSingleInternal(const btTransform& rayFromTrans, const btTransform& rayToTrans,
287 const btCollisionObjectWrapper* collisionObjectWrap,
288 RayResultCallback& resultCallback)
290 btSphereShape pointShape(btScalar(0.0));
291 pointShape.setMargin(0.f);
292 const btConvexShape* castShape = &pointShape;
293 const btCollisionShape* collisionShape = collisionObjectWrap->getCollisionShape();
294 const btTransform& colObjWorldTransform = collisionObjectWrap->getWorldTransform();
296 if (collisionShape->isConvex())
298 // BT_PROFILE("rayTestConvex");
299 btConvexCast::CastResult castResult;
300 castResult.m_fraction = resultCallback.m_closestHitFraction;
302 btConvexShape* convexShape = (btConvexShape*)collisionShape;
303 btVoronoiSimplexSolver simplexSolver;
304 btSubsimplexConvexCast subSimplexConvexCaster(castShape, convexShape, &simplexSolver);
306 btGjkConvexCast gjkConvexCaster(castShape, convexShape, &simplexSolver);
308 //btContinuousConvexCollision convexCaster(castShape,convexShape,&simplexSolver,0);
310 btConvexCast* convexCasterPtr = 0;
311 //use kF_UseSubSimplexConvexCastRaytest by default
312 if (resultCallback.m_flags & btTriangleRaycastCallback::kF_UseGjkConvexCastRaytest)
313 convexCasterPtr = &gjkConvexCaster;
315 convexCasterPtr = &subSimplexConvexCaster;
317 btConvexCast& convexCaster = *convexCasterPtr;
319 if (convexCaster.calcTimeOfImpact(rayFromTrans, rayToTrans, colObjWorldTransform, colObjWorldTransform, castResult))
322 if (castResult.m_normal.length2() > btScalar(0.0001))
324 if (castResult.m_fraction < resultCallback.m_closestHitFraction)
326 //todo: figure out what this is about. When is rayFromTest.getBasis() not identity?
327 #ifdef USE_SUBSIMPLEX_CONVEX_CAST
328 //rotate normal into worldspace
329 castResult.m_normal = rayFromTrans.getBasis() * castResult.m_normal;
330 #endif //USE_SUBSIMPLEX_CONVEX_CAST
332 castResult.m_normal.normalize();
333 btCollisionWorld::LocalRayResult localRayResult(
334 collisionObjectWrap->getCollisionObject(),
337 castResult.m_fraction);
339 bool normalInWorldSpace = true;
340 resultCallback.addSingleResult(localRayResult, normalInWorldSpace);
347 if (collisionShape->isConcave())
349 //ConvexCast::CastResult
350 struct BridgeTriangleRaycastCallback : public btTriangleRaycastCallback
352 btCollisionWorld::RayResultCallback* m_resultCallback;
353 const btCollisionObject* m_collisionObject;
354 const btConcaveShape* m_triangleMesh;
356 btTransform m_colObjWorldTransform;
358 BridgeTriangleRaycastCallback(const btVector3& from, const btVector3& to,
359 btCollisionWorld::RayResultCallback* resultCallback, const btCollisionObject* collisionObject, const btConcaveShape* triangleMesh, const btTransform& colObjWorldTransform) : //@BP Mod
360 btTriangleRaycastCallback(from, to, resultCallback->m_flags),
361 m_resultCallback(resultCallback),
362 m_collisionObject(collisionObject),
363 m_triangleMesh(triangleMesh),
364 m_colObjWorldTransform(colObjWorldTransform)
368 virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex)
370 btCollisionWorld::LocalShapeInfo shapeInfo;
371 shapeInfo.m_shapePart = partId;
372 shapeInfo.m_triangleIndex = triangleIndex;
374 btVector3 hitNormalWorld = m_colObjWorldTransform.getBasis() * hitNormalLocal;
376 btCollisionWorld::LocalRayResult rayResult(m_collisionObject,
381 bool normalInWorldSpace = true;
382 return m_resultCallback->addSingleResult(rayResult, normalInWorldSpace);
386 btTransform worldTocollisionObject = colObjWorldTransform.inverse();
387 btVector3 rayFromLocal = worldTocollisionObject * rayFromTrans.getOrigin();
388 btVector3 rayToLocal = worldTocollisionObject * rayToTrans.getOrigin();
390 // BT_PROFILE("rayTestConcave");
391 if (collisionShape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE)
393 ///optimized version for btBvhTriangleMeshShape
394 btBvhTriangleMeshShape* triangleMesh = (btBvhTriangleMeshShape*)collisionShape;
396 BridgeTriangleRaycastCallback rcb(rayFromLocal, rayToLocal, &resultCallback, collisionObjectWrap->getCollisionObject(), triangleMesh, colObjWorldTransform);
397 rcb.m_hitFraction = resultCallback.m_closestHitFraction;
398 triangleMesh->performRaycast(&rcb, rayFromLocal, rayToLocal);
400 else if (collisionShape->getShapeType() == SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE)
402 ///optimized version for btScaledBvhTriangleMeshShape
403 btScaledBvhTriangleMeshShape* scaledTriangleMesh = (btScaledBvhTriangleMeshShape*)collisionShape;
404 btBvhTriangleMeshShape* triangleMesh = (btBvhTriangleMeshShape*)scaledTriangleMesh->getChildShape();
406 //scale the ray positions
407 btVector3 scale = scaledTriangleMesh->getLocalScaling();
408 btVector3 rayFromLocalScaled = rayFromLocal / scale;
409 btVector3 rayToLocalScaled = rayToLocal / scale;
411 //perform raycast in the underlying btBvhTriangleMeshShape
412 BridgeTriangleRaycastCallback rcb(rayFromLocalScaled, rayToLocalScaled, &resultCallback, collisionObjectWrap->getCollisionObject(), triangleMesh, colObjWorldTransform);
413 rcb.m_hitFraction = resultCallback.m_closestHitFraction;
414 triangleMesh->performRaycast(&rcb, rayFromLocalScaled, rayToLocalScaled);
416 else if (((resultCallback.m_flags&btTriangleRaycastCallback::kF_DisableHeightfieldAccelerator)==0)
417 && collisionShape->getShapeType() == TERRAIN_SHAPE_PROXYTYPE
420 ///optimized version for btHeightfieldTerrainShape
421 btHeightfieldTerrainShape* heightField = (btHeightfieldTerrainShape*)collisionShape;
422 btTransform worldTocollisionObject = colObjWorldTransform.inverse();
423 btVector3 rayFromLocal = worldTocollisionObject * rayFromTrans.getOrigin();
424 btVector3 rayToLocal = worldTocollisionObject * rayToTrans.getOrigin();
426 BridgeTriangleRaycastCallback rcb(rayFromLocal, rayToLocal, &resultCallback, collisionObjectWrap->getCollisionObject(), heightField, colObjWorldTransform);
427 rcb.m_hitFraction = resultCallback.m_closestHitFraction;
428 heightField->performRaycast(&rcb, rayFromLocal, rayToLocal);
432 //generic (slower) case
433 btConcaveShape* concaveShape = (btConcaveShape*)collisionShape;
435 btTransform worldTocollisionObject = colObjWorldTransform.inverse();
437 btVector3 rayFromLocal = worldTocollisionObject * rayFromTrans.getOrigin();
438 btVector3 rayToLocal = worldTocollisionObject * rayToTrans.getOrigin();
440 //ConvexCast::CastResult
442 struct BridgeTriangleRaycastCallback : public btTriangleRaycastCallback
444 btCollisionWorld::RayResultCallback* m_resultCallback;
445 const btCollisionObject* m_collisionObject;
446 btConcaveShape* m_triangleMesh;
448 btTransform m_colObjWorldTransform;
450 BridgeTriangleRaycastCallback(const btVector3& from, const btVector3& to,
451 btCollisionWorld::RayResultCallback* resultCallback, const btCollisionObject* collisionObject, btConcaveShape* triangleMesh, const btTransform& colObjWorldTransform) : //@BP Mod
452 btTriangleRaycastCallback(from, to, resultCallback->m_flags),
453 m_resultCallback(resultCallback),
454 m_collisionObject(collisionObject),
455 m_triangleMesh(triangleMesh),
456 m_colObjWorldTransform(colObjWorldTransform)
460 virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex)
462 btCollisionWorld::LocalShapeInfo shapeInfo;
463 shapeInfo.m_shapePart = partId;
464 shapeInfo.m_triangleIndex = triangleIndex;
466 btVector3 hitNormalWorld = m_colObjWorldTransform.getBasis() * hitNormalLocal;
468 btCollisionWorld::LocalRayResult rayResult(m_collisionObject,
473 bool normalInWorldSpace = true;
474 return m_resultCallback->addSingleResult(rayResult, normalInWorldSpace);
478 BridgeTriangleRaycastCallback rcb(rayFromLocal, rayToLocal, &resultCallback, collisionObjectWrap->getCollisionObject(), concaveShape, colObjWorldTransform);
479 rcb.m_hitFraction = resultCallback.m_closestHitFraction;
481 btVector3 rayAabbMinLocal = rayFromLocal;
482 rayAabbMinLocal.setMin(rayToLocal);
483 btVector3 rayAabbMaxLocal = rayFromLocal;
484 rayAabbMaxLocal.setMax(rayToLocal);
486 concaveShape->processAllTriangles(&rcb, rayAabbMinLocal, rayAabbMaxLocal);
491 // BT_PROFILE("rayTestCompound");
492 if (collisionShape->isCompound())
494 struct LocalInfoAdder2 : public RayResultCallback
496 RayResultCallback* m_userCallback;
499 LocalInfoAdder2(int i, RayResultCallback* user)
500 : m_userCallback(user), m_i(i)
502 m_closestHitFraction = m_userCallback->m_closestHitFraction;
503 m_flags = m_userCallback->m_flags;
505 virtual bool needsCollision(btBroadphaseProxy* p) const
507 return m_userCallback->needsCollision(p);
510 virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult& r, bool b)
512 btCollisionWorld::LocalShapeInfo shapeInfo;
513 shapeInfo.m_shapePart = -1;
514 shapeInfo.m_triangleIndex = m_i;
515 if (r.m_localShapeInfo == NULL)
516 r.m_localShapeInfo = &shapeInfo;
518 const btScalar result = m_userCallback->addSingleResult(r, b);
519 m_closestHitFraction = m_userCallback->m_closestHitFraction;
524 struct RayTester : btDbvt::ICollide
526 const btCollisionObject* m_collisionObject;
527 const btCompoundShape* m_compoundShape;
528 const btTransform& m_colObjWorldTransform;
529 const btTransform& m_rayFromTrans;
530 const btTransform& m_rayToTrans;
531 RayResultCallback& m_resultCallback;
533 RayTester(const btCollisionObject* collisionObject,
534 const btCompoundShape* compoundShape,
535 const btTransform& colObjWorldTransform,
536 const btTransform& rayFromTrans,
537 const btTransform& rayToTrans,
538 RayResultCallback& resultCallback) : m_collisionObject(collisionObject),
539 m_compoundShape(compoundShape),
540 m_colObjWorldTransform(colObjWorldTransform),
541 m_rayFromTrans(rayFromTrans),
542 m_rayToTrans(rayToTrans),
543 m_resultCallback(resultCallback)
547 void ProcessLeaf(int i)
549 const btCollisionShape* childCollisionShape = m_compoundShape->getChildShape(i);
550 const btTransform& childTrans = m_compoundShape->getChildTransform(i);
551 btTransform childWorldTrans = m_colObjWorldTransform * childTrans;
553 btCollisionObjectWrapper tmpOb(0, childCollisionShape, m_collisionObject, childWorldTrans, -1, i);
554 // replace collision shape so that callback can determine the triangle
556 LocalInfoAdder2 my_cb(i, &m_resultCallback);
558 rayTestSingleInternal(
565 void Process(const btDbvtNode* leaf)
567 ProcessLeaf(leaf->dataAsInt);
571 const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(collisionShape);
572 const btDbvt* dbvt = compoundShape->getDynamicAabbTree();
575 collisionObjectWrap->getCollisionObject(),
577 colObjWorldTransform,
581 #ifndef DISABLE_DBVT_COMPOUNDSHAPE_RAYCAST_ACCELERATION
584 btVector3 localRayFrom = colObjWorldTransform.inverseTimes(rayFromTrans).getOrigin();
585 btVector3 localRayTo = colObjWorldTransform.inverseTimes(rayToTrans).getOrigin();
586 btDbvt::rayTest(dbvt->m_root, localRayFrom, localRayTo, rayCB);
589 #endif //DISABLE_DBVT_COMPOUNDSHAPE_RAYCAST_ACCELERATION
591 for (int i = 0, n = compoundShape->getNumChildShapes(); i < n; ++i)
593 rayCB.ProcessLeaf(i);
601 void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape, const btTransform& convexFromTrans, const btTransform& convexToTrans,
602 btCollisionObject* collisionObject,
603 const btCollisionShape* collisionShape,
604 const btTransform& colObjWorldTransform,
605 ConvexResultCallback& resultCallback, btScalar allowedPenetration)
607 btCollisionObjectWrapper tmpOb(0, collisionShape, collisionObject, colObjWorldTransform, -1, -1);
608 btCollisionWorld::objectQuerySingleInternal(castShape, convexFromTrans, convexToTrans, &tmpOb, resultCallback, allowedPenetration);
611 void btCollisionWorld::objectQuerySingleInternal(const btConvexShape* castShape, const btTransform& convexFromTrans, const btTransform& convexToTrans,
612 const btCollisionObjectWrapper* colObjWrap,
613 ConvexResultCallback& resultCallback, btScalar allowedPenetration)
615 const btCollisionShape* collisionShape = colObjWrap->getCollisionShape();
616 const btTransform& colObjWorldTransform = colObjWrap->getWorldTransform();
618 if (collisionShape->isConvex())
620 //BT_PROFILE("convexSweepConvex");
621 btConvexCast::CastResult castResult;
622 castResult.m_allowedPenetration = allowedPenetration;
623 castResult.m_fraction = resultCallback.m_closestHitFraction; //btScalar(1.);//??
625 btConvexShape* convexShape = (btConvexShape*)collisionShape;
626 btVoronoiSimplexSolver simplexSolver;
627 btGjkEpaPenetrationDepthSolver gjkEpaPenetrationSolver;
629 btContinuousConvexCollision convexCaster1(castShape, convexShape, &simplexSolver, &gjkEpaPenetrationSolver);
630 //btGjkConvexCast convexCaster2(castShape,convexShape,&simplexSolver);
631 //btSubsimplexConvexCast convexCaster3(castShape,convexShape,&simplexSolver);
633 btConvexCast* castPtr = &convexCaster1;
635 if (castPtr->calcTimeOfImpact(convexFromTrans, convexToTrans, colObjWorldTransform, colObjWorldTransform, castResult))
638 if (castResult.m_normal.length2() > btScalar(0.0001))
640 if (castResult.m_fraction < resultCallback.m_closestHitFraction)
642 castResult.m_normal.normalize();
643 btCollisionWorld::LocalConvexResult localConvexResult(
644 colObjWrap->getCollisionObject(),
647 castResult.m_hitPoint,
648 castResult.m_fraction);
650 bool normalInWorldSpace = true;
651 resultCallback.addSingleResult(localConvexResult, normalInWorldSpace);
658 if (collisionShape->isConcave())
660 if (collisionShape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE)
662 //BT_PROFILE("convexSweepbtBvhTriangleMesh");
663 btBvhTriangleMeshShape* triangleMesh = (btBvhTriangleMeshShape*)collisionShape;
664 btTransform worldTocollisionObject = colObjWorldTransform.inverse();
665 btVector3 convexFromLocal = worldTocollisionObject * convexFromTrans.getOrigin();
666 btVector3 convexToLocal = worldTocollisionObject * convexToTrans.getOrigin();
667 // rotation of box in local mesh space = MeshRotation^-1 * ConvexToRotation
668 btTransform rotationXform = btTransform(worldTocollisionObject.getBasis() * convexToTrans.getBasis());
670 //ConvexCast::CastResult
671 struct BridgeTriangleConvexcastCallback : public btTriangleConvexcastCallback
673 btCollisionWorld::ConvexResultCallback* m_resultCallback;
674 const btCollisionObject* m_collisionObject;
675 btTriangleMeshShape* m_triangleMesh;
677 BridgeTriangleConvexcastCallback(const btConvexShape* castShape, const btTransform& from, const btTransform& to,
678 btCollisionWorld::ConvexResultCallback* resultCallback, const btCollisionObject* collisionObject, btTriangleMeshShape* triangleMesh, const btTransform& triangleToWorld) : btTriangleConvexcastCallback(castShape, from, to, triangleToWorld, triangleMesh->getMargin()),
679 m_resultCallback(resultCallback),
680 m_collisionObject(collisionObject),
681 m_triangleMesh(triangleMesh)
685 virtual btScalar reportHit(const btVector3& hitNormalLocal, const btVector3& hitPointLocal, btScalar hitFraction, int partId, int triangleIndex)
687 btCollisionWorld::LocalShapeInfo shapeInfo;
688 shapeInfo.m_shapePart = partId;
689 shapeInfo.m_triangleIndex = triangleIndex;
690 if (hitFraction <= m_resultCallback->m_closestHitFraction)
692 btCollisionWorld::LocalConvexResult convexResult(m_collisionObject,
698 bool normalInWorldSpace = true;
700 return m_resultCallback->addSingleResult(convexResult, normalInWorldSpace);
706 BridgeTriangleConvexcastCallback tccb(castShape, convexFromTrans, convexToTrans, &resultCallback, colObjWrap->getCollisionObject(), triangleMesh, colObjWorldTransform);
707 tccb.m_hitFraction = resultCallback.m_closestHitFraction;
708 tccb.m_allowedPenetration = allowedPenetration;
709 btVector3 boxMinLocal, boxMaxLocal;
710 castShape->getAabb(rotationXform, boxMinLocal, boxMaxLocal);
711 triangleMesh->performConvexcast(&tccb, convexFromLocal, convexToLocal, boxMinLocal, boxMaxLocal);
715 if (collisionShape->getShapeType() == STATIC_PLANE_PROXYTYPE)
717 btConvexCast::CastResult castResult;
718 castResult.m_allowedPenetration = allowedPenetration;
719 castResult.m_fraction = resultCallback.m_closestHitFraction;
720 btStaticPlaneShape* planeShape = (btStaticPlaneShape*)collisionShape;
721 btContinuousConvexCollision convexCaster1(castShape, planeShape);
722 btConvexCast* castPtr = &convexCaster1;
724 if (castPtr->calcTimeOfImpact(convexFromTrans, convexToTrans, colObjWorldTransform, colObjWorldTransform, castResult))
727 if (castResult.m_normal.length2() > btScalar(0.0001))
729 if (castResult.m_fraction < resultCallback.m_closestHitFraction)
731 castResult.m_normal.normalize();
732 btCollisionWorld::LocalConvexResult localConvexResult(
733 colObjWrap->getCollisionObject(),
736 castResult.m_hitPoint,
737 castResult.m_fraction);
739 bool normalInWorldSpace = true;
740 resultCallback.addSingleResult(localConvexResult, normalInWorldSpace);
747 //BT_PROFILE("convexSweepConcave");
748 btConcaveShape* concaveShape = (btConcaveShape*)collisionShape;
749 btTransform worldTocollisionObject = colObjWorldTransform.inverse();
750 btVector3 convexFromLocal = worldTocollisionObject * convexFromTrans.getOrigin();
751 btVector3 convexToLocal = worldTocollisionObject * convexToTrans.getOrigin();
752 // rotation of box in local mesh space = MeshRotation^-1 * ConvexToRotation
753 btTransform rotationXform = btTransform(worldTocollisionObject.getBasis() * convexToTrans.getBasis());
755 //ConvexCast::CastResult
756 struct BridgeTriangleConvexcastCallback : public btTriangleConvexcastCallback
758 btCollisionWorld::ConvexResultCallback* m_resultCallback;
759 const btCollisionObject* m_collisionObject;
760 btConcaveShape* m_triangleMesh;
762 BridgeTriangleConvexcastCallback(const btConvexShape* castShape, const btTransform& from, const btTransform& to,
763 btCollisionWorld::ConvexResultCallback* resultCallback, const btCollisionObject* collisionObject, btConcaveShape* triangleMesh, const btTransform& triangleToWorld) : btTriangleConvexcastCallback(castShape, from, to, triangleToWorld, triangleMesh->getMargin()),
764 m_resultCallback(resultCallback),
765 m_collisionObject(collisionObject),
766 m_triangleMesh(triangleMesh)
770 virtual btScalar reportHit(const btVector3& hitNormalLocal, const btVector3& hitPointLocal, btScalar hitFraction, int partId, int triangleIndex)
772 btCollisionWorld::LocalShapeInfo shapeInfo;
773 shapeInfo.m_shapePart = partId;
774 shapeInfo.m_triangleIndex = triangleIndex;
775 if (hitFraction <= m_resultCallback->m_closestHitFraction)
777 btCollisionWorld::LocalConvexResult convexResult(m_collisionObject,
783 bool normalInWorldSpace = true;
785 return m_resultCallback->addSingleResult(convexResult, normalInWorldSpace);
791 BridgeTriangleConvexcastCallback tccb(castShape, convexFromTrans, convexToTrans, &resultCallback, colObjWrap->getCollisionObject(), concaveShape, colObjWorldTransform);
792 tccb.m_hitFraction = resultCallback.m_closestHitFraction;
793 tccb.m_allowedPenetration = allowedPenetration;
794 btVector3 boxMinLocal, boxMaxLocal;
795 castShape->getAabb(rotationXform, boxMinLocal, boxMaxLocal);
797 btVector3 rayAabbMinLocal = convexFromLocal;
798 rayAabbMinLocal.setMin(convexToLocal);
799 btVector3 rayAabbMaxLocal = convexFromLocal;
800 rayAabbMaxLocal.setMax(convexToLocal);
801 rayAabbMinLocal += boxMinLocal;
802 rayAabbMaxLocal += boxMaxLocal;
803 concaveShape->processAllTriangles(&tccb, rayAabbMinLocal, rayAabbMaxLocal);
809 if (collisionShape->isCompound())
811 struct btCompoundLeafCallback : btDbvt::ICollide
813 btCompoundLeafCallback(
814 const btCollisionObjectWrapper* colObjWrap,
815 const btConvexShape* castShape,
816 const btTransform& convexFromTrans,
817 const btTransform& convexToTrans,
818 btScalar allowedPenetration,
819 const btCompoundShape* compoundShape,
820 const btTransform& colObjWorldTransform,
821 ConvexResultCallback& resultCallback)
822 : m_colObjWrap(colObjWrap),
823 m_castShape(castShape),
824 m_convexFromTrans(convexFromTrans),
825 m_convexToTrans(convexToTrans),
826 m_allowedPenetration(allowedPenetration),
827 m_compoundShape(compoundShape),
828 m_colObjWorldTransform(colObjWorldTransform),
829 m_resultCallback(resultCallback)
833 const btCollisionObjectWrapper* m_colObjWrap;
834 const btConvexShape* m_castShape;
835 const btTransform& m_convexFromTrans;
836 const btTransform& m_convexToTrans;
837 btScalar m_allowedPenetration;
838 const btCompoundShape* m_compoundShape;
839 const btTransform& m_colObjWorldTransform;
840 ConvexResultCallback& m_resultCallback;
843 void ProcessChild(int index, const btTransform& childTrans, const btCollisionShape* childCollisionShape)
845 btTransform childWorldTrans = m_colObjWorldTransform * childTrans;
847 struct LocalInfoAdder : public ConvexResultCallback
849 ConvexResultCallback* m_userCallback;
852 LocalInfoAdder(int i, ConvexResultCallback* user)
853 : m_userCallback(user), m_i(i)
855 m_closestHitFraction = m_userCallback->m_closestHitFraction;
857 virtual bool needsCollision(btBroadphaseProxy* p) const
859 return m_userCallback->needsCollision(p);
861 virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult& r, bool b)
863 btCollisionWorld::LocalShapeInfo shapeInfo;
864 shapeInfo.m_shapePart = -1;
865 shapeInfo.m_triangleIndex = m_i;
866 if (r.m_localShapeInfo == NULL)
867 r.m_localShapeInfo = &shapeInfo;
868 const btScalar result = m_userCallback->addSingleResult(r, b);
869 m_closestHitFraction = m_userCallback->m_closestHitFraction;
874 LocalInfoAdder my_cb(index, &m_resultCallback);
876 btCollisionObjectWrapper tmpObj(m_colObjWrap, childCollisionShape, m_colObjWrap->getCollisionObject(), childWorldTrans, -1, index);
878 objectQuerySingleInternal(m_castShape, m_convexFromTrans, m_convexToTrans, &tmpObj, my_cb, m_allowedPenetration);
881 void Process(const btDbvtNode* leaf)
883 // Processing leaf node
884 int index = leaf->dataAsInt;
886 btTransform childTrans = m_compoundShape->getChildTransform(index);
887 const btCollisionShape* childCollisionShape = m_compoundShape->getChildShape(index);
889 ProcessChild(index, childTrans, childCollisionShape);
893 BT_PROFILE("convexSweepCompound");
894 const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(collisionShape);
896 btVector3 fromLocalAabbMin, fromLocalAabbMax;
897 btVector3 toLocalAabbMin, toLocalAabbMax;
899 castShape->getAabb(colObjWorldTransform.inverse() * convexFromTrans, fromLocalAabbMin, fromLocalAabbMax);
900 castShape->getAabb(colObjWorldTransform.inverse() * convexToTrans, toLocalAabbMin, toLocalAabbMax);
902 fromLocalAabbMin.setMin(toLocalAabbMin);
903 fromLocalAabbMax.setMax(toLocalAabbMax);
905 btCompoundLeafCallback callback(colObjWrap, castShape, convexFromTrans, convexToTrans,
906 allowedPenetration, compoundShape, colObjWorldTransform, resultCallback);
908 const btDbvt* tree = compoundShape->getDynamicAabbTree();
911 const ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds = btDbvtVolume::FromMM(fromLocalAabbMin, fromLocalAabbMax);
912 tree->collideTV(tree->m_root, bounds, callback);
917 for (i = 0; i < compoundShape->getNumChildShapes(); i++)
919 const btCollisionShape* childCollisionShape = compoundShape->getChildShape(i);
920 btTransform childTrans = compoundShape->getChildTransform(i);
921 callback.ProcessChild(i, childTrans, childCollisionShape);
929 struct btSingleRayCallback : public btBroadphaseRayCallback
931 btVector3 m_rayFromWorld;
932 btVector3 m_rayToWorld;
933 btTransform m_rayFromTrans;
934 btTransform m_rayToTrans;
935 btVector3 m_hitNormal;
937 const btCollisionWorld* m_world;
938 btCollisionWorld::RayResultCallback& m_resultCallback;
940 btSingleRayCallback(const btVector3& rayFromWorld, const btVector3& rayToWorld, const btCollisionWorld* world, btCollisionWorld::RayResultCallback& resultCallback)
941 : m_rayFromWorld(rayFromWorld),
942 m_rayToWorld(rayToWorld),
944 m_resultCallback(resultCallback)
946 m_rayFromTrans.setIdentity();
947 m_rayFromTrans.setOrigin(m_rayFromWorld);
948 m_rayToTrans.setIdentity();
949 m_rayToTrans.setOrigin(m_rayToWorld);
951 btVector3 rayDir = (rayToWorld - rayFromWorld);
954 ///what about division by zero? --> just set rayDirection[i] to INF/BT_LARGE_FLOAT
955 m_rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[0];
956 m_rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[1];
957 m_rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[2];
958 m_signs[0] = m_rayDirectionInverse[0] < 0.0;
959 m_signs[1] = m_rayDirectionInverse[1] < 0.0;
960 m_signs[2] = m_rayDirectionInverse[2] < 0.0;
962 m_lambda_max = rayDir.dot(m_rayToWorld - m_rayFromWorld);
965 virtual bool process(const btBroadphaseProxy* proxy)
967 ///terminate further ray tests, once the closestHitFraction reached zero
968 if (m_resultCallback.m_closestHitFraction == btScalar(0.f))
971 btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject;
973 //only perform raycast if filterMask matches
974 if (m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
976 //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
977 //btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
979 #ifdef RECALCULATE_AABB
980 btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
981 collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax);
983 //getBroadphase()->getAabb(collisionObject->getBroadphaseHandle(),collisionObjectAabbMin,collisionObjectAabbMax);
984 const btVector3& collisionObjectAabbMin = collisionObject->getBroadphaseHandle()->m_aabbMin;
985 const btVector3& collisionObjectAabbMax = collisionObject->getBroadphaseHandle()->m_aabbMax;
988 //btScalar hitLambda = m_resultCallback.m_closestHitFraction;
989 //culling already done by broadphase
990 //if (btRayAabb(m_rayFromWorld,m_rayToWorld,collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,m_hitNormal))
992 m_world->rayTestSingle(m_rayFromTrans, m_rayToTrans,
994 collisionObject->getCollisionShape(),
995 collisionObject->getWorldTransform(),
1003 void btCollisionWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const
1005 //BT_PROFILE("rayTest");
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 btSingleRayCallback rayCB(rayFromWorld, rayToWorld, this, resultCallback);
1010 #ifndef USE_BRUTEFORCE_RAYBROADPHASE
1011 m_broadphasePairCache->rayTest(rayFromWorld, rayToWorld, rayCB);
1013 for (int i = 0; i < this->getNumCollisionObjects(); i++)
1015 rayCB.process(m_collisionObjects[i]->getBroadphaseHandle());
1017 #endif //USE_BRUTEFORCE_RAYBROADPHASE
1020 struct btSingleSweepCallback : public btBroadphaseRayCallback
1022 btTransform m_convexFromTrans;
1023 btTransform m_convexToTrans;
1024 btVector3 m_hitNormal;
1025 const btCollisionWorld* m_world;
1026 btCollisionWorld::ConvexResultCallback& m_resultCallback;
1027 btScalar m_allowedCcdPenetration;
1028 const btConvexShape* m_castShape;
1030 btSingleSweepCallback(const btConvexShape* castShape, const btTransform& convexFromTrans, const btTransform& convexToTrans, const btCollisionWorld* world, btCollisionWorld::ConvexResultCallback& resultCallback, btScalar allowedPenetration)
1031 : m_convexFromTrans(convexFromTrans),
1032 m_convexToTrans(convexToTrans),
1034 m_resultCallback(resultCallback),
1035 m_allowedCcdPenetration(allowedPenetration),
1036 m_castShape(castShape)
1038 btVector3 unnormalizedRayDir = (m_convexToTrans.getOrigin() - m_convexFromTrans.getOrigin());
1039 btVector3 rayDir = unnormalizedRayDir.fuzzyZero() ? btVector3(btScalar(0.0), btScalar(0.0), btScalar(0.0)) : unnormalizedRayDir.normalized();
1040 ///what about division by zero? --> just set rayDirection[i] to INF/BT_LARGE_FLOAT
1041 m_rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[0];
1042 m_rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[1];
1043 m_rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[2];
1044 m_signs[0] = m_rayDirectionInverse[0] < 0.0;
1045 m_signs[1] = m_rayDirectionInverse[1] < 0.0;
1046 m_signs[2] = m_rayDirectionInverse[2] < 0.0;
1048 m_lambda_max = rayDir.dot(unnormalizedRayDir);
1051 virtual bool process(const btBroadphaseProxy* proxy)
1053 ///terminate further convex sweep tests, once the closestHitFraction reached zero
1054 if (m_resultCallback.m_closestHitFraction == btScalar(0.f))
1057 btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject;
1059 //only perform raycast if filterMask matches
1060 if (m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
1062 //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
1063 m_world->objectQuerySingle(m_castShape, m_convexFromTrans, m_convexToTrans,
1065 collisionObject->getCollisionShape(),
1066 collisionObject->getWorldTransform(),
1068 m_allowedCcdPenetration);
1075 void btCollisionWorld::convexSweepTest(const btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, ConvexResultCallback& resultCallback, btScalar allowedCcdPenetration) const
1077 BT_PROFILE("convexSweepTest");
1078 /// use the broadphase to accelerate the search for objects, based on their aabb
1079 /// and for each object with ray-aabb overlap, perform an exact ray test
1080 /// unfortunately the implementation for rayTest and convexSweepTest duplicated, albeit practically identical
1082 btTransform convexFromTrans, convexToTrans;
1083 convexFromTrans = convexFromWorld;
1084 convexToTrans = convexToWorld;
1085 btVector3 castShapeAabbMin, castShapeAabbMax;
1086 /* Compute AABB that encompasses angular movement */
1088 btVector3 linVel, angVel;
1089 btTransformUtil::calculateVelocity(convexFromTrans, convexToTrans, 1.0f, linVel, angVel);
1090 btVector3 zeroLinVel;
1091 zeroLinVel.setValue(0, 0, 0);
1094 R.setRotation(convexFromTrans.getRotation());
1095 castShape->calculateTemporalAabb(R, zeroLinVel, angVel, 1.0f, castShapeAabbMin, castShapeAabbMax);
1098 #ifndef USE_BRUTEFORCE_RAYBROADPHASE
1100 btSingleSweepCallback convexCB(castShape, convexFromWorld, convexToWorld, this, resultCallback, allowedCcdPenetration);
1102 m_broadphasePairCache->rayTest(convexFromTrans.getOrigin(), convexToTrans.getOrigin(), convexCB, castShapeAabbMin, castShapeAabbMax);
1105 /// go over all objects, and if the ray intersects their aabb + cast shape aabb,
1106 // do a ray-shape query using convexCaster (CCD)
1108 for (i = 0; i < m_collisionObjects.size(); i++)
1110 btCollisionObject* collisionObject = m_collisionObjects[i];
1111 //only perform raycast if filterMask matches
1112 if (resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
1114 //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
1115 btVector3 collisionObjectAabbMin, collisionObjectAabbMax;
1116 collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(), collisionObjectAabbMin, collisionObjectAabbMax);
1117 AabbExpand(collisionObjectAabbMin, collisionObjectAabbMax, castShapeAabbMin, castShapeAabbMax);
1118 btScalar hitLambda = btScalar(1.); //could use resultCallback.m_closestHitFraction, but needs testing
1119 btVector3 hitNormal;
1120 if (btRayAabb(convexFromWorld.getOrigin(), convexToWorld.getOrigin(), collisionObjectAabbMin, collisionObjectAabbMax, hitLambda, hitNormal))
1122 objectQuerySingle(castShape, convexFromTrans, convexToTrans,
1124 collisionObject->getCollisionShape(),
1125 collisionObject->getWorldTransform(),
1127 allowedCcdPenetration);
1131 #endif //USE_BRUTEFORCE_RAYBROADPHASE
1134 struct btBridgedManifoldResult : public btManifoldResult
1136 btCollisionWorld::ContactResultCallback& m_resultCallback;
1138 btBridgedManifoldResult(const btCollisionObjectWrapper* obj0Wrap, const btCollisionObjectWrapper* obj1Wrap, btCollisionWorld::ContactResultCallback& resultCallback)
1139 : btManifoldResult(obj0Wrap, obj1Wrap),
1140 m_resultCallback(resultCallback)
1144 virtual void addContactPoint(const btVector3& normalOnBInWorld, const btVector3& pointInWorld, btScalar depth)
1146 bool isSwapped = m_manifoldPtr->getBody0() != m_body0Wrap->getCollisionObject();
1147 btVector3 pointA = pointInWorld + normalOnBInWorld * depth;
1152 localA = m_body1Wrap->getCollisionObject()->getWorldTransform().invXform(pointA);
1153 localB = m_body0Wrap->getCollisionObject()->getWorldTransform().invXform(pointInWorld);
1157 localA = m_body0Wrap->getCollisionObject()->getWorldTransform().invXform(pointA);
1158 localB = m_body1Wrap->getCollisionObject()->getWorldTransform().invXform(pointInWorld);
1161 btManifoldPoint newPt(localA, localB, normalOnBInWorld, depth);
1162 newPt.m_positionWorldOnA = pointA;
1163 newPt.m_positionWorldOnB = pointInWorld;
1165 //BP mod, store contact triangles.
1168 newPt.m_partId0 = m_partId1;
1169 newPt.m_partId1 = m_partId0;
1170 newPt.m_index0 = m_index1;
1171 newPt.m_index1 = m_index0;
1175 newPt.m_partId0 = m_partId0;
1176 newPt.m_partId1 = m_partId1;
1177 newPt.m_index0 = m_index0;
1178 newPt.m_index1 = m_index1;
1181 //experimental feature info, for per-triangle material etc.
1182 const btCollisionObjectWrapper* obj0Wrap = isSwapped ? m_body1Wrap : m_body0Wrap;
1183 const btCollisionObjectWrapper* obj1Wrap = isSwapped ? m_body0Wrap : m_body1Wrap;
1184 m_resultCallback.addSingleResult(newPt, obj0Wrap, newPt.m_partId0, newPt.m_index0, obj1Wrap, newPt.m_partId1, newPt.m_index1);
1188 struct btSingleContactCallback : public btBroadphaseAabbCallback
1190 btCollisionObject* m_collisionObject;
1191 btCollisionWorld* m_world;
1192 btCollisionWorld::ContactResultCallback& m_resultCallback;
1194 btSingleContactCallback(btCollisionObject* collisionObject, btCollisionWorld* world, btCollisionWorld::ContactResultCallback& resultCallback)
1195 : m_collisionObject(collisionObject),
1197 m_resultCallback(resultCallback)
1201 virtual bool process(const btBroadphaseProxy* proxy)
1203 btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject;
1204 if (collisionObject == m_collisionObject)
1207 //only perform raycast if filterMask matches
1208 if (m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
1210 btCollisionObjectWrapper ob0(0, m_collisionObject->getCollisionShape(), m_collisionObject, m_collisionObject->getWorldTransform(), -1, -1);
1211 btCollisionObjectWrapper ob1(0, collisionObject->getCollisionShape(), collisionObject, collisionObject->getWorldTransform(), -1, -1);
1213 btCollisionAlgorithm* algorithm = m_world->getDispatcher()->findAlgorithm(&ob0, &ob1, 0, BT_CLOSEST_POINT_ALGORITHMS);
1216 btBridgedManifoldResult contactPointResult(&ob0, &ob1, m_resultCallback);
1217 //discrete collision detection query
1219 algorithm->processCollision(&ob0, &ob1, m_world->getDispatchInfo(), &contactPointResult);
1221 algorithm->~btCollisionAlgorithm();
1222 m_world->getDispatcher()->freeCollisionAlgorithm(algorithm);
1229 ///contactTest performs a discrete collision test against all objects in the btCollisionWorld, and calls the resultCallback.
1230 ///it reports one or more contact points for every overlapping object (including the one with deepest penetration)
1231 void btCollisionWorld::contactTest(btCollisionObject* colObj, ContactResultCallback& resultCallback)
1233 btVector3 aabbMin, aabbMax;
1234 colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), aabbMin, aabbMax);
1235 btSingleContactCallback contactCB(colObj, this, resultCallback);
1237 m_broadphasePairCache->aabbTest(aabbMin, aabbMax, contactCB);
1240 ///contactTest performs a discrete collision test between two collision objects and calls the resultCallback if overlap if detected.
1241 ///it reports one or more contact points (including the one with deepest penetration)
1242 void btCollisionWorld::contactPairTest(btCollisionObject* colObjA, btCollisionObject* colObjB, ContactResultCallback& resultCallback)
1244 btCollisionObjectWrapper obA(0, colObjA->getCollisionShape(), colObjA, colObjA->getWorldTransform(), -1, -1);
1245 btCollisionObjectWrapper obB(0, colObjB->getCollisionShape(), colObjB, colObjB->getWorldTransform(), -1, -1);
1247 btCollisionAlgorithm* algorithm = getDispatcher()->findAlgorithm(&obA, &obB, 0, BT_CLOSEST_POINT_ALGORITHMS);
1250 btBridgedManifoldResult contactPointResult(&obA, &obB, resultCallback);
1251 contactPointResult.m_closestPointDistanceThreshold = resultCallback.m_closestDistanceThreshold;
1252 //discrete collision detection query
1253 algorithm->processCollision(&obA, &obB, getDispatchInfo(), &contactPointResult);
1255 algorithm->~btCollisionAlgorithm();
1256 getDispatcher()->freeCollisionAlgorithm(algorithm);
1260 class DebugDrawcallback : public btTriangleCallback, public btInternalTriangleIndexCallback
1262 btIDebugDraw* m_debugDrawer;
1264 btTransform m_worldTrans;
1267 DebugDrawcallback(btIDebugDraw* debugDrawer, const btTransform& worldTrans, const btVector3& color) : m_debugDrawer(debugDrawer),
1269 m_worldTrans(worldTrans)
1273 virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex)
1275 processTriangle(triangle, partId, triangleIndex);
1278 virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
1281 (void)triangleIndex;
1283 btVector3 wv0, wv1, wv2;
1284 wv0 = m_worldTrans * triangle[0];
1285 wv1 = m_worldTrans * triangle[1];
1286 wv2 = m_worldTrans * triangle[2];
1287 btVector3 center = (wv0 + wv1 + wv2) * btScalar(1. / 3.);
1289 if (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawNormals)
1291 btVector3 normal = (wv1 - wv0).cross(wv2 - wv0);
1293 btVector3 normalColor(1, 1, 0);
1294 m_debugDrawer->drawLine(center, center + normal, normalColor);
1296 m_debugDrawer->drawTriangle(wv0, wv1, wv2, m_color, 1.0);
1300 void btCollisionWorld::debugDrawObject(const btTransform& worldTransform, const btCollisionShape* shape, const btVector3& color)
1302 // Draw a small simplex at the center of the object
1303 if (getDebugDrawer() && getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawFrames)
1305 getDebugDrawer()->drawTransform(worldTransform, .1);
1308 if (shape->getShapeType() == COMPOUND_SHAPE_PROXYTYPE)
1310 const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(shape);
1311 for (int i = compoundShape->getNumChildShapes() - 1; i >= 0; i--)
1313 btTransform childTrans = compoundShape->getChildTransform(i);
1314 const btCollisionShape* colShape = compoundShape->getChildShape(i);
1315 debugDrawObject(worldTransform * childTrans, colShape, color);
1320 switch (shape->getShapeType())
1322 case BOX_SHAPE_PROXYTYPE:
1324 const btBoxShape* boxShape = static_cast<const btBoxShape*>(shape);
1325 btVector3 halfExtents = boxShape->getHalfExtentsWithMargin();
1326 getDebugDrawer()->drawBox(-halfExtents, halfExtents, worldTransform, color);
1330 case SPHERE_SHAPE_PROXYTYPE:
1332 const btSphereShape* sphereShape = static_cast<const btSphereShape*>(shape);
1333 btScalar radius = sphereShape->getMargin(); //radius doesn't include the margin, so draw with margin
1335 getDebugDrawer()->drawSphere(radius, worldTransform, color);
1338 case MULTI_SPHERE_SHAPE_PROXYTYPE:
1340 const btMultiSphereShape* multiSphereShape = static_cast<const btMultiSphereShape*>(shape);
1342 btTransform childTransform;
1343 childTransform.setIdentity();
1345 for (int i = multiSphereShape->getSphereCount() - 1; i >= 0; i--)
1347 childTransform.setOrigin(multiSphereShape->getSpherePosition(i));
1348 getDebugDrawer()->drawSphere(multiSphereShape->getSphereRadius(i), worldTransform * childTransform, color);
1353 case CAPSULE_SHAPE_PROXYTYPE:
1355 const btCapsuleShape* capsuleShape = static_cast<const btCapsuleShape*>(shape);
1357 btScalar radius = capsuleShape->getRadius();
1358 btScalar halfHeight = capsuleShape->getHalfHeight();
1360 int upAxis = capsuleShape->getUpAxis();
1361 getDebugDrawer()->drawCapsule(radius, halfHeight, upAxis, worldTransform, color);
1364 case CONE_SHAPE_PROXYTYPE:
1366 const btConeShape* coneShape = static_cast<const btConeShape*>(shape);
1367 btScalar radius = coneShape->getRadius(); //+coneShape->getMargin();
1368 btScalar height = coneShape->getHeight(); //+coneShape->getMargin();
1370 int upAxis = coneShape->getConeUpIndex();
1371 getDebugDrawer()->drawCone(radius, height, upAxis, worldTransform, color);
1374 case CYLINDER_SHAPE_PROXYTYPE:
1376 const btCylinderShape* cylinder = static_cast<const btCylinderShape*>(shape);
1377 int upAxis = cylinder->getUpAxis();
1378 btScalar radius = cylinder->getRadius();
1379 btScalar halfHeight = cylinder->getHalfExtentsWithMargin()[upAxis];
1380 getDebugDrawer()->drawCylinder(radius, halfHeight, upAxis, worldTransform, color);
1384 case STATIC_PLANE_PROXYTYPE:
1386 const btStaticPlaneShape* staticPlaneShape = static_cast<const btStaticPlaneShape*>(shape);
1387 btScalar planeConst = staticPlaneShape->getPlaneConstant();
1388 const btVector3& planeNormal = staticPlaneShape->getPlaneNormal();
1389 getDebugDrawer()->drawPlane(planeNormal, planeConst, worldTransform, color);
1394 /// for polyhedral shapes
1395 if (shape->isPolyhedral())
1397 btPolyhedralConvexShape* polyshape = (btPolyhedralConvexShape*)shape;
1400 if (polyshape->getConvexPolyhedron())
1402 const btConvexPolyhedron* poly = polyshape->getConvexPolyhedron();
1403 for (i = 0; i < poly->m_faces.size(); i++)
1405 btVector3 centroid(0, 0, 0);
1406 int numVerts = poly->m_faces[i].m_indices.size();
1409 int lastV = poly->m_faces[i].m_indices[numVerts - 1];
1410 for (int v = 0; v < poly->m_faces[i].m_indices.size(); v++)
1412 int curVert = poly->m_faces[i].m_indices[v];
1413 centroid += poly->m_vertices[curVert];
1414 getDebugDrawer()->drawLine(worldTransform * poly->m_vertices[lastV], worldTransform * poly->m_vertices[curVert], color);
1418 centroid *= btScalar(1.f) / btScalar(numVerts);
1419 if (getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawNormals)
1421 btVector3 normalColor(1, 1, 0);
1422 btVector3 faceNormal(poly->m_faces[i].m_plane[0], poly->m_faces[i].m_plane[1], poly->m_faces[i].m_plane[2]);
1423 getDebugDrawer()->drawLine(worldTransform * centroid, worldTransform * (centroid + faceNormal), normalColor);
1429 for (i = 0; i < polyshape->getNumEdges(); i++)
1432 polyshape->getEdge(i, a, b);
1433 btVector3 wa = worldTransform * a;
1434 btVector3 wb = worldTransform * b;
1435 getDebugDrawer()->drawLine(wa, wb, color);
1440 if (shape->isConcave())
1442 btConcaveShape* concaveMesh = (btConcaveShape*)shape;
1444 ///@todo pass camera, for some culling? no -> we are not a graphics lib
1445 btVector3 aabbMax(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
1446 btVector3 aabbMin(btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT));
1448 DebugDrawcallback drawCallback(getDebugDrawer(), worldTransform, color);
1449 concaveMesh->processAllTriangles(&drawCallback, aabbMin, aabbMax);
1452 if (shape->getShapeType() == CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE)
1454 btConvexTriangleMeshShape* convexMesh = (btConvexTriangleMeshShape*)shape;
1455 //todo: pass camera for some culling
1456 btVector3 aabbMax(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
1457 btVector3 aabbMin(btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT));
1458 //DebugDrawcallback drawCallback;
1459 DebugDrawcallback drawCallback(getDebugDrawer(), worldTransform, color);
1460 convexMesh->getMeshInterface()->InternalProcessAllTriangles(&drawCallback, aabbMin, aabbMax);
1467 void btCollisionWorld::debugDrawWorld()
1469 if (getDebugDrawer())
1471 getDebugDrawer()->clearLines();
1473 btIDebugDraw::DefaultColors defaultColors = getDebugDrawer()->getDefaultColors();
1475 if (getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawContactPoints)
1477 if (getDispatcher())
1479 int numManifolds = getDispatcher()->getNumManifolds();
1481 for (int i = 0; i < numManifolds; i++)
1483 btPersistentManifold* contactManifold = getDispatcher()->getManifoldByIndexInternal(i);
1484 //btCollisionObject* obA = static_cast<btCollisionObject*>(contactManifold->getBody0());
1485 //btCollisionObject* obB = static_cast<btCollisionObject*>(contactManifold->getBody1());
1487 int numContacts = contactManifold->getNumContacts();
1488 for (int j = 0; j < numContacts; j++)
1490 btManifoldPoint& cp = contactManifold->getContactPoint(j);
1491 getDebugDrawer()->drawContactPoint(cp.m_positionWorldOnB, cp.m_normalWorldOnB, cp.getDistance(), cp.getLifeTime(), defaultColors.m_contactPoint);
1497 if ((getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe | btIDebugDraw::DBG_DrawAabb)))
1501 for (i = 0; i < m_collisionObjects.size(); i++)
1503 btCollisionObject* colObj = m_collisionObjects[i];
1504 if ((colObj->getCollisionFlags() & btCollisionObject::CF_DISABLE_VISUALIZE_OBJECT) == 0)
1506 if (getDebugDrawer() && (getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawWireframe))
1508 btVector3 color(btScalar(0.4), btScalar(0.4), btScalar(0.4));
1510 switch (colObj->getActivationState())
1513 color = defaultColors.m_activeObject;
1515 case ISLAND_SLEEPING:
1516 color = defaultColors.m_deactivatedObject;
1518 case WANTS_DEACTIVATION:
1519 color = defaultColors.m_wantsDeactivationObject;
1521 case DISABLE_DEACTIVATION:
1522 color = defaultColors.m_disabledDeactivationObject;
1524 case DISABLE_SIMULATION:
1525 color = defaultColors.m_disabledSimulationObject;
1529 color = btVector3(btScalar(.3), btScalar(0.3), btScalar(0.3));
1533 colObj->getCustomDebugColor(color);
1535 debugDrawObject(colObj->getWorldTransform(), colObj->getCollisionShape(), color);
1537 if (m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawAabb))
1539 btVector3 minAabb, maxAabb;
1540 btVector3 colorvec = defaultColors.m_aabb;
1541 colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb, maxAabb);
1542 btVector3 contactThreshold(gContactBreakingThreshold, gContactBreakingThreshold, gContactBreakingThreshold);
1543 minAabb -= contactThreshold;
1544 maxAabb += contactThreshold;
1546 btVector3 minAabb2, maxAabb2;
1548 if (getDispatchInfo().m_useContinuous && colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY && !colObj->isStaticOrKinematicObject())
1550 colObj->getCollisionShape()->getAabb(colObj->getInterpolationWorldTransform(), minAabb2, maxAabb2);
1551 minAabb2 -= contactThreshold;
1552 maxAabb2 += contactThreshold;
1553 minAabb.setMin(minAabb2);
1554 maxAabb.setMax(maxAabb2);
1557 m_debugDrawer->drawAabb(minAabb, maxAabb, colorvec);
1565 void btCollisionWorld::serializeCollisionObjects(btSerializer* serializer)
1569 ///keep track of shapes already serialized
1570 btHashMap<btHashPtr, btCollisionShape*> serializedShapes;
1572 for (i = 0; i < m_collisionObjects.size(); i++)
1574 btCollisionObject* colObj = m_collisionObjects[i];
1575 btCollisionShape* shape = colObj->getCollisionShape();
1577 if (!serializedShapes.find(shape))
1579 serializedShapes.insert(shape, shape);
1580 shape->serializeSingleShape(serializer);
1584 //serialize all collision objects
1585 for (i = 0; i < m_collisionObjects.size(); i++)
1587 btCollisionObject* colObj = m_collisionObjects[i];
1588 if (colObj->getInternalType() == btCollisionObject::CO_COLLISION_OBJECT)
1590 colObj->serializeSingleObject(serializer);
1595 void btCollisionWorld::serializeContactManifolds(btSerializer* serializer)
1597 if (serializer->getSerializationFlags() & BT_SERIALIZE_CONTACT_MANIFOLDS)
1599 int numManifolds = getDispatcher()->getNumManifolds();
1600 for (int i = 0; i < numManifolds; i++)
1602 const btPersistentManifold* manifold = getDispatcher()->getInternalManifoldPointer()[i];
1603 //don't serialize empty manifolds, they just take space
1604 //(may have to do it anyway if it destroys determinism)
1605 if (manifold->getNumContacts() == 0)
1608 btChunk* chunk = serializer->allocate(manifold->calculateSerializeBufferSize(), 1);
1609 const char* structType = manifold->serialize(manifold, chunk->m_oldPtr, serializer);
1610 serializer->finalizeChunk(chunk, structType, BT_CONTACTMANIFOLD_CODE, (void*)manifold);
1615 void btCollisionWorld::serialize(btSerializer* serializer)
1617 serializer->startSerialization();
1619 serializeCollisionObjects(serializer);
1621 serializeContactManifolds(serializer);
1623 serializer->finishSerialization();