00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "SpuGatheringCollisionTask.h"
00017
00018
00019 #include "../SpuDoubleBuffer.h"
00020
00021 #include "../SpuCollisionTaskProcess.h"
00022 #include "../SpuGatheringCollisionDispatcher.h"
00023
00024 #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
00025 #include "../SpuContactManifoldCollisionAlgorithm.h"
00026 #include "BulletCollision/CollisionDispatch/btCollisionObject.h"
00027 #include "SpuContactResult.h"
00028 #include "BulletCollision/CollisionShapes/btOptimizedBvh.h"
00029 #include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h"
00030 #include "BulletCollision/CollisionShapes/btSphereShape.h"
00031 #include "BulletCollision/CollisionShapes/btConvexPointCloudShape.h"
00032
00033 #include "BulletCollision/CollisionShapes/btCapsuleShape.h"
00034
00035 #include "BulletCollision/CollisionShapes/btConvexShape.h"
00036 #include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h"
00037 #include "BulletCollision/CollisionShapes/btConvexHullShape.h"
00038 #include "BulletCollision/CollisionShapes/btCompoundShape.h"
00039
00040 #include "SpuMinkowskiPenetrationDepthSolver.h"
00041
00042 #include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h"
00043
00044
00045 #include "boxBoxDistance.h"
00046 #include "BulletMultiThreaded/vectormath2bullet.h"
00047 #include "SpuCollisionShapes.h"
00048 #include "BulletCollision/CollisionDispatch/btBoxBoxDetector.h"
00049 #include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h"
00050 #include "BulletCollision/CollisionShapes/btTriangleShape.h"
00051
00052 #ifdef __SPU__
00054 #ifndef USE_LIBSPE2
00055 #define USE_SOFTWARE_CACHE 1
00056 #endif
00057 #endif //__SPU__
00058
00059 int gSkippedCol = 0;
00060 int gProcessedCol = 0;
00061
00064 #if USE_SOFTWARE_CACHE
00065 #include <spu_intrinsics.h>
00066 #include <sys/spu_thread.h>
00067 #include <sys/spu_event.h>
00068 #include <stdint.h>
00069 #define SPE_CACHE_NWAY 4
00070
00071 #define SPE_CACHE_NSETS 8
00072
00073 #define SPE_CACHELINE_SIZE 128
00074 #define SPE_CACHE_SET_TAGID(set) 15
00076 #include "../Extras/software_cache/cache/include/spe_cache.h"
00077
00078
00079 int g_CacheMisses=0;
00080 int g_CacheHits=0;
00081
00082 #if 0 // Added to allow cache misses and hits to be tracked, change this to 1 to restore unmodified version
00083 #define spe_cache_read(ea) _spe_cache_lookup_xfer_wait_(ea, 0, 1)
00084 #else
00085 #define spe_cache_read(ea) \
00086 ({ \
00087 int set, idx, line, byte; \
00088 _spe_cache_nway_lookup_(ea, set, idx); \
00089 \
00090 if (btUnlikely(idx < 0)) { \
00091 ++g_CacheMisses; \
00092 idx = _spe_cache_miss_(ea, set, -1); \
00093 spu_writech(22, SPE_CACHE_SET_TAGMASK(set)); \
00094 spu_mfcstat(MFC_TAG_UPDATE_ALL); \
00095 } \
00096 else \
00097 { \
00098 ++g_CacheHits; \
00099 } \
00100 line = _spe_cacheline_num_(set, idx); \
00101 byte = _spe_cacheline_byte_offset_(ea); \
00102 (void *) &spe_cache_mem[line + byte]; \
00103 })
00104
00105 #endif
00106
00107 #endif // USE_SOFTWARE_CACHE
00108
00109 bool gUseEpa = false;
00110
00111 #ifdef USE_SN_TUNER
00112 #include <LibSN_SPU.h>
00113 #endif //USE_SN_TUNER
00114
00115 #if defined (__SPU__) && !defined (USE_LIBSPE2)
00116 #include <spu_printf.h>
00117 #elif defined (USE_LIBSPE2)
00118 #define spu_printf(a)
00119 #else
00120 #define IGNORE_ALIGNMENT 1
00121 #include <stdio.h>
00122 #include <stdlib.h>
00123 #define spu_printf printf
00124
00125 #endif
00126
00127
00128
00130 struct CollisionTask_LocalStoreMemory
00131 {
00134
00135 ATTRIBUTE_ALIGNED16(btBroadphasePair gBroadphasePairsBuffer[SPU_BATCHSIZE_BROADPHASE_PAIRS]);
00136 DoubleBuffer<unsigned char, MIDPHASE_WORKUNIT_PAGE_SIZE> g_workUnitTaskBuffers;
00137 ATTRIBUTE_ALIGNED16(char gSpuContactManifoldAlgoBuffer [sizeof(SpuContactManifoldCollisionAlgorithm)+16]);
00138 ATTRIBUTE_ALIGNED16(char gColObj0Buffer [sizeof(btCollisionObject)+16]);
00139 ATTRIBUTE_ALIGNED16(char gColObj1Buffer [sizeof(btCollisionObject)+16]);
00141 ATTRIBUTE_ALIGNED16(int spuIndices[16]);
00142 btPersistentManifold gPersistentManifoldBuffer;
00143 CollisionShape_LocalStoreMemory gCollisionShapes[2];
00144 bvhMeshShape_LocalStoreMemory bvhShapeData;
00145 SpuConvexPolyhedronVertexData convexVertexData[2];
00146 CompoundShape_LocalStoreMemory compoundShapeData[2];
00147
00150 btCollisionObject* m_lsColObj0Ptr;
00151 btCollisionObject* m_lsColObj1Ptr;
00152 btBroadphasePair* m_pairsPointer;
00153 btPersistentManifold* m_lsManifoldPtr;
00154 SpuContactManifoldCollisionAlgorithm* m_lsCollisionAlgorithmPtr;
00155
00156 bool needsDmaPutContactManifoldAlgo;
00157
00158 btCollisionObject* getColObj0()
00159 {
00160 return m_lsColObj0Ptr;
00161 }
00162 btCollisionObject* getColObj1()
00163 {
00164 return m_lsColObj1Ptr;
00165 }
00166
00167
00168 btBroadphasePair* getBroadphasePairPtr()
00169 {
00170 return m_pairsPointer;
00171 }
00172
00173 SpuContactManifoldCollisionAlgorithm* getlocalCollisionAlgorithm()
00174 {
00175 return m_lsCollisionAlgorithmPtr;
00176 }
00177
00178 btPersistentManifold* getContactManifoldPtr()
00179 {
00180 return m_lsManifoldPtr;
00181 }
00182 };
00183
00184
00185 #if defined(__CELLOS_LV2__) || defined(USE_LIBSPE2)
00186
00187 ATTRIBUTE_ALIGNED16(CollisionTask_LocalStoreMemory gLocalStoreMemory);
00188
00189 void* createCollisionLocalStoreMemory()
00190 {
00191 return &gLocalStoreMemory;
00192 }
00193 #else
00194 void* createCollisionLocalStoreMemory()
00195 {
00196 return new CollisionTask_LocalStoreMemory;
00197 }
00198
00199 #endif
00200
00201 void ProcessSpuConvexConvexCollision(SpuCollisionPairInput* wuInput, CollisionTask_LocalStoreMemory* lsMemPtr, SpuContactResult& spuContacts);
00202
00203
00204 SIMD_FORCE_INLINE void small_cache_read(void* buffer, ppu_address_t ea, size_t size)
00205 {
00206 #if USE_SOFTWARE_CACHE
00207
00208
00209 btAssert((ea & ~SPE_CACHELINE_MASK) == ((ea + size - 1) & ~SPE_CACHELINE_MASK));
00210
00211 void* ls = spe_cache_read(ea);
00212 memcpy(buffer, ls, size);
00213 #else
00214 stallingUnalignedDmaSmallGet(buffer,ea,size);
00215 #endif
00216 }
00217
00218 SIMD_FORCE_INLINE void small_cache_read_triple( void* ls0, ppu_address_t ea0,
00219 void* ls1, ppu_address_t ea1,
00220 void* ls2, ppu_address_t ea2,
00221 size_t size)
00222 {
00223 btAssert(size<16);
00224 ATTRIBUTE_ALIGNED16(char tmpBuffer0[32]);
00225 ATTRIBUTE_ALIGNED16(char tmpBuffer1[32]);
00226 ATTRIBUTE_ALIGNED16(char tmpBuffer2[32]);
00227
00228 uint32_t i;
00229
00230
00232 char* localStore0 = (char*)ls0;
00233 uint32_t last4BitsOffset = ea0 & 0x0f;
00234 char* tmpTarget0 = tmpBuffer0 + last4BitsOffset;
00235 #ifdef __SPU__
00236 cellDmaSmallGet(tmpTarget0,ea0,size,DMA_TAG(1),0,0);
00237 #else
00238 tmpTarget0 = (char*)cellDmaSmallGetReadOnly(tmpTarget0,ea0,size,DMA_TAG(1),0,0);
00239 #endif
00240
00241
00242 char* localStore1 = (char*)ls1;
00243 last4BitsOffset = ea1 & 0x0f;
00244 char* tmpTarget1 = tmpBuffer1 + last4BitsOffset;
00245 #ifdef __SPU__
00246 cellDmaSmallGet(tmpTarget1,ea1,size,DMA_TAG(1),0,0);
00247 #else
00248 tmpTarget1 = (char*)cellDmaSmallGetReadOnly(tmpTarget1,ea1,size,DMA_TAG(1),0,0);
00249 #endif
00250
00251 char* localStore2 = (char*)ls2;
00252 last4BitsOffset = ea2 & 0x0f;
00253 char* tmpTarget2 = tmpBuffer2 + last4BitsOffset;
00254 #ifdef __SPU__
00255 cellDmaSmallGet(tmpTarget2,ea2,size,DMA_TAG(1),0,0);
00256 #else
00257 tmpTarget2 = (char*)cellDmaSmallGetReadOnly(tmpTarget2,ea2,size,DMA_TAG(1),0,0);
00258 #endif
00259
00260
00261 cellDmaWaitTagStatusAll( DMA_MASK(1) );
00262
00263
00264 for (i=0; btLikely( i<size );i++)
00265 {
00266 localStore0[i] = tmpTarget0[i];
00267 localStore1[i] = tmpTarget1[i];
00268 localStore2[i] = tmpTarget2[i];
00269 }
00270
00271
00272 }
00273
00274
00275
00276
00277 class spuNodeCallback : public btNodeOverlapCallback
00278 {
00279 SpuCollisionPairInput* m_wuInput;
00280 SpuContactResult& m_spuContacts;
00281 CollisionTask_LocalStoreMemory* m_lsMemPtr;
00282 ATTRIBUTE_ALIGNED16(btTriangleShape) m_tmpTriangleShape;
00283
00284 ATTRIBUTE_ALIGNED16(btVector3 spuTriangleVertices[3]);
00285 ATTRIBUTE_ALIGNED16(btScalar spuUnscaledVertex[4]);
00286
00287
00288
00289 public:
00290 spuNodeCallback(SpuCollisionPairInput* wuInput, CollisionTask_LocalStoreMemory* lsMemPtr,SpuContactResult& spuContacts)
00291 : m_wuInput(wuInput),
00292 m_spuContacts(spuContacts),
00293 m_lsMemPtr(lsMemPtr)
00294 {
00295 }
00296
00297 virtual void processNode(int subPart, int triangleIndex)
00298 {
00301
00302
00303
00304 if (m_lsMemPtr->bvhShapeData.gIndexMesh.m_indexType == PHY_SHORT)
00305 {
00306 unsigned short int* indexBasePtr = (unsigned short int*)(m_lsMemPtr->bvhShapeData.gIndexMesh.m_triangleIndexBase+triangleIndex*m_lsMemPtr->bvhShapeData.gIndexMesh.m_triangleIndexStride);
00307 ATTRIBUTE_ALIGNED16(unsigned short int tmpIndices[3]);
00308
00309 small_cache_read_triple(&tmpIndices[0],(ppu_address_t)&indexBasePtr[0],
00310 &tmpIndices[1],(ppu_address_t)&indexBasePtr[1],
00311 &tmpIndices[2],(ppu_address_t)&indexBasePtr[2],
00312 sizeof(unsigned short int));
00313
00314 m_lsMemPtr->spuIndices[0] = int(tmpIndices[0]);
00315 m_lsMemPtr->spuIndices[1] = int(tmpIndices[1]);
00316 m_lsMemPtr->spuIndices[2] = int(tmpIndices[2]);
00317 } else
00318 {
00319 unsigned int* indexBasePtr = (unsigned int*)(m_lsMemPtr->bvhShapeData.gIndexMesh.m_triangleIndexBase+triangleIndex*m_lsMemPtr->bvhShapeData.gIndexMesh.m_triangleIndexStride);
00320
00321 small_cache_read_triple(&m_lsMemPtr->spuIndices[0],(ppu_address_t)&indexBasePtr[0],
00322 &m_lsMemPtr->spuIndices[1],(ppu_address_t)&indexBasePtr[1],
00323 &m_lsMemPtr->spuIndices[2],(ppu_address_t)&indexBasePtr[2],
00324 sizeof(int));
00325 }
00326
00327
00328
00329
00330
00331
00332 const btVector3& meshScaling = m_lsMemPtr->bvhShapeData.gTriangleMeshInterfacePtr->getScaling();
00333 for (int j=2;btLikely( j>=0 );j--)
00334 {
00335 int graphicsindex = m_lsMemPtr->spuIndices[j];
00336
00337
00338 btScalar* graphicsbasePtr = (btScalar*)(m_lsMemPtr->bvhShapeData.gIndexMesh.m_vertexBase+graphicsindex*m_lsMemPtr->bvhShapeData.gIndexMesh.m_vertexStride);
00339
00340
00341
00343
00344
00345 small_cache_read_triple(&spuUnscaledVertex[0],(ppu_address_t)&graphicsbasePtr[0],
00346 &spuUnscaledVertex[1],(ppu_address_t)&graphicsbasePtr[1],
00347 &spuUnscaledVertex[2],(ppu_address_t)&graphicsbasePtr[2],
00348 sizeof(btScalar));
00349
00350 m_tmpTriangleShape.getVertexPtr(j).setValue(spuUnscaledVertex[0]*meshScaling.getX(),
00351 spuUnscaledVertex[1]*meshScaling.getY(),
00352 spuUnscaledVertex[2]*meshScaling.getZ());
00353
00354
00355 }
00356
00357
00358 SpuCollisionPairInput triangleConcaveInput(*m_wuInput);
00359
00360 triangleConcaveInput.m_spuCollisionShapes[1] = &m_tmpTriangleShape;
00361 triangleConcaveInput.m_shapeType1 = TRIANGLE_SHAPE_PROXYTYPE;
00362
00363 m_spuContacts.setShapeIdentifiersB(subPart,triangleIndex);
00364
00365
00366
00367 ProcessSpuConvexConvexCollision(&triangleConcaveInput, m_lsMemPtr,m_spuContacts);
00369
00370 }
00371
00372 };
00373
00374
00375
00376 void btConvexPlaneCollideSingleContact (SpuCollisionPairInput* wuInput,CollisionTask_LocalStoreMemory* lsMemPtr,SpuContactResult& spuContacts)
00377 {
00378
00379 btConvexShape* convexShape = (btConvexShape*) wuInput->m_spuCollisionShapes[0];
00380 btStaticPlaneShape* planeShape = (btStaticPlaneShape*) wuInput->m_spuCollisionShapes[1];
00381
00382 bool hasCollision = false;
00383 const btVector3& planeNormal = planeShape->getPlaneNormal();
00384 const btScalar& planeConstant = planeShape->getPlaneConstant();
00385
00386
00387 btTransform convexWorldTransform = wuInput->m_worldTransform0;
00388 btTransform convexInPlaneTrans;
00389 convexInPlaneTrans= wuInput->m_worldTransform1.inverse() * convexWorldTransform;
00390 btTransform planeInConvex;
00391 planeInConvex= convexWorldTransform.inverse() * wuInput->m_worldTransform1;
00392
00393
00394 btVector3 vtx = convexShape->localGetSupportVertexNonVirtual(planeInConvex.getBasis()*-planeNormal);
00395
00396 btVector3 vtxInPlane = convexInPlaneTrans(vtx);
00397 btScalar distance = (planeNormal.dot(vtxInPlane) - planeConstant);
00398
00399 btVector3 vtxInPlaneProjected = vtxInPlane - distance*planeNormal;
00400 btVector3 vtxInPlaneWorld = wuInput->m_worldTransform1 * vtxInPlaneProjected;
00401
00402 hasCollision = distance < lsMemPtr->getContactManifoldPtr()->getContactBreakingThreshold();
00403
00404 if (hasCollision)
00405 {
00407 btVector3 normalOnSurfaceB =wuInput->m_worldTransform1.getBasis() * planeNormal;
00408 btVector3 pOnB = vtxInPlaneWorld;
00409 spuContacts.addContactPoint(normalOnSurfaceB,pOnB,distance);
00410 }
00411 }
00412
00413 void ProcessConvexPlaneSpuCollision(SpuCollisionPairInput* wuInput, CollisionTask_LocalStoreMemory* lsMemPtr, SpuContactResult& spuContacts)
00414 {
00415
00416 register int dmaSize = 0;
00417 register ppu_address_t dmaPpuAddress2;
00418 btPersistentManifold* manifold = (btPersistentManifold*)wuInput->m_persistentManifoldPtr;
00419
00421 ATTRIBUTE_ALIGNED16(char convexHullShape0[sizeof(btConvexHullShape)]);
00422 ATTRIBUTE_ALIGNED16(char convexHullShape1[sizeof(btConvexHullShape)]);
00423
00424 if ( btLikely( wuInput->m_shapeType0== CONVEX_HULL_SHAPE_PROXYTYPE ) )
00425 {
00426
00427
00428 dmaSize = sizeof(btConvexHullShape);
00429 dmaPpuAddress2 = wuInput->m_collisionShapes[0];
00430
00431 cellDmaGet(&convexHullShape0, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0);
00432
00433 }
00434
00435 if ( btLikely( wuInput->m_shapeType1 == CONVEX_HULL_SHAPE_PROXYTYPE ) )
00436 {
00437
00438 dmaSize = sizeof(btConvexHullShape);
00439 dmaPpuAddress2 = wuInput->m_collisionShapes[1];
00440 cellDmaGet(&convexHullShape1, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0);
00441
00442 }
00443
00444 if ( btLikely( wuInput->m_shapeType0 == CONVEX_HULL_SHAPE_PROXYTYPE ) )
00445 {
00446 cellDmaWaitTagStatusAll(DMA_MASK(1));
00447 dmaConvexVertexData (&lsMemPtr->convexVertexData[0], (btConvexHullShape*)&convexHullShape0);
00448 lsMemPtr->convexVertexData[0].gSpuConvexShapePtr = wuInput->m_spuCollisionShapes[0];
00449 }
00450
00451
00452 if ( btLikely( wuInput->m_shapeType1 == CONVEX_HULL_SHAPE_PROXYTYPE ) )
00453 {
00454 cellDmaWaitTagStatusAll(DMA_MASK(1));
00455 dmaConvexVertexData (&lsMemPtr->convexVertexData[1], (btConvexHullShape*)&convexHullShape1);
00456 lsMemPtr->convexVertexData[1].gSpuConvexShapePtr = wuInput->m_spuCollisionShapes[1];
00457 }
00458
00459
00460 btConvexPointCloudShape cpc0,cpc1;
00461
00462 if ( btLikely( wuInput->m_shapeType0 == CONVEX_HULL_SHAPE_PROXYTYPE ) )
00463 {
00464 cellDmaWaitTagStatusAll(DMA_MASK(2));
00465 lsMemPtr->convexVertexData[0].gConvexPoints = &lsMemPtr->convexVertexData[0].g_convexPointBuffer[0];
00466 btConvexHullShape* ch = (btConvexHullShape*)wuInput->m_spuCollisionShapes[0];
00467 const btVector3& localScaling = ch->getLocalScalingNV();
00468 cpc0.setPoints(lsMemPtr->convexVertexData[0].gConvexPoints,lsMemPtr->convexVertexData[0].gNumConvexPoints,false,localScaling);
00469 wuInput->m_spuCollisionShapes[0] = &cpc0;
00470 }
00471
00472 if ( btLikely( wuInput->m_shapeType1 == CONVEX_HULL_SHAPE_PROXYTYPE ) )
00473 {
00474 cellDmaWaitTagStatusAll(DMA_MASK(2));
00475 lsMemPtr->convexVertexData[1].gConvexPoints = &lsMemPtr->convexVertexData[1].g_convexPointBuffer[0];
00476 btConvexHullShape* ch = (btConvexHullShape*)wuInput->m_spuCollisionShapes[1];
00477 const btVector3& localScaling = ch->getLocalScalingNV();
00478 cpc1.setPoints(lsMemPtr->convexVertexData[1].gConvexPoints,lsMemPtr->convexVertexData[1].gNumConvexPoints,false,localScaling);
00479 wuInput->m_spuCollisionShapes[1] = &cpc1;
00480
00481 }
00482
00483
00484 const btConvexShape* shape0Ptr = (const btConvexShape*)wuInput->m_spuCollisionShapes[0];
00485 const btConvexShape* shape1Ptr = (const btConvexShape*)wuInput->m_spuCollisionShapes[1];
00486 int shapeType0 = wuInput->m_shapeType0;
00487 int shapeType1 = wuInput->m_shapeType1;
00488 float marginA = wuInput->m_collisionMargin0;
00489 float marginB = wuInput->m_collisionMargin1;
00490
00491 SpuClosestPointInput cpInput;
00492 cpInput.m_convexVertexData[0] = &lsMemPtr->convexVertexData[0];
00493 cpInput.m_convexVertexData[1] = &lsMemPtr->convexVertexData[1];
00494 cpInput.m_transformA = wuInput->m_worldTransform0;
00495 cpInput.m_transformB = wuInput->m_worldTransform1;
00496 float sumMargin = (marginA+marginB+lsMemPtr->getContactManifoldPtr()->getContactBreakingThreshold());
00497 cpInput.m_maximumDistanceSquared = sumMargin * sumMargin;
00498
00499 ppu_address_t manifoldAddress = (ppu_address_t)manifold;
00500
00501 btPersistentManifold* spuManifold=lsMemPtr->getContactManifoldPtr();
00502
00503 spuContacts.setContactInfo(spuManifold,manifoldAddress,lsMemPtr->getColObj0()->getWorldTransform(),
00504 lsMemPtr->getColObj1()->getWorldTransform(),
00505 lsMemPtr->getColObj0()->getRestitution(),lsMemPtr->getColObj1()->getRestitution(),
00506 lsMemPtr->getColObj0()->getFriction(),lsMemPtr->getColObj1()->getFriction(),
00507 wuInput->m_isSwapped);
00508
00509
00510 btConvexPlaneCollideSingleContact(wuInput,lsMemPtr,spuContacts);
00511
00512
00513
00514
00515 }
00516
00517
00518
00519
00523 void ProcessConvexConcaveSpuCollision(SpuCollisionPairInput* wuInput, CollisionTask_LocalStoreMemory* lsMemPtr, SpuContactResult& spuContacts)
00524 {
00525
00526
00527 btBvhTriangleMeshShape* trimeshShape = (btBvhTriangleMeshShape*)wuInput->m_spuCollisionShapes[1];
00528
00529 dmaBvhShapeData (&lsMemPtr->bvhShapeData, trimeshShape);
00530
00531 btVector3 aabbMin(-1,-400,-1);
00532 btVector3 aabbMax(1,400,1);
00533
00534
00535
00536 btTransform convexInTriangleSpace;
00537 convexInTriangleSpace = wuInput->m_worldTransform1.inverse() * wuInput->m_worldTransform0;
00538 btConvexInternalShape* convexShape = (btConvexInternalShape*)wuInput->m_spuCollisionShapes[0];
00539
00540 computeAabb (aabbMin, aabbMax, convexShape, wuInput->m_collisionShapes[0], wuInput->m_shapeType0, convexInTriangleSpace);
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00552 unsigned short int quantizedQueryAabbMin[3];
00553 unsigned short int quantizedQueryAabbMax[3];
00554 lsMemPtr->bvhShapeData.getOptimizedBvh()->quantizeWithClamp(quantizedQueryAabbMin,aabbMin,0);
00555 lsMemPtr->bvhShapeData.getOptimizedBvh()->quantizeWithClamp(quantizedQueryAabbMax,aabbMax,1);
00556
00557 QuantizedNodeArray& nodeArray = lsMemPtr->bvhShapeData.getOptimizedBvh()->getQuantizedNodeArray();
00558
00559
00560 BvhSubtreeInfoArray& subTrees = lsMemPtr->bvhShapeData.getOptimizedBvh()->getSubtreeInfoArray();
00561
00562
00563 spuNodeCallback nodeCallback(wuInput,lsMemPtr,spuContacts);
00564 IndexedMeshArray& indexArray = lsMemPtr->bvhShapeData.gTriangleMeshInterfacePtr->getIndexedMeshArray();
00565
00566
00567
00568
00569 if (subTrees.size() && indexArray.size() == 1)
00570 {
00572 dmaBvhIndexedMesh (&lsMemPtr->bvhShapeData.gIndexMesh, indexArray, 0 , 1 );
00573 cellDmaWaitTagStatusAll(DMA_MASK(1));
00574
00575
00576 int numBatch = subTrees.size();
00577 for (int i=0;i<numBatch;)
00578 {
00579
00580 int remaining = subTrees.size() - i;
00581 int nextBatch = remaining < MAX_SPU_SUBTREE_HEADERS ? remaining : MAX_SPU_SUBTREE_HEADERS;
00582
00583 dmaBvhSubTreeHeaders (&lsMemPtr->bvhShapeData.gSubtreeHeaders[0], (ppu_address_t)(&subTrees[i]), nextBatch, 1);
00584 cellDmaWaitTagStatusAll(DMA_MASK(1));
00585
00586
00587
00588
00589 for (int j=0;j<nextBatch;j++)
00590 {
00591 const btBvhSubtreeInfo& subtree = lsMemPtr->bvhShapeData.gSubtreeHeaders[j];
00592
00593 unsigned int overlap = spuTestQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax);
00594 if (overlap)
00595 {
00596 btAssert(subtree.m_subtreeSize);
00597
00598
00599 dmaBvhSubTreeNodes (&lsMemPtr->bvhShapeData.gSubtreeNodes[0], subtree, nodeArray, 2);
00600 cellDmaWaitTagStatusAll(DMA_MASK(2));
00601
00602
00603 spuWalkStacklessQuantizedTree(&nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax,
00604 &lsMemPtr->bvhShapeData.gSubtreeNodes[0],
00605 0,
00606 subtree.m_subtreeSize);
00607 }
00608
00609 }
00610
00611
00612
00613
00614
00615 i+=nextBatch;
00616 }
00617
00618
00619 }
00620
00621 }
00622
00623
00624 int stats[11]={0,0,0,0,0,0,0,0,0,0,0};
00625 int degenerateStats[11]={0,0,0,0,0,0,0,0,0,0,0};
00626
00627
00631 void ProcessSpuConvexConvexCollision(SpuCollisionPairInput* wuInput, CollisionTask_LocalStoreMemory* lsMemPtr, SpuContactResult& spuContacts)
00632 {
00633 register int dmaSize;
00634 register ppu_address_t dmaPpuAddress2;
00635
00636 #ifdef DEBUG_SPU_COLLISION_DETECTION
00637
00638 #endif //DEBUG_SPU_COLLISION_DETECTION
00639
00640
00641 btPersistentManifold* manifold = (btPersistentManifold*)wuInput->m_persistentManifoldPtr;
00642
00643 bool genericGjk = true;
00644
00645 if (genericGjk)
00646 {
00647
00648
00649
00650
00651
00652 btVoronoiSimplexSolver simplexSolver;
00653 btGjkEpaPenetrationDepthSolver epaPenetrationSolver2;
00654
00655 btConvexPenetrationDepthSolver* penetrationSolver = &epaPenetrationSolver2;
00656
00657
00658 #ifdef ENABLE_EPA
00659 if (gUseEpa)
00660 {
00661 penetrationSolver = &epaPenetrationSolver2;
00662 } else
00663 #endif
00664 {
00665
00666 }
00667
00668
00670 ATTRIBUTE_ALIGNED16(char convexHullShape0[sizeof(btConvexHullShape)]);
00671 ATTRIBUTE_ALIGNED16(char convexHullShape1[sizeof(btConvexHullShape)]);
00672
00673 if ( btLikely( wuInput->m_shapeType0== CONVEX_HULL_SHAPE_PROXYTYPE ) )
00674 {
00675
00676
00677 dmaSize = sizeof(btConvexHullShape);
00678 dmaPpuAddress2 = wuInput->m_collisionShapes[0];
00679
00680 cellDmaGet(&convexHullShape0, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0);
00681
00682 }
00683
00684 if ( btLikely( wuInput->m_shapeType1 == CONVEX_HULL_SHAPE_PROXYTYPE ) )
00685 {
00686
00687 dmaSize = sizeof(btConvexHullShape);
00688 dmaPpuAddress2 = wuInput->m_collisionShapes[1];
00689 cellDmaGet(&convexHullShape1, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0);
00690
00691 }
00692
00693 if ( btLikely( wuInput->m_shapeType0 == CONVEX_HULL_SHAPE_PROXYTYPE ) )
00694 {
00695 cellDmaWaitTagStatusAll(DMA_MASK(1));
00696 dmaConvexVertexData (&lsMemPtr->convexVertexData[0], (btConvexHullShape*)&convexHullShape0);
00697 lsMemPtr->convexVertexData[0].gSpuConvexShapePtr = wuInput->m_spuCollisionShapes[0];
00698 }
00699
00700
00701 if ( btLikely( wuInput->m_shapeType1 == CONVEX_HULL_SHAPE_PROXYTYPE ) )
00702 {
00703 cellDmaWaitTagStatusAll(DMA_MASK(1));
00704 dmaConvexVertexData (&lsMemPtr->convexVertexData[1], (btConvexHullShape*)&convexHullShape1);
00705 lsMemPtr->convexVertexData[1].gSpuConvexShapePtr = wuInput->m_spuCollisionShapes[1];
00706 }
00707
00708
00709 btConvexPointCloudShape cpc0,cpc1;
00710
00711 if ( btLikely( wuInput->m_shapeType0 == CONVEX_HULL_SHAPE_PROXYTYPE ) )
00712 {
00713 cellDmaWaitTagStatusAll(DMA_MASK(2));
00714 lsMemPtr->convexVertexData[0].gConvexPoints = &lsMemPtr->convexVertexData[0].g_convexPointBuffer[0];
00715 btConvexHullShape* ch = (btConvexHullShape*)wuInput->m_spuCollisionShapes[0];
00716 const btVector3& localScaling = ch->getLocalScalingNV();
00717 cpc0.setPoints(lsMemPtr->convexVertexData[0].gConvexPoints,lsMemPtr->convexVertexData[0].gNumConvexPoints,false,localScaling);
00718 wuInput->m_spuCollisionShapes[0] = &cpc0;
00719 }
00720
00721 if ( btLikely( wuInput->m_shapeType1 == CONVEX_HULL_SHAPE_PROXYTYPE ) )
00722 {
00723 cellDmaWaitTagStatusAll(DMA_MASK(2));
00724 lsMemPtr->convexVertexData[1].gConvexPoints = &lsMemPtr->convexVertexData[1].g_convexPointBuffer[0];
00725 btConvexHullShape* ch = (btConvexHullShape*)wuInput->m_spuCollisionShapes[1];
00726 const btVector3& localScaling = ch->getLocalScalingNV();
00727 cpc1.setPoints(lsMemPtr->convexVertexData[1].gConvexPoints,lsMemPtr->convexVertexData[1].gNumConvexPoints,false,localScaling);
00728 wuInput->m_spuCollisionShapes[1] = &cpc1;
00729
00730 }
00731
00732
00733 const btConvexShape* shape0Ptr = (const btConvexShape*)wuInput->m_spuCollisionShapes[0];
00734 const btConvexShape* shape1Ptr = (const btConvexShape*)wuInput->m_spuCollisionShapes[1];
00735 int shapeType0 = wuInput->m_shapeType0;
00736 int shapeType1 = wuInput->m_shapeType1;
00737 float marginA = wuInput->m_collisionMargin0;
00738 float marginB = wuInput->m_collisionMargin1;
00739
00740 SpuClosestPointInput cpInput;
00741 cpInput.m_convexVertexData[0] = &lsMemPtr->convexVertexData[0];
00742 cpInput.m_convexVertexData[1] = &lsMemPtr->convexVertexData[1];
00743 cpInput.m_transformA = wuInput->m_worldTransform0;
00744 cpInput.m_transformB = wuInput->m_worldTransform1;
00745 float sumMargin = (marginA+marginB+lsMemPtr->getContactManifoldPtr()->getContactBreakingThreshold());
00746 cpInput.m_maximumDistanceSquared = sumMargin * sumMargin;
00747
00748 ppu_address_t manifoldAddress = (ppu_address_t)manifold;
00749
00750 btPersistentManifold* spuManifold=lsMemPtr->getContactManifoldPtr();
00751
00752 spuContacts.setContactInfo(spuManifold,manifoldAddress,lsMemPtr->getColObj0()->getWorldTransform(),
00753 lsMemPtr->getColObj1()->getWorldTransform(),
00754 lsMemPtr->getColObj0()->getRestitution(),lsMemPtr->getColObj1()->getRestitution(),
00755 lsMemPtr->getColObj0()->getFriction(),lsMemPtr->getColObj1()->getFriction(),
00756 wuInput->m_isSwapped);
00757
00758 {
00759 btGjkPairDetector gjk(shape0Ptr,shape1Ptr,shapeType0,shapeType1,marginA,marginB,&simplexSolver,penetrationSolver);
00760 gjk.getClosestPoints(cpInput,spuContacts,0);
00761
00762 stats[gjk.m_lastUsedMethod]++;
00763 degenerateStats[gjk.m_degenerateSimplex]++;
00764
00765 #ifdef USE_SEPDISTANCE_UTIL
00766 btScalar sepDist = gjk.getCachedSeparatingDistance()+spuManifold->getContactBreakingThreshold();
00767 lsMemPtr->getlocalCollisionAlgorithm()->m_sepDistance.initSeparatingDistance(gjk.getCachedSeparatingAxis(),sepDist,wuInput->m_worldTransform0,wuInput->m_worldTransform1);
00768 lsMemPtr->needsDmaPutContactManifoldAlgo = true;
00769 #endif //USE_SEPDISTANCE_UTIL
00770
00771 }
00772
00773 }
00774
00775
00776 }
00777
00778
00779 template<typename T> void DoSwap(T& a, T& b)
00780 {
00781 char tmp[sizeof(T)];
00782 memcpy(tmp, &a, sizeof(T));
00783 memcpy(&a, &b, sizeof(T));
00784 memcpy(&b, tmp, sizeof(T));
00785 }
00786
00787 SIMD_FORCE_INLINE void dmaAndSetupCollisionObjects(SpuCollisionPairInput& collisionPairInput, CollisionTask_LocalStoreMemory& lsMem)
00788 {
00789 register int dmaSize;
00790 register ppu_address_t dmaPpuAddress2;
00791
00792 dmaSize = sizeof(btCollisionObject);
00793 dmaPpuAddress2 = (ppu_address_t)lsMem.getlocalCollisionAlgorithm()->getCollisionObject0();
00794 lsMem.m_lsColObj0Ptr = (btCollisionObject*)cellDmaGetReadOnly(&lsMem.gColObj0Buffer, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0);
00795
00796 dmaSize = sizeof(btCollisionObject);
00797 dmaPpuAddress2 = (ppu_address_t)lsMem.getlocalCollisionAlgorithm()->getCollisionObject1();
00798 lsMem.m_lsColObj1Ptr = (btCollisionObject*)cellDmaGetReadOnly(&lsMem.gColObj1Buffer, dmaPpuAddress2 , dmaSize, DMA_TAG(2), 0, 0);
00799
00800 cellDmaWaitTagStatusAll(DMA_MASK(1) | DMA_MASK(2));
00801
00802 btCollisionObject* ob0 = lsMem.getColObj0();
00803 btCollisionObject* ob1 = lsMem.getColObj1();
00804
00805 collisionPairInput.m_worldTransform0 = ob0->getWorldTransform();
00806 collisionPairInput.m_worldTransform1 = ob1->getWorldTransform();
00807 }
00808
00809
00810
00811 void handleCollisionPair(SpuCollisionPairInput& collisionPairInput, CollisionTask_LocalStoreMemory& lsMem,
00812 SpuContactResult &spuContacts,
00813 ppu_address_t collisionShape0Ptr, void* collisionShape0Loc,
00814 ppu_address_t collisionShape1Ptr, void* collisionShape1Loc, bool dmaShapes = true)
00815 {
00816
00817 if (btBroadphaseProxy::isConvex(collisionPairInput.m_shapeType0)
00818 && btBroadphaseProxy::isConvex(collisionPairInput.m_shapeType1))
00819 {
00820 if (dmaShapes)
00821 {
00822 dmaCollisionShape (collisionShape0Loc, collisionShape0Ptr, 1, collisionPairInput.m_shapeType0);
00823 dmaCollisionShape (collisionShape1Loc, collisionShape1Ptr, 2, collisionPairInput.m_shapeType1);
00824 cellDmaWaitTagStatusAll(DMA_MASK(1) | DMA_MASK(2));
00825 }
00826
00827 btConvexInternalShape* spuConvexShape0 = (btConvexInternalShape*)collisionShape0Loc;
00828 btConvexInternalShape* spuConvexShape1 = (btConvexInternalShape*)collisionShape1Loc;
00829
00830 btVector3 dim0 = spuConvexShape0->getImplicitShapeDimensions();
00831 btVector3 dim1 = spuConvexShape1->getImplicitShapeDimensions();
00832
00833 collisionPairInput.m_primitiveDimensions0 = dim0;
00834 collisionPairInput.m_primitiveDimensions1 = dim1;
00835 collisionPairInput.m_collisionShapes[0] = collisionShape0Ptr;
00836 collisionPairInput.m_collisionShapes[1] = collisionShape1Ptr;
00837 collisionPairInput.m_spuCollisionShapes[0] = spuConvexShape0;
00838 collisionPairInput.m_spuCollisionShapes[1] = spuConvexShape1;
00839 ProcessSpuConvexConvexCollision(&collisionPairInput,&lsMem,spuContacts);
00840 }
00841 else if (btBroadphaseProxy::isCompound(collisionPairInput.m_shapeType0) &&
00842 btBroadphaseProxy::isCompound(collisionPairInput.m_shapeType1))
00843 {
00844
00845
00846 dmaCollisionShape (collisionShape0Loc, collisionShape0Ptr, 1, collisionPairInput.m_shapeType0);
00847 dmaCollisionShape (collisionShape1Loc, collisionShape1Ptr, 2, collisionPairInput.m_shapeType1);
00848 cellDmaWaitTagStatusAll(DMA_MASK(1) | DMA_MASK(2));
00849
00850
00852
00853 btCompoundShape* spuCompoundShape0 = (btCompoundShape*)collisionShape0Loc;
00854 btCompoundShape* spuCompoundShape1 = (btCompoundShape*)collisionShape1Loc;
00855
00856 dmaCompoundShapeInfo (&lsMem.compoundShapeData[0], spuCompoundShape0, 1);
00857 dmaCompoundShapeInfo (&lsMem.compoundShapeData[1], spuCompoundShape1, 2);
00858 cellDmaWaitTagStatusAll(DMA_MASK(1) | DMA_MASK(2));
00859
00860
00861 dmaCompoundSubShapes (&lsMem.compoundShapeData[0], spuCompoundShape0, 1);
00862 cellDmaWaitTagStatusAll(DMA_MASK(1));
00863 dmaCompoundSubShapes (&lsMem.compoundShapeData[1], spuCompoundShape1, 1);
00864 cellDmaWaitTagStatusAll(DMA_MASK(1));
00865
00866 int childShapeCount0 = spuCompoundShape0->getNumChildShapes();
00867 int childShapeCount1 = spuCompoundShape1->getNumChildShapes();
00868
00869
00870 for (int i = 0; i < childShapeCount0; ++i)
00871 {
00872 btCompoundShapeChild& childShape0 = lsMem.compoundShapeData[0].gSubshapes[i];
00873
00874 for (int j = 0; j < childShapeCount1; ++j)
00875 {
00876 btCompoundShapeChild& childShape1 = lsMem.compoundShapeData[1].gSubshapes[j];
00877
00878
00879 SpuCollisionPairInput cinput (collisionPairInput);
00880
00881 cinput.m_worldTransform0 = collisionPairInput.m_worldTransform0 * childShape0.m_transform;
00882 cinput.m_shapeType0 = childShape0.m_childShapeType;
00883 cinput.m_collisionMargin0 = childShape0.m_childMargin;
00884
00885 cinput.m_worldTransform1 = collisionPairInput.m_worldTransform1 * childShape1.m_transform;
00886 cinput.m_shapeType1 = childShape1.m_childShapeType;
00887 cinput.m_collisionMargin1 = childShape1.m_childMargin;
00888
00889 handleCollisionPair(cinput, lsMem, spuContacts,
00890 (ppu_address_t)childShape0.m_childShape, lsMem.compoundShapeData[0].gSubshapeShape[i],
00891 (ppu_address_t)childShape1.m_childShape, lsMem.compoundShapeData[1].gSubshapeShape[j], false);
00892 }
00893 }
00894 }
00895 else if (btBroadphaseProxy::isCompound(collisionPairInput.m_shapeType0) )
00896 {
00897
00898
00899 dmaCollisionShape (collisionShape0Loc, collisionShape0Ptr, 1, collisionPairInput.m_shapeType0);
00900 dmaCollisionShape (collisionShape1Loc, collisionShape1Ptr, 2, collisionPairInput.m_shapeType1);
00901 cellDmaWaitTagStatusAll(DMA_MASK(1) | DMA_MASK(2));
00902
00903
00904 btCompoundShape* spuCompoundShape = (btCompoundShape*)collisionShape0Loc;
00905 dmaCompoundShapeInfo (&lsMem.compoundShapeData[0], spuCompoundShape, 1);
00906 cellDmaWaitTagStatusAll(DMA_MASK(1));
00907
00908 int childShapeCount = spuCompoundShape->getNumChildShapes();
00909
00910 for (int i = 0; i < childShapeCount; ++i)
00911 {
00912 btCompoundShapeChild& childShape = lsMem.compoundShapeData[0].gSubshapes[i];
00913
00914
00915 dmaCollisionShape (&lsMem.compoundShapeData[0].gSubshapeShape[i], (ppu_address_t)childShape.m_childShape, 1, childShape.m_childShapeType);
00916 cellDmaWaitTagStatusAll(DMA_MASK(1));
00917
00918 SpuCollisionPairInput cinput (collisionPairInput);
00919 cinput.m_worldTransform0 = collisionPairInput.m_worldTransform0 * childShape.m_transform;
00920 cinput.m_shapeType0 = childShape.m_childShapeType;
00921 cinput.m_collisionMargin0 = childShape.m_childMargin;
00922
00923 handleCollisionPair(cinput, lsMem, spuContacts,
00924 (ppu_address_t)childShape.m_childShape, lsMem.compoundShapeData[0].gSubshapeShape[i],
00925 collisionShape1Ptr, collisionShape1Loc, false);
00926 }
00927 }
00928 else if (btBroadphaseProxy::isCompound(collisionPairInput.m_shapeType1) )
00929 {
00930
00931
00932 dmaCollisionShape (collisionShape0Loc, collisionShape0Ptr, 1, collisionPairInput.m_shapeType0);
00933 dmaCollisionShape (collisionShape1Loc, collisionShape1Ptr, 2, collisionPairInput.m_shapeType1);
00934 cellDmaWaitTagStatusAll(DMA_MASK(1) | DMA_MASK(2));
00935
00936 btCompoundShape* spuCompoundShape = (btCompoundShape*)collisionShape1Loc;
00937 dmaCompoundShapeInfo (&lsMem.compoundShapeData[0], spuCompoundShape, 1);
00938 cellDmaWaitTagStatusAll(DMA_MASK(1));
00939
00940 int childShapeCount = spuCompoundShape->getNumChildShapes();
00941
00942 for (int i = 0; i < childShapeCount; ++i)
00943 {
00944 btCompoundShapeChild& childShape = lsMem.compoundShapeData[0].gSubshapes[i];
00945
00946 dmaCollisionShape (&lsMem.compoundShapeData[0].gSubshapeShape[i], (ppu_address_t)childShape.m_childShape, 1, childShape.m_childShapeType);
00947 cellDmaWaitTagStatusAll(DMA_MASK(1));
00948
00949 SpuCollisionPairInput cinput (collisionPairInput);
00950 cinput.m_worldTransform1 = collisionPairInput.m_worldTransform1 * childShape.m_transform;
00951 cinput.m_shapeType1 = childShape.m_childShapeType;
00952 cinput.m_collisionMargin1 = childShape.m_childMargin;
00953 handleCollisionPair(cinput, lsMem, spuContacts,
00954 collisionShape0Ptr, collisionShape0Loc,
00955 (ppu_address_t)childShape.m_childShape, lsMem.compoundShapeData[0].gSubshapeShape[i], false);
00956 }
00957
00958 }
00959 else
00960 {
00961
00962 bool handleConvexConcave = false;
00963
00964
00965
00966 if (btBroadphaseProxy::isConcave(collisionPairInput.m_shapeType0) &&
00967 btBroadphaseProxy::isConvex(collisionPairInput.m_shapeType1))
00968 {
00969
00970 DoSwap(collisionShape0Ptr, collisionShape1Ptr);
00971 DoSwap(collisionShape0Loc, collisionShape1Loc);
00972 DoSwap(collisionPairInput.m_shapeType0, collisionPairInput.m_shapeType1);
00973 DoSwap(collisionPairInput.m_worldTransform0, collisionPairInput.m_worldTransform1);
00974 DoSwap(collisionPairInput.m_collisionMargin0, collisionPairInput.m_collisionMargin1);
00975
00976 collisionPairInput.m_isSwapped = true;
00977 }
00978
00979 if (btBroadphaseProxy::isConvex(collisionPairInput.m_shapeType0)&&
00980 btBroadphaseProxy::isConcave(collisionPairInput.m_shapeType1))
00981 {
00982 handleConvexConcave = true;
00983 }
00984 if (handleConvexConcave)
00985 {
00986 if (dmaShapes)
00987 {
00988 dmaCollisionShape (collisionShape0Loc, collisionShape0Ptr, 1, collisionPairInput.m_shapeType0);
00989 dmaCollisionShape (collisionShape1Loc, collisionShape1Ptr, 2, collisionPairInput.m_shapeType1);
00990 cellDmaWaitTagStatusAll(DMA_MASK(1) | DMA_MASK(2));
00991 }
00992
00993 if (collisionPairInput.m_shapeType1 == STATIC_PLANE_PROXYTYPE)
00994 {
00995 btConvexInternalShape* spuConvexShape0 = (btConvexInternalShape*)collisionShape0Loc;
00996 btStaticPlaneShape* planeShape= (btStaticPlaneShape*)collisionShape1Loc;
00997
00998 btVector3 dim0 = spuConvexShape0->getImplicitShapeDimensions();
00999 collisionPairInput.m_primitiveDimensions0 = dim0;
01000 collisionPairInput.m_collisionShapes[0] = collisionShape0Ptr;
01001 collisionPairInput.m_collisionShapes[1] = collisionShape1Ptr;
01002 collisionPairInput.m_spuCollisionShapes[0] = spuConvexShape0;
01003 collisionPairInput.m_spuCollisionShapes[1] = planeShape;
01004
01005 ProcessConvexPlaneSpuCollision(&collisionPairInput,&lsMem,spuContacts);
01006 } else
01007 {
01008 btConvexInternalShape* spuConvexShape0 = (btConvexInternalShape*)collisionShape0Loc;
01009 btBvhTriangleMeshShape* trimeshShape = (btBvhTriangleMeshShape*)collisionShape1Loc;
01010
01011 btVector3 dim0 = spuConvexShape0->getImplicitShapeDimensions();
01012 collisionPairInput.m_primitiveDimensions0 = dim0;
01013 collisionPairInput.m_collisionShapes[0] = collisionShape0Ptr;
01014 collisionPairInput.m_collisionShapes[1] = collisionShape1Ptr;
01015 collisionPairInput.m_spuCollisionShapes[0] = spuConvexShape0;
01016 collisionPairInput.m_spuCollisionShapes[1] = trimeshShape;
01017
01018 ProcessConvexConcaveSpuCollision(&collisionPairInput,&lsMem,spuContacts);
01019 }
01020 }
01021
01022 }
01023
01024 spuContacts.flush();
01025
01026 }
01027
01028
01029 void processCollisionTask(void* userPtr, void* lsMemPtr)
01030 {
01031
01032 SpuGatherAndProcessPairsTaskDesc* taskDescPtr = (SpuGatherAndProcessPairsTaskDesc*)userPtr;
01033 SpuGatherAndProcessPairsTaskDesc& taskDesc = *taskDescPtr;
01034 CollisionTask_LocalStoreMemory* colMemPtr = (CollisionTask_LocalStoreMemory*)lsMemPtr;
01035 CollisionTask_LocalStoreMemory& lsMem = *(colMemPtr);
01036
01037 gUseEpa = taskDesc.m_useEpa;
01038
01039
01040
01041 SpuContactResult spuContacts;
01042
01044
01045 ppu_address_t dmaInPtr = taskDesc.m_inPairPtr;
01046 unsigned int numPages = taskDesc.numPages;
01047 unsigned int numOnLastPage = taskDesc.numOnLastPage;
01048
01049
01050 lsMem.g_workUnitTaskBuffers.init();
01051
01052 unsigned int nextNumOnPage = (numPages > 1)? MIDPHASE_NUM_WORKUNITS_PER_PAGE : numOnLastPage;
01053 lsMem.g_workUnitTaskBuffers.backBufferDmaGet(dmaInPtr, nextNumOnPage*sizeof(SpuGatherAndProcessWorkUnitInput), DMA_TAG(3));
01054 dmaInPtr += MIDPHASE_WORKUNIT_PAGE_SIZE;
01055
01056
01057 register unsigned char *inputPtr;
01058 register unsigned int numOnPage;
01059 register unsigned int j;
01060 SpuGatherAndProcessWorkUnitInput* wuInputs;
01061 register int dmaSize;
01062 register ppu_address_t dmaPpuAddress;
01063 register ppu_address_t dmaPpuAddress2;
01064
01065 int numPairs;
01066 register int p;
01067 SpuCollisionPairInput collisionPairInput;
01068
01069 for (unsigned int i = 0; btLikely(i < numPages); i++)
01070 {
01071
01072
01073 inputPtr = lsMem.g_workUnitTaskBuffers.swapBuffers();
01074
01075
01076 numOnPage = nextNumOnPage;
01077
01078
01079
01080 #if MIDPHASE_NUM_WORKUNIT_PAGES > 2
01081 if ( btLikely( i < numPages-1 ) )
01082 #else
01083 if ( btUnlikely( i < numPages-1 ) )
01084 #endif
01085 {
01086 nextNumOnPage = (i == numPages-2)? numOnLastPage : MIDPHASE_NUM_WORKUNITS_PER_PAGE;
01087 lsMem.g_workUnitTaskBuffers.backBufferDmaGet(dmaInPtr, nextNumOnPage*sizeof(SpuGatherAndProcessWorkUnitInput), DMA_TAG(3));
01088 dmaInPtr += MIDPHASE_WORKUNIT_PAGE_SIZE;
01089 }
01090
01091 wuInputs = reinterpret_cast<SpuGatherAndProcessWorkUnitInput *>(inputPtr);
01092
01093
01094 for (j = 0; btLikely( j < numOnPage ); j++)
01095 {
01096 #ifdef DEBUG_SPU_COLLISION_DETECTION
01097
01098 #endif //DEBUG_SPU_COLLISION_DETECTION
01099
01100
01101 numPairs = wuInputs[j].m_endIndex - wuInputs[j].m_startIndex;
01102
01103 if ( btLikely( numPairs ) )
01104 {
01105 dmaSize = numPairs*sizeof(btBroadphasePair);
01106 dmaPpuAddress = wuInputs[j].m_pairArrayPtr+wuInputs[j].m_startIndex * sizeof(btBroadphasePair);
01107 lsMem.m_pairsPointer = (btBroadphasePair*)cellDmaGetReadOnly(&lsMem.gBroadphasePairsBuffer, dmaPpuAddress , dmaSize, DMA_TAG(1), 0, 0);
01108 cellDmaWaitTagStatusAll(DMA_MASK(1));
01109
01110
01111 for (p=0;p<numPairs;p++)
01112 {
01113
01114
01115
01116 btBroadphasePair& pair = lsMem.getBroadphasePairPtr()[p];
01117 #ifdef DEBUG_SPU_COLLISION_DETECTION
01118 spu_printf("pair->m_userInfo = %d\n",pair.m_userInfo);
01119 spu_printf("pair->m_algorithm = %d\n",pair.m_algorithm);
01120 spu_printf("pair->m_pProxy0 = %d\n",pair.m_pProxy0);
01121 spu_printf("pair->m_pProxy1 = %d\n",pair.m_pProxy1);
01122 #endif //DEBUG_SPU_COLLISION_DETECTION
01123
01124 if (pair.m_internalTmpValue == 2 && pair.m_algorithm && pair.m_pProxy0 && pair.m_pProxy1)
01125 {
01126 dmaSize = sizeof(SpuContactManifoldCollisionAlgorithm);
01127 dmaPpuAddress2 = (ppu_address_t)pair.m_algorithm;
01128 lsMem.m_lsCollisionAlgorithmPtr = (SpuContactManifoldCollisionAlgorithm*)cellDmaGetReadOnly(&lsMem.gSpuContactManifoldAlgoBuffer, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0);
01129
01130 cellDmaWaitTagStatusAll(DMA_MASK(1));
01131
01132 lsMem.needsDmaPutContactManifoldAlgo = false;
01133
01134 collisionPairInput.m_persistentManifoldPtr = (ppu_address_t) lsMem.getlocalCollisionAlgorithm()->getContactManifoldPtr();
01135 collisionPairInput.m_isSwapped = false;
01136
01137 if (1)
01138 {
01139
01141
01142
01143 #ifdef DEBUG_SPU_COLLISION_DETECTION
01144
01145
01146 #endif //DEBUG_SPU_COLLISION_DETECTION
01147
01148
01149 dmaSize = sizeof(btPersistentManifold);
01150
01151 dmaPpuAddress2 = collisionPairInput.m_persistentManifoldPtr;
01152 lsMem.m_lsManifoldPtr = (btPersistentManifold*)cellDmaGetReadOnly(&lsMem.gPersistentManifoldBuffer, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0);
01153
01154 collisionPairInput.m_shapeType0 = lsMem.getlocalCollisionAlgorithm()->getShapeType0();
01155 collisionPairInput.m_shapeType1 = lsMem.getlocalCollisionAlgorithm()->getShapeType1();
01156 collisionPairInput.m_collisionMargin0 = lsMem.getlocalCollisionAlgorithm()->getCollisionMargin0();
01157 collisionPairInput.m_collisionMargin1 = lsMem.getlocalCollisionAlgorithm()->getCollisionMargin1();
01158
01159
01160
01161
01162
01163
01164 if (1)
01165 {
01166
01167
01168
01169 dmaAndSetupCollisionObjects(collisionPairInput, lsMem);
01170
01171 if (lsMem.getColObj0()->isActive() || lsMem.getColObj1()->isActive())
01172 {
01173
01174 lsMem.needsDmaPutContactManifoldAlgo = true;
01175 #ifdef USE_SEPDISTANCE_UTIL
01176 lsMem.getlocalCollisionAlgorithm()->m_sepDistance.updateSeparatingDistance(collisionPairInput.m_worldTransform0,collisionPairInput.m_worldTransform1);
01177 #endif //USE_SEPDISTANCE_UTIL
01178
01179 #define USE_DEDICATED_BOX_BOX 1
01180 #ifdef USE_DEDICATED_BOX_BOX
01181 bool boxbox = ((lsMem.getlocalCollisionAlgorithm()->getShapeType0()==BOX_SHAPE_PROXYTYPE)&&
01182 (lsMem.getlocalCollisionAlgorithm()->getShapeType1()==BOX_SHAPE_PROXYTYPE));
01183 if (boxbox)
01184 {
01185
01186 btPersistentManifold* spuManifold=lsMem.getContactManifoldPtr();
01187 btPersistentManifold* manifold = (btPersistentManifold*)collisionPairInput.m_persistentManifoldPtr;
01188 ppu_address_t manifoldAddress = (ppu_address_t)manifold;
01189
01190 spuContacts.setContactInfo(spuManifold,manifoldAddress,lsMem.getColObj0()->getWorldTransform(),
01191 lsMem.getColObj1()->getWorldTransform(),
01192 lsMem.getColObj0()->getRestitution(),lsMem.getColObj1()->getRestitution(),
01193 lsMem.getColObj0()->getFriction(),lsMem.getColObj1()->getFriction(),
01194 collisionPairInput.m_isSwapped);
01195
01196
01197
01198 btVector3 normalInB;
01199
01200
01201 if (
01202 #ifdef USE_SEPDISTANCE_UTIL
01203 lsMem.getlocalCollisionAlgorithm()->m_sepDistance.getConservativeSeparatingDistance()<=0.f
01204 #else
01205 1
01206 #endif
01207 )
01208 {
01209
01210 #ifdef USE_PE_BOX_BOX
01211 {
01212
01213
01214 btScalar margin0 = lsMem.getlocalCollisionAlgorithm()->getCollisionMargin0();
01215 btScalar margin1 = lsMem.getlocalCollisionAlgorithm()->getCollisionMargin1();
01216 btVector3 shapeDim0 = lsMem.getlocalCollisionAlgorithm()->getShapeDimensions0()+btVector3(margin0,margin0,margin0);
01217 btVector3 shapeDim1 = lsMem.getlocalCollisionAlgorithm()->getShapeDimensions1()+btVector3(margin1,margin1,margin1);
01218
01219 Box boxA(shapeDim0.getX(),shapeDim0.getY(),shapeDim0.getZ());
01220 Vector3 vmPos0 = getVmVector3(collisionPairInput.m_worldTransform0.getOrigin());
01221 Vector3 vmPos1 = getVmVector3(collisionPairInput.m_worldTransform1.getOrigin());
01222 Matrix3 vmMatrix0 = getVmMatrix3(collisionPairInput.m_worldTransform0.getBasis());
01223 Matrix3 vmMatrix1 = getVmMatrix3(collisionPairInput.m_worldTransform1.getBasis());
01224
01225 Transform3 transformA(vmMatrix0,vmPos0);
01226 Box boxB(shapeDim1.getX(),shapeDim1.getY(),shapeDim1.getZ());
01227 Transform3 transformB(vmMatrix1,vmPos1);
01228 BoxPoint resultClosestBoxPointA;
01229 BoxPoint resultClosestBoxPointB;
01230 Vector3 resultNormal;
01231 #ifdef USE_SEPDISTANCE_UTIL
01232 float distanceThreshold = FLT_MAX
01233 #else
01234 float distanceThreshold = 0.f;
01235 #endif
01236
01237
01238 distance = boxBoxDistance(resultNormal,resultClosestBoxPointA,resultClosestBoxPointB, boxA, transformA, boxB,transformB,distanceThreshold);
01239
01240 normalInB = -getBtVector3(resultNormal);
01241
01242 if(distance < spuManifold->getContactBreakingThreshold())
01243 {
01244 btVector3 pointOnB = collisionPairInput.m_worldTransform1(getBtVector3(resultClosestBoxPointB.localPoint));
01245
01246 spuContacts.addContactPoint(
01247 normalInB,
01248 pointOnB,
01249 distance);
01250 }
01251 }
01252 #else
01253 {
01254
01255 btScalar margin0 = lsMem.getlocalCollisionAlgorithm()->getCollisionMargin0();
01256 btScalar margin1 = lsMem.getlocalCollisionAlgorithm()->getCollisionMargin1();
01257 btVector3 shapeDim0 = lsMem.getlocalCollisionAlgorithm()->getShapeDimensions0()+btVector3(margin0,margin0,margin0);
01258 btVector3 shapeDim1 = lsMem.getlocalCollisionAlgorithm()->getShapeDimensions1()+btVector3(margin1,margin1,margin1);
01259
01260
01261 btBoxShape box0(shapeDim0);
01262 btBoxShape box1(shapeDim1);
01263
01264 struct SpuBridgeContactCollector : public btDiscreteCollisionDetectorInterface::Result
01265 {
01266 SpuContactResult& m_spuContacts;
01267
01268 virtual void setShapeIdentifiersA(int partId0,int index0)
01269 {
01270 m_spuContacts.setShapeIdentifiersA(partId0,index0);
01271 }
01272 virtual void setShapeIdentifiersB(int partId1,int index1)
01273 {
01274 m_spuContacts.setShapeIdentifiersB(partId1,index1);
01275 }
01276 virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth)
01277 {
01278 m_spuContacts.addContactPoint(normalOnBInWorld,pointInWorld,depth);
01279 }
01280
01281 SpuBridgeContactCollector(SpuContactResult& spuContacts)
01282 :m_spuContacts(spuContacts)
01283 {
01284
01285 }
01286 };
01287
01288 SpuBridgeContactCollector bridgeOutput(spuContacts);
01289
01290 btDiscreteCollisionDetectorInterface::ClosestPointInput input;
01291 input.m_maximumDistanceSquared = BT_LARGE_FLOAT;
01292 input.m_transformA = collisionPairInput.m_worldTransform0;
01293 input.m_transformB = collisionPairInput.m_worldTransform1;
01294
01295 btBoxBoxDetector detector(&box0,&box1);
01296
01297 detector.getClosestPoints(input,bridgeOutput,0);
01298
01299 }
01300 #endif //USE_PE_BOX_BOX
01301
01302 lsMem.needsDmaPutContactManifoldAlgo = true;
01303 #ifdef USE_SEPDISTANCE_UTIL
01304 btScalar sepDist2 = distance+spuManifold->getContactBreakingThreshold();
01305 lsMem.getlocalCollisionAlgorithm()->m_sepDistance.initSeparatingDistance(normalInB,sepDist2,collisionPairInput.m_worldTransform0,collisionPairInput.m_worldTransform1);
01306 #endif //USE_SEPDISTANCE_UTIL
01307 gProcessedCol++;
01308 } else
01309 {
01310 gSkippedCol++;
01311 }
01312
01313 spuContacts.flush();
01314
01315
01316 } else
01317 #endif //USE_DEDICATED_BOX_BOX
01318 {
01319 if (
01320 #ifdef USE_SEPDISTANCE_UTIL
01321 lsMem.getlocalCollisionAlgorithm()->m_sepDistance.getConservativeSeparatingDistance()<=0.f
01322 #else
01323 1
01324 #endif //USE_SEPDISTANCE_UTIL
01325 )
01326 {
01327 handleCollisionPair(collisionPairInput, lsMem, spuContacts,
01328 (ppu_address_t)lsMem.getColObj0()->getRootCollisionShape(), &lsMem.gCollisionShapes[0].collisionShape,
01329 (ppu_address_t)lsMem.getColObj1()->getRootCollisionShape(), &lsMem.gCollisionShapes[1].collisionShape);
01330 } else
01331 {
01332
01333 btPersistentManifold* spuManifold=lsMem.getContactManifoldPtr();
01334 btPersistentManifold* manifold = (btPersistentManifold*)collisionPairInput.m_persistentManifoldPtr;
01335 ppu_address_t manifoldAddress = (ppu_address_t)manifold;
01336
01337 spuContacts.setContactInfo(spuManifold,manifoldAddress,lsMem.getColObj0()->getWorldTransform(),
01338 lsMem.getColObj1()->getWorldTransform(),
01339 lsMem.getColObj0()->getRestitution(),lsMem.getColObj1()->getRestitution(),
01340 lsMem.getColObj0()->getFriction(),lsMem.getColObj1()->getFriction(),
01341 collisionPairInput.m_isSwapped);
01342
01343 spuContacts.flush();
01344 }
01345 }
01346
01347 }
01348
01349 }
01350 }
01351
01352 #ifdef USE_SEPDISTANCE_UTIL
01353 #if defined (__SPU__) || defined (USE_LIBSPE2)
01354 if (lsMem.needsDmaPutContactManifoldAlgo)
01355 {
01356 dmaSize = sizeof(SpuContactManifoldCollisionAlgorithm);
01357 dmaPpuAddress2 = (ppu_address_t)pair.m_algorithm;
01358 cellDmaLargePut(&lsMem.gSpuContactManifoldAlgoBuffer, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0);
01359 cellDmaWaitTagStatusAll(DMA_MASK(1));
01360 }
01361 #endif
01362 #endif //#ifdef USE_SEPDISTANCE_UTIL
01363
01364 }
01365 }
01366 }
01367 }
01368
01369 }
01370
01371
01372
01373 return;
01374 }
01375
01376