Back to index

supertuxkart  0.5+dfsg1
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 
00029 int gNumManifold = 0;
00030 
00031 #ifdef BT_DEBUG
00032 #include <stdio.h>
00033 #endif
00034 
00035 
00036 btCollisionDispatcher::btCollisionDispatcher (btCollisionConfiguration* collisionConfiguration): 
00037        m_count(0),
00038        m_useIslands(true),
00039        m_staticWarningReported(false),
00040        m_collisionConfiguration(collisionConfiguration)
00041 {
00042        int i;
00043 
00044        setNearCallback(defaultNearCallback);
00045        
00046        m_collisionAlgorithmPoolAllocator = collisionConfiguration->getCollisionAlgorithmPool();
00047 
00048        m_persistentManifoldPoolAllocator = collisionConfiguration->getPersistentManifoldPool();
00049 
00050        for (i=0;i<MAX_BROADPHASE_COLLISION_TYPES;i++)
00051        {
00052               for (int j=0;j<MAX_BROADPHASE_COLLISION_TYPES;j++)
00053               {
00054                      m_doubleDispatch[i][j] = m_collisionConfiguration->getCollisionAlgorithmCreateFunc(i,j);
00055                      assert(m_doubleDispatch[i][j]);
00056               }
00057        }
00058        
00059        
00060 };
00061 
00062 
00063 void btCollisionDispatcher::registerCollisionCreateFunc(int proxyType0, int proxyType1, btCollisionAlgorithmCreateFunc *createFunc)
00064 {
00065        m_doubleDispatch[proxyType0][proxyType1] = createFunc;
00066 }
00067 
00068 btCollisionDispatcher::~btCollisionDispatcher()
00069 {
00070 }
00071 
00072 btPersistentManifold*       btCollisionDispatcher::getNewManifold(void* b0,void* b1) 
00073 { 
00074        gNumManifold++;
00075        
00076        //btAssert(gNumManifold < 65535);
00077        
00078 
00079        btCollisionObject* body0 = (btCollisionObject*)b0;
00080        btCollisionObject* body1 = (btCollisionObject*)b1;
00081        
00082        void* mem = 0;
00083        
00084        if (m_persistentManifoldPoolAllocator->getFreeCount())
00085        {
00086               mem = m_persistentManifoldPoolAllocator->allocate(sizeof(btPersistentManifold));
00087        } else
00088        {
00089               mem = btAlignedAlloc(sizeof(btPersistentManifold),16);
00090 
00091        }
00092        btPersistentManifold* manifold = new(mem) btPersistentManifold (body0,body1,0);
00093        manifold->m_index1a = m_manifoldsPtr.size();
00094        m_manifoldsPtr.push_back(manifold);
00095 
00096        return manifold;
00097 }
00098 
00099 void btCollisionDispatcher::clearManifold(btPersistentManifold* manifold)
00100 {
00101        manifold->clearManifold();
00102 }
00103 
00104        
00105 void btCollisionDispatcher::releaseManifold(btPersistentManifold* manifold)
00106 {
00107        
00108        gNumManifold--;
00109 
00110        //printf("releaseManifold: gNumManifold %d\n",gNumManifold);
00111        clearManifold(manifold);
00112 
00113        int findIndex = manifold->m_index1a;
00114        btAssert(findIndex < m_manifoldsPtr.size());
00115        m_manifoldsPtr.swap(findIndex,m_manifoldsPtr.size()-1);
00116        m_manifoldsPtr[findIndex]->m_index1a = findIndex;
00117        m_manifoldsPtr.pop_back();
00118 
00119        manifold->~btPersistentManifold();
00120        if (m_persistentManifoldPoolAllocator->validPtr(manifold))
00121        {
00122               m_persistentManifoldPoolAllocator->freeMemory(manifold);
00123        } else
00124        {
00125               btAlignedFree(manifold);
00126        }
00127        
00128 }
00129 
00130        
00131 
00132 btCollisionAlgorithm* btCollisionDispatcher::findAlgorithm(btCollisionObject* body0,btCollisionObject* body1,btPersistentManifold* sharedManifold)
00133 {
00134        
00135        btCollisionAlgorithmConstructionInfo ci;
00136 
00137        ci.m_dispatcher1 = this;
00138        ci.m_manifold = sharedManifold;
00139        btCollisionAlgorithm* algo = m_doubleDispatch[body0->getCollisionShape()->getShapeType()][body1->getCollisionShape()->getShapeType()]->CreateCollisionAlgorithm(ci,body0,body1);
00140 
00141        return algo;
00142 }
00143 
00144 
00145 
00146 
00147 
00148 bool   btCollisionDispatcher::needsResponse(btCollisionObject* body0,btCollisionObject* body1)
00149 {
00150        //here you can do filtering
00151        bool hasResponse = 
00152               (body0->hasContactResponse() && body1->hasContactResponse());
00153        //no response between two static/kinematic bodies:
00154        hasResponse = hasResponse &&
00155               ((!body0->isStaticOrKinematicObject()) ||(! body1->isStaticOrKinematicObject()));
00156        return hasResponse;
00157 }
00158 
00159 bool   btCollisionDispatcher::needsCollision(btCollisionObject* body0,btCollisionObject* body1)
00160 {
00161        assert(body0);
00162        assert(body1);
00163 
00164        bool needsCollision = true;
00165 
00166 #ifdef BT_DEBUG
00167        if (!m_staticWarningReported)
00168        {
00169               //broadphase filtering already deals with this
00170               if ((body0->isStaticObject() || body0->isKinematicObject()) &&
00171                      (body1->isStaticObject() || body1->isKinematicObject()))
00172               {
00173                      m_staticWarningReported = true;
00174                      printf("warning btCollisionDispatcher::needsCollision: static-static collision!\n");
00175               }
00176        }
00177 #endif //BT_DEBUG
00178 
00179        if ((!body0->isActive()) && (!body1->isActive()))
00180               needsCollision = false;
00181        else if (!body0->checkCollideWith(body1))
00182               needsCollision = false;
00183        
00184        return needsCollision ;
00185 
00186 }
00187 
00188 
00189 
00192 class btCollisionPairCallback : public btOverlapCallback
00193 {
00194        btDispatcherInfo& m_dispatchInfo;
00195        btCollisionDispatcher*      m_dispatcher;
00196 
00197 public:
00198 
00199        btCollisionPairCallback(btDispatcherInfo& dispatchInfo,btCollisionDispatcher*       dispatcher)
00200        :m_dispatchInfo(dispatchInfo),
00201        m_dispatcher(dispatcher)
00202        {
00203        }
00204 
00205        btCollisionPairCallback& operator=(btCollisionPairCallback& other)
00206        {
00207               m_dispatchInfo = other.m_dispatchInfo;
00208               m_dispatcher = other.m_dispatcher;
00209               return *this;
00210        }
00211 
00212        virtual ~btCollisionPairCallback() {}
00213 
00214 
00215        virtual bool  processOverlap(btBroadphasePair& pair)
00216        {
00217               (*m_dispatcher->getNearCallback())(pair,*m_dispatcher,m_dispatchInfo);
00218 
00219               return false;
00220        }
00221 };
00222 
00223 
00224 void   btCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher)
00225 {
00226        //m_blockedForChanges = true;
00227 
00228        btCollisionPairCallback     collisionCallback(dispatchInfo,this);
00229 
00230        pairCache->processAllOverlappingPairs(&collisionCallback,dispatcher);
00231 
00232        //m_blockedForChanges = false;
00233 
00234 }
00235 
00236 
00237 
00238 
00239 //by default, Bullet will use this near callback
00240 void btCollisionDispatcher::defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, btDispatcherInfo& dispatchInfo)
00241 {
00242               btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject;
00243               btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject;
00244 
00245               if (dispatcher.needsCollision(colObj0,colObj1))
00246               {
00247                      //dispatcher will keep algorithms persistent in the collision pair
00248                      if (!collisionPair.m_algorithm)
00249                      {
00250                             collisionPair.m_algorithm = dispatcher.findAlgorithm(colObj0,colObj1);
00251                      }
00252 
00253                      if (collisionPair.m_algorithm)
00254                      {
00255                             btManifoldResult contactPointResult(colObj0,colObj1);
00256                             
00257                             if (dispatchInfo.m_dispatchFunc ==               btDispatcherInfo::DISPATCH_DISCRETE)
00258                             {
00259                                    //discrete collision detection query
00260                                    collisionPair.m_algorithm->processCollision(colObj0,colObj1,dispatchInfo,&contactPointResult);
00261                             } else
00262                             {
00263                                    //continuous collision detection query, time of impact (toi)
00264                                    btScalar toi = collisionPair.m_algorithm->calculateTimeOfImpact(colObj0,colObj1,dispatchInfo,&contactPointResult);
00265                                    if (dispatchInfo.m_timeOfImpact > toi)
00266                                           dispatchInfo.m_timeOfImpact = toi;
00267 
00268                             }
00269                      }
00270               }
00271 
00272 }
00273 
00274 
00275 void* btCollisionDispatcher::allocateCollisionAlgorithm(int size)
00276 {
00277        if (m_collisionAlgorithmPoolAllocator->getFreeCount())
00278        {
00279               return m_collisionAlgorithmPoolAllocator->allocate(size);
00280        }
00281        
00282        //warn user for overflow?
00283        return btAlignedAlloc(size,16);
00284 }
00285 
00286 void btCollisionDispatcher::freeCollisionAlgorithm(void* ptr)
00287 {
00288        if (m_collisionAlgorithmPoolAllocator->validPtr(ptr))
00289        {
00290               m_collisionAlgorithmPoolAllocator->freeMemory(ptr);
00291        } else
00292        {
00293               btAlignedFree(ptr);
00294        }
00295 }