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

Generated on Mon Feb 15 22:17:02 2010 for Bullet Collision Detection & Physics Library by  doxygen 1.6.1