2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
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.
18 #include "btCollisionDispatcher.h"
21 #include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
23 #include "BulletCollision/CollisionShapes/btCollisionShape.h"
24 #include "BulletCollision/CollisionDispatch/btCollisionObject.h"
25 #include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
26 #include "LinearMath/btPoolAllocator.h"
27 #include "BulletCollision/CollisionDispatch/btCollisionConfiguration.h"
36 btCollisionDispatcher::btCollisionDispatcher (btCollisionConfiguration* collisionConfiguration):
37 m_dispatcherFlags(btCollisionDispatcher::CD_USE_RELATIVE_CONTACT_BREAKING_THRESHOLD),
38 m_collisionConfiguration(collisionConfiguration)
42 setNearCallback(defaultNearCallback);
44 m_collisionAlgorithmPoolAllocator = collisionConfiguration->getCollisionAlgorithmPool();
46 m_persistentManifoldPoolAllocator = collisionConfiguration->getPersistentManifoldPool();
48 for (i=0;i<MAX_BROADPHASE_COLLISION_TYPES;i++)
50 for (int j=0;j<MAX_BROADPHASE_COLLISION_TYPES;j++)
52 m_doubleDispatch[i][j] = m_collisionConfiguration->getCollisionAlgorithmCreateFunc(i,j);
53 btAssert(m_doubleDispatch[i][j]);
61 void btCollisionDispatcher::registerCollisionCreateFunc(int proxyType0, int proxyType1, btCollisionAlgorithmCreateFunc *createFunc)
63 m_doubleDispatch[proxyType0][proxyType1] = createFunc;
66 btCollisionDispatcher::~btCollisionDispatcher()
70 btPersistentManifold* btCollisionDispatcher::getNewManifold(void* b0,void* b1)
74 //btAssert(gNumManifold < 65535);
77 btCollisionObject* body0 = (btCollisionObject*)b0;
78 btCollisionObject* body1 = (btCollisionObject*)b1;
80 //optional relative contact breaking threshold, turned on by default (use setDispatcherFlags to switch off feature for improved performance)
82 btScalar contactBreakingThreshold = (m_dispatcherFlags & btCollisionDispatcher::CD_USE_RELATIVE_CONTACT_BREAKING_THRESHOLD) ?
83 btMin(body0->getCollisionShape()->getContactBreakingThreshold(gContactBreakingThreshold) , body1->getCollisionShape()->getContactBreakingThreshold(gContactBreakingThreshold))
84 : gContactBreakingThreshold ;
86 btScalar contactProcessingThreshold = btMin(body0->getContactProcessingThreshold(),body1->getContactProcessingThreshold());
90 if (m_persistentManifoldPoolAllocator->getFreeCount())
92 mem = m_persistentManifoldPoolAllocator->allocate(sizeof(btPersistentManifold));
95 //we got a pool memory overflow, by default we fallback to dynamically allocate memory. If we require a contiguous contact pool then assert.
96 if ((m_dispatcherFlags&CD_DISABLE_CONTACTPOOL_DYNAMIC_ALLOCATION)==0)
98 mem = btAlignedAlloc(sizeof(btPersistentManifold),16);
102 //make sure to increase the m_defaultMaxPersistentManifoldPoolSize in the btDefaultCollisionConstructionInfo/btDefaultCollisionConfiguration
106 btPersistentManifold* manifold = new(mem) btPersistentManifold (body0,body1,0,contactBreakingThreshold,contactProcessingThreshold);
107 manifold->m_index1a = m_manifoldsPtr.size();
108 m_manifoldsPtr.push_back(manifold);
113 void btCollisionDispatcher::clearManifold(btPersistentManifold* manifold)
115 manifold->clearManifold();
119 void btCollisionDispatcher::releaseManifold(btPersistentManifold* manifold)
124 //printf("releaseManifold: gNumManifold %d\n",gNumManifold);
125 clearManifold(manifold);
127 int findIndex = manifold->m_index1a;
128 btAssert(findIndex < m_manifoldsPtr.size());
129 m_manifoldsPtr.swap(findIndex,m_manifoldsPtr.size()-1);
130 m_manifoldsPtr[findIndex]->m_index1a = findIndex;
131 m_manifoldsPtr.pop_back();
133 manifold->~btPersistentManifold();
134 if (m_persistentManifoldPoolAllocator->validPtr(manifold))
136 m_persistentManifoldPoolAllocator->freeMemory(manifold);
139 btAlignedFree(manifold);
146 btCollisionAlgorithm* btCollisionDispatcher::findAlgorithm(btCollisionObject* body0,btCollisionObject* body1,btPersistentManifold* sharedManifold)
149 btCollisionAlgorithmConstructionInfo ci;
151 ci.m_dispatcher1 = this;
152 ci.m_manifold = sharedManifold;
153 btCollisionAlgorithm* algo = m_doubleDispatch[body0->getCollisionShape()->getShapeType()][body1->getCollisionShape()->getShapeType()]->CreateCollisionAlgorithm(ci,body0,body1);
161 bool btCollisionDispatcher::needsResponse(btCollisionObject* body0,btCollisionObject* body1)
163 //here you can do filtering
165 (body0->hasContactResponse() && body1->hasContactResponse());
166 //no response between two static/kinematic bodies:
167 hasResponse = hasResponse &&
168 ((!body0->isStaticOrKinematicObject()) ||(! body1->isStaticOrKinematicObject()));
172 bool btCollisionDispatcher::needsCollision(btCollisionObject* body0,btCollisionObject* body1)
177 bool needsCollision = true;
180 if (!(m_dispatcherFlags & btCollisionDispatcher::CD_STATIC_STATIC_REPORTED))
182 //broadphase filtering already deals with this
183 if (body0->isStaticOrKinematicObject() && body1->isStaticOrKinematicObject())
185 m_dispatcherFlags |= btCollisionDispatcher::CD_STATIC_STATIC_REPORTED;
186 printf("warning btCollisionDispatcher::needsCollision: static-static collision!\n");
191 if ((!body0->isActive()) && (!body1->isActive()))
192 needsCollision = false;
193 else if (!body0->checkCollideWith(body1))
194 needsCollision = false;
196 return needsCollision ;
202 ///interface for iterating all overlapping collision pairs, no matter how those pairs are stored (array, set, map etc)
203 ///this is useful for the collision dispatcher.
204 class btCollisionPairCallback : public btOverlapCallback
206 const btDispatcherInfo& m_dispatchInfo;
207 btCollisionDispatcher* m_dispatcher;
211 btCollisionPairCallback(const btDispatcherInfo& dispatchInfo,btCollisionDispatcher* dispatcher)
212 :m_dispatchInfo(dispatchInfo),
213 m_dispatcher(dispatcher)
217 /*btCollisionPairCallback& operator=(btCollisionPairCallback& other)
219 m_dispatchInfo = other.m_dispatchInfo;
220 m_dispatcher = other.m_dispatcher;
226 virtual ~btCollisionPairCallback() {}
229 virtual bool processOverlap(btBroadphasePair& pair)
231 (*m_dispatcher->getNearCallback())(pair,*m_dispatcher,m_dispatchInfo);
239 void btCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher)
241 //m_blockedForChanges = true;
243 btCollisionPairCallback collisionCallback(dispatchInfo,this);
245 pairCache->processAllOverlappingPairs(&collisionCallback,dispatcher);
247 //m_blockedForChanges = false;
254 //by default, Bullet will use this near callback
255 void btCollisionDispatcher::defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo)
257 btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject;
258 btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject;
260 if (dispatcher.needsCollision(colObj0,colObj1))
262 //dispatcher will keep algorithms persistent in the collision pair
263 if (!collisionPair.m_algorithm)
265 collisionPair.m_algorithm = dispatcher.findAlgorithm(colObj0,colObj1);
268 if (collisionPair.m_algorithm)
270 btManifoldResult contactPointResult(colObj0,colObj1);
272 if (dispatchInfo.m_dispatchFunc == btDispatcherInfo::DISPATCH_DISCRETE)
274 //discrete collision detection query
275 collisionPair.m_algorithm->processCollision(colObj0,colObj1,dispatchInfo,&contactPointResult);
278 //continuous collision detection query, time of impact (toi)
279 btScalar toi = collisionPair.m_algorithm->calculateTimeOfImpact(colObj0,colObj1,dispatchInfo,&contactPointResult);
280 if (dispatchInfo.m_timeOfImpact > toi)
281 dispatchInfo.m_timeOfImpact = toi;
290 void* btCollisionDispatcher::allocateCollisionAlgorithm(int size)
292 if (m_collisionAlgorithmPoolAllocator->getFreeCount())
294 return m_collisionAlgorithmPoolAllocator->allocate(size);
297 //warn user for overflow?
298 return btAlignedAlloc(static_cast<size_t>(size), 16);
301 void btCollisionDispatcher::freeCollisionAlgorithm(void* ptr)
303 if (m_collisionAlgorithmPoolAllocator->validPtr(ptr))
305 m_collisionAlgorithmPoolAllocator->freeMemory(ptr);