2
Bullet Continuous Collision Detection and Physics Library
3
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
5
This software is provided 'as-is', without any express or implied warranty.
6
In no event will the authors be held liable for any damages arising from the use of this software.
7
Permission is granted to anyone to use this software for any purpose,
8
including commercial applications, and to alter it and redistribute it freely,
9
subject to the following restrictions:
11
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.
12
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
13
3. This notice may not be removed or altered from any source distribution.
16
#include "SpuGatheringCollisionTask.h"
18
//#define DEBUG_SPU_COLLISION_DETECTION 1
19
#include "../SpuDoubleBuffer.h"
21
#include "../SpuCollisionTaskProcess.h"
22
#include "../SpuGatheringCollisionDispatcher.h" //for SPU_BATCHSIZE_BROADPHASE_PAIRS
24
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
25
#include "../SpuContactManifoldCollisionAlgorithm.h"
26
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
27
#include "SpuContactResult.h"
28
#include "BulletCollision/CollisionShapes/btOptimizedBvh.h"
29
#include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h"
30
#include "BulletCollision/CollisionShapes/btSphereShape.h"
31
#include "BulletCollision/CollisionShapes/btConvexPointCloudShape.h"
33
#include "BulletCollision/CollisionShapes/btCapsuleShape.h"
35
#include "BulletCollision/CollisionShapes/btConvexShape.h"
36
#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h"
37
#include "BulletCollision/CollisionShapes/btConvexHullShape.h"
38
#include "BulletCollision/CollisionShapes/btCompoundShape.h"
40
#include "SpuMinkowskiPenetrationDepthSolver.h"
41
//#include "SpuEpaPenetrationDepthSolver.h"
42
#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h"
45
#include "boxBoxDistance.h"
46
#include "BulletMultiThreaded/vectormath2bullet.h"
47
#include "SpuCollisionShapes.h" //definition of SpuConvexPolyhedronVertexData
48
#include "BulletCollision/CollisionDispatch/btBoxBoxDetector.h"
49
#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h"
50
#include "BulletCollision/CollisionShapes/btTriangleShape.h"
53
///Software caching from the IBM Cell SDK, it reduces 25% SPU time for our test cases
55
//#define USE_SOFTWARE_CACHE 1
60
int gProcessedCol = 0;
62
////////////////////////////////////////////////
64
#if USE_SOFTWARE_CACHE
65
#include <spu_intrinsics.h>
66
#include <sys/spu_thread.h>
67
#include <sys/spu_event.h>
69
#define SPE_CACHE_NWAY 4
70
//#define SPE_CACHE_NSETS 32, 16
71
#define SPE_CACHE_NSETS 8
72
//#define SPE_CACHELINE_SIZE 512
73
#define SPE_CACHELINE_SIZE 128
74
#define SPE_CACHE_SET_TAGID(set) 15
75
///make sure that spe_cache.h is below those defines!
76
#include "../Extras/software_cache/cache/include/spe_cache.h"
82
#if 0 // Added to allow cache misses and hits to be tracked, change this to 1 to restore unmodified version
83
#define spe_cache_read(ea) _spe_cache_lookup_xfer_wait_(ea, 0, 1)
85
#define spe_cache_read(ea) \
87
int set, idx, line, byte; \
88
_spe_cache_nway_lookup_(ea, set, idx); \
90
if (btUnlikely(idx < 0)) { \
92
idx = _spe_cache_miss_(ea, set, -1); \
93
spu_writech(22, SPE_CACHE_SET_TAGMASK(set)); \
94
spu_mfcstat(MFC_TAG_UPDATE_ALL); \
100
line = _spe_cacheline_num_(set, idx); \
101
byte = _spe_cacheline_byte_offset_(ea); \
102
(void *) &spe_cache_mem[line + byte]; \
107
#endif // USE_SOFTWARE_CACHE
109
bool gUseEpa = false;
112
#include <LibSN_SPU.h>
113
#endif //USE_SN_TUNER
115
#if defined (__SPU__) && !defined (USE_LIBSPE2)
116
#include <spu_printf.h>
117
#elif defined (USE_LIBSPE2)
118
#define spu_printf(a)
120
#define IGNORE_ALIGNMENT 1
123
#define spu_printf printf
127
//int gNumConvexPoints0=0;
129
///Make sure no destructors are called on this memory
130
struct CollisionTask_LocalStoreMemory
132
///This CollisionTask_LocalStoreMemory is mainly used for the SPU version, using explicit DMA
133
///Other platforms can use other memory programming models.
135
ATTRIBUTE_ALIGNED16(btBroadphasePair gBroadphasePairsBuffer[SPU_BATCHSIZE_BROADPHASE_PAIRS]);
136
DoubleBuffer<unsigned char, MIDPHASE_WORKUNIT_PAGE_SIZE> g_workUnitTaskBuffers;
137
ATTRIBUTE_ALIGNED16(char gSpuContactManifoldAlgoBuffer [sizeof(SpuContactManifoldCollisionAlgorithm)+16]);
138
ATTRIBUTE_ALIGNED16(char gColObj0Buffer [sizeof(btCollisionObject)+16]);
139
ATTRIBUTE_ALIGNED16(char gColObj1Buffer [sizeof(btCollisionObject)+16]);
140
///we reserve 32bit integer indices, even though they might be 16bit
141
ATTRIBUTE_ALIGNED16(int spuIndices[16]);
142
btPersistentManifold gPersistentManifoldBuffer;
143
CollisionShape_LocalStoreMemory gCollisionShapes[2];
144
bvhMeshShape_LocalStoreMemory bvhShapeData;
145
SpuConvexPolyhedronVertexData convexVertexData[2];
146
CompoundShape_LocalStoreMemory compoundShapeData[2];
148
///The following pointers might either point into this local store memory, or to the original/other memory locations.
149
///See SpuFakeDma for implementation of cellDmaSmallGetReadOnly.
150
btCollisionObject* m_lsColObj0Ptr;
151
btCollisionObject* m_lsColObj1Ptr;
152
btBroadphasePair* m_pairsPointer;
153
btPersistentManifold* m_lsManifoldPtr;
154
SpuContactManifoldCollisionAlgorithm* m_lsCollisionAlgorithmPtr;
156
bool needsDmaPutContactManifoldAlgo;
158
btCollisionObject* getColObj0()
160
return m_lsColObj0Ptr;
162
btCollisionObject* getColObj1()
164
return m_lsColObj1Ptr;
168
btBroadphasePair* getBroadphasePairPtr()
170
return m_pairsPointer;
173
SpuContactManifoldCollisionAlgorithm* getlocalCollisionAlgorithm()
175
return m_lsCollisionAlgorithmPtr;
178
btPersistentManifold* getContactManifoldPtr()
180
return m_lsManifoldPtr;
185
#if defined(__CELLOS_LV2__) || defined(USE_LIBSPE2)
187
ATTRIBUTE_ALIGNED16(CollisionTask_LocalStoreMemory gLocalStoreMemory);
189
void* createCollisionLocalStoreMemory()
191
return &gLocalStoreMemory;
194
void* createCollisionLocalStoreMemory()
196
return new CollisionTask_LocalStoreMemory;
201
void ProcessSpuConvexConvexCollision(SpuCollisionPairInput* wuInput, CollisionTask_LocalStoreMemory* lsMemPtr, SpuContactResult& spuContacts);
204
SIMD_FORCE_INLINE void small_cache_read(void* buffer, ppu_address_t ea, size_t size)
206
#if USE_SOFTWARE_CACHE
207
// Check for alignment requirements. We need to make sure the entire request fits within one cache line,
208
// so the first and last bytes should fall on the same cache line
209
btAssert((ea & ~SPE_CACHELINE_MASK) == ((ea + size - 1) & ~SPE_CACHELINE_MASK));
211
void* ls = spe_cache_read(ea);
212
memcpy(buffer, ls, size);
214
stallingUnalignedDmaSmallGet(buffer,ea,size);
218
SIMD_FORCE_INLINE void small_cache_read_triple( void* ls0, ppu_address_t ea0,
219
void* ls1, ppu_address_t ea1,
220
void* ls2, ppu_address_t ea2,
224
ATTRIBUTE_ALIGNED16(char tmpBuffer0[32]);
225
ATTRIBUTE_ALIGNED16(char tmpBuffer1[32]);
226
ATTRIBUTE_ALIGNED16(char tmpBuffer2[32]);
231
///make sure last 4 bits are the same, for cellDmaSmallGet
232
char* localStore0 = (char*)ls0;
233
uint32_t last4BitsOffset = ea0 & 0x0f;
234
char* tmpTarget0 = tmpBuffer0 + last4BitsOffset;
236
cellDmaSmallGet(tmpTarget0,ea0,size,DMA_TAG(1),0,0);
238
tmpTarget0 = (char*)cellDmaSmallGetReadOnly(tmpTarget0,ea0,size,DMA_TAG(1),0,0);
242
char* localStore1 = (char*)ls1;
243
last4BitsOffset = ea1 & 0x0f;
244
char* tmpTarget1 = tmpBuffer1 + last4BitsOffset;
246
cellDmaSmallGet(tmpTarget1,ea1,size,DMA_TAG(1),0,0);
248
tmpTarget1 = (char*)cellDmaSmallGetReadOnly(tmpTarget1,ea1,size,DMA_TAG(1),0,0);
251
char* localStore2 = (char*)ls2;
252
last4BitsOffset = ea2 & 0x0f;
253
char* tmpTarget2 = tmpBuffer2 + last4BitsOffset;
255
cellDmaSmallGet(tmpTarget2,ea2,size,DMA_TAG(1),0,0);
257
tmpTarget2 = (char*)cellDmaSmallGetReadOnly(tmpTarget2,ea2,size,DMA_TAG(1),0,0);
261
cellDmaWaitTagStatusAll( DMA_MASK(1) );
263
//this is slowish, perhaps memcpy on SPU is smarter?
264
for (i=0; btLikely( i<size );i++)
266
localStore0[i] = tmpTarget0[i];
267
localStore1[i] = tmpTarget1[i];
268
localStore2[i] = tmpTarget2[i];
277
class spuNodeCallback : public btNodeOverlapCallback
279
SpuCollisionPairInput* m_wuInput;
280
SpuContactResult& m_spuContacts;
281
CollisionTask_LocalStoreMemory* m_lsMemPtr;
282
ATTRIBUTE_ALIGNED16(btTriangleShape) m_tmpTriangleShape;
284
ATTRIBUTE_ALIGNED16(btVector3 spuTriangleVertices[3]);
285
ATTRIBUTE_ALIGNED16(btScalar spuUnscaledVertex[4]);
290
spuNodeCallback(SpuCollisionPairInput* wuInput, CollisionTask_LocalStoreMemory* lsMemPtr,SpuContactResult& spuContacts)
291
: m_wuInput(wuInput),
292
m_spuContacts(spuContacts),
297
virtual void processNode(int subPart, int triangleIndex)
299
///Create a triangle on the stack, call process collision, with GJK
300
///DMA the vertices, can benefit from software caching
302
// spu_printf("processNode with triangleIndex %d\n",triangleIndex);
304
if (m_lsMemPtr->bvhShapeData.gIndexMesh.m_indexType == PHY_SHORT)
306
unsigned short int* indexBasePtr = (unsigned short int*)(m_lsMemPtr->bvhShapeData.gIndexMesh.m_triangleIndexBase+triangleIndex*m_lsMemPtr->bvhShapeData.gIndexMesh.m_triangleIndexStride);
307
ATTRIBUTE_ALIGNED16(unsigned short int tmpIndices[3]);
309
small_cache_read_triple(&tmpIndices[0],(ppu_address_t)&indexBasePtr[0],
310
&tmpIndices[1],(ppu_address_t)&indexBasePtr[1],
311
&tmpIndices[2],(ppu_address_t)&indexBasePtr[2],
312
sizeof(unsigned short int));
314
m_lsMemPtr->spuIndices[0] = int(tmpIndices[0]);
315
m_lsMemPtr->spuIndices[1] = int(tmpIndices[1]);
316
m_lsMemPtr->spuIndices[2] = int(tmpIndices[2]);
319
unsigned int* indexBasePtr = (unsigned int*)(m_lsMemPtr->bvhShapeData.gIndexMesh.m_triangleIndexBase+triangleIndex*m_lsMemPtr->bvhShapeData.gIndexMesh.m_triangleIndexStride);
321
small_cache_read_triple(&m_lsMemPtr->spuIndices[0],(ppu_address_t)&indexBasePtr[0],
322
&m_lsMemPtr->spuIndices[1],(ppu_address_t)&indexBasePtr[1],
323
&m_lsMemPtr->spuIndices[2],(ppu_address_t)&indexBasePtr[2],
327
// spu_printf("SPU index0=%d ,",spuIndices[0]);
328
// spu_printf("SPU index1=%d ,",spuIndices[1]);
329
// spu_printf("SPU index2=%d ,",spuIndices[2]);
330
// spu_printf("SPU: indexBasePtr=%llx\n",indexBasePtr);
332
const btVector3& meshScaling = m_lsMemPtr->bvhShapeData.gTriangleMeshInterfacePtr->getScaling();
333
for (int j=2;btLikely( j>=0 );j--)
335
int graphicsindex = m_lsMemPtr->spuIndices[j];
337
// spu_printf("SPU index=%d ,",graphicsindex);
338
btScalar* graphicsbasePtr = (btScalar*)(m_lsMemPtr->bvhShapeData.gIndexMesh.m_vertexBase+graphicsindex*m_lsMemPtr->bvhShapeData.gIndexMesh.m_vertexStride);
339
// spu_printf("SPU graphicsbasePtr=%llx\n",graphicsbasePtr);
342
///handle un-aligned vertices...
344
//another DMA for each vertex
345
small_cache_read_triple(&spuUnscaledVertex[0],(ppu_address_t)&graphicsbasePtr[0],
346
&spuUnscaledVertex[1],(ppu_address_t)&graphicsbasePtr[1],
347
&spuUnscaledVertex[2],(ppu_address_t)&graphicsbasePtr[2],
350
m_tmpTriangleShape.getVertexPtr(j).setValue(spuUnscaledVertex[0]*meshScaling.getX(),
351
spuUnscaledVertex[1]*meshScaling.getY(),
352
spuUnscaledVertex[2]*meshScaling.getZ());
354
// spu_printf("SPU:triangle vertices:%f,%f,%f\n",spuTriangleVertices[j].x(),spuTriangleVertices[j].y(),spuTriangleVertices[j].z());
358
SpuCollisionPairInput triangleConcaveInput(*m_wuInput);
359
// triangleConcaveInput.m_spuCollisionShapes[1] = &spuTriangleVertices[0];
360
triangleConcaveInput.m_spuCollisionShapes[1] = &m_tmpTriangleShape;
361
triangleConcaveInput.m_shapeType1 = TRIANGLE_SHAPE_PROXYTYPE;
363
m_spuContacts.setShapeIdentifiersB(subPart,triangleIndex);
365
// m_spuContacts.flush();
367
ProcessSpuConvexConvexCollision(&triangleConcaveInput, m_lsMemPtr,m_spuContacts);
368
///this flush should be automatic
369
// m_spuContacts.flush();
376
void btConvexPlaneCollideSingleContact (SpuCollisionPairInput* wuInput,CollisionTask_LocalStoreMemory* lsMemPtr,SpuContactResult& spuContacts)
379
btConvexShape* convexShape = (btConvexShape*) wuInput->m_spuCollisionShapes[0];
380
btStaticPlaneShape* planeShape = (btStaticPlaneShape*) wuInput->m_spuCollisionShapes[1];
382
bool hasCollision = false;
383
const btVector3& planeNormal = planeShape->getPlaneNormal();
384
const btScalar& planeConstant = planeShape->getPlaneConstant();
387
btTransform convexWorldTransform = wuInput->m_worldTransform0;
388
btTransform convexInPlaneTrans;
389
convexInPlaneTrans= wuInput->m_worldTransform1.inverse() * convexWorldTransform;
390
btTransform planeInConvex;
391
planeInConvex= convexWorldTransform.inverse() * wuInput->m_worldTransform1;
393
//btVector3 vtx = convexShape->localGetSupportVertexWithoutMarginNonVirtual(planeInConvex.getBasis()*-planeNormal);
394
btVector3 vtx = convexShape->localGetSupportVertexNonVirtual(planeInConvex.getBasis()*-planeNormal);
396
btVector3 vtxInPlane = convexInPlaneTrans(vtx);
397
btScalar distance = (planeNormal.dot(vtxInPlane) - planeConstant);
399
btVector3 vtxInPlaneProjected = vtxInPlane - distance*planeNormal;
400
btVector3 vtxInPlaneWorld = wuInput->m_worldTransform1 * vtxInPlaneProjected;
402
hasCollision = distance < lsMemPtr->getContactManifoldPtr()->getContactBreakingThreshold();
403
//resultOut->setPersistentManifold(m_manifoldPtr);
406
/// report a contact. internally this will be kept persistent, and contact reduction is done
407
btVector3 normalOnSurfaceB =wuInput->m_worldTransform1.getBasis() * planeNormal;
408
btVector3 pOnB = vtxInPlaneWorld;
409
spuContacts.addContactPoint(normalOnSurfaceB,pOnB,distance);
413
void ProcessConvexPlaneSpuCollision(SpuCollisionPairInput* wuInput, CollisionTask_LocalStoreMemory* lsMemPtr, SpuContactResult& spuContacts)
416
register int dmaSize = 0;
417
register ppu_address_t dmaPpuAddress2;
418
btPersistentManifold* manifold = (btPersistentManifold*)wuInput->m_persistentManifoldPtr;
420
///DMA in the vertices for convex shapes
421
ATTRIBUTE_ALIGNED16(char convexHullShape0[sizeof(btConvexHullShape)]);
422
ATTRIBUTE_ALIGNED16(char convexHullShape1[sizeof(btConvexHullShape)]);
424
if ( btLikely( wuInput->m_shapeType0== CONVEX_HULL_SHAPE_PROXYTYPE ) )
426
// spu_printf("SPU: DMA btConvexHullShape\n");
428
dmaSize = sizeof(btConvexHullShape);
429
dmaPpuAddress2 = wuInput->m_collisionShapes[0];
431
cellDmaGet(&convexHullShape0, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0);
432
//cellDmaWaitTagStatusAll(DMA_MASK(1));
435
if ( btLikely( wuInput->m_shapeType1 == CONVEX_HULL_SHAPE_PROXYTYPE ) )
437
// spu_printf("SPU: DMA btConvexHullShape\n");
438
dmaSize = sizeof(btConvexHullShape);
439
dmaPpuAddress2 = wuInput->m_collisionShapes[1];
440
cellDmaGet(&convexHullShape1, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0);
441
//cellDmaWaitTagStatusAll(DMA_MASK(1));
444
if ( btLikely( wuInput->m_shapeType0 == CONVEX_HULL_SHAPE_PROXYTYPE ) )
446
cellDmaWaitTagStatusAll(DMA_MASK(1));
447
dmaConvexVertexData (&lsMemPtr->convexVertexData[0], (btConvexHullShape*)&convexHullShape0);
448
lsMemPtr->convexVertexData[0].gSpuConvexShapePtr = wuInput->m_spuCollisionShapes[0];
452
if ( btLikely( wuInput->m_shapeType1 == CONVEX_HULL_SHAPE_PROXYTYPE ) )
454
cellDmaWaitTagStatusAll(DMA_MASK(1));
455
dmaConvexVertexData (&lsMemPtr->convexVertexData[1], (btConvexHullShape*)&convexHullShape1);
456
lsMemPtr->convexVertexData[1].gSpuConvexShapePtr = wuInput->m_spuCollisionShapes[1];
460
btConvexPointCloudShape cpc0,cpc1;
462
if ( btLikely( wuInput->m_shapeType0 == CONVEX_HULL_SHAPE_PROXYTYPE ) )
464
cellDmaWaitTagStatusAll(DMA_MASK(2));
465
lsMemPtr->convexVertexData[0].gConvexPoints = &lsMemPtr->convexVertexData[0].g_convexPointBuffer[0];
466
btConvexHullShape* ch = (btConvexHullShape*)wuInput->m_spuCollisionShapes[0];
467
const btVector3& localScaling = ch->getLocalScalingNV();
468
cpc0.setPoints(lsMemPtr->convexVertexData[0].gConvexPoints,lsMemPtr->convexVertexData[0].gNumConvexPoints,false,localScaling);
469
wuInput->m_spuCollisionShapes[0] = &cpc0;
472
if ( btLikely( wuInput->m_shapeType1 == CONVEX_HULL_SHAPE_PROXYTYPE ) )
474
cellDmaWaitTagStatusAll(DMA_MASK(2));
475
lsMemPtr->convexVertexData[1].gConvexPoints = &lsMemPtr->convexVertexData[1].g_convexPointBuffer[0];
476
btConvexHullShape* ch = (btConvexHullShape*)wuInput->m_spuCollisionShapes[1];
477
const btVector3& localScaling = ch->getLocalScalingNV();
478
cpc1.setPoints(lsMemPtr->convexVertexData[1].gConvexPoints,lsMemPtr->convexVertexData[1].gNumConvexPoints,false,localScaling);
479
wuInput->m_spuCollisionShapes[1] = &cpc1;
484
// const btConvexShape* shape0Ptr = (const btConvexShape*)wuInput->m_spuCollisionShapes[0];
485
// const btConvexShape* shape1Ptr = (const btConvexShape*)wuInput->m_spuCollisionShapes[1];
486
// int shapeType0 = wuInput->m_shapeType0;
487
// int shapeType1 = wuInput->m_shapeType1;
488
float marginA = wuInput->m_collisionMargin0;
489
float marginB = wuInput->m_collisionMargin1;
491
SpuClosestPointInput cpInput;
492
cpInput.m_convexVertexData[0] = &lsMemPtr->convexVertexData[0];
493
cpInput.m_convexVertexData[1] = &lsMemPtr->convexVertexData[1];
494
cpInput.m_transformA = wuInput->m_worldTransform0;
495
cpInput.m_transformB = wuInput->m_worldTransform1;
496
float sumMargin = (marginA+marginB+lsMemPtr->getContactManifoldPtr()->getContactBreakingThreshold());
497
cpInput.m_maximumDistanceSquared = sumMargin * sumMargin;
499
ppu_address_t manifoldAddress = (ppu_address_t)manifold;
501
btPersistentManifold* spuManifold=lsMemPtr->getContactManifoldPtr();
502
//spuContacts.setContactInfo(spuManifold,manifoldAddress,wuInput->m_worldTransform0,wuInput->m_worldTransform1,wuInput->m_isSwapped);
503
spuContacts.setContactInfo(spuManifold,manifoldAddress,lsMemPtr->getColObj0()->getWorldTransform(),
504
lsMemPtr->getColObj1()->getWorldTransform(),
505
lsMemPtr->getColObj0()->getRestitution(),lsMemPtr->getColObj1()->getRestitution(),
506
lsMemPtr->getColObj0()->getFriction(),lsMemPtr->getColObj1()->getFriction(),
507
wuInput->m_isSwapped);
510
btConvexPlaneCollideSingleContact(wuInput,lsMemPtr,spuContacts);
520
////////////////////////
521
/// Convex versus Concave triangle mesh collision detection (handles concave triangle mesh versus sphere, box, cylinder, triangle, cone, convex polyhedron etc)
523
void ProcessConvexConcaveSpuCollision(SpuCollisionPairInput* wuInput, CollisionTask_LocalStoreMemory* lsMemPtr, SpuContactResult& spuContacts)
525
//order: first collision shape is convex, second concave. m_isSwapped is true, if the original order was opposite
527
btBvhTriangleMeshShape* trimeshShape = (btBvhTriangleMeshShape*)wuInput->m_spuCollisionShapes[1];
528
//need the mesh interface, for access to triangle vertices
529
dmaBvhShapeData (&lsMemPtr->bvhShapeData, trimeshShape);
531
btVector3 aabbMin(-1,-400,-1);
532
btVector3 aabbMax(1,400,1);
536
btTransform convexInTriangleSpace;
537
convexInTriangleSpace = wuInput->m_worldTransform1.inverse() * wuInput->m_worldTransform0;
538
btConvexInternalShape* convexShape = (btConvexInternalShape*)wuInput->m_spuCollisionShapes[0];
540
computeAabb (aabbMin, aabbMax, convexShape, wuInput->m_collisionShapes[0], wuInput->m_shapeType0, convexInTriangleSpace);
543
//CollisionShape* triangleShape = static_cast<btCollisionShape*>(triBody->m_collisionShape);
544
//convexShape->getAabb(convexInTriangleSpace,m_aabbMin,m_aabbMax);
546
// btScalar extraMargin = collisionMarginTriangle;
547
// btVector3 extra(extraMargin,extraMargin,extraMargin);
551
///quantize query AABB
552
unsigned short int quantizedQueryAabbMin[3];
553
unsigned short int quantizedQueryAabbMax[3];
554
lsMemPtr->bvhShapeData.getOptimizedBvh()->quantizeWithClamp(quantizedQueryAabbMin,aabbMin,0);
555
lsMemPtr->bvhShapeData.getOptimizedBvh()->quantizeWithClamp(quantizedQueryAabbMax,aabbMax,1);
557
QuantizedNodeArray& nodeArray = lsMemPtr->bvhShapeData.getOptimizedBvh()->getQuantizedNodeArray();
558
//spu_printf("SPU: numNodes = %d\n",nodeArray.size());
560
BvhSubtreeInfoArray& subTrees = lsMemPtr->bvhShapeData.getOptimizedBvh()->getSubtreeInfoArray();
563
spuNodeCallback nodeCallback(wuInput,lsMemPtr,spuContacts);
564
IndexedMeshArray& indexArray = lsMemPtr->bvhShapeData.gTriangleMeshInterfacePtr->getIndexedMeshArray();
565
//spu_printf("SPU:indexArray.size() = %d\n",indexArray.size());
567
// spu_printf("SPU: numSubTrees = %d\n",subTrees.size());
568
//not likely to happen
569
if (subTrees.size() && indexArray.size() == 1)
571
///DMA in the index info
572
dmaBvhIndexedMesh (&lsMemPtr->bvhShapeData.gIndexMesh, indexArray, 0 /* index into indexArray */, 1 /* dmaTag */);
573
cellDmaWaitTagStatusAll(DMA_MASK(1));
575
//display the headers
576
int numBatch = subTrees.size();
577
for (int i=0;i<numBatch;)
579
//@todo- can reorder DMA transfers for less stall
580
int remaining = subTrees.size() - i;
581
int nextBatch = remaining < MAX_SPU_SUBTREE_HEADERS ? remaining : MAX_SPU_SUBTREE_HEADERS;
583
dmaBvhSubTreeHeaders (&lsMemPtr->bvhShapeData.gSubtreeHeaders[0], (ppu_address_t)(&subTrees[i]), nextBatch, 1);
584
cellDmaWaitTagStatusAll(DMA_MASK(1));
587
// spu_printf("nextBatch = %d\n",nextBatch);
589
for (int j=0;j<nextBatch;j++)
591
const btBvhSubtreeInfo& subtree = lsMemPtr->bvhShapeData.gSubtreeHeaders[j];
593
unsigned int overlap = spuTestQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax);
596
btAssert(subtree.m_subtreeSize);
598
//dma the actual nodes of this subtree
599
dmaBvhSubTreeNodes (&lsMemPtr->bvhShapeData.gSubtreeNodes[0], subtree, nodeArray, 2);
600
cellDmaWaitTagStatusAll(DMA_MASK(2));
602
/* Walk this subtree */
603
spuWalkStacklessQuantizedTree(&nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax,
604
&lsMemPtr->bvhShapeData.gSubtreeNodes[0],
606
subtree.m_subtreeSize);
608
// spu_printf("subtreeSize = %d\n",gSubtreeHeaders[j].m_subtreeSize);
611
// unsigned short int m_quantizedAabbMin[3];
612
// unsigned short int m_quantizedAabbMax[3];
613
// int m_rootNodeIndex;
614
// int m_subtreeSize;
618
//pre-fetch first tree, then loop and double buffer
624
int stats[11]={0,0,0,0,0,0,0,0,0,0,0};
625
int degenerateStats[11]={0,0,0,0,0,0,0,0,0,0,0};
628
////////////////////////
629
/// Convex versus Convex collision detection (handles collision between sphere, box, cylinder, triangle, cone, convex polyhedron etc)
631
void ProcessSpuConvexConvexCollision(SpuCollisionPairInput* wuInput, CollisionTask_LocalStoreMemory* lsMemPtr, SpuContactResult& spuContacts)
633
register int dmaSize;
634
register ppu_address_t dmaPpuAddress2;
636
#ifdef DEBUG_SPU_COLLISION_DETECTION
637
//spu_printf("SPU: ProcessSpuConvexConvexCollision\n");
638
#endif //DEBUG_SPU_COLLISION_DETECTION
639
//CollisionShape* shape0 = (CollisionShape*)wuInput->m_collisionShapes[0];
640
//CollisionShape* shape1 = (CollisionShape*)wuInput->m_collisionShapes[1];
641
btPersistentManifold* manifold = (btPersistentManifold*)wuInput->m_persistentManifoldPtr;
643
bool genericGjk = true;
651
//SpuConvexPenetrationDepthSolver* penetrationSolver=0;
652
btVoronoiSimplexSolver simplexSolver;
653
btGjkEpaPenetrationDepthSolver epaPenetrationSolver2;
655
btConvexPenetrationDepthSolver* penetrationSolver = &epaPenetrationSolver2;
657
//SpuMinkowskiPenetrationDepthSolver minkowskiPenetrationSolver;
661
penetrationSolver = &epaPenetrationSolver2;
665
//penetrationSolver = &minkowskiPenetrationSolver;
669
///DMA in the vertices for convex shapes
670
ATTRIBUTE_ALIGNED16(char convexHullShape0[sizeof(btConvexHullShape)]);
671
ATTRIBUTE_ALIGNED16(char convexHullShape1[sizeof(btConvexHullShape)]);
673
if ( btLikely( wuInput->m_shapeType0== CONVEX_HULL_SHAPE_PROXYTYPE ) )
675
// spu_printf("SPU: DMA btConvexHullShape\n");
677
dmaSize = sizeof(btConvexHullShape);
678
dmaPpuAddress2 = wuInput->m_collisionShapes[0];
680
cellDmaGet(&convexHullShape0, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0);
681
//cellDmaWaitTagStatusAll(DMA_MASK(1));
684
if ( btLikely( wuInput->m_shapeType1 == CONVEX_HULL_SHAPE_PROXYTYPE ) )
686
// spu_printf("SPU: DMA btConvexHullShape\n");
687
dmaSize = sizeof(btConvexHullShape);
688
dmaPpuAddress2 = wuInput->m_collisionShapes[1];
689
cellDmaGet(&convexHullShape1, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0);
690
//cellDmaWaitTagStatusAll(DMA_MASK(1));
693
if ( btLikely( wuInput->m_shapeType0 == CONVEX_HULL_SHAPE_PROXYTYPE ) )
695
cellDmaWaitTagStatusAll(DMA_MASK(1));
696
dmaConvexVertexData (&lsMemPtr->convexVertexData[0], (btConvexHullShape*)&convexHullShape0);
697
lsMemPtr->convexVertexData[0].gSpuConvexShapePtr = wuInput->m_spuCollisionShapes[0];
701
if ( btLikely( wuInput->m_shapeType1 == CONVEX_HULL_SHAPE_PROXYTYPE ) )
703
cellDmaWaitTagStatusAll(DMA_MASK(1));
704
dmaConvexVertexData (&lsMemPtr->convexVertexData[1], (btConvexHullShape*)&convexHullShape1);
705
lsMemPtr->convexVertexData[1].gSpuConvexShapePtr = wuInput->m_spuCollisionShapes[1];
709
btConvexPointCloudShape cpc0,cpc1;
711
if ( btLikely( wuInput->m_shapeType0 == CONVEX_HULL_SHAPE_PROXYTYPE ) )
713
cellDmaWaitTagStatusAll(DMA_MASK(2));
714
lsMemPtr->convexVertexData[0].gConvexPoints = &lsMemPtr->convexVertexData[0].g_convexPointBuffer[0];
715
btConvexHullShape* ch = (btConvexHullShape*)wuInput->m_spuCollisionShapes[0];
716
const btVector3& localScaling = ch->getLocalScalingNV();
717
cpc0.setPoints(lsMemPtr->convexVertexData[0].gConvexPoints,lsMemPtr->convexVertexData[0].gNumConvexPoints,false,localScaling);
718
wuInput->m_spuCollisionShapes[0] = &cpc0;
721
if ( btLikely( wuInput->m_shapeType1 == CONVEX_HULL_SHAPE_PROXYTYPE ) )
723
cellDmaWaitTagStatusAll(DMA_MASK(2));
724
lsMemPtr->convexVertexData[1].gConvexPoints = &lsMemPtr->convexVertexData[1].g_convexPointBuffer[0];
725
btConvexHullShape* ch = (btConvexHullShape*)wuInput->m_spuCollisionShapes[1];
726
const btVector3& localScaling = ch->getLocalScalingNV();
727
cpc1.setPoints(lsMemPtr->convexVertexData[1].gConvexPoints,lsMemPtr->convexVertexData[1].gNumConvexPoints,false,localScaling);
728
wuInput->m_spuCollisionShapes[1] = &cpc1;
733
const btConvexShape* shape0Ptr = (const btConvexShape*)wuInput->m_spuCollisionShapes[0];
734
const btConvexShape* shape1Ptr = (const btConvexShape*)wuInput->m_spuCollisionShapes[1];
735
int shapeType0 = wuInput->m_shapeType0;
736
int shapeType1 = wuInput->m_shapeType1;
737
float marginA = wuInput->m_collisionMargin0;
738
float marginB = wuInput->m_collisionMargin1;
740
SpuClosestPointInput cpInput;
741
cpInput.m_convexVertexData[0] = &lsMemPtr->convexVertexData[0];
742
cpInput.m_convexVertexData[1] = &lsMemPtr->convexVertexData[1];
743
cpInput.m_transformA = wuInput->m_worldTransform0;
744
cpInput.m_transformB = wuInput->m_worldTransform1;
745
float sumMargin = (marginA+marginB+lsMemPtr->getContactManifoldPtr()->getContactBreakingThreshold());
746
cpInput.m_maximumDistanceSquared = sumMargin * sumMargin;
748
ppu_address_t manifoldAddress = (ppu_address_t)manifold;
750
btPersistentManifold* spuManifold=lsMemPtr->getContactManifoldPtr();
751
//spuContacts.setContactInfo(spuManifold,manifoldAddress,wuInput->m_worldTransform0,wuInput->m_worldTransform1,wuInput->m_isSwapped);
752
spuContacts.setContactInfo(spuManifold,manifoldAddress,lsMemPtr->getColObj0()->getWorldTransform(),
753
lsMemPtr->getColObj1()->getWorldTransform(),
754
lsMemPtr->getColObj0()->getRestitution(),lsMemPtr->getColObj1()->getRestitution(),
755
lsMemPtr->getColObj0()->getFriction(),lsMemPtr->getColObj1()->getFriction(),
756
wuInput->m_isSwapped);
759
btGjkPairDetector gjk(shape0Ptr,shape1Ptr,shapeType0,shapeType1,marginA,marginB,&simplexSolver,penetrationSolver);//&vsSolver,penetrationSolver);
760
gjk.getClosestPoints(cpInput,spuContacts,0);//,debugDraw);
762
stats[gjk.m_lastUsedMethod]++;
763
degenerateStats[gjk.m_degenerateSimplex]++;
765
#ifdef USE_SEPDISTANCE_UTIL
766
btScalar sepDist = gjk.getCachedSeparatingDistance()+spuManifold->getContactBreakingThreshold();
767
lsMemPtr->getlocalCollisionAlgorithm()->m_sepDistance.initSeparatingDistance(gjk.getCachedSeparatingAxis(),sepDist,wuInput->m_worldTransform0,wuInput->m_worldTransform1);
768
lsMemPtr->needsDmaPutContactManifoldAlgo = true;
769
#endif //USE_SEPDISTANCE_UTIL
779
template<typename T> void DoSwap(T& a, T& b)
782
memcpy(tmp, &a, sizeof(T));
783
memcpy(&a, &b, sizeof(T));
784
memcpy(&b, tmp, sizeof(T));
787
SIMD_FORCE_INLINE void dmaAndSetupCollisionObjects(SpuCollisionPairInput& collisionPairInput, CollisionTask_LocalStoreMemory& lsMem)
789
register int dmaSize;
790
register ppu_address_t dmaPpuAddress2;
792
dmaSize = sizeof(btCollisionObject);//btTransform);
793
dmaPpuAddress2 = /*collisionPairInput.m_isSwapped ? (ppu_address_t)lsMem.gProxyPtr1->m_clientObject :*/ (ppu_address_t)lsMem.getlocalCollisionAlgorithm()->getCollisionObject0();
794
lsMem.m_lsColObj0Ptr = (btCollisionObject*)cellDmaGetReadOnly(&lsMem.gColObj0Buffer, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0);
796
dmaSize = sizeof(btCollisionObject);//btTransform);
797
dmaPpuAddress2 = /*collisionPairInput.m_isSwapped ? (ppu_address_t)lsMem.gProxyPtr0->m_clientObject :*/ (ppu_address_t)lsMem.getlocalCollisionAlgorithm()->getCollisionObject1();
798
lsMem.m_lsColObj1Ptr = (btCollisionObject*)cellDmaGetReadOnly(&lsMem.gColObj1Buffer, dmaPpuAddress2 , dmaSize, DMA_TAG(2), 0, 0);
800
cellDmaWaitTagStatusAll(DMA_MASK(1) | DMA_MASK(2));
802
btCollisionObject* ob0 = lsMem.getColObj0();
803
btCollisionObject* ob1 = lsMem.getColObj1();
805
collisionPairInput.m_worldTransform0 = ob0->getWorldTransform();
806
collisionPairInput.m_worldTransform1 = ob1->getWorldTransform();
811
void handleCollisionPair(SpuCollisionPairInput& collisionPairInput, CollisionTask_LocalStoreMemory& lsMem,
812
SpuContactResult &spuContacts,
813
ppu_address_t collisionShape0Ptr, void* collisionShape0Loc,
814
ppu_address_t collisionShape1Ptr, void* collisionShape1Loc, bool dmaShapes = true)
817
if (btBroadphaseProxy::isConvex(collisionPairInput.m_shapeType0)
818
&& btBroadphaseProxy::isConvex(collisionPairInput.m_shapeType1))
822
dmaCollisionShape (collisionShape0Loc, collisionShape0Ptr, 1, collisionPairInput.m_shapeType0);
823
dmaCollisionShape (collisionShape1Loc, collisionShape1Ptr, 2, collisionPairInput.m_shapeType1);
824
cellDmaWaitTagStatusAll(DMA_MASK(1) | DMA_MASK(2));
827
btConvexInternalShape* spuConvexShape0 = (btConvexInternalShape*)collisionShape0Loc;
828
btConvexInternalShape* spuConvexShape1 = (btConvexInternalShape*)collisionShape1Loc;
830
btVector3 dim0 = spuConvexShape0->getImplicitShapeDimensions();
831
btVector3 dim1 = spuConvexShape1->getImplicitShapeDimensions();
833
collisionPairInput.m_primitiveDimensions0 = dim0;
834
collisionPairInput.m_primitiveDimensions1 = dim1;
835
collisionPairInput.m_collisionShapes[0] = collisionShape0Ptr;
836
collisionPairInput.m_collisionShapes[1] = collisionShape1Ptr;
837
collisionPairInput.m_spuCollisionShapes[0] = spuConvexShape0;
838
collisionPairInput.m_spuCollisionShapes[1] = spuConvexShape1;
839
ProcessSpuConvexConvexCollision(&collisionPairInput,&lsMem,spuContacts);
841
else if (btBroadphaseProxy::isCompound(collisionPairInput.m_shapeType0) &&
842
btBroadphaseProxy::isCompound(collisionPairInput.m_shapeType1))
846
dmaCollisionShape (collisionShape0Loc, collisionShape0Ptr, 1, collisionPairInput.m_shapeType0);
847
dmaCollisionShape (collisionShape1Loc, collisionShape1Ptr, 2, collisionPairInput.m_shapeType1);
848
cellDmaWaitTagStatusAll(DMA_MASK(1) | DMA_MASK(2));
850
// Both are compounds, do N^2 CD for now
851
///@todo: add some AABB-based pruning (probably not -> slower)
853
btCompoundShape* spuCompoundShape0 = (btCompoundShape*)collisionShape0Loc;
854
btCompoundShape* spuCompoundShape1 = (btCompoundShape*)collisionShape1Loc;
856
dmaCompoundShapeInfo (&lsMem.compoundShapeData[0], spuCompoundShape0, 1);
857
dmaCompoundShapeInfo (&lsMem.compoundShapeData[1], spuCompoundShape1, 2);
858
cellDmaWaitTagStatusAll(DMA_MASK(1) | DMA_MASK(2));
861
dmaCompoundSubShapes (&lsMem.compoundShapeData[0], spuCompoundShape0, 1);
862
cellDmaWaitTagStatusAll(DMA_MASK(1));
863
dmaCompoundSubShapes (&lsMem.compoundShapeData[1], spuCompoundShape1, 1);
864
cellDmaWaitTagStatusAll(DMA_MASK(1));
866
int childShapeCount0 = spuCompoundShape0->getNumChildShapes();
867
btAssert(childShapeCount0< MAX_SPU_COMPOUND_SUBSHAPES);
868
int childShapeCount1 = spuCompoundShape1->getNumChildShapes();
869
btAssert(childShapeCount1< MAX_SPU_COMPOUND_SUBSHAPES);
872
for (int i = 0; i < childShapeCount0; ++i)
874
btCompoundShapeChild& childShape0 = lsMem.compoundShapeData[0].gSubshapes[i];
875
btAssert(!btBroadphaseProxy::isCompound(childShape0.m_childShapeType));
877
for (int j = 0; j < childShapeCount1; ++j)
879
btCompoundShapeChild& childShape1 = lsMem.compoundShapeData[1].gSubshapes[j];
880
btAssert(!btBroadphaseProxy::isCompound(childShape1.m_childShapeType));
883
/* Create a new collision pair input struct using the two child shapes */
884
SpuCollisionPairInput cinput (collisionPairInput);
886
cinput.m_worldTransform0 = collisionPairInput.m_worldTransform0 * childShape0.m_transform;
887
cinput.m_shapeType0 = childShape0.m_childShapeType;
888
cinput.m_collisionMargin0 = childShape0.m_childMargin;
890
cinput.m_worldTransform1 = collisionPairInput.m_worldTransform1 * childShape1.m_transform;
891
cinput.m_shapeType1 = childShape1.m_childShapeType;
892
cinput.m_collisionMargin1 = childShape1.m_childMargin;
893
/* Recursively call handleCollisionPair () with new collision pair input */
895
handleCollisionPair(cinput, lsMem, spuContacts,
896
(ppu_address_t)childShape0.m_childShape, lsMem.compoundShapeData[0].gSubshapeShape[i],
897
(ppu_address_t)childShape1.m_childShape, lsMem.compoundShapeData[1].gSubshapeShape[j], false);
901
else if (btBroadphaseProxy::isCompound(collisionPairInput.m_shapeType0) )
905
dmaCollisionShape (collisionShape0Loc, collisionShape0Ptr, 1, collisionPairInput.m_shapeType0);
906
dmaCollisionShape (collisionShape1Loc, collisionShape1Ptr, 2, collisionPairInput.m_shapeType1);
907
cellDmaWaitTagStatusAll(DMA_MASK(1) | DMA_MASK(2));
909
// object 0 compound, object 1 non-compound
910
btCompoundShape* spuCompoundShape = (btCompoundShape*)collisionShape0Loc;
911
dmaCompoundShapeInfo (&lsMem.compoundShapeData[0], spuCompoundShape, 1);
912
cellDmaWaitTagStatusAll(DMA_MASK(1));
914
int childShapeCount = spuCompoundShape->getNumChildShapes();
915
btAssert(childShapeCount< MAX_SPU_COMPOUND_SUBSHAPES);
917
for (int i = 0; i < childShapeCount; ++i)
919
btCompoundShapeChild& childShape = lsMem.compoundShapeData[0].gSubshapes[i];
920
btAssert(!btBroadphaseProxy::isCompound(childShape.m_childShapeType));
921
// Dma the child shape
922
dmaCollisionShape (&lsMem.compoundShapeData[0].gSubshapeShape[i], (ppu_address_t)childShape.m_childShape, 1, childShape.m_childShapeType);
923
cellDmaWaitTagStatusAll(DMA_MASK(1));
925
SpuCollisionPairInput cinput (collisionPairInput);
926
cinput.m_worldTransform0 = collisionPairInput.m_worldTransform0 * childShape.m_transform;
927
cinput.m_shapeType0 = childShape.m_childShapeType;
928
cinput.m_collisionMargin0 = childShape.m_childMargin;
930
handleCollisionPair(cinput, lsMem, spuContacts,
931
(ppu_address_t)childShape.m_childShape, lsMem.compoundShapeData[0].gSubshapeShape[i],
932
collisionShape1Ptr, collisionShape1Loc, false);
935
else if (btBroadphaseProxy::isCompound(collisionPairInput.m_shapeType1) )
939
dmaCollisionShape (collisionShape0Loc, collisionShape0Ptr, 1, collisionPairInput.m_shapeType0);
940
dmaCollisionShape (collisionShape1Loc, collisionShape1Ptr, 2, collisionPairInput.m_shapeType1);
941
cellDmaWaitTagStatusAll(DMA_MASK(1) | DMA_MASK(2));
942
// object 0 non-compound, object 1 compound
943
btCompoundShape* spuCompoundShape = (btCompoundShape*)collisionShape1Loc;
944
dmaCompoundShapeInfo (&lsMem.compoundShapeData[0], spuCompoundShape, 1);
945
cellDmaWaitTagStatusAll(DMA_MASK(1));
947
int childShapeCount = spuCompoundShape->getNumChildShapes();
948
btAssert(childShapeCount< MAX_SPU_COMPOUND_SUBSHAPES);
951
for (int i = 0; i < childShapeCount; ++i)
953
btCompoundShapeChild& childShape = lsMem.compoundShapeData[0].gSubshapes[i];
954
btAssert(!btBroadphaseProxy::isCompound(childShape.m_childShapeType));
955
// Dma the child shape
956
dmaCollisionShape (&lsMem.compoundShapeData[0].gSubshapeShape[i], (ppu_address_t)childShape.m_childShape, 1, childShape.m_childShapeType);
957
cellDmaWaitTagStatusAll(DMA_MASK(1));
959
SpuCollisionPairInput cinput (collisionPairInput);
960
cinput.m_worldTransform1 = collisionPairInput.m_worldTransform1 * childShape.m_transform;
961
cinput.m_shapeType1 = childShape.m_childShapeType;
962
cinput.m_collisionMargin1 = childShape.m_childMargin;
963
handleCollisionPair(cinput, lsMem, spuContacts,
964
collisionShape0Ptr, collisionShape0Loc,
965
(ppu_address_t)childShape.m_childShape, lsMem.compoundShapeData[0].gSubshapeShape[i], false);
971
//a non-convex shape is involved
972
bool handleConvexConcave = false;
976
if (btBroadphaseProxy::isConcave(collisionPairInput.m_shapeType0) &&
977
btBroadphaseProxy::isConvex(collisionPairInput.m_shapeType1))
980
DoSwap(collisionShape0Ptr, collisionShape1Ptr);
981
DoSwap(collisionShape0Loc, collisionShape1Loc);
982
DoSwap(collisionPairInput.m_shapeType0, collisionPairInput.m_shapeType1);
983
DoSwap(collisionPairInput.m_worldTransform0, collisionPairInput.m_worldTransform1);
984
DoSwap(collisionPairInput.m_collisionMargin0, collisionPairInput.m_collisionMargin1);
986
collisionPairInput.m_isSwapped = true;
989
if (btBroadphaseProxy::isConvex(collisionPairInput.m_shapeType0)&&
990
btBroadphaseProxy::isConcave(collisionPairInput.m_shapeType1))
992
handleConvexConcave = true;
994
if (handleConvexConcave)
998
dmaCollisionShape (collisionShape0Loc, collisionShape0Ptr, 1, collisionPairInput.m_shapeType0);
999
dmaCollisionShape (collisionShape1Loc, collisionShape1Ptr, 2, collisionPairInput.m_shapeType1);
1000
cellDmaWaitTagStatusAll(DMA_MASK(1) | DMA_MASK(2));
1003
if (collisionPairInput.m_shapeType1 == STATIC_PLANE_PROXYTYPE)
1005
btConvexInternalShape* spuConvexShape0 = (btConvexInternalShape*)collisionShape0Loc;
1006
btStaticPlaneShape* planeShape= (btStaticPlaneShape*)collisionShape1Loc;
1008
btVector3 dim0 = spuConvexShape0->getImplicitShapeDimensions();
1009
collisionPairInput.m_primitiveDimensions0 = dim0;
1010
collisionPairInput.m_collisionShapes[0] = collisionShape0Ptr;
1011
collisionPairInput.m_collisionShapes[1] = collisionShape1Ptr;
1012
collisionPairInput.m_spuCollisionShapes[0] = spuConvexShape0;
1013
collisionPairInput.m_spuCollisionShapes[1] = planeShape;
1015
ProcessConvexPlaneSpuCollision(&collisionPairInput,&lsMem,spuContacts);
1018
btConvexInternalShape* spuConvexShape0 = (btConvexInternalShape*)collisionShape0Loc;
1019
btBvhTriangleMeshShape* trimeshShape = (btBvhTriangleMeshShape*)collisionShape1Loc;
1021
btVector3 dim0 = spuConvexShape0->getImplicitShapeDimensions();
1022
collisionPairInput.m_primitiveDimensions0 = dim0;
1023
collisionPairInput.m_collisionShapes[0] = collisionShape0Ptr;
1024
collisionPairInput.m_collisionShapes[1] = collisionShape1Ptr;
1025
collisionPairInput.m_spuCollisionShapes[0] = spuConvexShape0;
1026
collisionPairInput.m_spuCollisionShapes[1] = trimeshShape;
1028
ProcessConvexConcaveSpuCollision(&collisionPairInput,&lsMem,spuContacts);
1034
spuContacts.flush();
1039
void processCollisionTask(void* userPtr, void* lsMemPtr)
1042
SpuGatherAndProcessPairsTaskDesc* taskDescPtr = (SpuGatherAndProcessPairsTaskDesc*)userPtr;
1043
SpuGatherAndProcessPairsTaskDesc& taskDesc = *taskDescPtr;
1044
CollisionTask_LocalStoreMemory* colMemPtr = (CollisionTask_LocalStoreMemory*)lsMemPtr;
1045
CollisionTask_LocalStoreMemory& lsMem = *(colMemPtr);
1047
gUseEpa = taskDesc.m_useEpa;
1049
// spu_printf("taskDescPtr=%llx\n",taskDescPtr);
1051
SpuContactResult spuContacts;
1053
////////////////////
1055
ppu_address_t dmaInPtr = taskDesc.m_inPairPtr;
1056
unsigned int numPages = taskDesc.numPages;
1057
unsigned int numOnLastPage = taskDesc.numOnLastPage;
1059
// prefetch first set of inputs and wait
1060
lsMem.g_workUnitTaskBuffers.init();
1062
unsigned int nextNumOnPage = (numPages > 1)? MIDPHASE_NUM_WORKUNITS_PER_PAGE : numOnLastPage;
1063
lsMem.g_workUnitTaskBuffers.backBufferDmaGet(dmaInPtr, nextNumOnPage*sizeof(SpuGatherAndProcessWorkUnitInput), DMA_TAG(3));
1064
dmaInPtr += MIDPHASE_WORKUNIT_PAGE_SIZE;
1067
register unsigned char *inputPtr;
1068
register unsigned int numOnPage;
1069
register unsigned int j;
1070
SpuGatherAndProcessWorkUnitInput* wuInputs;
1071
register int dmaSize;
1072
register ppu_address_t dmaPpuAddress;
1073
register ppu_address_t dmaPpuAddress2;
1077
SpuCollisionPairInput collisionPairInput;
1079
for (unsigned int i = 0; btLikely(i < numPages); i++)
1082
// wait for back buffer dma and swap buffers
1083
inputPtr = lsMem.g_workUnitTaskBuffers.swapBuffers();
1085
// number on current page is number prefetched last iteration
1086
numOnPage = nextNumOnPage;
1089
// prefetch next set of inputs
1090
#if MIDPHASE_NUM_WORKUNIT_PAGES > 2
1091
if ( btLikely( i < numPages-1 ) )
1093
if ( btUnlikely( i < numPages-1 ) )
1096
nextNumOnPage = (i == numPages-2)? numOnLastPage : MIDPHASE_NUM_WORKUNITS_PER_PAGE;
1097
lsMem.g_workUnitTaskBuffers.backBufferDmaGet(dmaInPtr, nextNumOnPage*sizeof(SpuGatherAndProcessWorkUnitInput), DMA_TAG(3));
1098
dmaInPtr += MIDPHASE_WORKUNIT_PAGE_SIZE;
1101
wuInputs = reinterpret_cast<SpuGatherAndProcessWorkUnitInput *>(inputPtr);
1104
for (j = 0; btLikely( j < numOnPage ); j++)
1106
#ifdef DEBUG_SPU_COLLISION_DETECTION
1107
// printMidphaseInput(&wuInputs[j]);
1108
#endif //DEBUG_SPU_COLLISION_DETECTION
1111
numPairs = wuInputs[j].m_endIndex - wuInputs[j].m_startIndex;
1113
if ( btLikely( numPairs ) )
1115
dmaSize = numPairs*sizeof(btBroadphasePair);
1116
dmaPpuAddress = wuInputs[j].m_pairArrayPtr+wuInputs[j].m_startIndex * sizeof(btBroadphasePair);
1117
lsMem.m_pairsPointer = (btBroadphasePair*)cellDmaGetReadOnly(&lsMem.gBroadphasePairsBuffer, dmaPpuAddress , dmaSize, DMA_TAG(1), 0, 0);
1118
cellDmaWaitTagStatusAll(DMA_MASK(1));
1121
for (p=0;p<numPairs;p++)
1124
//for each broadphase pair, do something
1126
btBroadphasePair& pair = lsMem.getBroadphasePairPtr()[p];
1127
#ifdef DEBUG_SPU_COLLISION_DETECTION
1128
spu_printf("pair->m_userInfo = %d\n",pair.m_userInfo);
1129
spu_printf("pair->m_algorithm = %d\n",pair.m_algorithm);
1130
spu_printf("pair->m_pProxy0 = %d\n",pair.m_pProxy0);
1131
spu_printf("pair->m_pProxy1 = %d\n",pair.m_pProxy1);
1132
#endif //DEBUG_SPU_COLLISION_DETECTION
1134
if (pair.m_internalTmpValue == 2 && pair.m_algorithm && pair.m_pProxy0 && pair.m_pProxy1)
1136
dmaSize = sizeof(SpuContactManifoldCollisionAlgorithm);
1137
dmaPpuAddress2 = (ppu_address_t)pair.m_algorithm;
1138
lsMem.m_lsCollisionAlgorithmPtr = (SpuContactManifoldCollisionAlgorithm*)cellDmaGetReadOnly(&lsMem.gSpuContactManifoldAlgoBuffer, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0);
1140
cellDmaWaitTagStatusAll(DMA_MASK(1));
1142
lsMem.needsDmaPutContactManifoldAlgo = false;
1144
collisionPairInput.m_persistentManifoldPtr = (ppu_address_t) lsMem.getlocalCollisionAlgorithm()->getContactManifoldPtr();
1145
collisionPairInput.m_isSwapped = false;
1150
///can wait on the combined DMA_MASK, or dma on the same tag
1153
#ifdef DEBUG_SPU_COLLISION_DETECTION
1154
// spu_printf("SPU collisionPairInput->m_shapeType0 = %d\n",collisionPairInput->m_shapeType0);
1155
// spu_printf("SPU collisionPairInput->m_shapeType1 = %d\n",collisionPairInput->m_shapeType1);
1156
#endif //DEBUG_SPU_COLLISION_DETECTION
1159
dmaSize = sizeof(btPersistentManifold);
1161
dmaPpuAddress2 = collisionPairInput.m_persistentManifoldPtr;
1162
lsMem.m_lsManifoldPtr = (btPersistentManifold*)cellDmaGetReadOnly(&lsMem.gPersistentManifoldBuffer, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0);
1164
collisionPairInput.m_shapeType0 = lsMem.getlocalCollisionAlgorithm()->getShapeType0();
1165
collisionPairInput.m_shapeType1 = lsMem.getlocalCollisionAlgorithm()->getShapeType1();
1166
collisionPairInput.m_collisionMargin0 = lsMem.getlocalCollisionAlgorithm()->getCollisionMargin0();
1167
collisionPairInput.m_collisionMargin1 = lsMem.getlocalCollisionAlgorithm()->getCollisionMargin1();
1171
//??cellDmaWaitTagStatusAll(DMA_MASK(1));
1178
// Get the collision objects
1179
dmaAndSetupCollisionObjects(collisionPairInput, lsMem);
1181
if (lsMem.getColObj0()->isActive() || lsMem.getColObj1()->isActive())
1184
lsMem.needsDmaPutContactManifoldAlgo = true;
1185
#ifdef USE_SEPDISTANCE_UTIL
1186
lsMem.getlocalCollisionAlgorithm()->m_sepDistance.updateSeparatingDistance(collisionPairInput.m_worldTransform0,collisionPairInput.m_worldTransform1);
1187
#endif //USE_SEPDISTANCE_UTIL
1189
#define USE_DEDICATED_BOX_BOX 1
1190
#ifdef USE_DEDICATED_BOX_BOX
1191
bool boxbox = ((lsMem.getlocalCollisionAlgorithm()->getShapeType0()==BOX_SHAPE_PROXYTYPE)&&
1192
(lsMem.getlocalCollisionAlgorithm()->getShapeType1()==BOX_SHAPE_PROXYTYPE));
1195
//spu_printf("boxbox dist = %f\n",distance);
1196
btPersistentManifold* spuManifold=lsMem.getContactManifoldPtr();
1197
btPersistentManifold* manifold = (btPersistentManifold*)collisionPairInput.m_persistentManifoldPtr;
1198
ppu_address_t manifoldAddress = (ppu_address_t)manifold;
1200
spuContacts.setContactInfo(spuManifold,manifoldAddress,lsMem.getColObj0()->getWorldTransform(),
1201
lsMem.getColObj1()->getWorldTransform(),
1202
lsMem.getColObj0()->getRestitution(),lsMem.getColObj1()->getRestitution(),
1203
lsMem.getColObj0()->getFriction(),lsMem.getColObj1()->getFriction(),
1204
collisionPairInput.m_isSwapped);
1207
//float distance=0.f;
1208
btVector3 normalInB;
1212
#ifdef USE_SEPDISTANCE_UTIL
1213
lsMem.getlocalCollisionAlgorithm()->m_sepDistance.getConservativeSeparatingDistance()<=0.f
1219
//#define USE_PE_BOX_BOX 1
1220
#ifdef USE_PE_BOX_BOX
1223
//getCollisionMargin0
1224
btScalar margin0 = lsMem.getlocalCollisionAlgorithm()->getCollisionMargin0();
1225
btScalar margin1 = lsMem.getlocalCollisionAlgorithm()->getCollisionMargin1();
1226
btVector3 shapeDim0 = lsMem.getlocalCollisionAlgorithm()->getShapeDimensions0()+btVector3(margin0,margin0,margin0);
1227
btVector3 shapeDim1 = lsMem.getlocalCollisionAlgorithm()->getShapeDimensions1()+btVector3(margin1,margin1,margin1);
1229
//Box boxA(shapeDim0.getX(),shapeDim0.getY(),shapeDim0.getZ());
1230
vmVector3 vmPos0 = getVmVector3(collisionPairInput.m_worldTransform0.getOrigin());
1231
vmVector3 vmPos1 = getVmVector3(collisionPairInput.m_worldTransform1.getOrigin());
1232
vmMatrix3 vmMatrix0 = getVmMatrix3(collisionPairInput.m_worldTransform0.getBasis());
1233
vmMatrix3 vmMatrix1 = getVmMatrix3(collisionPairInput.m_worldTransform1.getBasis());
1235
vmTransform3 transformA(vmMatrix0,vmPos0);
1236
Box boxB(shapeDim1.getX(),shapeDim1.getY(),shapeDim1.getZ());
1237
vmTransform3 transformB(vmMatrix1,vmPos1);
1238
BoxPoint resultClosestBoxPointA;
1239
BoxPoint resultClosestBoxPointB;
1240
vmVector3 resultNormal;
1243
#ifdef USE_SEPDISTANCE_UTIL
1244
float distanceThreshold = FLT_MAX
1246
//float distanceThreshold = 0.f;
1252
vmVector3 hA(shapeDim0.getX(),shapeDim0.getY(),shapeDim0.getZ());
1253
vmVector3 hB(shapeDim1.getX(),shapeDim1.getY(),shapeDim1.getZ());
1256
trA.setTranslation(getVmVector3(collisionPairInput.m_worldTransform0.getOrigin()));
1257
trA.setUpper3x3(getVmMatrix3(collisionPairInput.m_worldTransform0.getBasis()));
1261
trB.setTranslation(getVmVector3(collisionPairInput.m_worldTransform1.getOrigin()));
1262
trB.setUpper3x3(getVmMatrix3(collisionPairInput.m_worldTransform1.getBasis()));
1264
float distanceThreshold = spuManifold->getContactBreakingThreshold();//0.001f;
1268
float dist = boxBoxDistance(n, ptA, ptB,
1269
boxA, trA, boxB, trB,
1270
distanceThreshold );
1273
// float distance = boxBoxDistance(resultNormal,resultClosestBoxPointA,resultClosestBoxPointB, boxA, transformA, boxB,transformB,distanceThreshold);
1275
normalInB = -getBtVector3(n);//resultNormal);
1277
//if(dist < distanceThreshold)//spuManifold->getContactBreakingThreshold())
1278
if(dist < spuManifold->getContactBreakingThreshold())
1280
btVector3 pointOnB = collisionPairInput.m_worldTransform1(getBtVector3(ptB.localPoint));
1282
spuContacts.addContactPoint(
1291
btScalar margin0 = lsMem.getlocalCollisionAlgorithm()->getCollisionMargin0();
1292
btScalar margin1 = lsMem.getlocalCollisionAlgorithm()->getCollisionMargin1();
1293
btVector3 shapeDim0 = lsMem.getlocalCollisionAlgorithm()->getShapeDimensions0()+btVector3(margin0,margin0,margin0);
1294
btVector3 shapeDim1 = lsMem.getlocalCollisionAlgorithm()->getShapeDimensions1()+btVector3(margin1,margin1,margin1);
1297
btBoxShape box0(shapeDim0);
1298
btBoxShape box1(shapeDim1);
1300
struct SpuBridgeContactCollector : public btDiscreteCollisionDetectorInterface::Result
1302
SpuContactResult& m_spuContacts;
1304
virtual void setShapeIdentifiersA(int partId0,int index0)
1306
m_spuContacts.setShapeIdentifiersA(partId0,index0);
1308
virtual void setShapeIdentifiersB(int partId1,int index1)
1310
m_spuContacts.setShapeIdentifiersB(partId1,index1);
1312
virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth)
1314
m_spuContacts.addContactPoint(normalOnBInWorld,pointInWorld,depth);
1317
SpuBridgeContactCollector(SpuContactResult& spuContacts)
1318
:m_spuContacts(spuContacts)
1324
SpuBridgeContactCollector bridgeOutput(spuContacts);
1326
btDiscreteCollisionDetectorInterface::ClosestPointInput input;
1327
input.m_maximumDistanceSquared = BT_LARGE_FLOAT;
1328
input.m_transformA = collisionPairInput.m_worldTransform0;
1329
input.m_transformB = collisionPairInput.m_worldTransform1;
1331
btBoxBoxDetector detector(&box0,&box1);
1333
detector.getClosestPoints(input,bridgeOutput,0);
1336
#endif //USE_PE_BOX_BOX
1338
lsMem.needsDmaPutContactManifoldAlgo = true;
1339
#ifdef USE_SEPDISTANCE_UTIL
1340
btScalar sepDist2 = distance+spuManifold->getContactBreakingThreshold();
1341
lsMem.getlocalCollisionAlgorithm()->m_sepDistance.initSeparatingDistance(normalInB,sepDist2,collisionPairInput.m_worldTransform0,collisionPairInput.m_worldTransform1);
1342
#endif //USE_SEPDISTANCE_UTIL
1349
spuContacts.flush();
1353
#endif //USE_DEDICATED_BOX_BOX
1356
#ifdef USE_SEPDISTANCE_UTIL
1357
lsMem.getlocalCollisionAlgorithm()->m_sepDistance.getConservativeSeparatingDistance()<=0.f
1360
#endif //USE_SEPDISTANCE_UTIL
1363
handleCollisionPair(collisionPairInput, lsMem, spuContacts,
1364
(ppu_address_t)lsMem.getColObj0()->getRootCollisionShape(), &lsMem.gCollisionShapes[0].collisionShape,
1365
(ppu_address_t)lsMem.getColObj1()->getRootCollisionShape(), &lsMem.gCollisionShapes[1].collisionShape);
1368
//spu_printf("boxbox dist = %f\n",distance);
1369
btPersistentManifold* spuManifold=lsMem.getContactManifoldPtr();
1370
btPersistentManifold* manifold = (btPersistentManifold*)collisionPairInput.m_persistentManifoldPtr;
1371
ppu_address_t manifoldAddress = (ppu_address_t)manifold;
1373
spuContacts.setContactInfo(spuManifold,manifoldAddress,lsMem.getColObj0()->getWorldTransform(),
1374
lsMem.getColObj1()->getWorldTransform(),
1375
lsMem.getColObj0()->getRestitution(),lsMem.getColObj1()->getRestitution(),
1376
lsMem.getColObj0()->getFriction(),lsMem.getColObj1()->getFriction(),
1377
collisionPairInput.m_isSwapped);
1379
spuContacts.flush();
1388
#ifdef USE_SEPDISTANCE_UTIL
1389
#if defined (__SPU__) || defined (USE_LIBSPE2)
1390
if (lsMem.needsDmaPutContactManifoldAlgo)
1392
dmaSize = sizeof(SpuContactManifoldCollisionAlgorithm);
1393
dmaPpuAddress2 = (ppu_address_t)pair.m_algorithm;
1394
cellDmaLargePut(&lsMem.gSpuContactManifoldAlgoBuffer, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0);
1395
cellDmaWaitTagStatusAll(DMA_MASK(1));
1398
#endif //#ifdef USE_SEPDISTANCE_UTIL
1403
} //end for (j = 0; j < numOnPage; j++)