BulletMultiThreaded (SPU/multi-core): added compound shape support and concave-convex (swapped case). Thanks to Marten Svanfeldt

This commit is contained in:
ejcoumans
2007-08-02 20:16:58 +00:00
parent 8a1d556e93
commit 5279f9e129
6 changed files with 1040 additions and 779 deletions

View File

@@ -45,7 +45,8 @@ bool SpuGatheringCollisionDispatcher::supportsDispatchPairOnSpu(int proxyType0,i
(proxyType0 == CYLINDER_SHAPE_PROXYTYPE) ||
// (proxyType0 == CONE_SHAPE_PROXYTYPE) ||
(proxyType0 == TRIANGLE_MESH_SHAPE_PROXYTYPE) ||
(proxyType0 == CONVEX_HULL_SHAPE_PROXYTYPE)
(proxyType0 == CONVEX_HULL_SHAPE_PROXYTYPE)||
(proxyType0 == COMPOUND_SHAPE_PROXYTYPE)
);
bool supported1 = (
@@ -56,7 +57,8 @@ bool SpuGatheringCollisionDispatcher::supportsDispatchPairOnSpu(int proxyType0,i
(proxyType1 == CYLINDER_SHAPE_PROXYTYPE) ||
// (proxyType1 == CONE_SHAPE_PROXYTYPE) ||
(proxyType1 == TRIANGLE_MESH_SHAPE_PROXYTYPE) ||
(proxyType1 == CONVEX_HULL_SHAPE_PROXYTYPE)
(proxyType1 == CONVEX_HULL_SHAPE_PROXYTYPE) ||
(proxyType1 == COMPOUND_SHAPE_PROXYTYPE)
);
return supported0 && supported1;

View File

@@ -34,13 +34,14 @@ SpuContactResult::SpuContactResult()
g_manifoldDmaExport.swapBuffers();
}
void SpuContactResult::setContactInfo(btPersistentManifold* spuManifold, uint64_t manifoldAddress,const btTransform& worldTrans0,const btTransform& worldTrans1)
void SpuContactResult::setContactInfo(btPersistentManifold* spuManifold, uint64_t manifoldAddress,const btTransform& worldTrans0,const btTransform& worldTrans1, bool isSwapped)
{
// spu_printf("SpuContactResult::setContactInfo\n");
//spu_printf("SpuContactResult::setContactInfo ManifoldAddress: %lu\n", manifoldAddress);
m_rootWorldTransform0 = worldTrans0;
m_rootWorldTransform1 = worldTrans1;
m_manifoldAddress = manifoldAddress;
m_spuManifold = spuManifold;
m_isSwapped = isSwapped;
}
void SpuContactResult::setShapeIdentifiers(int partId0,int index0, int partId1,int index1)
@@ -56,8 +57,8 @@ bool ManifoldResultAddContactPoint(const btVector3& normalOnBInWorld,
float depth,
btPersistentManifold* manifoldPtr,
btTransform& transA,
btTransform& transB
)
btTransform& transB,
bool isSwapped)
{
float contactTreshold = manifoldPtr->getContactBreakingThreshold();
@@ -74,10 +75,29 @@ bool ManifoldResultAddContactPoint(const btVector3& normalOnBInWorld,
btTransform transAInv = transA.inverse();//m_body0->m_cachedInvertedWorldTransform;
btTransform transBInv= transB.inverse();//m_body1->m_cachedInvertedWorldTransform;
btVector3 pointA = pointInWorld + normalOnBInWorld * depth;
btVector3 localA = transAInv(pointA );
btVector3 localB = transBInv(pointInWorld);
btManifoldPoint newPt(localA,localB,normalOnBInWorld,depth);
btVector3 pointA;
btVector3 localA;
btVector3 localB;
btVector3 normal;
if (isSwapped)
{
normal = normalOnBInWorld * -1;
pointA = pointInWorld + normal * depth;
localA = transAInv(pointA );
localB = transBInv(pointInWorld);
/*localA = transBInv(pointA );
localB = transAInv(pointInWorld);*/
}
else
{
normal = normalOnBInWorld;
pointA = pointInWorld + normal * depth;
localA = transAInv(pointA );
localB = transBInv(pointInWorld);
}
btManifoldPoint newPt(localA,localB,normal,depth);
int insertIndex = manifoldPtr->getCacheEntry(newPt);
if (insertIndex >= 0)
@@ -128,7 +148,7 @@ void SpuContactResult::writeDoubleBufferedManifold(btPersistentManifold* lsManif
void SpuContactResult::addContactPoint(const btVector3& normalOnBInWorld,const btPoint3& pointInWorld,float depth)
{
// spu_printf("*** SpuContactResult::addContactPoint: depth = %f\n",depth);
//spu_printf("*** SpuContactResult::addContactPoint: depth = %f\n",depth);
#ifdef DEBUG_SPU_COLLISION_DETECTION
// int sman = sizeof(rage::phManifold);
@@ -146,8 +166,8 @@ void SpuContactResult::addContactPoint(const btVector3& normalOnBInWorld,const b
depth,
localManifold,
m_rootWorldTransform0,
m_rootWorldTransform1
);
m_rootWorldTransform1,
m_isSwapped);
m_RequiresWriteBack = m_RequiresWriteBack || retVal;
}
@@ -156,7 +176,9 @@ void SpuContactResult::flush()
if (m_RequiresWriteBack)
{
#ifdef DEBUG_SPU_COLLISION_DETECTION
spu_printf("SPU: Start rage::phManifold Write (Put) DMA\n");
spu_printf("SPU: Start SpuContactResult::flush (Put) DMA\n");
spu_printf("Num contacts:%d\n", m_spuManifold->getNumContacts());
spu_printf("Manifold address: %llu\n", m_manifoldAddress);
#endif //DEBUG_SPU_COLLISION_DETECTION
// spu_printf("writeDoubleBufferedManifold\n");
writeDoubleBufferedManifold(m_spuManifold, (btPersistentManifold*)m_manifoldAddress);

View File

@@ -81,6 +81,7 @@ class SpuContactResult
btPersistentManifold* m_spuManifold;
bool m_RequiresWriteBack;
bool m_isSwapped;
DoubleBuffer<btPersistentManifold, 1> g_manifoldDmaExport;
@@ -95,7 +96,7 @@ class SpuContactResult
virtual void setShapeIdentifiers(int partId0,int index0, int partId1,int index1);
void setContactInfo(btPersistentManifold* spuManifold, uint64_t manifoldAddress,const btTransform& worldTrans0,const btTransform& worldTrans1);
void setContactInfo(btPersistentManifold* spuManifold, uint64_t manifoldAddress,const btTransform& worldTrans0,const btTransform& worldTrans1, bool isSwapped = false);
void writeDoubleBufferedManifold(btPersistentManifold* lsManifold, btPersistentManifold* mmManifold);

View File

@@ -19,6 +19,7 @@
#include "BulletCollision/CollisionShapes/btConvexShape.h"
#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h"
#include "BulletCollision/CollisionShapes/btConvexHullShape.h"
#include "BulletCollision/CollisionShapes/btCompoundShape.h"
#include "SpuMinkowskiPenetrationDepthSolver.h"
#include "SpuGjkPairDetector.h"
@@ -26,6 +27,9 @@
#include "SpuLocalSupport.h" //definition of SpuConvexPolyhedronVertexData
#ifdef USE_SN_TUNER
#include <LibSN_SPU.h>
#endif //USE_SN_TUNER
#ifdef WIN32
@@ -80,13 +84,17 @@ struct CollisionTask_LocalStoreMemory
///only a single mesh part for now, we can add support for multiple parts, but quantized trees don't support this at the moment
ATTRIBUTE_ALIGNED16(btIndexedMesh gIndexMesh);
#define MAX_SPU_SUBTREE_HEADERS 32
#define MAX_SPU_SUBTREE_HEADERS 32
//1024
ATTRIBUTE_ALIGNED16(btBvhSubtreeInfo gSubtreeHeaders[MAX_SPU_SUBTREE_HEADERS]);
ATTRIBUTE_ALIGNED16(btQuantizedBvhNode gSubtreeNodes[MAX_SUBTREE_SIZE_IN_BYTES/sizeof(btQuantizedBvhNode)]);
SpuConvexPolyhedronVertexData convexVertexData;
// Compound data
#define MAX_SPU_COMPOUND_SUBSHAPES 16
ATTRIBUTE_ALIGNED16(btCompoundShapeChild gSubshapes[MAX_SPU_COMPOUND_SUBSHAPES*2]);
ATTRIBUTE_ALIGNED16(char gSubshapeShape[MAX_SPU_COMPOUND_SUBSHAPES*2][MAX_SHAPE_SIZE]);
};
@@ -147,7 +155,7 @@ void spuWalkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallback,unsigned
{
//printf("overlap with node %d\n",rootNode->getTriangleIndex());
nodeCallback->processNode(0,rootNode->getTriangleIndex());
// spu_printf("SPU: overlap detected with triangleIndex:%d\n",rootNode->getTriangleIndex());
// spu_printf("SPU: overlap detected with triangleIndex:%d\n",rootNode->getTriangleIndex());
}
if (aabbOverlap || isLeafNode)
@@ -205,7 +213,7 @@ public:
///Create a triangle on the stack, call process collision, with GJK
///DMA the vertices, can benefit from software caching
// spu_printf("processNode with triangleIndex %d\n",triangleIndex);
// spu_printf("processNode with triangleIndex %d\n",triangleIndex);
@@ -216,19 +224,19 @@ public:
small_cache_read(&m_lsMemPtr->spuIndices[1],(uint64_t)&indexBasePtr[1],sizeof(int));
small_cache_read(&m_lsMemPtr->spuIndices[2],(uint64_t)&indexBasePtr[2],sizeof(int));
// spu_printf("SPU index0=%d ,",spuIndices[0]);
// spu_printf("SPU index1=%d ,",spuIndices[1]);
// spu_printf("SPU index2=%d ,",spuIndices[2]);
// spu_printf("SPU: indexBasePtr=%llx\n",indexBasePtr);
// spu_printf("SPU index0=%d ,",spuIndices[0]);
// spu_printf("SPU index1=%d ,",spuIndices[1]);
// spu_printf("SPU index2=%d ,",spuIndices[2]);
// spu_printf("SPU: indexBasePtr=%llx\n",indexBasePtr);
const btVector3& meshScaling = m_lsMemPtr->gTriangleMeshInterface.getScaling();
for (int j=2;j>=0;j--)
{
int graphicsindex = m_lsMemPtr->spuIndices[j];
// spu_printf("SPU index=%d ,",graphicsindex);
// spu_printf("SPU index=%d ,",graphicsindex);
btScalar* graphicsbasePtr = (btScalar*)(m_lsMemPtr->gIndexMesh.m_vertexBase+graphicsindex*m_lsMemPtr->gIndexMesh.m_vertexStride);
// spu_printf("SPU graphicsbasePtr=%llx\n",graphicsbasePtr);
// spu_printf("SPU graphicsbasePtr=%llx\n",graphicsbasePtr);
///handle un-aligned vertices...
@@ -243,7 +251,7 @@ public:
spuUnscaledVertex[1]*meshScaling.getY(),
spuUnscaledVertex[2]*meshScaling.getZ());
// spu_printf("SPU:triangle vertices:%f,%f,%f\n",spuTriangleVertices[j].x(),spuTriangleVertices[j].y(),spuTriangleVertices[j].z());
// spu_printf("SPU:triangle vertices:%f,%f,%f\n",spuTriangleVertices[j].x(),spuTriangleVertices[j].y(),spuTriangleVertices[j].z());
}
@@ -257,7 +265,7 @@ public:
m_spuContacts.setShapeIdentifiers(-1,-1,subPart,triangleIndex);
// m_spuContacts.flush();
// m_spuContacts.flush();
ProcessSpuConvexConvexCollision(&triangleConcaveInput, m_lsMemPtr,m_spuContacts);
///this flush should be automatic
@@ -388,10 +396,10 @@ void ProcessConvexConcaveSpuCollision(SpuCollisionPairInput* wuInput, CollisionT
//CollisionShape* triangleShape = static_cast<btCollisionShape*>(triBody->m_collisionShape);
//convexShape->getAabb(convexInTriangleSpace,m_aabbMin,m_aabbMax);
// btScalar extraMargin = collisionMarginTriangle;
// btVector3 extra(extraMargin,extraMargin,extraMargin);
// aabbMax += extra;
// aabbMin -= extra;
// btScalar extraMargin = collisionMarginTriangle;
// btVector3 extra(extraMargin,extraMargin,extraMargin);
// aabbMax += extra;
// aabbMin -= extra;
@@ -411,7 +419,7 @@ void ProcessConvexConcaveSpuCollision(SpuCollisionPairInput* wuInput, CollisionT
//spu_printf("SPU:indexArray.size() = %d\n",indexArray.size());
// spu_printf("SPU: numSubTrees = %d\n",subTrees.size());
// spu_printf("SPU: numSubTrees = %d\n",subTrees.size());
//not likely to happen
if (subTrees.size() && indexArray.size() == 1)
{
@@ -435,12 +443,12 @@ void ProcessConvexConcaveSpuCollision(SpuCollisionPairInput* wuInput, CollisionT
{
int dmaSize = nextBatch* sizeof(btBvhSubtreeInfo);
uint64_t dmaPpuAddress2 = reinterpret_cast<uint64_t>(&subTrees[i]);
// spu_printf("&subtree[i]=%llx, dmaSize = %d\n",dmaPpuAddress2,dmaSize);
// spu_printf("&subtree[i]=%llx, dmaSize = %d\n",dmaPpuAddress2,dmaSize);
cellDmaGet(&lsMemPtr->gSubtreeHeaders[0], dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0);
cellDmaWaitTagStatusAll(DMA_MASK(1));
}
// spu_printf("nextBatch = %d\n",nextBatch);
// spu_printf("nextBatch = %d\n",nextBatch);
for (int j=0;j<nextBatch;j++)
{
@@ -469,7 +477,7 @@ void ProcessConvexConcaveSpuCollision(SpuCollisionPairInput* wuInput, CollisionT
}
// spu_printf("subtreeSize = %d\n",gSubtreeHeaders[j].m_subtreeSize);
// spu_printf("subtreeSize = %d\n",gSubtreeHeaders[j].m_subtreeSize);
}
// unsigned short int m_quantizedAabbMin[3];
@@ -532,6 +540,13 @@ int getShapeTypeSize(int shapeType)
return shapeSize;
}
case COMPOUND_SHAPE_PROXYTYPE:
{
int shapeSize = sizeof(btCompoundShape);
btAssert(shapeSize < MAX_SHAPE_SIZE);
return shapeSize;
}
default:
btAssert(0);
//unsupported shapetype, please add here
@@ -653,13 +668,13 @@ void ProcessSpuConvexConvexCollision(SpuCollisionPairInput* wuInput, CollisionTa
cpInput.m_convexVertexData = &lsMemPtr->convexVertexData;
cpInput.m_transformA = wuInput->m_worldTransform0;
cpInput.m_transformB = wuInput->m_worldTransform1;
float sumMargin = (marginA+marginB);
float sumMargin = (marginA+marginB+lsMemPtr->gPersistentManifold.getContactBreakingThreshold());
cpInput.m_maximumDistanceSquared = sumMargin * sumMargin;
uint64_t manifoldAddress = (uint64_t)manifold;
btPersistentManifold* spuManifold=&lsMemPtr->gPersistentManifold;
spuContacts.setContactInfo(spuManifold,manifoldAddress,wuInput->m_worldTransform0,wuInput->m_worldTransform1);
//spuContacts.setContactInfo(spuManifold,manifoldAddress,wuInput->m_worldTransform0,wuInput->m_worldTransform1,wuInput->m_isSwapped);
spuContacts.setContactInfo(spuManifold,manifoldAddress,lsMemPtr->gColObj0.getWorldTransform(),lsMemPtr->gColObj1.getWorldTransform(),wuInput->m_isSwapped);
SpuGjkPairDetector gjk(shape0Ptr,shape1Ptr,shapeType0,shapeType1,marginA,marginB,&vsSolver,&penetrationSolver);
gjk.getClosestPoints(cpInput,spuContacts);//,debugDraw);
@@ -668,7 +683,345 @@ void ProcessSpuConvexConvexCollision(SpuCollisionPairInput* wuInput, CollisionTa
}
template<typename T>
void DoSwap(T& a, T& b)
{
char tmp[sizeof(T)];
memcpy(tmp, &a, sizeof(T));
memcpy(&a, &b, sizeof(T));
memcpy(&b, tmp, sizeof(T));
}
void dmaAndSetupCollisionObjects(SpuCollisionPairInput& collisionPairInput, CollisionTask_LocalStoreMemory& lsMem)
{
{
int dmaSize = sizeof(btCollisionObject);
uint64_t dmaPpuAddress2 = /*collisionPairInput.m_isSwapped ? (uint64_t)lsMem.gProxyPtr1->m_clientObject :*/ (uint64_t)lsMem.gProxyPtr0->m_clientObject;
cellDmaGet(&lsMem.gColObj0, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0);
}
{
int dmaSize = sizeof(btCollisionObject);
uint64_t dmaPpuAddress2 = /*collisionPairInput.m_isSwapped ? (uint64_t)lsMem.gProxyPtr0->m_clientObject :*/ (uint64_t)lsMem.gProxyPtr1->m_clientObject;
cellDmaGet(&lsMem.gColObj1, dmaPpuAddress2 , dmaSize, DMA_TAG(2), 0, 0);
}
cellDmaWaitTagStatusAll(DMA_MASK(1) | DMA_MASK(2));
collisionPairInput.m_worldTransform0 = lsMem.gColObj0.getWorldTransform();
collisionPairInput.m_worldTransform1 = lsMem.gColObj1.getWorldTransform();
#ifdef DEBUG_SPU_COLLISION_DETECTION
spu_printf("SPU worldTrans0.origin = (%f,%f,%f)\n",
collisionPairInput->m_worldTransform0.getOrigin().getX(),
collisionPairInput->m_worldTransform0.getOrigin().getY(),
collisionPairInput->m_worldTransform0.getOrigin().getZ());
spu_printf("SPU worldTrans1.origin = (%f,%f,%f)\n",
collisionPairInput->m_worldTransform1.getOrigin().getX(),
collisionPairInput->m_worldTransform1.getOrigin().getY(),
collisionPairInput->m_worldTransform1.getOrigin().getZ());
#endif //DEBUG_SPU_COLLISION_DETECTION
}
void handleCollisionPair(SpuCollisionPairInput& collisionPairInput, CollisionTask_LocalStoreMemory& lsMem,
SpuContactResult &spuContacts,
uint64_t collisionShape0Ptr, void* collisionShape0Loc,
uint64_t collisionShape1Ptr, void* collisionShape1Loc, bool dmaShapes = true)
{
if (btBroadphaseProxy::isConvex(collisionPairInput.m_shapeType0)
&& btBroadphaseProxy::isConvex(collisionPairInput.m_shapeType1))
{
//dmaAndSetupCollisionObjects(collisionPairInput, lsMem);
if (dmaShapes)
{
{
int dmaSize = getShapeTypeSize(collisionPairInput.m_shapeType0);
//uint64_t dmaPpuAddress2 = (uint64_t)lsMem.gColObj0.getCollisionShape();
uint64_t dmaPpuAddress2 = collisionShape0Ptr;
cellDmaGet(collisionShape0Loc, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0);
cellDmaWaitTagStatusAll(DMA_MASK(1));
}
{
int dmaSize = getShapeTypeSize(collisionPairInput.m_shapeType1);
uint64_t dmaPpuAddress2 = collisionShape1Ptr;
cellDmaGet(collisionShape1Loc, dmaPpuAddress2 , dmaSize, DMA_TAG(2), 0, 0);
cellDmaWaitTagStatusAll(DMA_MASK(2));
}
}
btConvexInternalShape* spuConvexShape0 = (btConvexInternalShape*)collisionShape0Loc;
btConvexInternalShape* spuConvexShape1 = (btConvexInternalShape*)collisionShape1Loc;
btVector3 dim0 = spuConvexShape0->getImplicitShapeDimensions();
btVector3 dim1 = spuConvexShape1->getImplicitShapeDimensions();
collisionPairInput.m_primitiveDimensions0 = dim0;
collisionPairInput.m_primitiveDimensions1 = dim1;
collisionPairInput.m_collisionShapes[0] = collisionShape0Ptr;
collisionPairInput.m_collisionShapes[1] = collisionShape1Ptr;
collisionPairInput.m_spuCollisionShapes[0] = spuConvexShape0;
collisionPairInput.m_spuCollisionShapes[1] = spuConvexShape1;
ProcessSpuConvexConvexCollision(&collisionPairInput,&lsMem,spuContacts);
}
else if (btBroadphaseProxy::isCompound(collisionPairInput.m_shapeType0) &&
btBroadphaseProxy::isCompound(collisionPairInput.m_shapeType1))
{
//snPause();
// Both are compounds, do N^2 CD for now
// TODO: add some AABB-based pruning
{
int dmaSize = getShapeTypeSize(collisionPairInput.m_shapeType0);
uint64_t dmaPpuAddress2 = collisionShape0Ptr;
cellDmaGet(collisionShape0Loc, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0);
cellDmaWaitTagStatusAll(DMA_MASK(1));
}
{
int dmaSize = getShapeTypeSize(collisionPairInput.m_shapeType1);
uint64_t dmaPpuAddress2 = collisionShape1Ptr;
cellDmaGet(collisionShape1Loc, dmaPpuAddress2 , dmaSize, DMA_TAG(2), 0, 0);
cellDmaWaitTagStatusAll(DMA_MASK(2));
}
btCompoundShape* spuCompoundShape0 = (btCompoundShape*)collisionShape0Loc;
btCompoundShape* spuCompoundShape1 = (btCompoundShape*)collisionShape1Loc;
int childShapeCount0 = spuCompoundShape0->getNumChildShapes();
int childShapeCount1 = spuCompoundShape1->getNumChildShapes();
// dma the first list of child shapes
{
int dmaSize = childShapeCount0 * sizeof(btCompoundShapeChild);
uint64_t dmaPpuAddress2 = (uint64_t)spuCompoundShape0->getChildList();
cellDmaGet(lsMem.gSubshapes, dmaPpuAddress2, dmaSize, DMA_TAG(1), 0, 0);
cellDmaWaitTagStatusAll(DMA_MASK(1));
}
// dma the second list of child shapes
{
int dmaSize = childShapeCount1 * sizeof(btCompoundShapeChild);
uint64_t dmaPpuAddress2 = (uint64_t)spuCompoundShape1->getChildList();
cellDmaGet(&lsMem.gSubshapes[MAX_SPU_COMPOUND_SUBSHAPES], dmaPpuAddress2, dmaSize, DMA_TAG(2), 0, 0);
cellDmaWaitTagStatusAll(DMA_MASK(2));
}
// DMA all the subshapes
for (int i = 0; i < childShapeCount0; ++i)
{
btCompoundShapeChild& childShape = lsMem.gSubshapes[i];
int dmaSize = getShapeTypeSize(childShape.m_childShapeType);
uint64_t dmaPpuAddress2 = (uint64_t)childShape.m_childShape;
cellDmaGet(lsMem.gSubshapeShape[i], dmaPpuAddress2, dmaSize, DMA_TAG(1), 0, 0);
cellDmaWaitTagStatusAll(DMA_MASK(1));
}
for (int i = 0; i < childShapeCount1; ++i)
{
btCompoundShapeChild& childShape = lsMem.gSubshapes[MAX_SPU_COMPOUND_SUBSHAPES+i];
int dmaSize = getShapeTypeSize(childShape.m_childShapeType);
uint64_t dmaPpuAddress2 = (uint64_t)childShape.m_childShape;
cellDmaGet(lsMem.gSubshapeShape[MAX_SPU_COMPOUND_SUBSHAPES+i], dmaPpuAddress2, dmaSize, DMA_TAG(1), 0, 0);
cellDmaWaitTagStatusAll(DMA_MASK(1));
}
// Start the N^2
for (int i = 0; i < childShapeCount0; ++i)
{
btCompoundShapeChild& childShape0 = lsMem.gSubshapes[i];
for (int j = 0; j < childShapeCount1; ++j)
{
btCompoundShapeChild& childShape1 = lsMem.gSubshapes[MAX_SPU_COMPOUND_SUBSHAPES+j];
SpuCollisionPairInput cinput (collisionPairInput);
cinput.m_worldTransform0 = collisionPairInput.m_worldTransform0 * childShape0.m_transform;
cinput.m_shapeType0 = childShape0.m_childShapeType;
cinput.m_collisionMargin0 = childShape0.m_childMargin;
cinput.m_worldTransform1 = collisionPairInput.m_worldTransform1 * childShape1.m_transform;
cinput.m_shapeType1 = childShape1.m_childShapeType;
cinput.m_collisionMargin1 = childShape1.m_childMargin;
handleCollisionPair(cinput, lsMem, spuContacts,
(uint64_t)childShape0.m_childShape, lsMem.gSubshapeShape[i],
(uint64_t)childShape1.m_childShape, lsMem.gSubshapeShape[MAX_SPU_COMPOUND_SUBSHAPES+i], false);
}
}
}
else if (btBroadphaseProxy::isCompound(collisionPairInput.m_shapeType0) )
{
//snPause();
{
int dmaSize = getShapeTypeSize(collisionPairInput.m_shapeType0);
uint64_t dmaPpuAddress2 = collisionShape0Ptr;
cellDmaGet(collisionShape0Loc, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0);
cellDmaWaitTagStatusAll(DMA_MASK(1));
}
{
int dmaSize = getShapeTypeSize(collisionPairInput.m_shapeType1);
uint64_t dmaPpuAddress2 = collisionShape1Ptr;
cellDmaGet(collisionShape1Loc, dmaPpuAddress2 , dmaSize, DMA_TAG(2), 0, 0);
cellDmaWaitTagStatusAll(DMA_MASK(2));
}
// object 0 compound, object 1 non-compound
btCompoundShape* spuCompoundShape = (btCompoundShape*)collisionShape0Loc;
int childShapeCount = spuCompoundShape->getNumChildShapes();
// dma the list of child shapes
{
int dmaSize = childShapeCount * sizeof(btCompoundShapeChild);
uint64_t dmaPpuAddress2 = (uint64_t)spuCompoundShape->getChildList();
cellDmaGet(lsMem.gSubshapes, dmaPpuAddress2, dmaSize, DMA_TAG(1), 0, 0);
cellDmaWaitTagStatusAll(DMA_MASK(1));
}
for (int i = 0; i < childShapeCount; ++i)
{
btCompoundShapeChild& childShape = lsMem.gSubshapes[i];
// Dma the child shape
{
int dmaSize = getShapeTypeSize(childShape.m_childShapeType);
uint64_t dmaPpuAddress2 = (uint64_t)childShape.m_childShape;
cellDmaGet(lsMem.gSubshapeShape[i], dmaPpuAddress2, dmaSize, DMA_TAG(1), 0, 0);
cellDmaWaitTagStatusAll(DMA_MASK(1));
}
SpuCollisionPairInput cinput (collisionPairInput);
cinput.m_worldTransform0 = collisionPairInput.m_worldTransform0 * childShape.m_transform;
cinput.m_shapeType0 = childShape.m_childShapeType;
cinput.m_collisionMargin0 = childShape.m_childMargin;
handleCollisionPair(cinput, lsMem, spuContacts,
(uint64_t)childShape.m_childShape, lsMem.gSubshapeShape[i],
collisionShape1Ptr, collisionShape1Loc, false);
}
}
else if (btBroadphaseProxy::isCompound(collisionPairInput.m_shapeType1) )
{
//snPause();
{
int dmaSize = getShapeTypeSize(collisionPairInput.m_shapeType0);
uint64_t dmaPpuAddress2 = collisionShape0Ptr;
cellDmaGet(collisionShape0Loc, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0);
cellDmaWaitTagStatusAll(DMA_MASK(1));
}
{
int dmaSize = getShapeTypeSize(collisionPairInput.m_shapeType1);
uint64_t dmaPpuAddress2 = collisionShape1Ptr;
cellDmaGet(collisionShape1Loc, dmaPpuAddress2 , dmaSize, DMA_TAG(2), 0, 0);
cellDmaWaitTagStatusAll(DMA_MASK(2));
}
// object 0 non-compound, object 1 compound
btCompoundShape* spuCompoundShape = (btCompoundShape*)collisionShape1Loc;
int childShapeCount = spuCompoundShape->getNumChildShapes();
// dma the list of child shapes
{
int dmaSize = childShapeCount * sizeof(btCompoundShapeChild);
uint64_t dmaPpuAddress2 = (uint64_t)spuCompoundShape->getChildList();
cellDmaGet(lsMem.gSubshapes, dmaPpuAddress2, dmaSize, DMA_TAG(1), 0, 0);
cellDmaWaitTagStatusAll(DMA_MASK(1));
}
for (int i = 0; i < childShapeCount; ++i)
{
btCompoundShapeChild& childShape = lsMem.gSubshapes[i];
// Dma the child shape
{
int dmaSize = getShapeTypeSize(childShape.m_childShapeType);
uint64_t dmaPpuAddress2 = (uint64_t)childShape.m_childShape;
cellDmaGet(lsMem.gSubshapeShape[i], dmaPpuAddress2, dmaSize, DMA_TAG(1), 0, 0);
cellDmaWaitTagStatusAll(DMA_MASK(1));
}
SpuCollisionPairInput cinput (collisionPairInput);
cinput.m_worldTransform1 = collisionPairInput.m_worldTransform1 * childShape.m_transform;
cinput.m_shapeType1 = childShape.m_childShapeType;
cinput.m_collisionMargin1 = childShape.m_childMargin;
handleCollisionPair(cinput, lsMem, spuContacts,
collisionShape0Ptr, collisionShape0Loc,
(uint64_t)childShape.m_childShape, lsMem.gSubshapeShape[i], false);
}
}
else
{
//a non-convex shape is involved
bool handleConvexConcave = false;
//snPause();
if (btBroadphaseProxy::isConcave(collisionPairInput.m_shapeType0) &&
btBroadphaseProxy::isConvex(collisionPairInput.m_shapeType1))
{
// Swap stuff
DoSwap(collisionShape0Ptr, collisionShape1Ptr);
DoSwap(collisionShape0Loc, collisionShape1Loc);
DoSwap(collisionPairInput.m_shapeType0, collisionPairInput.m_shapeType1);
DoSwap(collisionPairInput.m_worldTransform0, collisionPairInput.m_worldTransform1);
DoSwap(collisionPairInput.m_collisionMargin0, collisionPairInput.m_collisionMargin1);
collisionPairInput.m_isSwapped = true;
}
if (btBroadphaseProxy::isConvex(collisionPairInput.m_shapeType0)&&
btBroadphaseProxy::isConcave(collisionPairInput.m_shapeType1))
{
handleConvexConcave = true;
}
if (handleConvexConcave)
{
if (dmaShapes)
{
///dma and initialize the convex object
{
int dmaSize = getShapeTypeSize(collisionPairInput.m_shapeType0);
//uint64_t dmaPpuAddress2 = (uint64_t)lsMem.gColObj0.getCollisionShape();
uint64_t dmaPpuAddress2 = collisionShape0Ptr;
cellDmaGet(collisionShape0Loc, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0);
cellDmaWaitTagStatusAll(DMA_MASK(1));
}
///dma and initialize the concave object
{
int dmaSize = getShapeTypeSize(collisionPairInput.m_shapeType1);
uint64_t dmaPpuAddress2 = collisionShape1Ptr;
cellDmaGet(collisionShape1Loc, dmaPpuAddress2 , dmaSize, DMA_TAG(2), 0, 0);
cellDmaWaitTagStatusAll(DMA_MASK(2));
}
}
btConvexInternalShape* spuConvexShape0 = (btConvexInternalShape*)collisionShape0Loc;
btBvhTriangleMeshShape* trimeshShape = (btBvhTriangleMeshShape*)collisionShape1Loc;
btVector3 dim0 = spuConvexShape0->getImplicitShapeDimensions();
collisionPairInput.m_primitiveDimensions0 = dim0;
collisionPairInput.m_collisionShapes[0] = collisionShape0Ptr;
collisionPairInput.m_collisionShapes[1] = collisionShape1Ptr;
collisionPairInput.m_spuCollisionShapes[0] = spuConvexShape0;
collisionPairInput.m_spuCollisionShapes[1] = trimeshShape;
ProcessConvexConcaveSpuCollision(&collisionPairInput,&lsMem,spuContacts);
}
}
spuContacts.flush();
}
void processCollisionTask(void* userPtr, void* lsMemPtr)
{
@@ -678,11 +1031,11 @@ void processCollisionTask(void* userPtr, void* lsMemPtr)
CollisionTask_LocalStoreMemory* colMemPtr = (CollisionTask_LocalStoreMemory*)lsMemPtr;
CollisionTask_LocalStoreMemory& lsMem = *(colMemPtr);
// spu_printf("taskDescPtr=%llx\n",taskDescPtr);
// spu_printf("taskDescPtr=%llx\n",taskDescPtr);
SpuContactResult spuContacts;
////////////////////
////////////////////
uint64_t dmaInPtr = taskDesc.inPtr;
unsigned int numPages = taskDesc.numPages;
@@ -761,6 +1114,8 @@ void processCollisionTask(void* userPtr, void* lsMemPtr)
SpuCollisionPairInput collisionPairInput;
collisionPairInput.m_persistentManifoldPtr = (uint64_t) lsMem.gSpuContactManifoldAlgo.getContactManifoldPtr();
collisionPairInput.m_isSwapped = false;
//snPause();
#ifdef DEBUG_SPU_COLLISION_DETECTION
spu_printf("SPU: manifoldPtr: %llx",collisionPairInput->m_persistentManifoldPtr);
@@ -785,23 +1140,10 @@ void processCollisionTask(void* userPtr, void* lsMemPtr)
//btCollisionObject* colObj0 = (btCollisionObject*)gProxy0.m_clientObject;
//btCollisionObject* colObj1 = (btCollisionObject*)gProxy1.m_clientObject;
{
int dmaSize = sizeof(btCollisionObject);
uint64_t dmaPpuAddress2 = (uint64_t)lsMem.gProxyPtr0->m_clientObject;
cellDmaGet(&lsMem.gColObj0, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0);
cellDmaWaitTagStatusAll(DMA_MASK(1));
}
{
int dmaSize = sizeof(btCollisionObject);
uint64_t dmaPpuAddress2 = (uint64_t)lsMem.gProxyPtr1->m_clientObject;
cellDmaGet(&lsMem.gColObj1, dmaPpuAddress2 , dmaSize, DMA_TAG(2), 0, 0);
cellDmaWaitTagStatusAll(DMA_MASK(2));
}
if (1)
{
///can wait on the combined DMA_MASK, or dma on the same tag
collisionPairInput.m_shapeType0 = lsMem.gSpuContactManifoldAlgo.getShapeType0();
@@ -809,157 +1151,29 @@ void processCollisionTask(void* userPtr, void* lsMemPtr)
collisionPairInput.m_collisionMargin0 = lsMem.gSpuContactManifoldAlgo.getCollisionMargin0();
collisionPairInput.m_collisionMargin1 = lsMem.gSpuContactManifoldAlgo.getCollisionMargin1();
#ifdef DEBUG_SPU_COLLISION_DETECTION
#ifdef DEBUG_SPU_COLLISION_DETECTION
spu_printf("SPU collisionPairInput->m_shapeType0 = %d\n",collisionPairInput->m_shapeType0);
spu_printf("SPU collisionPairInput->m_shapeType1 = %d\n",collisionPairInput->m_shapeType1);
#endif //DEBUG_SPU_COLLISION_DETECTION
if (1)
{
collisionPairInput.m_worldTransform0 = lsMem.gColObj0.getWorldTransform();
collisionPairInput.m_worldTransform1 = lsMem.gColObj1.getWorldTransform();
#ifdef DEBUG_SPU_COLLISION_DETECTION
spu_printf("SPU worldTrans0.origin = (%f,%f,%f)\n",
collisionPairInput->m_worldTransform0.getOrigin().getX(),
collisionPairInput->m_worldTransform0.getOrigin().getY(),
collisionPairInput->m_worldTransform0.getOrigin().getZ());
spu_printf("SPU worldTrans1.origin = (%f,%f,%f)\n",
collisionPairInput->m_worldTransform1.getOrigin().getX(),
collisionPairInput->m_worldTransform1.getOrigin().getY(),
collisionPairInput->m_worldTransform1.getOrigin().getZ());
#endif //DEBUG_SPU_COLLISION_DETECTION
#endif //DEBUG_SPU_COLLISION_DETECTION
{
int dmaSize = sizeof(btPersistentManifold);
uint64_t dmaPpuAddress2 = collisionPairInput.m_persistentManifoldPtr;
if (dmaPpuAddress2 & 0x0f)
{
#ifndef IGNORE_ALIGNMENT
spu_printf("SPU ALIGNMENT ERROR\n");
spuContacts.flush();
return;
#endif
}
cellDmaGet(&lsMem.gPersistentManifold, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0);
cellDmaWaitTagStatusAll(DMA_MASK(1));
}
if (btBroadphaseProxy::isConvex(collisionPairInput.m_shapeType0)
&& btBroadphaseProxy::isConvex(collisionPairInput.m_shapeType1))
if (1)
{
//snPause();
{
int dmaSize = getShapeTypeSize(collisionPairInput.m_shapeType0);
uint64_t dmaPpuAddress2 = (uint64_t)lsMem.gColObj0.getCollisionShape();
cellDmaGet(lsMem.gCollisionShape0, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0);
cellDmaWaitTagStatusAll(DMA_MASK(1));
}
{
int dmaSize = getShapeTypeSize(collisionPairInput.m_shapeType1);
uint64_t dmaPpuAddress2 = (uint64_t)lsMem.gColObj1.getCollisionShape();
if (dmaPpuAddress2 & 0x0f)
{
#ifndef IGNORE_ALIGNMENT
spu_printf("SPU ALIGNMENT ERROR2\n");
spuContacts.flush();
return;
#endif //IGNORE_ALIGNMENT
}
cellDmaGet(lsMem.gCollisionShape1, dmaPpuAddress2 , dmaSize, DMA_TAG(2), 0, 0);
cellDmaWaitTagStatusAll(DMA_MASK(2));
}
btConvexInternalShape* spuConvexShape0 = (btConvexInternalShape*)lsMem.gCollisionShape0;
btConvexInternalShape* spuConvexShape1 = (btConvexInternalShape*)lsMem.gCollisionShape1;
btVector3 dim0 = spuConvexShape0->getImplicitShapeDimensions();
btVector3 dim1 = spuConvexShape1->getImplicitShapeDimensions();
collisionPairInput.m_primitiveDimensions0 = dim0;
collisionPairInput.m_primitiveDimensions1 = dim1;
collisionPairInput.m_collisionShapes[0] = (uint64_t)lsMem.gColObj0.getCollisionShape();
collisionPairInput.m_collisionShapes[1] = (uint64_t)lsMem.gColObj1.getCollisionShape();
collisionPairInput.m_spuCollisionShapes[0] = spuConvexShape0;
collisionPairInput.m_spuCollisionShapes[1] = spuConvexShape1;
ProcessSpuConvexConvexCollision(&collisionPairInput,&lsMem,spuContacts);
} else
{
//a non-convex shape is involved
bool isSwapped = false;
bool handleConvexConcave = false;
if (btBroadphaseProxy::isConcave(collisionPairInput.m_shapeType0) &&
btBroadphaseProxy::isConvex(collisionPairInput.m_shapeType1))
{
isSwapped = true;
spu_printf("SPU convex/concave swapped, unsupported!\n");
handleConvexConcave = true;
}
if (btBroadphaseProxy::isConvex(collisionPairInput.m_shapeType0)&&
btBroadphaseProxy::isConcave(collisionPairInput.m_shapeType1))
{
handleConvexConcave = true;
}
if (handleConvexConcave && !isSwapped)
{
// spu_printf("SPU: non-convex detected\n");
{
// uint64_t dmaPpuAddress2 = (uint64_t)gProxy1.m_clientObject;
// spu_printf("SPU: gColObj1 trimesh = %llx\n",dmaPpuAddress2);
}
///dma and initialize the convex object
{
int dmaSize = getShapeTypeSize(collisionPairInput.m_shapeType0);
uint64_t dmaPpuAddress2 = (uint64_t)lsMem.gColObj0.getCollisionShape();
cellDmaGet(lsMem.gCollisionShape0, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0);
cellDmaWaitTagStatusAll(DMA_MASK(1));
}
///dma and initialize the convex object
{
int dmaSize = getShapeTypeSize(collisionPairInput.m_shapeType1);
uint64_t dmaPpuAddress2 = (uint64_t)lsMem.gColObj1.getCollisionShape();
if (dmaPpuAddress2 & 0x0f)
{
#ifndef IGNORE_ALIGNMENT
spu_printf("SPU ALIGNMENT ERROR3\n");
spuContacts.flush();
return;
#endif //
}
// spu_printf("SPU: trimesh = %llx\n",dmaPpuAddress2);
cellDmaGet(lsMem.gCollisionShape1, dmaPpuAddress2 , dmaSize, DMA_TAG(2), 0, 0);
cellDmaWaitTagStatusAll(DMA_MASK(2));
}
btConvexInternalShape* spuConvexShape0 = (btConvexInternalShape*)lsMem.gCollisionShape0;
btBvhTriangleMeshShape* trimeshShape = (btBvhTriangleMeshShape*)lsMem.gCollisionShape1;
btVector3 dim0 = spuConvexShape0->getImplicitShapeDimensions();
collisionPairInput.m_primitiveDimensions0 = dim0;
collisionPairInput.m_collisionShapes[0] = (uint64_t)lsMem.gColObj0.getCollisionShape();
collisionPairInput.m_collisionShapes[1] = (uint64_t)lsMem.gColObj1.getCollisionShape();
collisionPairInput.m_spuCollisionShapes[0] = spuConvexShape0;
collisionPairInput.m_spuCollisionShapes[1] = trimeshShape;
ProcessConvexConcaveSpuCollision(&collisionPairInput,&lsMem,spuContacts);
}
}
spuContacts.flush();
// Get the collision objects
dmaAndSetupCollisionObjects(collisionPairInput, lsMem);
handleCollisionPair(collisionPairInput, lsMem, spuContacts,
(uint64_t)lsMem.gColObj0.getCollisionShape(), lsMem.gCollisionShape0,
(uint64_t)lsMem.gColObj1.getCollisionShape(), lsMem.gCollisionShape1);
}
}

View File

@@ -35,8 +35,15 @@ btCompoundShape::~btCompoundShape()
void btCompoundShape::addChildShape(const btTransform& localTransform,btCollisionShape* shape)
{
m_childTransforms.push_back(localTransform);
m_childShapes.push_back(shape);
//m_childTransforms.push_back(localTransform);
//m_childShapes.push_back(shape);
btCompoundShapeChild child;
child.m_transform = localTransform;
child.m_childShape = shape;
child.m_childShapeType = shape->getShapeType();
child.m_childMargin = shape->getMargin();
m_children.push_back(child);
//extend the local aabbMin/aabbMax
btVector3 localAabbMin,localAabbMax;

View File

@@ -26,12 +26,21 @@ subject to the following restrictions:
class btOptimizedBvh;
ATTRIBUTE_ALIGNED16(struct) btCompoundShapeChild
{
btTransform m_transform;
btCollisionShape* m_childShape;
int m_childShapeType;
btScalar m_childMargin;
};
/// btCompoundShape allows to store multiple other btCollisionShapes
/// This allows for concave collision objects. This is more general then the Static Concave btTriangleMeshShape.
class btCompoundShape : public btCollisionShape
ATTRIBUTE_ALIGNED16(class) btCompoundShape : public btCollisionShape
{
btAlignedObjectArray<btTransform> m_childTransforms;
btAlignedObjectArray<btCollisionShape*> m_childShapes;
//btAlignedObjectArray<btTransform> m_childTransforms;
//btAlignedObjectArray<btCollisionShape*> m_childShapes;
btAlignedObjectArray<btCompoundShapeChild> m_children;
btVector3 m_localAabbMin;
btVector3 m_localAabbMax;
@@ -46,25 +55,31 @@ public:
int getNumChildShapes() const
{
return int (m_childShapes.size());
return int (m_children.size());
}
btCollisionShape* getChildShape(int index)
{
return m_childShapes[index];
return m_children[index].m_childShape;
}
const btCollisionShape* getChildShape(int index) const
{
return m_childShapes[index];
return m_children[index].m_childShape;
}
btTransform& getChildTransform(int index)
btTransform getChildTransform(int index)
{
return m_childTransforms[index];
return m_children[index].m_transform;
}
const btTransform& getChildTransform(int index) const
const btTransform getChildTransform(int index) const
{
return m_childTransforms[index];
return m_children[index].m_transform;
}
btCompoundShapeChild* getChildList()
{
return &m_children[0];
}
///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version