Bullet Collision Detection & Physics Library

SpuGatheringCollisionDispatcher.cpp

Go to the documentation of this file.
00001 /*
00002 Bullet Continuous Collision Detection and Physics Library
00003 Copyright (c) 2003-2007 Erwin Coumans  http://bulletphysics.com
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 #include "SpuGatheringCollisionDispatcher.h"
00017 #include "SpuCollisionTaskProcess.h"
00018 
00019 
00020 #include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
00021 #include "BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h"
00022 #include "SpuContactManifoldCollisionAlgorithm.h"
00023 #include "BulletCollision/CollisionDispatch/btCollisionObject.h"
00024 #include "BulletCollision/CollisionShapes/btCollisionShape.h"
00025 #include "LinearMath/btQuickprof.h"
00026 #include "BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuCollisionShapes.h"
00027 
00028 
00029 
00030 
00031 
00032 SpuGatheringCollisionDispatcher::SpuGatheringCollisionDispatcher(class  btThreadSupportInterface*       threadInterface, unsigned int   maxNumOutstandingTasks,btCollisionConfiguration* collisionConfiguration)
00033 :btCollisionDispatcher(collisionConfiguration),
00034 m_spuCollisionTaskProcess(0),
00035 m_threadInterface(threadInterface),
00036 m_maxNumOutstandingTasks(maxNumOutstandingTasks)
00037 {
00038         
00039 }
00040 
00041 
00042 bool    SpuGatheringCollisionDispatcher::supportsDispatchPairOnSpu(int proxyType0,int proxyType1)
00043 {
00044         bool supported0 = (
00045                 (proxyType0 == BOX_SHAPE_PROXYTYPE) ||
00046                 (proxyType0 == TRIANGLE_SHAPE_PROXYTYPE) ||
00047                 (proxyType0 == SPHERE_SHAPE_PROXYTYPE) ||
00048                 (proxyType0 == CAPSULE_SHAPE_PROXYTYPE) ||
00049                 (proxyType0 == CYLINDER_SHAPE_PROXYTYPE) ||
00050 //              (proxyType0 == CONE_SHAPE_PROXYTYPE) ||
00051                 (proxyType0 == TRIANGLE_MESH_SHAPE_PROXYTYPE) ||
00052                 (proxyType0 == CONVEX_HULL_SHAPE_PROXYTYPE)||
00053                 (proxyType0 == STATIC_PLANE_PROXYTYPE)||
00054                 (proxyType0 == COMPOUND_SHAPE_PROXYTYPE)
00055                 );
00056 
00057         bool supported1 = (
00058                 (proxyType1 == BOX_SHAPE_PROXYTYPE) ||
00059                 (proxyType1 == TRIANGLE_SHAPE_PROXYTYPE) ||
00060                 (proxyType1 == SPHERE_SHAPE_PROXYTYPE) ||
00061                 (proxyType1 == CAPSULE_SHAPE_PROXYTYPE) ||
00062                 (proxyType1 == CYLINDER_SHAPE_PROXYTYPE) ||
00063 //              (proxyType1 == CONE_SHAPE_PROXYTYPE) ||
00064                 (proxyType1 == TRIANGLE_MESH_SHAPE_PROXYTYPE) ||
00065                 (proxyType1 == CONVEX_HULL_SHAPE_PROXYTYPE) ||
00066                 (proxyType1 == STATIC_PLANE_PROXYTYPE) ||
00067                 (proxyType1 == COMPOUND_SHAPE_PROXYTYPE)
00068                 );
00069 
00070         
00071         return supported0 && supported1;
00072 }
00073 
00074 
00075 
00076 SpuGatheringCollisionDispatcher::~SpuGatheringCollisionDispatcher()
00077 {
00078         if (m_spuCollisionTaskProcess)
00079                 delete m_spuCollisionTaskProcess;
00080         
00081 }
00082 
00083 #include "stdio.h"
00084 
00085 
00086 
00089 class btSpuCollisionPairCallback : public btOverlapCallback
00090 {
00091         const btDispatcherInfo& m_dispatchInfo;
00092         SpuGatheringCollisionDispatcher*        m_dispatcher;
00093 
00094 public:
00095 
00096         btSpuCollisionPairCallback(const btDispatcherInfo& dispatchInfo, SpuGatheringCollisionDispatcher*       dispatcher)
00097         :m_dispatchInfo(dispatchInfo),
00098         m_dispatcher(dispatcher)
00099         {
00100         }
00101 
00102         virtual bool    processOverlap(btBroadphasePair& collisionPair)
00103         {
00104 
00105 
00106                 //PPU version
00107                 //(*m_dispatcher->getNearCallback())(collisionPair,*m_dispatcher,m_dispatchInfo);
00108 
00109                 //only support discrete collision detection for now, we could fallback on PPU/unoptimized version for TOI/CCD
00110                 btAssert(m_dispatchInfo.m_dispatchFunc == btDispatcherInfo::DISPATCH_DISCRETE);
00111 
00112                 //by default, Bullet will use this near callback
00113                 {
00115                         if (!collisionPair.m_internalTmpValue)
00116                         {
00117                                 collisionPair.m_internalTmpValue = 1;
00118                         }
00119                         if (!collisionPair.m_algorithm)
00120                         {
00121                                 btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject;
00122                                 btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject;
00123 
00124                                 btCollisionAlgorithmConstructionInfo ci;
00125                                 ci.m_dispatcher1 = m_dispatcher;
00126                                 ci.m_manifold = 0;
00127 
00128                                 if (m_dispatcher->needsCollision(colObj0,colObj1))
00129                                 {
00130                                         int     proxyType0 = colObj0->getCollisionShape()->getShapeType();
00131                                         int     proxyType1 = colObj1->getCollisionShape()->getShapeType();
00132                                         bool supportsSpuDispatch = m_dispatcher->supportsDispatchPairOnSpu(proxyType0,proxyType1) 
00133                                                 && ((colObj0->getCollisionFlags() & btCollisionObject::CF_DISABLE_SPU_COLLISION_PROCESSING) == 0)
00134                                                 && ((colObj1->getCollisionFlags() & btCollisionObject::CF_DISABLE_SPU_COLLISION_PROCESSING) == 0);
00135 
00136                                         if (proxyType0 == COMPOUND_SHAPE_PROXYTYPE)
00137                                         {
00138                                                 btCompoundShape* compound = (btCompoundShape*)colObj0->getCollisionShape();
00139                                                 if (compound->getNumChildShapes()>MAX_SPU_COMPOUND_SUBSHAPES)
00140                                                 {
00141                                                         //printf("PPU fallback, compound->getNumChildShapes(%d)>%d\n",compound->getNumChildShapes(),MAX_SPU_COMPOUND_SUBSHAPES);
00142                                                         supportsSpuDispatch = false;
00143                                                 }
00144                                         }
00145 
00146                                         if (proxyType1 == COMPOUND_SHAPE_PROXYTYPE)
00147                                         {
00148                                                 btCompoundShape* compound = (btCompoundShape*)colObj1->getCollisionShape();
00149                                                 if (compound->getNumChildShapes()>MAX_SPU_COMPOUND_SUBSHAPES)
00150                                                 {
00151                                                         //printf("PPU fallback, compound->getNumChildShapes(%d)>%d\n",compound->getNumChildShapes(),MAX_SPU_COMPOUND_SUBSHAPES);
00152                                                         supportsSpuDispatch = false;
00153                                                 }
00154                                         }
00155 
00156                                         if (supportsSpuDispatch)
00157                                         {
00158 
00159                                                 int so = sizeof(SpuContactManifoldCollisionAlgorithm);
00160 #ifdef ALLOCATE_SEPARATELY
00161                                                 void* mem = btAlignedAlloc(so,16);//m_dispatcher->allocateCollisionAlgorithm(so);
00162 #else
00163                                                 void* mem = m_dispatcher->allocateCollisionAlgorithm(so);
00164 #endif
00165                                                 collisionPair.m_algorithm = new(mem) SpuContactManifoldCollisionAlgorithm(ci,colObj0,colObj1);
00166                                                 collisionPair.m_internalTmpValue =  2;
00167                                         } else
00168                                         {
00169                                                 collisionPair.m_algorithm = m_dispatcher->findAlgorithm(colObj0,colObj1);
00170                                                 collisionPair.m_internalTmpValue = 3;
00171                                         }
00172                                 } 
00173                         }
00174                 }
00175                 return false;
00176         }
00177 };
00178 
00179 void    SpuGatheringCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo, btDispatcher* dispatcher) 
00180 {
00181 
00182         if (dispatchInfo.m_enableSPU)
00183         {
00184                 m_maxNumOutstandingTasks = m_threadInterface->getNumTasks();
00185 
00186                 {
00187                         BT_PROFILE("processAllOverlappingPairs");
00188 
00189                         if (!m_spuCollisionTaskProcess)
00190                                 m_spuCollisionTaskProcess = new SpuCollisionTaskProcess(m_threadInterface,m_maxNumOutstandingTasks);
00191                 
00192                         m_spuCollisionTaskProcess->setNumTasks(m_maxNumOutstandingTasks);
00193         //              printf("m_maxNumOutstandingTasks =%d\n",m_maxNumOutstandingTasks);
00194 
00195                         m_spuCollisionTaskProcess->initialize2(dispatchInfo.m_useEpa);
00196                         
00197                 
00199                         {
00200                                 btSpuCollisionPairCallback      collisionCallback(dispatchInfo,this);
00201 
00202                                 pairCache->processAllOverlappingPairs(&collisionCallback,dispatcher);
00203                         }
00204                 }
00205 
00206                 //send one big batch
00207                 int numTotalPairs = pairCache->getNumOverlappingPairs();
00208                 if (numTotalPairs)
00209                 {
00210                         btBroadphasePair* pairPtr = pairCache->getOverlappingPairArrayPtr();
00211                         int i;
00212                         {
00213                                 int pairRange = SPU_BATCHSIZE_BROADPHASE_PAIRS;
00214                                 if (numTotalPairs < (m_spuCollisionTaskProcess->getNumTasks()*SPU_BATCHSIZE_BROADPHASE_PAIRS))
00215                                 {
00216                                         pairRange = (numTotalPairs/m_spuCollisionTaskProcess->getNumTasks())+1;
00217                                 }
00218         
00219                                 BT_PROFILE("addWorkToTask");
00220                                 for (i=0;i<numTotalPairs;)
00221                                 {
00222                                         //Performance Hint: tweak this number during benchmarking
00223                                         
00224                                         int endIndex = (i+pairRange) < numTotalPairs ? i+pairRange : numTotalPairs;
00225                                         m_spuCollisionTaskProcess->addWorkToTask(pairPtr,i,endIndex);
00226                                         i = endIndex;
00227                                 }
00228                         }
00229                         {
00230                                 BT_PROFILE("PPU fallback");
00231                                 //handle PPU fallback pairs
00232                                 for (i=0;i<numTotalPairs;i++)
00233                                 {
00234                                         btBroadphasePair& collisionPair = pairPtr[i];
00235                                         if (collisionPair.m_internalTmpValue == 3)
00236                                         {
00237                                                 if (collisionPair.m_algorithm)
00238                                                 {
00239                                                         btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject;
00240                                                         btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject;
00241         
00242                                                         if (dispatcher->needsCollision(colObj0,colObj1))
00243                                                         {
00244                                                                 btManifoldResult contactPointResult(colObj0,colObj1);
00245                                                                 
00246                                                                 if (dispatchInfo.m_dispatchFunc ==              btDispatcherInfo::DISPATCH_DISCRETE)
00247                                                                 {
00248                                                                         //discrete collision detection query
00249                                                                         collisionPair.m_algorithm->processCollision(colObj0,colObj1,dispatchInfo,&contactPointResult);
00250                                                                 } else
00251                                                                 {
00252                                                                         //continuous collision detection query, time of impact (toi)
00253                                                                         btScalar toi = collisionPair.m_algorithm->calculateTimeOfImpact(colObj0,colObj1,dispatchInfo,&contactPointResult);
00254                                                                         if (dispatchInfo.m_timeOfImpact > toi)
00255                                                                                 dispatchInfo.m_timeOfImpact = toi;
00256         
00257                                                                 }
00258                                                         }
00259                                                 }
00260                                         }
00261                                 }
00262                         }
00263                 }
00264                 {
00265                         BT_PROFILE("flush2");
00266                         //make sure all SPU work is done
00267                         m_spuCollisionTaskProcess->flush2();
00268                 }
00269 
00270         } else
00271         {
00274                 btCollisionDispatcher::dispatchAllCollisionPairs(pairCache,dispatchInfo,dispatcher);
00275         }
00276 }