PageRenderTime 77ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/cocos2d/external/bullet/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.cpp

https://gitlab.com/gasabr/flappy-test
C++ | 1281 lines | 827 code | 298 blank | 156 comment | 79 complexity | 69103c099b05e2968abce3f8d83eb762 MD5 | raw file
  1. /*
  2. Bullet Continuous Collision Detection and Physics Library
  3. Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
  4. This software is provided 'as-is', without any express or implied warranty.
  5. In no event will the authors be held liable for any damages arising from the use of this software.
  6. Permission is granted to anyone to use this software for any purpose,
  7. including commercial applications, and to alter it and redistribute it freely,
  8. subject to the following restrictions:
  9. 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.
  10. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
  11. 3. This notice may not be removed or altered from any source distribution.
  12. */
  13. #include "SpuGatheringCollisionTask.h"
  14. //#define DEBUG_SPU_COLLISION_DETECTION 1
  15. #include "../SpuDoubleBuffer.h"
  16. #include "../SpuCollisionTaskProcess.h"
  17. #include "../SpuGatheringCollisionDispatcher.h" //for SPU_BATCHSIZE_BROADPHASE_PAIRS
  18. #include "bullet/BulletCollision//BroadphaseCollision/btBroadphaseProxy.h"
  19. #include "../SpuContactManifoldCollisionAlgorithm.h"
  20. #include "bullet/BulletCollision//CollisionDispatch/btCollisionObject.h"
  21. #include "SpuContactResult.h"
  22. #include "bullet/BulletCollision//CollisionShapes/btOptimizedBvh.h"
  23. #include "bullet/BulletCollision//CollisionShapes/btTriangleIndexVertexArray.h"
  24. #include "bullet/BulletCollision//CollisionShapes/btSphereShape.h"
  25. #include "bullet/BulletCollision//CollisionShapes/btConvexPointCloudShape.h"
  26. #include "bullet/BulletCollision//CollisionShapes/btCapsuleShape.h"
  27. #include "bullet/BulletCollision//CollisionShapes/btConvexShape.h"
  28. #include "bullet/BulletCollision//CollisionShapes/btBvhTriangleMeshShape.h"
  29. #include "bullet/BulletCollision//CollisionShapes/btConvexHullShape.h"
  30. #include "bullet/BulletCollision//CollisionShapes/btCompoundShape.h"
  31. #include "SpuMinkowskiPenetrationDepthSolver.h"
  32. //#include "SpuEpaPenetrationDepthSolver.h"
  33. #include "bullet/BulletCollision//NarrowPhaseCollision/btGjkPairDetector.h"
  34. #include "boxBoxDistance.h"
  35. #include "bullet/BulletMultiThreaded/vectormath2bullet.h"
  36. #include "SpuCollisionShapes.h" //definition of SpuConvexPolyhedronVertexData
  37. #include "bullet/BulletCollision//CollisionDispatch/btBoxBoxDetector.h"
  38. #include "bullet/BulletCollision//NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h"
  39. #include "bullet/BulletCollision//CollisionShapes/btTriangleShape.h"
  40. #ifdef __SPU__
  41. ///Software caching from the IBM Cell SDK, it reduces 25% SPU time for our test cases
  42. #ifndef USE_LIBSPE2
  43. //#define USE_SOFTWARE_CACHE 1
  44. #endif
  45. #endif //__SPU__
  46. int gSkippedCol = 0;
  47. int gProcessedCol = 0;
  48. ////////////////////////////////////////////////
  49. /// software caching
  50. #if USE_SOFTWARE_CACHE
  51. #include <spu_intrinsics.h>
  52. #include <sys/spu_thread.h>
  53. #include <sys/spu_event.h>
  54. #include <stdint.h>
  55. #define SPE_CACHE_NWAY 4
  56. //#define SPE_CACHE_NSETS 32, 16
  57. #define SPE_CACHE_NSETS 8
  58. //#define SPE_CACHELINE_SIZE 512
  59. #define SPE_CACHELINE_SIZE 128
  60. #define SPE_CACHE_SET_TAGID(set) 15
  61. ///make sure that spe_cache.h is below those defines!
  62. #include "../Extras/software_cache/cache/include/spe_cache.h"
  63. int g_CacheMisses=0;
  64. int g_CacheHits=0;
  65. #if 0 // Added to allow cache misses and hits to be tracked, change this to 1 to restore unmodified version
  66. #define spe_cache_read(ea) _spe_cache_lookup_xfer_wait_(ea, 0, 1)
  67. #else
  68. #define spe_cache_read(ea) \
  69. ({ \
  70. int set, idx, line, byte; \
  71. _spe_cache_nway_lookup_(ea, set, idx); \
  72. \
  73. if (btUnlikely(idx < 0)) { \
  74. ++g_CacheMisses; \
  75. idx = _spe_cache_miss_(ea, set, -1); \
  76. spu_writech(22, SPE_CACHE_SET_TAGMASK(set)); \
  77. spu_mfcstat(MFC_TAG_UPDATE_ALL); \
  78. } \
  79. else \
  80. { \
  81. ++g_CacheHits; \
  82. } \
  83. line = _spe_cacheline_num_(set, idx); \
  84. byte = _spe_cacheline_byte_offset_(ea); \
  85. (void *) &spe_cache_mem[line + byte]; \
  86. })
  87. #endif
  88. #endif // USE_SOFTWARE_CACHE
  89. bool gUseEpa = false;
  90. #ifdef USE_SN_TUNER
  91. #include <LibSN_SPU.h>
  92. #endif //USE_SN_TUNER
  93. #if defined (__SPU__) && !defined (USE_LIBSPE2)
  94. #include <spu_printf.h>
  95. #elif defined (USE_LIBSPE2)
  96. #define spu_printf(a)
  97. #else
  98. #define IGNORE_ALIGNMENT 1
  99. #include <stdio.h>
  100. #include <stdlib.h>
  101. #define spu_printf printf
  102. #endif
  103. //int gNumConvexPoints0=0;
  104. ///Make sure no destructors are called on this memory
  105. ATTRIBUTE_ALIGNED16(struct) CollisionTask_LocalStoreMemory
  106. {
  107. ///This CollisionTask_LocalStoreMemory is mainly used for the SPU version, using explicit DMA
  108. ///Other platforms can use other memory programming models.
  109. ATTRIBUTE_ALIGNED16(btBroadphasePair gBroadphasePairsBuffer[SPU_BATCHSIZE_BROADPHASE_PAIRS]);
  110. DoubleBuffer<unsigned char, MIDPHASE_WORKUNIT_PAGE_SIZE> g_workUnitTaskBuffers;
  111. ATTRIBUTE_ALIGNED16(char gSpuContactManifoldAlgoBuffer [sizeof(SpuContactManifoldCollisionAlgorithm)+16]);
  112. ATTRIBUTE_ALIGNED16(char gColObj0Buffer [sizeof(btCollisionObject)+16]);
  113. ATTRIBUTE_ALIGNED16(char gColObj1Buffer [sizeof(btCollisionObject)+16]);
  114. ///we reserve 32bit integer indices, even though they might be 16bit
  115. ATTRIBUTE_ALIGNED16(int spuIndices[16]);
  116. btPersistentManifold gPersistentManifoldBuffer;
  117. CollisionShape_LocalStoreMemory gCollisionShapes[2];
  118. bvhMeshShape_LocalStoreMemory bvhShapeData;
  119. ATTRIBUTE_ALIGNED16(SpuConvexPolyhedronVertexData convexVertexData[2]);
  120. CompoundShape_LocalStoreMemory compoundShapeData[2];
  121. ///The following pointers might either point into this local store memory, or to the original/other memory locations.
  122. ///See SpuFakeDma for implementation of cellDmaSmallGetReadOnly.
  123. btCollisionObject* m_lsColObj0Ptr;
  124. btCollisionObject* m_lsColObj1Ptr;
  125. btBroadphasePair* m_pairsPointer;
  126. btPersistentManifold* m_lsManifoldPtr;
  127. SpuContactManifoldCollisionAlgorithm* m_lsCollisionAlgorithmPtr;
  128. bool needsDmaPutContactManifoldAlgo;
  129. btCollisionObject* getColObj0()
  130. {
  131. return m_lsColObj0Ptr;
  132. }
  133. btCollisionObject* getColObj1()
  134. {
  135. return m_lsColObj1Ptr;
  136. }
  137. btBroadphasePair* getBroadphasePairPtr()
  138. {
  139. return m_pairsPointer;
  140. }
  141. SpuContactManifoldCollisionAlgorithm* getlocalCollisionAlgorithm()
  142. {
  143. return m_lsCollisionAlgorithmPtr;
  144. }
  145. btPersistentManifold* getContactManifoldPtr()
  146. {
  147. return m_lsManifoldPtr;
  148. }
  149. };
  150. #if defined(__CELLOS_LV2__) || defined(USE_LIBSPE2)
  151. ATTRIBUTE_ALIGNED16(CollisionTask_LocalStoreMemory gLocalStoreMemory);
  152. void* createCollisionLocalStoreMemory()
  153. {
  154. return &gLocalStoreMemory;
  155. }
  156. void deleteCollisionLocalStoreMemory()
  157. {
  158. }
  159. #else
  160. btAlignedObjectArray<CollisionTask_LocalStoreMemory*> sLocalStorePointers;
  161. void* createCollisionLocalStoreMemory()
  162. {
  163. CollisionTask_LocalStoreMemory* localStore = (CollisionTask_LocalStoreMemory*)btAlignedAlloc( sizeof(CollisionTask_LocalStoreMemory),16);
  164. sLocalStorePointers.push_back(localStore);
  165. return localStore;
  166. }
  167. void deleteCollisionLocalStoreMemory()
  168. {
  169. for (int i=0;i<sLocalStorePointers.size();i++)
  170. {
  171. btAlignedFree(sLocalStorePointers[i]);
  172. }
  173. sLocalStorePointers.clear();
  174. }
  175. #endif
  176. void ProcessSpuConvexConvexCollision(SpuCollisionPairInput* wuInput, CollisionTask_LocalStoreMemory* lsMemPtr, SpuContactResult& spuContacts);
  177. SIMD_FORCE_INLINE void small_cache_read(void* buffer, ppu_address_t ea, size_t size)
  178. {
  179. #if USE_SOFTWARE_CACHE
  180. // Check for alignment requirements. We need to make sure the entire request fits within one cache line,
  181. // so the first and last bytes should fall on the same cache line
  182. btAssert((ea & ~SPE_CACHELINE_MASK) == ((ea + size - 1) & ~SPE_CACHELINE_MASK));
  183. void* ls = spe_cache_read(ea);
  184. memcpy(buffer, ls, size);
  185. #else
  186. stallingUnalignedDmaSmallGet(buffer,ea,size);
  187. #endif
  188. }
  189. SIMD_FORCE_INLINE void small_cache_read_triple( void* ls0, ppu_address_t ea0,
  190. void* ls1, ppu_address_t ea1,
  191. void* ls2, ppu_address_t ea2,
  192. size_t size)
  193. {
  194. btAssert(size<16);
  195. ATTRIBUTE_ALIGNED16(char tmpBuffer0[32]);
  196. ATTRIBUTE_ALIGNED16(char tmpBuffer1[32]);
  197. ATTRIBUTE_ALIGNED16(char tmpBuffer2[32]);
  198. uint32_t i;
  199. ///make sure last 4 bits are the same, for cellDmaSmallGet
  200. char* localStore0 = (char*)ls0;
  201. uint32_t last4BitsOffset = ea0 & 0x0f;
  202. char* tmpTarget0 = tmpBuffer0 + last4BitsOffset;
  203. #ifdef __SPU__
  204. cellDmaSmallGet(tmpTarget0,ea0,size,DMA_TAG(1),0,0);
  205. #else
  206. tmpTarget0 = (char*)cellDmaSmallGetReadOnly(tmpTarget0,ea0,size,DMA_TAG(1),0,0);
  207. #endif
  208. char* localStore1 = (char*)ls1;
  209. last4BitsOffset = ea1 & 0x0f;
  210. char* tmpTarget1 = tmpBuffer1 + last4BitsOffset;
  211. #ifdef __SPU__
  212. cellDmaSmallGet(tmpTarget1,ea1,size,DMA_TAG(1),0,0);
  213. #else
  214. tmpTarget1 = (char*)cellDmaSmallGetReadOnly(tmpTarget1,ea1,size,DMA_TAG(1),0,0);
  215. #endif
  216. char* localStore2 = (char*)ls2;
  217. last4BitsOffset = ea2 & 0x0f;
  218. char* tmpTarget2 = tmpBuffer2 + last4BitsOffset;
  219. #ifdef __SPU__
  220. cellDmaSmallGet(tmpTarget2,ea2,size,DMA_TAG(1),0,0);
  221. #else
  222. tmpTarget2 = (char*)cellDmaSmallGetReadOnly(tmpTarget2,ea2,size,DMA_TAG(1),0,0);
  223. #endif
  224. cellDmaWaitTagStatusAll( DMA_MASK(1) );
  225. //this is slowish, perhaps memcpy on SPU is smarter?
  226. for (i=0; btLikely( i<size );i++)
  227. {
  228. localStore0[i] = tmpTarget0[i];
  229. localStore1[i] = tmpTarget1[i];
  230. localStore2[i] = tmpTarget2[i];
  231. }
  232. }
  233. ATTRIBUTE_ALIGNED16(class) spuNodeCallback : public btNodeOverlapCallback
  234. {
  235. SpuCollisionPairInput* m_wuInput;
  236. SpuContactResult& m_spuContacts;
  237. CollisionTask_LocalStoreMemory* m_lsMemPtr;
  238. ATTRIBUTE_ALIGNED16(btTriangleShape) m_tmpTriangleShape;
  239. ATTRIBUTE_ALIGNED16(btVector3 spuTriangleVertices[3]);
  240. ATTRIBUTE_ALIGNED16(btScalar spuUnscaledVertex[4]);
  241. public:
  242. spuNodeCallback(SpuCollisionPairInput* wuInput, CollisionTask_LocalStoreMemory* lsMemPtr,SpuContactResult& spuContacts)
  243. : m_wuInput(wuInput),
  244. m_spuContacts(spuContacts),
  245. m_lsMemPtr(lsMemPtr)
  246. {
  247. }
  248. virtual void processNode(int subPart, int triangleIndex)
  249. {
  250. ///Create a triangle on the stack, call process collision, with GJK
  251. ///DMA the vertices, can benefit from software caching
  252. // spu_printf("processNode with triangleIndex %d\n",triangleIndex);
  253. if (m_lsMemPtr->bvhShapeData.gIndexMesh.m_indexType == PHY_SHORT)
  254. {
  255. unsigned short int* indexBasePtr = (unsigned short int*)(m_lsMemPtr->bvhShapeData.gIndexMesh.m_triangleIndexBase+triangleIndex*m_lsMemPtr->bvhShapeData.gIndexMesh.m_triangleIndexStride);
  256. ATTRIBUTE_ALIGNED16(unsigned short int tmpIndices[3]);
  257. small_cache_read_triple(&tmpIndices[0],(ppu_address_t)&indexBasePtr[0],
  258. &tmpIndices[1],(ppu_address_t)&indexBasePtr[1],
  259. &tmpIndices[2],(ppu_address_t)&indexBasePtr[2],
  260. sizeof(unsigned short int));
  261. m_lsMemPtr->spuIndices[0] = int(tmpIndices[0]);
  262. m_lsMemPtr->spuIndices[1] = int(tmpIndices[1]);
  263. m_lsMemPtr->spuIndices[2] = int(tmpIndices[2]);
  264. } else
  265. {
  266. unsigned int* indexBasePtr = (unsigned int*)(m_lsMemPtr->bvhShapeData.gIndexMesh.m_triangleIndexBase+triangleIndex*m_lsMemPtr->bvhShapeData.gIndexMesh.m_triangleIndexStride);
  267. small_cache_read_triple(&m_lsMemPtr->spuIndices[0],(ppu_address_t)&indexBasePtr[0],
  268. &m_lsMemPtr->spuIndices[1],(ppu_address_t)&indexBasePtr[1],
  269. &m_lsMemPtr->spuIndices[2],(ppu_address_t)&indexBasePtr[2],
  270. sizeof(int));
  271. }
  272. // spu_printf("SPU index0=%d ,",spuIndices[0]);
  273. // spu_printf("SPU index1=%d ,",spuIndices[1]);
  274. // spu_printf("SPU index2=%d ,",spuIndices[2]);
  275. // spu_printf("SPU: indexBasePtr=%llx\n",indexBasePtr);
  276. const btVector3& meshScaling = m_lsMemPtr->bvhShapeData.gTriangleMeshInterfacePtr->getScaling();
  277. for (int j=2;btLikely( j>=0 );j--)
  278. {
  279. int graphicsindex = m_lsMemPtr->spuIndices[j];
  280. // spu_printf("SPU index=%d ,",graphicsindex);
  281. btScalar* graphicsbasePtr = (btScalar*)(m_lsMemPtr->bvhShapeData.gIndexMesh.m_vertexBase+graphicsindex*m_lsMemPtr->bvhShapeData.gIndexMesh.m_vertexStride);
  282. // spu_printf("SPU graphicsbasePtr=%llx\n",graphicsbasePtr);
  283. ///handle un-aligned vertices...
  284. //another DMA for each vertex
  285. small_cache_read_triple(&spuUnscaledVertex[0],(ppu_address_t)&graphicsbasePtr[0],
  286. &spuUnscaledVertex[1],(ppu_address_t)&graphicsbasePtr[1],
  287. &spuUnscaledVertex[2],(ppu_address_t)&graphicsbasePtr[2],
  288. sizeof(btScalar));
  289. m_tmpTriangleShape.getVertexPtr(j).setValue(spuUnscaledVertex[0]*meshScaling.getX(),
  290. spuUnscaledVertex[1]*meshScaling.getY(),
  291. spuUnscaledVertex[2]*meshScaling.getZ());
  292. // spu_printf("SPU:triangle vertices:%f,%f,%f\n",spuTriangleVertices[j].x(),spuTriangleVertices[j].y(),spuTriangleVertices[j].z());
  293. }
  294. SpuCollisionPairInput triangleConcaveInput(*m_wuInput);
  295. // triangleConcaveInput.m_spuCollisionShapes[1] = &spuTriangleVertices[0];
  296. triangleConcaveInput.m_spuCollisionShapes[1] = &m_tmpTriangleShape;
  297. triangleConcaveInput.m_shapeType1 = TRIANGLE_SHAPE_PROXYTYPE;
  298. m_spuContacts.setShapeIdentifiersB(subPart,triangleIndex);
  299. // m_spuContacts.flush();
  300. ProcessSpuConvexConvexCollision(&triangleConcaveInput, m_lsMemPtr,m_spuContacts);
  301. ///this flush should be automatic
  302. // m_spuContacts.flush();
  303. }
  304. };
  305. void btConvexPlaneCollideSingleContact (SpuCollisionPairInput* wuInput,CollisionTask_LocalStoreMemory* lsMemPtr,SpuContactResult& spuContacts)
  306. {
  307. btConvexShape* convexShape = (btConvexShape*) wuInput->m_spuCollisionShapes[0];
  308. btStaticPlaneShape* planeShape = (btStaticPlaneShape*) wuInput->m_spuCollisionShapes[1];
  309. bool hasCollision = false;
  310. const btVector3& planeNormal = planeShape->getPlaneNormal();
  311. const btScalar& planeConstant = planeShape->getPlaneConstant();
  312. btTransform convexWorldTransform = wuInput->m_worldTransform0;
  313. btTransform convexInPlaneTrans;
  314. convexInPlaneTrans= wuInput->m_worldTransform1.inverse() * convexWorldTransform;
  315. btTransform planeInConvex;
  316. planeInConvex= convexWorldTransform.inverse() * wuInput->m_worldTransform1;
  317. //btVector3 vtx = convexShape->localGetSupportVertexWithoutMarginNonVirtual(planeInConvex.getBasis()*-planeNormal);
  318. btVector3 vtx = convexShape->localGetSupportVertexNonVirtual(planeInConvex.getBasis()*-planeNormal);
  319. btVector3 vtxInPlane = convexInPlaneTrans(vtx);
  320. btScalar distance = (planeNormal.dot(vtxInPlane) - planeConstant);
  321. btVector3 vtxInPlaneProjected = vtxInPlane - distance*planeNormal;
  322. btVector3 vtxInPlaneWorld = wuInput->m_worldTransform1 * vtxInPlaneProjected;
  323. hasCollision = distance < lsMemPtr->getContactManifoldPtr()->getContactBreakingThreshold();
  324. //resultOut->setPersistentManifold(m_manifoldPtr);
  325. if (hasCollision)
  326. {
  327. /// report a contact. internally this will be kept persistent, and contact reduction is done
  328. btVector3 normalOnSurfaceB =wuInput->m_worldTransform1.getBasis() * planeNormal;
  329. btVector3 pOnB = vtxInPlaneWorld;
  330. spuContacts.addContactPoint(normalOnSurfaceB,pOnB,distance);
  331. }
  332. }
  333. void ProcessConvexPlaneSpuCollision(SpuCollisionPairInput* wuInput, CollisionTask_LocalStoreMemory* lsMemPtr, SpuContactResult& spuContacts)
  334. {
  335. register int dmaSize = 0;
  336. register ppu_address_t dmaPpuAddress2;
  337. btPersistentManifold* manifold = (btPersistentManifold*)wuInput->m_persistentManifoldPtr;
  338. ///DMA in the vertices for convex shapes
  339. ATTRIBUTE_ALIGNED16(char convexHullShape0[sizeof(btConvexHullShape)]);
  340. ATTRIBUTE_ALIGNED16(char convexHullShape1[sizeof(btConvexHullShape)]);
  341. if ( btLikely( wuInput->m_shapeType0== CONVEX_HULL_SHAPE_PROXYTYPE ) )
  342. {
  343. // spu_printf("SPU: DMA btConvexHullShape\n");
  344. dmaSize = sizeof(btConvexHullShape);
  345. dmaPpuAddress2 = wuInput->m_collisionShapes[0];
  346. cellDmaGet(&convexHullShape0, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0);
  347. //cellDmaWaitTagStatusAll(DMA_MASK(1));
  348. }
  349. if ( btLikely( wuInput->m_shapeType1 == CONVEX_HULL_SHAPE_PROXYTYPE ) )
  350. {
  351. // spu_printf("SPU: DMA btConvexHullShape\n");
  352. dmaSize = sizeof(btConvexHullShape);
  353. dmaPpuAddress2 = wuInput->m_collisionShapes[1];
  354. cellDmaGet(&convexHullShape1, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0);
  355. //cellDmaWaitTagStatusAll(DMA_MASK(1));
  356. }
  357. if ( btLikely( wuInput->m_shapeType0 == CONVEX_HULL_SHAPE_PROXYTYPE ) )
  358. {
  359. cellDmaWaitTagStatusAll(DMA_MASK(1));
  360. dmaConvexVertexData (&lsMemPtr->convexVertexData[0], (btConvexHullShape*)&convexHullShape0);
  361. lsMemPtr->convexVertexData[0].gSpuConvexShapePtr = wuInput->m_spuCollisionShapes[0];
  362. }
  363. if ( btLikely( wuInput->m_shapeType1 == CONVEX_HULL_SHAPE_PROXYTYPE ) )
  364. {
  365. cellDmaWaitTagStatusAll(DMA_MASK(1));
  366. dmaConvexVertexData (&lsMemPtr->convexVertexData[1], (btConvexHullShape*)&convexHullShape1);
  367. lsMemPtr->convexVertexData[1].gSpuConvexShapePtr = wuInput->m_spuCollisionShapes[1];
  368. }
  369. btConvexPointCloudShape cpc0,cpc1;
  370. if ( btLikely( wuInput->m_shapeType0 == CONVEX_HULL_SHAPE_PROXYTYPE ) )
  371. {
  372. cellDmaWaitTagStatusAll(DMA_MASK(2));
  373. lsMemPtr->convexVertexData[0].gConvexPoints = &lsMemPtr->convexVertexData[0].g_convexPointBuffer[0];
  374. btConvexHullShape* ch = (btConvexHullShape*)wuInput->m_spuCollisionShapes[0];
  375. const btVector3& localScaling = ch->getLocalScalingNV();
  376. cpc0.setPoints(lsMemPtr->convexVertexData[0].gConvexPoints,lsMemPtr->convexVertexData[0].gNumConvexPoints,false,localScaling);
  377. wuInput->m_spuCollisionShapes[0] = &cpc0;
  378. }
  379. if ( btLikely( wuInput->m_shapeType1 == CONVEX_HULL_SHAPE_PROXYTYPE ) )
  380. {
  381. cellDmaWaitTagStatusAll(DMA_MASK(2));
  382. lsMemPtr->convexVertexData[1].gConvexPoints = &lsMemPtr->convexVertexData[1].g_convexPointBuffer[0];
  383. btConvexHullShape* ch = (btConvexHullShape*)wuInput->m_spuCollisionShapes[1];
  384. const btVector3& localScaling = ch->getLocalScalingNV();
  385. cpc1.setPoints(lsMemPtr->convexVertexData[1].gConvexPoints,lsMemPtr->convexVertexData[1].gNumConvexPoints,false,localScaling);
  386. wuInput->m_spuCollisionShapes[1] = &cpc1;
  387. }
  388. // const btConvexShape* shape0Ptr = (const btConvexShape*)wuInput->m_spuCollisionShapes[0];
  389. // const btConvexShape* shape1Ptr = (const btConvexShape*)wuInput->m_spuCollisionShapes[1];
  390. // int shapeType0 = wuInput->m_shapeType0;
  391. // int shapeType1 = wuInput->m_shapeType1;
  392. float marginA = wuInput->m_collisionMargin0;
  393. float marginB = wuInput->m_collisionMargin1;
  394. SpuClosestPointInput cpInput;
  395. cpInput.m_convexVertexData[0] = &lsMemPtr->convexVertexData[0];
  396. cpInput.m_convexVertexData[1] = &lsMemPtr->convexVertexData[1];
  397. cpInput.m_transformA = wuInput->m_worldTransform0;
  398. cpInput.m_transformB = wuInput->m_worldTransform1;
  399. float sumMargin = (marginA+marginB+lsMemPtr->getContactManifoldPtr()->getContactBreakingThreshold());
  400. cpInput.m_maximumDistanceSquared = sumMargin * sumMargin;
  401. ppu_address_t manifoldAddress = (ppu_address_t)manifold;
  402. btPersistentManifold* spuManifold=lsMemPtr->getContactManifoldPtr();
  403. //spuContacts.setContactInfo(spuManifold,manifoldAddress,wuInput->m_worldTransform0,wuInput->m_worldTransform1,wuInput->m_isSwapped);
  404. spuContacts.setContactInfo(spuManifold,manifoldAddress,lsMemPtr->getColObj0()->getWorldTransform(),
  405. lsMemPtr->getColObj1()->getWorldTransform(),
  406. lsMemPtr->getColObj0()->getRestitution(),lsMemPtr->getColObj1()->getRestitution(),
  407. lsMemPtr->getColObj0()->getFriction(),lsMemPtr->getColObj1()->getFriction(),
  408. wuInput->m_isSwapped);
  409. btConvexPlaneCollideSingleContact(wuInput,lsMemPtr,spuContacts);
  410. }
  411. ////////////////////////
  412. /// Convex versus Concave triangle mesh collision detection (handles concave triangle mesh versus sphere, box, cylinder, triangle, cone, convex polyhedron etc)
  413. ///////////////////
  414. void ProcessConvexConcaveSpuCollision(SpuCollisionPairInput* wuInput, CollisionTask_LocalStoreMemory* lsMemPtr, SpuContactResult& spuContacts)
  415. {
  416. //order: first collision shape is convex, second concave. m_isSwapped is true, if the original order was opposite
  417. btBvhTriangleMeshShape* trimeshShape = (btBvhTriangleMeshShape*)wuInput->m_spuCollisionShapes[1];
  418. //need the mesh interface, for access to triangle vertices
  419. dmaBvhShapeData (&lsMemPtr->bvhShapeData, trimeshShape);
  420. btVector3 aabbMin(-1,-400,-1);
  421. btVector3 aabbMax(1,400,1);
  422. //recalc aabbs
  423. btTransform convexInTriangleSpace;
  424. convexInTriangleSpace = wuInput->m_worldTransform1.inverse() * wuInput->m_worldTransform0;
  425. btConvexInternalShape* convexShape = (btConvexInternalShape*)wuInput->m_spuCollisionShapes[0];
  426. computeAabb (aabbMin, aabbMax, convexShape, wuInput->m_collisionShapes[0], wuInput->m_shapeType0, convexInTriangleSpace);
  427. //CollisionShape* triangleShape = static_cast<btCollisionShape*>(triBody->m_collisionShape);
  428. //convexShape->getAabb(convexInTriangleSpace,m_aabbMin,m_aabbMax);
  429. // btScalar extraMargin = collisionMarginTriangle;
  430. // btVector3 extra(extraMargin,extraMargin,extraMargin);
  431. // aabbMax += extra;
  432. // aabbMin -= extra;
  433. ///quantize query AABB
  434. unsigned short int quantizedQueryAabbMin[3];
  435. unsigned short int quantizedQueryAabbMax[3];
  436. lsMemPtr->bvhShapeData.getOptimizedBvh()->quantizeWithClamp(quantizedQueryAabbMin,aabbMin,0);
  437. lsMemPtr->bvhShapeData.getOptimizedBvh()->quantizeWithClamp(quantizedQueryAabbMax,aabbMax,1);
  438. QuantizedNodeArray& nodeArray = lsMemPtr->bvhShapeData.getOptimizedBvh()->getQuantizedNodeArray();
  439. //spu_printf("SPU: numNodes = %d\n",nodeArray.size());
  440. BvhSubtreeInfoArray& subTrees = lsMemPtr->bvhShapeData.getOptimizedBvh()->getSubtreeInfoArray();
  441. spuNodeCallback nodeCallback(wuInput,lsMemPtr,spuContacts);
  442. IndexedMeshArray& indexArray = lsMemPtr->bvhShapeData.gTriangleMeshInterfacePtr->getIndexedMeshArray();
  443. //spu_printf("SPU:indexArray.size() = %d\n",indexArray.size());
  444. // spu_printf("SPU: numSubTrees = %d\n",subTrees.size());
  445. //not likely to happen
  446. if (subTrees.size() && indexArray.size() == 1)
  447. {
  448. ///DMA in the index info
  449. dmaBvhIndexedMesh (&lsMemPtr->bvhShapeData.gIndexMesh, indexArray, 0 /* index into indexArray */, 1 /* dmaTag */);
  450. cellDmaWaitTagStatusAll(DMA_MASK(1));
  451. //display the headers
  452. int numBatch = subTrees.size();
  453. for (int i=0;i<numBatch;)
  454. {
  455. //@todo- can reorder DMA transfers for less stall
  456. int remaining = subTrees.size() - i;
  457. int nextBatch = remaining < MAX_SPU_SUBTREE_HEADERS ? remaining : MAX_SPU_SUBTREE_HEADERS;
  458. dmaBvhSubTreeHeaders (&lsMemPtr->bvhShapeData.gSubtreeHeaders[0], (ppu_address_t)(&subTrees[i]), nextBatch, 1);
  459. cellDmaWaitTagStatusAll(DMA_MASK(1));
  460. // spu_printf("nextBatch = %d\n",nextBatch);
  461. for (int j=0;j<nextBatch;j++)
  462. {
  463. const btBvhSubtreeInfo& subtree = lsMemPtr->bvhShapeData.gSubtreeHeaders[j];
  464. unsigned int overlap = spuTestQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax);
  465. if (overlap)
  466. {
  467. btAssert(subtree.m_subtreeSize);
  468. //dma the actual nodes of this subtree
  469. dmaBvhSubTreeNodes (&lsMemPtr->bvhShapeData.gSubtreeNodes[0], subtree, nodeArray, 2);
  470. cellDmaWaitTagStatusAll(DMA_MASK(2));
  471. /* Walk this subtree */
  472. spuWalkStacklessQuantizedTree(&nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax,
  473. &lsMemPtr->bvhShapeData.gSubtreeNodes[0],
  474. 0,
  475. subtree.m_subtreeSize);
  476. }
  477. // spu_printf("subtreeSize = %d\n",gSubtreeHeaders[j].m_subtreeSize);
  478. }
  479. // unsigned short int m_quantizedAabbMin[3];
  480. // unsigned short int m_quantizedAabbMax[3];
  481. // int m_rootNodeIndex;
  482. // int m_subtreeSize;
  483. i+=nextBatch;
  484. }
  485. //pre-fetch first tree, then loop and double buffer
  486. }
  487. }
  488. #define MAX_DEGENERATE_STATS 15
  489. int stats[MAX_DEGENERATE_STATS]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
  490. int degenerateStats[MAX_DEGENERATE_STATS]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
  491. ////////////////////////
  492. /// Convex versus Convex collision detection (handles collision between sphere, box, cylinder, triangle, cone, convex polyhedron etc)
  493. ///////////////////
  494. void ProcessSpuConvexConvexCollision(SpuCollisionPairInput* wuInput, CollisionTask_LocalStoreMemory* lsMemPtr, SpuContactResult& spuContacts)
  495. {
  496. register int dmaSize;
  497. register ppu_address_t dmaPpuAddress2;
  498. #ifdef DEBUG_SPU_COLLISION_DETECTION
  499. //spu_printf("SPU: ProcessSpuConvexConvexCollision\n");
  500. #endif //DEBUG_SPU_COLLISION_DETECTION
  501. //CollisionShape* shape0 = (CollisionShape*)wuInput->m_collisionShapes[0];
  502. //CollisionShape* shape1 = (CollisionShape*)wuInput->m_collisionShapes[1];
  503. btPersistentManifold* manifold = (btPersistentManifold*)wuInput->m_persistentManifoldPtr;
  504. bool genericGjk = true;
  505. if (genericGjk)
  506. {
  507. //try generic GJK
  508. //SpuConvexPenetrationDepthSolver* penetrationSolver=0;
  509. btVoronoiSimplexSolver simplexSolver;
  510. btGjkEpaPenetrationDepthSolver epaPenetrationSolver2;
  511. btConvexPenetrationDepthSolver* penetrationSolver = &epaPenetrationSolver2;
  512. //SpuMinkowskiPenetrationDepthSolver minkowskiPenetrationSolver;
  513. #ifdef ENABLE_EPA
  514. if (gUseEpa)
  515. {
  516. penetrationSolver = &epaPenetrationSolver2;
  517. } else
  518. #endif
  519. {
  520. //penetrationSolver = &minkowskiPenetrationSolver;
  521. }
  522. ///DMA in the vertices for convex shapes
  523. ATTRIBUTE_ALIGNED16(char convexHullShape0[sizeof(btConvexHullShape)]);
  524. ATTRIBUTE_ALIGNED16(char convexHullShape1[sizeof(btConvexHullShape)]);
  525. if ( btLikely( wuInput->m_shapeType0== CONVEX_HULL_SHAPE_PROXYTYPE ) )
  526. {
  527. // spu_printf("SPU: DMA btConvexHullShape\n");
  528. dmaSize = sizeof(btConvexHullShape);
  529. dmaPpuAddress2 = wuInput->m_collisionShapes[0];
  530. cellDmaGet(&convexHullShape0, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0);
  531. //cellDmaWaitTagStatusAll(DMA_MASK(1));
  532. }
  533. if ( btLikely( wuInput->m_shapeType1 == CONVEX_HULL_SHAPE_PROXYTYPE ) )
  534. {
  535. // spu_printf("SPU: DMA btConvexHullShape\n");
  536. dmaSize = sizeof(btConvexHullShape);
  537. dmaPpuAddress2 = wuInput->m_collisionShapes[1];
  538. cellDmaGet(&convexHullShape1, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0);
  539. //cellDmaWaitTagStatusAll(DMA_MASK(1));
  540. }
  541. if ( btLikely( wuInput->m_shapeType0 == CONVEX_HULL_SHAPE_PROXYTYPE ) )
  542. {
  543. cellDmaWaitTagStatusAll(DMA_MASK(1));
  544. dmaConvexVertexData (&lsMemPtr->convexVertexData[0], (btConvexHullShape*)&convexHullShape0);
  545. lsMemPtr->convexVertexData[0].gSpuConvexShapePtr = wuInput->m_spuCollisionShapes[0];
  546. }
  547. if ( btLikely( wuInput->m_shapeType1 == CONVEX_HULL_SHAPE_PROXYTYPE ) )
  548. {
  549. cellDmaWaitTagStatusAll(DMA_MASK(1));
  550. dmaConvexVertexData (&lsMemPtr->convexVertexData[1], (btConvexHullShape*)&convexHullShape1);
  551. lsMemPtr->convexVertexData[1].gSpuConvexShapePtr = wuInput->m_spuCollisionShapes[1];
  552. }
  553. btConvexPointCloudShape cpc0,cpc1;
  554. if ( btLikely( wuInput->m_shapeType0 == CONVEX_HULL_SHAPE_PROXYTYPE ) )
  555. {
  556. cellDmaWaitTagStatusAll(DMA_MASK(2));
  557. lsMemPtr->convexVertexData[0].gConvexPoints = &lsMemPtr->convexVertexData[0].g_convexPointBuffer[0];
  558. btConvexHullShape* ch = (btConvexHullShape*)wuInput->m_spuCollisionShapes[0];
  559. const btVector3& localScaling = ch->getLocalScalingNV();
  560. cpc0.setPoints(lsMemPtr->convexVertexData[0].gConvexPoints,lsMemPtr->convexVertexData[0].gNumConvexPoints,false,localScaling);
  561. wuInput->m_spuCollisionShapes[0] = &cpc0;
  562. }
  563. if ( btLikely( wuInput->m_shapeType1 == CONVEX_HULL_SHAPE_PROXYTYPE ) )
  564. {
  565. cellDmaWaitTagStatusAll(DMA_MASK(2));
  566. lsMemPtr->convexVertexData[1].gConvexPoints = &lsMemPtr->convexVertexData[1].g_convexPointBuffer[0];
  567. btConvexHullShape* ch = (btConvexHullShape*)wuInput->m_spuCollisionShapes[1];
  568. const btVector3& localScaling = ch->getLocalScalingNV();
  569. cpc1.setPoints(lsMemPtr->convexVertexData[1].gConvexPoints,lsMemPtr->convexVertexData[1].gNumConvexPoints,false,localScaling);
  570. wuInput->m_spuCollisionShapes[1] = &cpc1;
  571. }
  572. const btConvexShape* shape0Ptr = (const btConvexShape*)wuInput->m_spuCollisionShapes[0];
  573. const btConvexShape* shape1Ptr = (const btConvexShape*)wuInput->m_spuCollisionShapes[1];
  574. int shapeType0 = wuInput->m_shapeType0;
  575. int shapeType1 = wuInput->m_shapeType1;
  576. float marginA = wuInput->m_collisionMargin0;
  577. float marginB = wuInput->m_collisionMargin1;
  578. SpuClosestPointInput cpInput;
  579. cpInput.m_convexVertexData[0] = &lsMemPtr->convexVertexData[0];
  580. cpInput.m_convexVertexData[1] = &lsMemPtr->convexVertexData[1];
  581. cpInput.m_transformA = wuInput->m_worldTransform0;
  582. cpInput.m_transformB = wuInput->m_worldTransform1;
  583. float sumMargin = (marginA+marginB+lsMemPtr->getContactManifoldPtr()->getContactBreakingThreshold());
  584. cpInput.m_maximumDistanceSquared = sumMargin * sumMargin;
  585. ppu_address_t manifoldAddress = (ppu_address_t)manifold;
  586. btPersistentManifold* spuManifold=lsMemPtr->getContactManifoldPtr();
  587. //spuContacts.setContactInfo(spuManifold,manifoldAddress,wuInput->m_worldTransform0,wuInput->m_worldTransform1,wuInput->m_isSwapped);
  588. spuContacts.setContactInfo(spuManifold,manifoldAddress,lsMemPtr->getColObj0()->getWorldTransform(),
  589. lsMemPtr->getColObj1()->getWorldTransform(),
  590. lsMemPtr->getColObj0()->getRestitution(),lsMemPtr->getColObj1()->getRestitution(),
  591. lsMemPtr->getColObj0()->getFriction(),lsMemPtr->getColObj1()->getFriction(),
  592. wuInput->m_isSwapped);
  593. {
  594. btGjkPairDetector gjk(shape0Ptr,shape1Ptr,shapeType0,shapeType1,marginA,marginB,&simplexSolver,penetrationSolver);//&vsSolver,penetrationSolver);
  595. gjk.getClosestPoints(cpInput,spuContacts,0);//,debugDraw);
  596. btAssert(gjk.m_lastUsedMethod <MAX_DEGENERATE_STATS);
  597. stats[gjk.m_lastUsedMethod]++;
  598. btAssert(gjk.m_degenerateSimplex <MAX_DEGENERATE_STATS);
  599. degenerateStats[gjk.m_degenerateSimplex]++;
  600. #ifdef USE_SEPDISTANCE_UTIL
  601. btScalar sepDist = gjk.getCachedSeparatingDistance()+spuManifold->getContactBreakingThreshold();
  602. lsMemPtr->getlocalCollisionAlgorithm()->m_sepDistance.initSeparatingDistance(gjk.getCachedSeparatingAxis(),sepDist,wuInput->m_worldTransform0,wuInput->m_worldTransform1);
  603. lsMemPtr->needsDmaPutContactManifoldAlgo = true;
  604. #endif //USE_SEPDISTANCE_UTIL
  605. }
  606. }
  607. }
  608. template<typename T> void DoSwap(T& a, T& b)
  609. {
  610. char tmp[sizeof(T)];
  611. memcpy(tmp, &a, sizeof(T));
  612. memcpy(&a, &b, sizeof(T));
  613. memcpy(&b, tmp, sizeof(T));
  614. }
  615. SIMD_FORCE_INLINE void dmaAndSetupCollisionObjects(SpuCollisionPairInput& collisionPairInput, CollisionTask_LocalStoreMemory& lsMem)
  616. {
  617. register int dmaSize;
  618. register ppu_address_t dmaPpuAddress2;
  619. dmaSize = sizeof(btCollisionObject);//btTransform);
  620. dmaPpuAddress2 = /*collisionPairInput.m_isSwapped ? (ppu_address_t)lsMem.gProxyPtr1->m_clientObject :*/ (ppu_address_t)lsMem.getlocalCollisionAlgorithm()->getCollisionObject0();
  621. lsMem.m_lsColObj0Ptr = (btCollisionObject*)cellDmaGetReadOnly(&lsMem.gColObj0Buffer, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0);
  622. dmaSize = sizeof(btCollisionObject);//btTransform);
  623. dmaPpuAddress2 = /*collisionPairInput.m_isSwapped ? (ppu_address_t)lsMem.gProxyPtr0->m_clientObject :*/ (ppu_address_t)lsMem.getlocalCollisionAlgorithm()->getCollisionObject1();
  624. lsMem.m_lsColObj1Ptr = (btCollisionObject*)cellDmaGetReadOnly(&lsMem.gColObj1Buffer, dmaPpuAddress2 , dmaSize, DMA_TAG(2), 0, 0);
  625. cellDmaWaitTagStatusAll(DMA_MASK(1) | DMA_MASK(2));
  626. btCollisionObject* ob0 = lsMem.getColObj0();
  627. btCollisionObject* ob1 = lsMem.getColObj1();
  628. collisionPairInput.m_worldTransform0 = ob0->getWorldTransform();
  629. collisionPairInput.m_worldTransform1 = ob1->getWorldTransform();
  630. }
  631. void handleCollisionPair(SpuCollisionPairInput& collisionPairInput, CollisionTask_LocalStoreMemory& lsMem,
  632. SpuContactResult &spuContacts,
  633. ppu_address_t collisionShape0Ptr, void* collisionShape0Loc,
  634. ppu_address_t collisionShape1Ptr, void* collisionShape1Loc, bool dmaShapes = true)
  635. {
  636. if (btBroadphaseProxy::isConvex(collisionPairInput.m_shapeType0)
  637. && btBroadphaseProxy::isConvex(collisionPairInput.m_shapeType1))
  638. {
  639. if (dmaShapes)
  640. {
  641. dmaCollisionShape (collisionShape0Loc, collisionShape0Ptr, 1, collisionPairInput.m_shapeType0);
  642. dmaCollisionShape (collisionShape1Loc, collisionShape1Ptr, 2, collisionPairInput.m_shapeType1);
  643. cellDmaWaitTagStatusAll(DMA_MASK(1) | DMA_MASK(2));
  644. }
  645. btConvexInternalShape* spuConvexShape0 = (btConvexInternalShape*)collisionShape0Loc;
  646. btConvexInternalShape* spuConvexShape1 = (btConvexInternalShape*)collisionShape1Loc;
  647. btVector3 dim0 = spuConvexShape0->getImplicitShapeDimensions();
  648. btVector3 dim1 = spuConvexShape1->getImplicitShapeDimensions();
  649. collisionPairInput.m_primitiveDimensions0 = dim0;
  650. collisionPairInput.m_primitiveDimensions1 = dim1;
  651. collisionPairInput.m_collisionShapes[0] = collisionShape0Ptr;
  652. collisionPairInput.m_collisionShapes[1] = collisionShape1Ptr;
  653. collisionPairInput.m_spuCollisionShapes[0] = spuConvexShape0;
  654. collisionPairInput.m_spuCollisionShapes[1] = spuConvexShape1;
  655. ProcessSpuConvexConvexCollision(&collisionPairInput,&lsMem,spuContacts);
  656. }
  657. else if (btBroadphaseProxy::isCompound(collisionPairInput.m_shapeType0) &&
  658. btBroadphaseProxy::isCompound(collisionPairInput.m_shapeType1))
  659. {
  660. //snPause();
  661. dmaCollisionShape (collisionShape0Loc, collisionShape0Ptr, 1, collisionPairInput.m_shapeType0);
  662. dmaCollisionShape (collisionShape1Loc, collisionShape1Ptr, 2, collisionPairInput.m_shapeType1);
  663. cellDmaWaitTagStatusAll(DMA_MASK(1) | DMA_MASK(2));
  664. // Both are compounds, do N^2 CD for now
  665. ///@todo: add some AABB-based pruning (probably not -> slower)
  666. btCompoundShape* spuCompoundShape0 = (btCompoundShape*)collisionShape0Loc;
  667. btCompoundShape* spuCompoundShape1 = (btCompoundShape*)collisionShape1Loc;
  668. dmaCompoundShapeInfo (&lsMem.compoundShapeData[0], spuCompoundShape0, 1);
  669. dmaCompoundShapeInfo (&lsMem.compoundShapeData[1], spuCompoundShape1, 2);
  670. cellDmaWaitTagStatusAll(DMA_MASK(1) | DMA_MASK(2));
  671. dmaCompoundSubShapes (&lsMem.compoundShapeData[0], spuCompoundShape0, 1);
  672. cellDmaWaitTagStatusAll(DMA_MASK(1));
  673. dmaCompoundSubShapes (&lsMem.compoundShapeData[1], spuCompoundShape1, 1);
  674. cellDmaWaitTagStatusAll(DMA_MASK(1));
  675. int childShapeCount0 = spuCompoundShape0->getNumChildShapes();
  676. btAssert(childShapeCount0< MAX_SPU_COMPOUND_SUBSHAPES);
  677. int childShapeCount1 = spuCompoundShape1->getNumChildShapes();
  678. btAssert(childShapeCount1< MAX_SPU_COMPOUND_SUBSHAPES);
  679. // Start the N^2
  680. for (int i = 0; i < childShapeCount0; ++i)
  681. {
  682. btCompoundShapeChild& childShape0 = lsMem.compoundShapeData[0].gSubshapes[i];
  683. btAssert(!btBroadphaseProxy::isCompound(childShape0.m_childShapeType));
  684. for (int j = 0; j < childShapeCount1; ++j)
  685. {
  686. btCompoundShapeChild& childShape1 = lsMem.compoundShapeData[1].gSubshapes[j];
  687. btAssert(!btBroadphaseProxy::isCompound(childShape1.m_childShapeType));
  688. /* Create a new collision pair input struct using the two child shapes */
  689. SpuCollisionPairInput cinput (collisionPairInput);
  690. cinput.m_worldTransform0 = collisionPairInput.m_worldTransform0 * childShape0.m_transform;
  691. cinput.m_shapeType0 = childShape0.m_childShapeType;
  692. cinput.m_collisionMargin0 = childShape0.m_childMargin;
  693. cinput.m_worldTransform1 = collisionPairInput.m_worldTransform1 * childShape1.m_transform;
  694. cinput.m_shapeType1 = childShape1.m_childShapeType;
  695. cinput.m_collisionMargin1 = childShape1.m_childMargin;
  696. /* Recursively call handleCollisionPair () with new collision pair input */
  697. handleCollisionPair(cinput, lsMem, spuContacts,
  698. (ppu_address_t)childShape0.m_childShape, lsMem.compoundShapeData[0].gSubshapeShape[i],
  699. (ppu_address_t)childShape1.m_childShape, lsMem.compoundShapeData[1].gSubshapeShape[j], false);
  700. }
  701. }
  702. }
  703. else if (btBroadphaseProxy::isCompound(collisionPairInput.m_shapeType0) )
  704. {
  705. //snPause();
  706. dmaCollisionShape (collisionShape0Loc, collisionShape0Ptr, 1, collisionPairInput.m_shapeType0);
  707. dmaCollisionShape (collisionShape1Loc, collisionShape1Ptr, 2, collisionPairInput.m_shapeType1);
  708. cellDmaWaitTagStatusAll(DMA_MASK(1) | DMA_MASK(2));
  709. // object 0 compound, object 1 non-compound
  710. btCompoundShape* spuCompoundShape = (btCompoundShape*)collisionShape0Loc;
  711. dmaCompoundShapeInfo (&lsMem.compoundShapeData[0], spuCompoundShape, 1);
  712. cellDmaWaitTagStatusAll(DMA_MASK(1));
  713. int childShapeCount = spuCompoundShape->getNumChildShapes();
  714. btAssert(childShapeCount< MAX_SPU_COMPOUND_SUBSHAPES);
  715. for (int i = 0; i < childShapeCount; ++i)
  716. {
  717. btCompoundShapeChild& childShape = lsMem.compoundShapeData[0].gSubshapes[i];
  718. btAssert(!btBroadphaseProxy::isCompound(childShape.m_childShapeType));
  719. // Dma the child shape
  720. dmaCollisionShape (&lsMem.compoundShapeData[0].gSubshapeShape[i], (ppu_address_t)childShape.m_childShape, 1, childShape.m_childShapeType);
  721. cellDmaWaitTagStatusAll(DMA_MASK(1));
  722. SpuCollisionPairInput cinput (collisionPairInput);
  723. cinput.m_worldTransform0 = collisionPairInput.m_worldTransform0 * childShape.m_transform;
  724. cinput.m_shapeType0 = childShape.m_childShapeType;
  725. cinput.m_collisionMargin0 = childShape.m_childMargin;
  726. handleCollisionPair(cinput, lsMem, spuContacts,
  727. (ppu_address_t)childShape.m_childShape, lsMem.compoundShapeData[0].gSubshapeShape[i],
  728. collisionShape1Ptr, collisionShape1Loc, false);
  729. }
  730. }
  731. else if (btBroadphaseProxy::isCompound(collisionPairInput.m_shapeType1) )
  732. {
  733. //snPause();
  734. dmaCollisionShape (collisionShape0Loc, collisionShape0Ptr, 1, collisionPairInput.m_shapeType0);
  735. dmaCollisionShape (collisionShape1Loc, collisionShape1Ptr, 2, collisionPairInput.m_shapeType1);
  736. cellDmaWaitTagStatusAll(DMA_MASK(1) | DMA_MASK(2));
  737. // object 0 non-compound, object 1 compound
  738. btCompoundShape* spuCompoundShape = (btCompoundShape*)collisionShape1Loc;
  739. dmaCompoundShapeInfo (&lsMem.compoundShapeData[0], spuCompoundShape, 1);
  740. cellDmaWaitTagStatusAll(DMA_MASK(1));
  741. int childShapeCount = spuCompoundShape->getNumChildShapes();
  742. btAssert(childShapeCount< MAX_SPU_COMPOUND_SUBSHAPES);
  743. for (int i = 0; i < childShapeCount; ++i)
  744. {
  745. btCompoundShapeChild& childShape = lsMem.compoundShapeData[0].gSubshapes[i];
  746. btAssert(!btBroadphaseProxy::isCompound(childShape.m_childShapeType));
  747. // Dma the child shape
  748. dmaCollisionShape (&lsMem.compoundShapeData[0].gSubshapeShape[i], (ppu_address_t)childShape.m_childShape, 1, childShape.m_childShapeType);
  749. cellDmaWaitTagStatusAll(DMA_MASK(1));
  750. SpuCollisionPairInput cinput (collisionPairInput);
  751. cinput.m_worldTransform1 = collisionPairInput.m_worldTransform1 * childShape.m_transform;
  752. cinput.m_shapeType1 = childShape.m_childShapeType;
  753. cinput.m_collisionMargin1 = childShape.m_childMargin;
  754. handleCollisionPair(cinput, lsMem, spuContacts,
  755. collisionShape0Ptr, collisionShape0Loc,
  756. (ppu_address_t)childShape.m_childShape, lsMem.compoundShapeData[0].gSubshapeShape[i], false);
  757. }
  758. }
  759. else
  760. {
  761. //a non-convex shape is involved
  762. bool handleConvexConcave = false;
  763. //snPause();
  764. if (btBroadphaseProxy::isConcave(collisionPairInput.m_shapeType0) &&
  765. btBroadphaseProxy::isConvex(collisionPairInput.m_shapeType1))
  766. {
  767. // Swap stuff
  768. DoSwap(collisionShape0Ptr, collisionShape1Ptr);
  769. DoSwap(collisionShape0Loc, collisionShape1Loc);
  770. DoSwap(collisionPairInput.m_shapeType0, collisionPairInput.m_shapeType1);
  771. DoSwap(collisionPairInput.m_worldTransform0, collisionPairInput.m_worldTransform1);
  772. DoSwap(collisionPairInput.m_collisionMargin0, collisionPairInput.m_collisionMargin1);
  773. collisionPairInput.m_isSwapped = true;
  774. }
  775. if (btBroadphaseProxy::isConvex(collisionPairInput.m_shapeType0)&&
  776. btBroadphaseProxy::isConcave(collisionPairInput.m_shapeType1))
  777. {
  778. handleConvexConcave = true;
  779. }
  780. if (handleConvexConcave)
  781. {
  782. if (dmaShapes)
  783. {
  784. dmaCollisionShape (collisionShape0Loc, collisionShape0Ptr, 1, collisionPairInput.m_shapeType0);
  785. dmaCollisionShape (collisionShape1Loc, collisionShape1Ptr, 2, collisionPairInput.m_shapeType1);
  786. cellDmaWaitTagStatusAll(DMA_MASK(1) | DMA_MASK(2));
  787. }
  788. if (collisionPairInput.m_shapeType1 == STATIC_PLANE_PROXYTYPE)
  789. {
  790. btConvexInternalShape* spuConvexShape0 = (btConvexInternalShape*)collisionShape0Loc;
  791. btStaticPlaneShape* planeShape= (btStaticPlaneShape*)collisionShape1Loc;
  792. btVector3 dim0 = spuConvexShape0->getImplicitShapeDimensions();
  793. collisionPairInput.m_primitiveDimensions0 = dim0;
  794. collisionPairInput.m_collisionShapes[0] = collisionShape0Ptr;
  795. collisionPairInput.m_collisionShapes[1] = collisionShape1Ptr;
  796. collisionPairInput.m_spuCollisionShapes[0] = spuConvexShape0;
  797. collisionPairInput.m_spuCollisionShapes[1] = planeShape;
  798. ProcessConvexPlaneSpuCollision(&collisionPairInput,&lsMem,spuContacts);
  799. } else
  800. {
  801. btConvexInternalShape* spuConvexShape0 = (btConvexInternalShape*)collisionShape0Loc;
  802. btBvhTriangleMeshShape* trimeshShape = (btBvhTriangleMeshShape*)collisionShape1Loc;
  803. btVector3 dim0 = spuConvexShape0->getImplicitShapeDimensions();
  804. collisionPairInput.m_primitiveDimensions0 = dim0;
  805. collisionPairInput.m_collisionShapes[0] = collisionShape0Ptr;
  806. collisionPairInput.m_collisionShapes[1] = collisionShape1Ptr;
  807. collisionPairInput.m_spuCollisionShapes[0] = spuConvexShape0;
  808. collisionPairInput.m_spuCollisionShapes[1] = trimeshShape;
  809. ProcessConvexConcaveSpuCollision(&collisionPairInput,&lsMem,spuContacts);
  810. }
  811. }
  812. }
  813. spuContacts.flush();
  814. }
  815. void processCollisionTask(void* userPtr, void* lsMemPtr)
  816. {
  817. SpuGatherAndProcessPairsTaskDesc* taskDescPtr = (SpuGatherAndProcessPairsTaskDesc*)userPtr;
  818. SpuGatherAndProcessPairsTaskDesc& taskDesc = *taskDescPtr;
  819. CollisionTask_LocalStoreMemory* colMemPtr = (CollisionTask_LocalStoreMemory*)lsMemPtr;
  820. CollisionTask_LocalStoreMemory& lsMem = *(colMemPtr);
  821. gUseEpa = taskDesc.m_useEpa;
  822. // spu_printf("taskDescPtr=%llx\n",taskDescPtr);
  823. SpuContactResult spuContacts;
  824. ////////////////////
  825. ppu_address_t dmaInPtr = taskDesc.m_inPairPtr;
  826. unsigned int numPages = taskDesc.numPages;
  827. unsigned int numOnLastPage = taskDesc.numOnLastPage;
  828. // prefetch first set of inputs and wait
  829. lsMem.g_workUnitTaskBuffers.init();
  830. unsigned int nextNumOnPage = (numPages > 1)? MIDPHASE_NUM_WORKUNITS_PER_PAGE : numOnLastPage;
  831. lsMem.g_workUnitTaskBuffers.backBufferDmaGet(dmaInPtr, nextNumOnPage*sizeof(SpuGatherAndProcessWorkUnitInput), DMA_TAG(3));
  832. dmaInPtr += MIDPHASE_WORKUNIT_PAGE_SIZE;
  833. register unsigned char *inputPtr;
  834. register unsigned int numOnPage;
  835. register unsigned int j;
  836. SpuGatherAndProcessWorkUnitInput* wuInputs;
  837. register int dmaSize;
  838. register ppu_address_t dmaPpuAddress;
  839. register ppu_address_t dmaPpuAddress2;
  840. int numPairs;
  841. register int p;
  842. SpuCollisionPairInput collisionPairInput;
  843. for (unsigned int i = 0; btLikely(i < numPages); i++)
  844. {
  845. // wait for back buffer dma and swap buffers
  846. inputPtr = lsMem.g_workUnitTaskBuffers.swapBuffers();
  847. // number on current page is number prefetched last iteration
  848. numOnPage = nextNumOnPage;
  849. // prefetch next set of inputs
  850. #if MIDPHASE_NUM_WORKUNIT_PAGES > 2
  851. if ( btLikely( i < numPages-1 ) )
  852. #else
  853. if ( btUnlikely( i < numPages-1 ) )
  854. #endif
  855. {
  856. nextNumOnPage = (i == numPages-2)? numOnLastPage : MIDPHASE_NUM_WORKUNITS_PER_PAGE;
  857. lsMem.g_workUnitTaskBuffers.backBufferDmaGet(dmaInPtr, nextNumOnPage*sizeof(SpuGatherAndProcessWorkUnitInput), DMA_TAG(3));
  858. dmaInPtr += MIDPHASE_WORKUNIT_PAGE_SIZE;
  859. }
  860. wuInputs = reinterpret_cast<SpuGatherAndProcessWorkUnitInput *>(inputPtr);
  861. for (j = 0; btLikely( j < numOnPage ); j++)
  862. {
  863. #ifdef DEBUG_SPU_COLLISION_DETECTION
  864. // printMidphaseInput(&wuInputs[j]);
  865. #endif //DEBUG_SPU_COLLISION_DETECTION
  866. numPairs = wuInputs[j].m_endIndex - wuInputs[j].m_startIndex;
  867. if ( btLikely( numPairs ) )
  868. {
  869. dmaSize = numPairs*sizeof(btBroadphasePair);
  870. dmaPpuAddress = wuInputs[j].m_pairArrayPtr+wuInputs[j].m_startIndex * sizeof(btBroadphasePair);
  871. lsMem.m_pairsPointer = (btBroadphasePair*)cellDmaGetReadOnly(&lsMem.gBroadphasePairsBuffer, dmaPpuAddress , dmaSize, DMA_TAG(1), 0, 0);
  872. cellDmaWaitTagStatusAll(DMA_MASK(1));
  873. for (p=0;p<numPairs;p++)
  874. {
  875. //for each broadphase pair, do something
  876. btBroadphasePair& pair = lsMem.getBroadphasePairPtr()[p];
  877. #ifdef DEBUG_SPU_COLLISION_DETECTION
  878. spu_printf("pair->m_userInfo = %d\n",pair.m_userInfo);
  879. spu_printf("pair->m_algorithm = %d\n",pair.m_algorithm);
  880. spu_printf("pair->m_pProxy0 = %d\n",pair.m_pProxy0);
  881. spu_printf("pair->m_pProxy1 = %d\n",pair.m_pProxy1);
  882. #endif //DEBUG_SPU_COLLISION_DETECTION
  883. if (pair.m_internalTmpValue == 2 && pair.m_algorithm && pair.m_pProxy0 && pair.m_pProxy1)
  884. {
  885. dmaSize = sizeof(SpuContactManifoldCollisionAlgorithm);
  886. dmaPpuAddress2 = (ppu_address_t)pair.m_algorithm;
  887. lsMem.m_lsCollisionAlgorithmPtr = (SpuContactManifoldCollisionAlgorithm*)cellDmaGetReadOnly(&lsMem.gSpuContactManifoldAlgoBuffer, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0);
  888. cellDmaWaitTagStatusAll(DMA_MASK(1));
  889. lsMem.needsDmaPutContactManifoldAlgo = false;
  890. collisionPairInput.m_persistentManifoldPtr = (ppu_address_t) lsMem.getlocalCollisionAlgorithm()->getContactManifoldPtr();
  891. collisionPairInput.m_isSwapped = false;
  892. if (1)
  893. {
  894. ///can wait on the combined DMA_MASK, or dma on the same tag
  895. #ifdef DEBUG_SPU_COLLISION_DETECTION
  896. // spu_printf("SPU collisionPairInput->m_shapeType0 = %d\n",collisionPairInput->m_shapeType0);
  897. // spu_printf("SPU collisionPairInput->m_shapeType1 = %d\n",collisionPairInput->m_shapeType1);
  898. #endif //DEBUG_SPU_COLLISION_DETECTION
  899. dmaSize = sizeof(btPersistentManifold);
  900. dmaPpuAddress2 = collisionPairInput.m_persistentManifoldPtr;
  901. lsMem.m_lsManifoldPtr = (btPersistentManifold*)cellDmaGetReadOnly(&lsMem.gPersistentManifoldBuffer, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0);
  902. collisionPairInput.m_shapeType0 = lsMem.getlocalCollisionAlgorithm()->getShapeType0();
  903. collisionPairInput.m_shapeType1 = lsMem.getlocalCollisionAlgorithm()->getShapeType1();
  904. collisionPairInput.m_collisionMargin0 = lsMem.getlocalCollisionAlgorithm()->getCollisionMargin0();
  905. collisionPairInput.m_collisionMargin1 = lsMem.getlocalCollisionAlgorithm()->getCollisionMargin1();
  906. //??cellDmaWaitTagStatusAll(DMA_MASK(1));
  907. if (1)
  908. {
  909. //snPause();
  910. // Get the collision objects
  911. dmaAndSetupCollisionObjects(collisionPairInput, lsMem);
  912. if (lsMem.getColObj0()->isActive() || lsMem.getColObj1()->isActive())
  913. {
  914. lsMem.needsDmaPutContactManifoldAlgo = true;
  915. #ifdef USE_SEPDISTANCE_UTIL
  916. lsMem.getlocalCollisionAlgorithm()->m_sepDistance.updateSeparatingDistance(collisionPairInput.m_worldTransform0,collisionPairInput.m_worldTransform1);
  917. #endif //USE_SEPDISTANCE_UTIL
  918. #define USE_DEDICATED_BOX_BOX 1
  919. #ifdef USE_DEDICATED_BOX_BOX
  920. bool boxbox = ((lsMem.getlocalCollisionAlgorithm()->getShapeType0()==BOX_SHAPE_PROXYTYPE)&&
  921. (lsMem.getlocalCollisionAlgorithm()->getShapeType1()==BOX_SHAPE_PROXYTYPE));
  922. if (boxbox)
  923. {
  924. //spu_printf("boxbox dist = %f\n",distance);
  925. btPersistentManifold* spuManifold=lsMem.getContactManifoldPtr();
  926. btPersistentManifold* manifold = (btPersistentManifold*)collisionPairInput.m_persistentManifoldPtr;
  927. ppu_address_t manifoldAddress = (ppu_address_t)manifold;
  928. spuContacts.setContactInfo(spuManifold,manifoldAddress,lsMem.getColObj0()->getWorldTransform(),
  929. lsMem.getColObj1()->getWorldTransform(),
  930. lsMem.getColObj0()->getRestitution(),lsMem.getColObj1()->getRestitution(),
  931. lsMem.getColObj0()->getFriction(),lsMem.getColObj1()->getFriction(),
  932. collisionPairInput.m_isSwapped);
  933. //float distance=0.f;
  934. btVector3 normalInB;
  935. if (//!gUseEpa &&
  936. #ifdef USE_SEPDISTANCE_UTIL
  937. lsMem.getlocalCollisionAlgorithm()->m_sepDistance.getConservativeSeparatingDistance()<=0.f
  938. #else
  939. 1
  940. #endif
  941. )
  942. {
  943. //#define USE_PE_BOX_BOX 1
  944. #ifdef USE_PE_BOX_BOX
  945. {
  946. //getCollisionMargin0
  947. btScalar margin0 = lsMem.getlocalCollisionAlgorithm()->getCollisionMargin0();
  948. btScalar margin1 = lsMem.getlocalCollisionAlgorithm()->getCollisionMargin1();
  949. btVector3 shapeDim0 = lsMem.getlocalCollisionAlgorithm()->getShapeDimensions0()+btVector3(margin0,margin0,margin0);
  950. btVector3 shapeDim1 = lsMem.getlocalCollisionAlgorithm()->getShapeDimensions1()+btVector3(margin1,margin1,margin1);
  951. /*
  952. //Box boxA(shapeDim0.getX(),shapeDim0.getY(),shapeDim0.getZ());
  953. vmVector3 vmPos0 = getVmVector3(collisionPairInput.m_worldTransform0.getOrigin());
  954. vmVector3 vmPos1 = getVmVector3(collisionPairInput.m_worldTransform1.getOrigin());
  955. vmMatrix3 vmMatrix0 = getVmMatrix3(collisionPairInput.m_worldTransform0.getBasis());
  956. vmMatrix3 vmMatrix1 = getVmMatrix3(collisionPairInput.m_worldTransform1.getBasis());
  957. vmTransform3 transformA(vmMatrix0,vmPos0);
  958. Box boxB(shapeDim1.getX(),shapeDim1.getY(),shapeDim1.getZ());
  959. vmTransform3 transformB(vmMatrix1,vmPos1);
  960. BoxPoint resultClosestBoxPointA;
  961. BoxPoint resultClosestBoxPointB;
  962. vmVector3 resultNormal;
  963. */
  964. #ifdef USE_SEPDISTANCE_UTIL
  965. float distanceThreshold = FLT_MAX
  966. #else
  967. //float distanceThreshold = 0.f;
  968. #endif
  969. vmVector3 n;
  970. Box boxA;
  971. vmVector3 hA(shapeDim0.getX(),shapeDim0.getY(),shapeDim0.getZ());
  972. vmVector3 hB(shapeDim1.getX(),shapeDim1.getY(),shapeDim1.getZ());
  973. boxA.mHalf= hA;
  974. vmTransform3 trA;
  975. trA.setTranslation(getVmVector3(collisionPairInput.m_worldTransform0.getOrigin()));
  976. trA.setUpper3x3(getVmMatrix3(collisionPairInput.m_worldTransform0.getBasis()));
  977. Box boxB;
  978. boxB.mHalf = hB;
  979. vmTransform3 trB;
  980. trB.setTranslation(getVmVector3(collisionP