Blender V2.61 - r43446

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 }