00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
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 #include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
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
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
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
00107
00108
00109
00110 btAssert(m_dispatchInfo.m_dispatchFunc == btDispatcherInfo::DISPATCH_DISCRETE);
00111
00112
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
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
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);
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 btCollisionObjectWrapper ob0(0,colObj0->getCollisionShape(),colObj0,colObj0->getWorldTransform(),-1,-1);
00170 btCollisionObjectWrapper ob1(0,colObj1->getCollisionShape(),colObj1,colObj1->getWorldTransform(),-1,-1);
00171
00172 collisionPair.m_algorithm = m_dispatcher->findAlgorithm(&ob0,&ob1);
00173 collisionPair.m_internalTmpValue = 3;
00174 }
00175 }
00176 }
00177 }
00178 return false;
00179 }
00180 };
00181
00182 void SpuGatheringCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo, btDispatcher* dispatcher)
00183 {
00184
00185 if (dispatchInfo.m_enableSPU)
00186 {
00187 m_maxNumOutstandingTasks = m_threadInterface->getNumTasks();
00188
00189 {
00190 BT_PROFILE("processAllOverlappingPairs");
00191
00192 if (!m_spuCollisionTaskProcess)
00193 m_spuCollisionTaskProcess = new SpuCollisionTaskProcess(m_threadInterface,m_maxNumOutstandingTasks);
00194
00195 m_spuCollisionTaskProcess->setNumTasks(m_maxNumOutstandingTasks);
00196
00197
00198 m_spuCollisionTaskProcess->initialize2(dispatchInfo.m_useEpa);
00199
00200
00202 {
00203 btSpuCollisionPairCallback collisionCallback(dispatchInfo,this);
00204
00205 pairCache->processAllOverlappingPairs(&collisionCallback,dispatcher);
00206 }
00207 }
00208
00209
00210 int numTotalPairs = pairCache->getNumOverlappingPairs();
00211 if (numTotalPairs)
00212 {
00213 btBroadphasePair* pairPtr = pairCache->getOverlappingPairArrayPtr();
00214 int i;
00215 {
00216 int pairRange = SPU_BATCHSIZE_BROADPHASE_PAIRS;
00217 if (numTotalPairs < (m_spuCollisionTaskProcess->getNumTasks()*SPU_BATCHSIZE_BROADPHASE_PAIRS))
00218 {
00219 pairRange = (numTotalPairs/m_spuCollisionTaskProcess->getNumTasks())+1;
00220 }
00221
00222 BT_PROFILE("addWorkToTask");
00223 for (i=0;i<numTotalPairs;)
00224 {
00225
00226
00227 int endIndex = (i+pairRange) < numTotalPairs ? i+pairRange : numTotalPairs;
00228 m_spuCollisionTaskProcess->addWorkToTask(pairPtr,i,endIndex);
00229 i = endIndex;
00230 }
00231 }
00232 {
00233 BT_PROFILE("PPU fallback");
00234
00235 for (i=0;i<numTotalPairs;i++)
00236 {
00237 btBroadphasePair& collisionPair = pairPtr[i];
00238 if (collisionPair.m_internalTmpValue == 3)
00239 {
00240 if (collisionPair.m_algorithm)
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
00248 btCollisionObjectWrapper ob0(0,colObj0->getCollisionShape(),colObj0,colObj0->getWorldTransform(),-1,-1);
00249 btCollisionObjectWrapper ob1(0,colObj1->getCollisionShape(),colObj1,colObj1->getWorldTransform(),-1,-1);
00250
00251 btManifoldResult contactPointResult(&ob0,&ob1);
00252
00253 if (dispatchInfo.m_dispatchFunc == btDispatcherInfo::DISPATCH_DISCRETE)
00254 {
00255
00256 collisionPair.m_algorithm->processCollision(&ob0,&ob1,dispatchInfo,&contactPointResult);
00257 } else
00258 {
00259
00260 btScalar toi = collisionPair.m_algorithm->calculateTimeOfImpact(colObj0,colObj1,dispatchInfo,&contactPointResult);
00261 if (dispatchInfo.m_timeOfImpact > toi)
00262 dispatchInfo.m_timeOfImpact = toi;
00263
00264 }
00265 }
00266 }
00267 }
00268 }
00269 }
00270 }
00271 {
00272 BT_PROFILE("flush2");
00273
00274 m_spuCollisionTaskProcess->flush2();
00275 }
00276
00277 } else
00278 {
00281 btCollisionDispatcher::dispatchAllCollisionPairs(pairCache,dispatchInfo,dispatcher);
00282 }
00283 }