btCollisionDispatcher.cpp

Go to the documentation of this file.
00001 /*
00002 Bullet Continuous Collision Detection and Physics Library
00003 Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
00004 
00005 This software is provided 'as-is', without any express or implied warranty.
00006 In no event will the authors be held liable for any damages arising from the use of this software.
00007 Permission is granted to anyone to use this software for any purpose, 
00008 including commercial applications, and to alter it and redistribute it freely, 
00009 subject to the following restrictions:
00010 
00011 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.
00012 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
00013 3. This notice may not be removed or altered from any source distribution.
00014 */
00015 
00016 
00017 
00018 #include "btCollisionDispatcher.h"
00019 
00020 
00021 #include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
00022 
00023 #include "BulletCollision/CollisionShapes/btCollisionShape.h"
00024 #include "BulletCollision/CollisionDispatch/btCollisionObject.h"
00025 #include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
00026 #include "LinearMath/btPoolAllocator.h"
00027 #include "BulletCollision/CollisionDispatch/btCollisionConfiguration.h"
00028 #include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
00029 
00030 int gNumManifold = 0;
00031 
00032 #ifdef BT_DEBUG
00033 #include <stdio.h>
00034 #endif
00035 
00036 
00037 btCollisionDispatcher::btCollisionDispatcher (btCollisionConfiguration* collisionConfiguration): 
00038 m_dispatcherFlags(btCollisionDispatcher::CD_USE_RELATIVE_CONTACT_BREAKING_THRESHOLD),
00039         m_collisionConfiguration(collisionConfiguration)
00040 {
00041         int i;
00042 
00043         setNearCallback(defaultNearCallback);
00044         
00045         m_collisionAlgorithmPoolAllocator = collisionConfiguration->getCollisionAlgorithmPool();
00046 
00047         m_persistentManifoldPoolAllocator = collisionConfiguration->getPersistentManifoldPool();
00048 
00049         for (i=0;i<MAX_BROADPHASE_COLLISION_TYPES;i++)
00050         {
00051                 for (int j=0;j<MAX_BROADPHASE_COLLISION_TYPES;j++)
00052                 {
00053                         m_doubleDispatch[i][j] = m_collisionConfiguration->getCollisionAlgorithmCreateFunc(i,j);
00054                         btAssert(m_doubleDispatch[i][j]);
00055                 }
00056         }
00057         
00058         
00059 }
00060 
00061 
00062 void btCollisionDispatcher::registerCollisionCreateFunc(int proxyType0, int proxyType1, btCollisionAlgorithmCreateFunc *createFunc)
00063 {
00064         m_doubleDispatch[proxyType0][proxyType1] = createFunc;
00065 }
00066 
00067 btCollisionDispatcher::~btCollisionDispatcher()
00068 {
00069 }
00070 
00071 btPersistentManifold*   btCollisionDispatcher::getNewManifold(const btCollisionObject* body0,const btCollisionObject* body1) 
00072 { 
00073         gNumManifold++;
00074         
00075         //btAssert(gNumManifold < 65535);
00076         
00077 
00078 
00079         //optional relative contact breaking threshold, turned on by default (use setDispatcherFlags to switch off feature for improved performance)
00080         
00081         btScalar contactBreakingThreshold =  (m_dispatcherFlags & btCollisionDispatcher::CD_USE_RELATIVE_CONTACT_BREAKING_THRESHOLD) ? 
00082                 btMin(body0->getCollisionShape()->getContactBreakingThreshold(gContactBreakingThreshold) , body1->getCollisionShape()->getContactBreakingThreshold(gContactBreakingThreshold))
00083                 : gContactBreakingThreshold ;
00084 
00085         btScalar contactProcessingThreshold = btMin(body0->getContactProcessingThreshold(),body1->getContactProcessingThreshold());
00086                 
00087         void* mem = 0;
00088         
00089         if (m_persistentManifoldPoolAllocator->getFreeCount())
00090         {
00091                 mem = m_persistentManifoldPoolAllocator->allocate(sizeof(btPersistentManifold));
00092         } else
00093         {
00094                 //we got a pool memory overflow, by default we fallback to dynamically allocate memory. If we require a contiguous contact pool then assert.
00095                 if ((m_dispatcherFlags&CD_DISABLE_CONTACTPOOL_DYNAMIC_ALLOCATION)==0)
00096                 {
00097                         mem = btAlignedAlloc(sizeof(btPersistentManifold),16);
00098                 } else
00099                 {
00100                         btAssert(0);
00101                         //make sure to increase the m_defaultMaxPersistentManifoldPoolSize in the btDefaultCollisionConstructionInfo/btDefaultCollisionConfiguration
00102                         return 0;
00103                 }
00104         }
00105         btPersistentManifold* manifold = new(mem) btPersistentManifold (body0,body1,0,contactBreakingThreshold,contactProcessingThreshold);
00106         manifold->m_index1a = m_manifoldsPtr.size();
00107         m_manifoldsPtr.push_back(manifold);
00108 
00109         return manifold;
00110 }
00111 
00112 void btCollisionDispatcher::clearManifold(btPersistentManifold* manifold)
00113 {
00114         manifold->clearManifold();
00115 }
00116 
00117         
00118 void btCollisionDispatcher::releaseManifold(btPersistentManifold* manifold)
00119 {
00120         
00121         gNumManifold--;
00122 
00123         //printf("releaseManifold: gNumManifold %d\n",gNumManifold);
00124         clearManifold(manifold);
00125 
00126         int findIndex = manifold->m_index1a;
00127         btAssert(findIndex < m_manifoldsPtr.size());
00128         m_manifoldsPtr.swap(findIndex,m_manifoldsPtr.size()-1);
00129         m_manifoldsPtr[findIndex]->m_index1a = findIndex;
00130         m_manifoldsPtr.pop_back();
00131 
00132         manifold->~btPersistentManifold();
00133         if (m_persistentManifoldPoolAllocator->validPtr(manifold))
00134         {
00135                 m_persistentManifoldPoolAllocator->freeMemory(manifold);
00136         } else
00137         {
00138                 btAlignedFree(manifold);
00139         }
00140         
00141 }
00142 
00143         
00144 
00145 btCollisionAlgorithm* btCollisionDispatcher::findAlgorithm(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,btPersistentManifold* sharedManifold)
00146 {
00147         
00148         btCollisionAlgorithmConstructionInfo ci;
00149 
00150         ci.m_dispatcher1 = this;
00151         ci.m_manifold = sharedManifold;
00152         btCollisionAlgorithm* algo = m_doubleDispatch[body0Wrap->getCollisionShape()->getShapeType()][body1Wrap->getCollisionShape()->getShapeType()]->CreateCollisionAlgorithm(ci,body0Wrap,body1Wrap);
00153 
00154         return algo;
00155 }
00156 
00157 
00158 
00159 
00160 bool    btCollisionDispatcher::needsResponse(const btCollisionObject* body0,const btCollisionObject* body1)
00161 {
00162         //here you can do filtering
00163         bool hasResponse = 
00164                 (body0->hasContactResponse() && body1->hasContactResponse());
00165         //no response between two static/kinematic bodies:
00166         hasResponse = hasResponse &&
00167                 ((!body0->isStaticOrKinematicObject()) ||(! body1->isStaticOrKinematicObject()));
00168         return hasResponse;
00169 }
00170 
00171 bool    btCollisionDispatcher::needsCollision(const btCollisionObject* body0,const btCollisionObject* body1)
00172 {
00173         btAssert(body0);
00174         btAssert(body1);
00175 
00176         bool needsCollision = true;
00177 
00178 #ifdef BT_DEBUG
00179         if (!(m_dispatcherFlags & btCollisionDispatcher::CD_STATIC_STATIC_REPORTED))
00180         {
00181                 //broadphase filtering already deals with this
00182                 if (body0->isStaticOrKinematicObject() && body1->isStaticOrKinematicObject())
00183                 {
00184                         m_dispatcherFlags |= btCollisionDispatcher::CD_STATIC_STATIC_REPORTED;
00185                         printf("warning btCollisionDispatcher::needsCollision: static-static collision!\n");
00186                 }
00187         }
00188 #endif //BT_DEBUG
00189 
00190         if ((!body0->isActive()) && (!body1->isActive()))
00191                 needsCollision = false;
00192         else if (!body0->checkCollideWith(body1))
00193                 needsCollision = false;
00194         
00195         return needsCollision ;
00196 
00197 }
00198 
00199 
00200 
00203 class btCollisionPairCallback : public btOverlapCallback
00204 {
00205         const btDispatcherInfo& m_dispatchInfo;
00206         btCollisionDispatcher*  m_dispatcher;
00207 
00208 public:
00209 
00210         btCollisionPairCallback(const btDispatcherInfo& dispatchInfo,btCollisionDispatcher*     dispatcher)
00211         :m_dispatchInfo(dispatchInfo),
00212         m_dispatcher(dispatcher)
00213         {
00214         }
00215 
00216         /*btCollisionPairCallback& operator=(btCollisionPairCallback& other)
00217         {
00218                 m_dispatchInfo = other.m_dispatchInfo;
00219                 m_dispatcher = other.m_dispatcher;
00220                 return *this;
00221         }
00222         */
00223 
00224 
00225         virtual ~btCollisionPairCallback() {}
00226 
00227 
00228         virtual bool    processOverlap(btBroadphasePair& pair)
00229         {
00230                 (*m_dispatcher->getNearCallback())(pair,*m_dispatcher,m_dispatchInfo);
00231 
00232                 return false;
00233         }
00234 };
00235 
00236 
00237 
00238 void    btCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher) 
00239 {
00240         //m_blockedForChanges = true;
00241 
00242         btCollisionPairCallback collisionCallback(dispatchInfo,this);
00243 
00244         pairCache->processAllOverlappingPairs(&collisionCallback,dispatcher);
00245 
00246         //m_blockedForChanges = false;
00247 
00248 }
00249 
00250 
00251 
00252 
00253 //by default, Bullet will use this near callback
00254 void btCollisionDispatcher::defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo)
00255 {
00256                 btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject;
00257                 btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject;
00258 
00259                 if (dispatcher.needsCollision(colObj0,colObj1))
00260                 {
00261                         btCollisionObjectWrapper obj0Wrap(0,colObj0->getCollisionShape(),colObj0,colObj0->getWorldTransform(),-1,-1);
00262                         btCollisionObjectWrapper obj1Wrap(0,colObj1->getCollisionShape(),colObj1,colObj1->getWorldTransform(),-1,-1);
00263 
00264 
00265                         //dispatcher will keep algorithms persistent in the collision pair
00266                         if (!collisionPair.m_algorithm)
00267                         {
00268                                 collisionPair.m_algorithm = dispatcher.findAlgorithm(&obj0Wrap,&obj1Wrap);
00269                         }
00270 
00271                         if (collisionPair.m_algorithm)
00272                         {
00273                                 btManifoldResult contactPointResult(&obj0Wrap,&obj1Wrap);
00274                                 
00275                                 if (dispatchInfo.m_dispatchFunc ==              btDispatcherInfo::DISPATCH_DISCRETE)
00276                                 {
00277                                         //discrete collision detection query
00278                                         
00279                                         collisionPair.m_algorithm->processCollision(&obj0Wrap,&obj1Wrap,dispatchInfo,&contactPointResult);
00280                                 } else
00281                                 {
00282                                         //continuous collision detection query, time of impact (toi)
00283                                         btScalar toi = collisionPair.m_algorithm->calculateTimeOfImpact(colObj0,colObj1,dispatchInfo,&contactPointResult);
00284                                         if (dispatchInfo.m_timeOfImpact > toi)
00285                                                 dispatchInfo.m_timeOfImpact = toi;
00286 
00287                                 }
00288                         }
00289                 }
00290 
00291 }
00292 
00293 
00294 void* btCollisionDispatcher::allocateCollisionAlgorithm(int size)
00295 {
00296         if (m_collisionAlgorithmPoolAllocator->getFreeCount())
00297         {
00298                 return m_collisionAlgorithmPoolAllocator->allocate(size);
00299         }
00300         
00301         //warn user for overflow?
00302         return  btAlignedAlloc(static_cast<size_t>(size), 16);
00303 }
00304 
00305 void btCollisionDispatcher::freeCollisionAlgorithm(void* ptr)
00306 {
00307         if (m_collisionAlgorithmPoolAllocator->validPtr(ptr))
00308         {
00309                 m_collisionAlgorithmPoolAllocator->freeMemory(ptr);
00310         } else
00311         {
00312                 btAlignedFree(ptr);
00313         }
00314 }