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 "btCollisionDispatcher.h"
17 #include "LinearMath/btQuickprof.h"
19 #include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
21 #include "BulletCollision/CollisionShapes/btCollisionShape.h"
22 #include "BulletCollision/CollisionDispatch/btCollisionObject.h"
23 #include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
24 #include "LinearMath/btPoolAllocator.h"
25 #include "BulletCollision/CollisionDispatch/btCollisionConfiguration.h"
26 #include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
32 btCollisionDispatcher::btCollisionDispatcher(btCollisionConfiguration* collisionConfiguration) : m_dispatcherFlags(btCollisionDispatcher::CD_USE_RELATIVE_CONTACT_BREAKING_THRESHOLD),
33 m_collisionConfiguration(collisionConfiguration)
37 setNearCallback(defaultNearCallback);
39 m_collisionAlgorithmPoolAllocator = collisionConfiguration->getCollisionAlgorithmPool();
41 m_persistentManifoldPoolAllocator = collisionConfiguration->getPersistentManifoldPool();
43 for (i = 0; i < MAX_BROADPHASE_COLLISION_TYPES; i++)
45 for (int j = 0; j < MAX_BROADPHASE_COLLISION_TYPES; j++)
47 m_doubleDispatchContactPoints[i][j] = m_collisionConfiguration->getCollisionAlgorithmCreateFunc(i, j);
48 btAssert(m_doubleDispatchContactPoints[i][j]);
49 m_doubleDispatchClosestPoints[i][j] = m_collisionConfiguration->getClosestPointsAlgorithmCreateFunc(i, j);
54 void btCollisionDispatcher::registerCollisionCreateFunc(int proxyType0, int proxyType1, btCollisionAlgorithmCreateFunc* createFunc)
56 m_doubleDispatchContactPoints[proxyType0][proxyType1] = createFunc;
59 void btCollisionDispatcher::registerClosestPointsCreateFunc(int proxyType0, int proxyType1, btCollisionAlgorithmCreateFunc* createFunc)
61 m_doubleDispatchClosestPoints[proxyType0][proxyType1] = createFunc;
64 btCollisionDispatcher::~btCollisionDispatcher()
68 btPersistentManifold* btCollisionDispatcher::getNewManifold(const btCollisionObject* body0, const btCollisionObject* body1)
70 //btAssert(gNumManifold < 65535);
72 //optional relative contact breaking threshold, turned on by default (use setDispatcherFlags to switch off feature for improved performance)
74 btScalar contactBreakingThreshold = (m_dispatcherFlags & btCollisionDispatcher::CD_USE_RELATIVE_CONTACT_BREAKING_THRESHOLD) ? btMin(body0->getCollisionShape()->getContactBreakingThreshold(gContactBreakingThreshold), body1->getCollisionShape()->getContactBreakingThreshold(gContactBreakingThreshold))
75 : gContactBreakingThreshold;
77 btScalar contactProcessingThreshold = btMin(body0->getContactProcessingThreshold(), body1->getContactProcessingThreshold());
79 void* mem = m_persistentManifoldPoolAllocator->allocate(sizeof(btPersistentManifold));
82 //we got a pool memory overflow, by default we fallback to dynamically allocate memory. If we require a contiguous contact pool then assert.
83 if ((m_dispatcherFlags & CD_DISABLE_CONTACTPOOL_DYNAMIC_ALLOCATION) == 0)
85 mem = btAlignedAlloc(sizeof(btPersistentManifold), 16);
90 //make sure to increase the m_defaultMaxPersistentManifoldPoolSize in the btDefaultCollisionConstructionInfo/btDefaultCollisionConfiguration
94 btPersistentManifold* manifold = new (mem) btPersistentManifold(body0, body1, 0, contactBreakingThreshold, contactProcessingThreshold);
95 manifold->m_index1a = m_manifoldsPtr.size();
96 m_manifoldsPtr.push_back(manifold);
101 void btCollisionDispatcher::clearManifold(btPersistentManifold* manifold)
103 manifold->clearManifold();
106 void btCollisionDispatcher::releaseManifold(btPersistentManifold* manifold)
108 //printf("releaseManifold: gNumManifold %d\n",gNumManifold);
109 clearManifold(manifold);
111 int findIndex = manifold->m_index1a;
112 btAssert(findIndex < m_manifoldsPtr.size());
113 m_manifoldsPtr.swap(findIndex, m_manifoldsPtr.size() - 1);
114 m_manifoldsPtr[findIndex]->m_index1a = findIndex;
115 m_manifoldsPtr.pop_back();
117 manifold->~btPersistentManifold();
118 if (m_persistentManifoldPoolAllocator->validPtr(manifold))
120 m_persistentManifoldPoolAllocator->freeMemory(manifold);
124 btAlignedFree(manifold);
128 btCollisionAlgorithm* btCollisionDispatcher::findAlgorithm(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, btPersistentManifold* sharedManifold, ebtDispatcherQueryType algoType)
130 btCollisionAlgorithmConstructionInfo ci;
132 ci.m_dispatcher1 = this;
133 ci.m_manifold = sharedManifold;
134 btCollisionAlgorithm* algo = 0;
135 if (algoType == BT_CONTACT_POINT_ALGORITHMS)
137 algo = m_doubleDispatchContactPoints[body0Wrap->getCollisionShape()->getShapeType()][body1Wrap->getCollisionShape()->getShapeType()]->CreateCollisionAlgorithm(ci, body0Wrap, body1Wrap);
141 algo = m_doubleDispatchClosestPoints[body0Wrap->getCollisionShape()->getShapeType()][body1Wrap->getCollisionShape()->getShapeType()]->CreateCollisionAlgorithm(ci, body0Wrap, body1Wrap);
147 bool btCollisionDispatcher::needsResponse(const btCollisionObject* body0, const btCollisionObject* body1)
149 //here you can do filtering
151 (body0->hasContactResponse() && body1->hasContactResponse());
152 //no response between two static/kinematic bodies:
153 hasResponse = hasResponse &&
154 ((!body0->isStaticOrKinematicObject()) || (!body1->isStaticOrKinematicObject()));
158 bool btCollisionDispatcher::needsCollision(const btCollisionObject* body0, const btCollisionObject* body1)
163 bool needsCollision = true;
166 if (!(m_dispatcherFlags & btCollisionDispatcher::CD_STATIC_STATIC_REPORTED))
168 //broadphase filtering already deals with this
169 if (body0->isStaticOrKinematicObject() && body1->isStaticOrKinematicObject())
171 m_dispatcherFlags |= btCollisionDispatcher::CD_STATIC_STATIC_REPORTED;
172 printf("warning btCollisionDispatcher::needsCollision: static-static collision!\n");
177 if ((!body0->isActive()) && (!body1->isActive()))
178 needsCollision = false;
179 else if ((!body0->checkCollideWith(body1)) || (!body1->checkCollideWith(body0)))
180 needsCollision = false;
182 return needsCollision;
185 ///interface for iterating all overlapping collision pairs, no matter how those pairs are stored (array, set, map etc)
186 ///this is useful for the collision dispatcher.
187 class btCollisionPairCallback : public btOverlapCallback
189 const btDispatcherInfo& m_dispatchInfo;
190 btCollisionDispatcher* m_dispatcher;
193 btCollisionPairCallback(const btDispatcherInfo& dispatchInfo, btCollisionDispatcher* dispatcher)
194 : m_dispatchInfo(dispatchInfo),
195 m_dispatcher(dispatcher)
199 /*btCollisionPairCallback& operator=(btCollisionPairCallback& other)
201 m_dispatchInfo = other.m_dispatchInfo;
202 m_dispatcher = other.m_dispatcher;
207 virtual ~btCollisionPairCallback() {}
209 virtual bool processOverlap(btBroadphasePair& pair)
211 (*m_dispatcher->getNearCallback())(pair, *m_dispatcher, m_dispatchInfo);
216 void btCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache, const btDispatcherInfo& dispatchInfo, btDispatcher* dispatcher)
218 //m_blockedForChanges = true;
220 btCollisionPairCallback collisionCallback(dispatchInfo, this);
223 BT_PROFILE("processAllOverlappingPairs");
224 pairCache->processAllOverlappingPairs(&collisionCallback, dispatcher, dispatchInfo);
227 //m_blockedForChanges = false;
230 //by default, Bullet will use this near callback
231 void btCollisionDispatcher::defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo)
233 btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject;
234 btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject;
236 if (dispatcher.needsCollision(colObj0, colObj1))
238 btCollisionObjectWrapper obj0Wrap(0, colObj0->getCollisionShape(), colObj0, colObj0->getWorldTransform(), -1, -1);
239 btCollisionObjectWrapper obj1Wrap(0, colObj1->getCollisionShape(), colObj1, colObj1->getWorldTransform(), -1, -1);
241 //dispatcher will keep algorithms persistent in the collision pair
242 if (!collisionPair.m_algorithm)
244 collisionPair.m_algorithm = dispatcher.findAlgorithm(&obj0Wrap, &obj1Wrap, 0, BT_CONTACT_POINT_ALGORITHMS);
247 if (collisionPair.m_algorithm)
249 btManifoldResult contactPointResult(&obj0Wrap, &obj1Wrap);
251 if (dispatchInfo.m_dispatchFunc == btDispatcherInfo::DISPATCH_DISCRETE)
253 //discrete collision detection query
255 collisionPair.m_algorithm->processCollision(&obj0Wrap, &obj1Wrap, dispatchInfo, &contactPointResult);
259 //continuous collision detection query, time of impact (toi)
260 btScalar toi = collisionPair.m_algorithm->calculateTimeOfImpact(colObj0, colObj1, dispatchInfo, &contactPointResult);
261 if (dispatchInfo.m_timeOfImpact > toi)
262 dispatchInfo.m_timeOfImpact = toi;
268 void* btCollisionDispatcher::allocateCollisionAlgorithm(int size)
270 void* mem = m_collisionAlgorithmPoolAllocator->allocate(size);
273 //warn user for overflow?
274 return btAlignedAlloc(static_cast<size_t>(size), 16);
279 void btCollisionDispatcher::freeCollisionAlgorithm(void* ptr)
281 if (m_collisionAlgorithmPoolAllocator->validPtr(ptr))
283 m_collisionAlgorithmPoolAllocator->freeMemory(ptr);