aboutsummaryrefslogtreecommitdiff
path: root/tests/bullet/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask
diff options
context:
space:
mode:
Diffstat (limited to 'tests/bullet/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask')
-rw-r--r--tests/bullet/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/Box.h167
-rw-r--r--tests/bullet/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuCollisionShapes.cpp302
-rw-r--r--tests/bullet/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuCollisionShapes.h128
-rw-r--r--tests/bullet/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuContactResult.cpp248
-rw-r--r--tests/bullet/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuContactResult.h106
-rw-r--r--tests/bullet/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuConvexPenetrationDepthSolver.h51
-rw-r--r--tests/bullet/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.cpp1412
-rw-r--r--tests/bullet/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h140
-rw-r--r--tests/bullet/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuLocalSupport.h19
-rw-r--r--tests/bullet/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuMinkowskiPenetrationDepthSolver.cpp348
-rw-r--r--tests/bullet/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuMinkowskiPenetrationDepthSolver.h48
-rw-r--r--tests/bullet/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuPreferredPenetrationDirections.h70
-rw-r--r--tests/bullet/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/boxBoxDistance.cpp1160
-rw-r--r--tests/bullet/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/boxBoxDistance.h65
-rw-r--r--tests/bullet/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/readme.txt1
15 files changed, 4265 insertions, 0 deletions
diff --git a/tests/bullet/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/Box.h b/tests/bullet/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/Box.h
new file mode 100644
index 00000000..e5179611
--- /dev/null
+++ b/tests/bullet/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/Box.h
@@ -0,0 +1,167 @@
+/*
+ Copyright (C) 2006, 2008 Sony Computer Entertainment Inc.
+ All rights reserved.
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+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.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+
+*/
+
+#ifndef __BOX_H__
+#define __BOX_H__
+
+
+#ifndef PE_REF
+#define PE_REF(a) a&
+#endif
+
+#include <math.h>
+
+
+#include "../PlatformDefinitions.h"
+
+
+
+
+enum FeatureType { F, E, V };
+
+//----------------------------------------------------------------------------
+// Box
+//----------------------------------------------------------------------------
+///The Box is an internal class used by the boxBoxDistance calculation.
+class Box
+{
+public:
+ vmVector3 mHalf;
+
+ inline Box()
+ {}
+ inline Box(PE_REF(vmVector3) half_);
+ inline Box(float hx, float hy, float hz);
+
+ inline void Set(PE_REF(vmVector3) half_);
+ inline void Set(float hx, float hy, float hz);
+
+ inline vmVector3 GetAABB(const vmMatrix3& rotation) const;
+};
+
+inline
+Box::Box(PE_REF(vmVector3) half_)
+{
+ Set(half_);
+}
+
+inline
+Box::Box(float hx, float hy, float hz)
+{
+ Set(hx, hy, hz);
+}
+
+inline
+void
+Box::Set(PE_REF(vmVector3) half_)
+{
+ mHalf = half_;
+}
+
+inline
+void
+Box::Set(float hx, float hy, float hz)
+{
+ mHalf = vmVector3(hx, hy, hz);
+}
+
+inline
+vmVector3
+Box::GetAABB(const vmMatrix3& rotation) const
+{
+ return absPerElem(rotation) * mHalf;
+}
+
+//-------------------------------------------------------------------------------------------------
+// BoxPoint
+//-------------------------------------------------------------------------------------------------
+
+///The BoxPoint class is an internally used class to contain feature information for boxBoxDistance calculation.
+class BoxPoint
+{
+public:
+ BoxPoint() : localPoint(0.0f) {}
+
+ vmPoint3 localPoint;
+ FeatureType featureType;
+ int featureIdx;
+
+ inline void setVertexFeature(int plusX, int plusY, int plusZ);
+ inline void setEdgeFeature(int dim0, int plus0, int dim1, int plus1);
+ inline void setFaceFeature(int dim, int plus);
+
+ inline void getVertexFeature(int & plusX, int & plusY, int & plusZ) const;
+ inline void getEdgeFeature(int & dim0, int & plus0, int & dim1, int & plus1) const;
+ inline void getFaceFeature(int & dim, int & plus) const;
+};
+
+inline
+void
+BoxPoint::setVertexFeature(int plusX, int plusY, int plusZ)
+{
+ featureType = V;
+ featureIdx = plusX << 2 | plusY << 1 | plusZ;
+}
+
+inline
+void
+BoxPoint::setEdgeFeature(int dim0, int plus0, int dim1, int plus1)
+{
+ featureType = E;
+
+ if (dim0 > dim1) {
+ featureIdx = plus1 << 5 | dim1 << 3 | plus0 << 2 | dim0;
+ } else {
+ featureIdx = plus0 << 5 | dim0 << 3 | plus1 << 2 | dim1;
+ }
+}
+
+inline
+void
+BoxPoint::setFaceFeature(int dim, int plus)
+{
+ featureType = F;
+ featureIdx = plus << 2 | dim;
+}
+
+inline
+void
+BoxPoint::getVertexFeature(int & plusX, int & plusY, int & plusZ) const
+{
+ plusX = featureIdx >> 2;
+ plusY = featureIdx >> 1 & 1;
+ plusZ = featureIdx & 1;
+}
+
+inline
+void
+BoxPoint::getEdgeFeature(int & dim0, int & plus0, int & dim1, int & plus1) const
+{
+ plus0 = featureIdx >> 5;
+ dim0 = featureIdx >> 3 & 3;
+ plus1 = featureIdx >> 2 & 1;
+ dim1 = featureIdx & 3;
+}
+
+inline
+void
+BoxPoint::getFaceFeature(int & dim, int & plus) const
+{
+ plus = featureIdx >> 2;
+ dim = featureIdx & 3;
+}
+
+#endif /* __BOX_H__ */
diff --git a/tests/bullet/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuCollisionShapes.cpp b/tests/bullet/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuCollisionShapes.cpp
new file mode 100644
index 00000000..dfcd8426
--- /dev/null
+++ b/tests/bullet/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuCollisionShapes.cpp
@@ -0,0 +1,302 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+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.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#include "SpuCollisionShapes.h"
+
+///not supported on IBM SDK, until we fix the alignment of btVector3
+#if defined (__CELLOS_LV2__) && defined (__SPU__)
+#include <spu_intrinsics.h>
+static inline vec_float4 vec_dot3( vec_float4 vec0, vec_float4 vec1 )
+{
+ vec_float4 result;
+ result = spu_mul( vec0, vec1 );
+ result = spu_madd( spu_rlqwbyte( vec0, 4 ), spu_rlqwbyte( vec1, 4 ), result );
+ return spu_madd( spu_rlqwbyte( vec0, 8 ), spu_rlqwbyte( vec1, 8 ), result );
+}
+#endif //__SPU__
+
+
+void computeAabb (btVector3& aabbMin, btVector3& aabbMax, btConvexInternalShape* convexShape, ppu_address_t convexShapePtr, int shapeType, const btTransform& xform)
+{
+ //calculate the aabb, given the types...
+ switch (shapeType)
+ {
+ case CYLINDER_SHAPE_PROXYTYPE:
+ /* fall through */
+ case BOX_SHAPE_PROXYTYPE:
+ {
+ btScalar margin=convexShape->getMarginNV();
+ btVector3 halfExtents = convexShape->getImplicitShapeDimensions();
+ halfExtents += btVector3(margin,margin,margin);
+ const btTransform& t = xform;
+ btMatrix3x3 abs_b = t.getBasis().absolute();
+ btVector3 center = t.getOrigin();
+ btVector3 extent = btVector3(abs_b[0].dot(halfExtents),abs_b[1].dot(halfExtents),abs_b[2].dot(halfExtents));
+
+ aabbMin = center - extent;
+ aabbMax = center + extent;
+ break;
+ }
+ case CAPSULE_SHAPE_PROXYTYPE:
+ {
+ btScalar margin=convexShape->getMarginNV();
+ btVector3 halfExtents = convexShape->getImplicitShapeDimensions();
+ //add the radius to y-axis to get full height
+ btScalar radius = halfExtents[0];
+ halfExtents[1] += radius;
+ halfExtents += btVector3(margin,margin,margin);
+#if 0
+ int capsuleUpAxis = convexShape->getUpAxis();
+ btScalar halfHeight = convexShape->getHalfHeight();
+ btScalar radius = convexShape->getRadius();
+ halfExtents[capsuleUpAxis] = radius + halfHeight;
+#endif
+ const btTransform& t = xform;
+ btMatrix3x3 abs_b = t.getBasis().absolute();
+ btVector3 center = t.getOrigin();
+ btVector3 extent = btVector3(abs_b[0].dot(halfExtents),abs_b[1].dot(halfExtents),abs_b[2].dot(halfExtents));
+
+ aabbMin = center - extent;
+ aabbMax = center + extent;
+ break;
+ }
+ case SPHERE_SHAPE_PROXYTYPE:
+ {
+ btScalar radius = convexShape->getImplicitShapeDimensions().getX();// * convexShape->getLocalScaling().getX();
+ btScalar margin = radius + convexShape->getMarginNV();
+ const btTransform& t = xform;
+ const btVector3& center = t.getOrigin();
+ btVector3 extent(margin,margin,margin);
+ aabbMin = center - extent;
+ aabbMax = center + extent;
+ break;
+ }
+ case CONVEX_HULL_SHAPE_PROXYTYPE:
+ {
+ ATTRIBUTE_ALIGNED16(char convexHullShape0[sizeof(btConvexHullShape)]);
+ cellDmaGet(&convexHullShape0, convexShapePtr , sizeof(btConvexHullShape), DMA_TAG(1), 0, 0);
+ cellDmaWaitTagStatusAll(DMA_MASK(1));
+ btConvexHullShape* localPtr = (btConvexHullShape*)&convexHullShape0;
+ const btTransform& t = xform;
+ btScalar margin = convexShape->getMarginNV();
+ localPtr->getNonvirtualAabb(t,aabbMin,aabbMax,margin);
+ //spu_printf("SPU convex aabbMin=%f,%f,%f=\n",aabbMin.getX(),aabbMin.getY(),aabbMin.getZ());
+ //spu_printf("SPU convex aabbMax=%f,%f,%f=\n",aabbMax.getX(),aabbMax.getY(),aabbMax.getZ());
+ break;
+ }
+ default:
+ {
+ // spu_printf("SPU: unsupported shapetype %d in AABB calculation\n");
+ }
+ };
+}
+
+void dmaBvhShapeData (bvhMeshShape_LocalStoreMemory* bvhMeshShape, btBvhTriangleMeshShape* triMeshShape)
+{
+ register int dmaSize;
+ register ppu_address_t dmaPpuAddress2;
+
+ dmaSize = sizeof(btTriangleIndexVertexArray);
+ dmaPpuAddress2 = reinterpret_cast<ppu_address_t>(triMeshShape->getMeshInterface());
+ // spu_printf("trimeshShape->getMeshInterface() == %llx\n",dmaPpuAddress2);
+#ifdef __SPU__
+ cellDmaGet(&bvhMeshShape->gTriangleMeshInterfaceStorage, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0);
+ bvhMeshShape->gTriangleMeshInterfacePtr = &bvhMeshShape->gTriangleMeshInterfaceStorage;
+#else
+ bvhMeshShape->gTriangleMeshInterfacePtr = (btTriangleIndexVertexArray*)cellDmaGetReadOnly(&bvhMeshShape->gTriangleMeshInterfaceStorage, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0);
+#endif
+
+ //cellDmaWaitTagStatusAll(DMA_MASK(1));
+
+ ///now DMA over the BVH
+
+ dmaSize = sizeof(btOptimizedBvh);
+ dmaPpuAddress2 = reinterpret_cast<ppu_address_t>(triMeshShape->getOptimizedBvh());
+ //spu_printf("trimeshShape->getOptimizedBvh() == %llx\n",dmaPpuAddress2);
+ cellDmaGet(&bvhMeshShape->gOptimizedBvh, dmaPpuAddress2 , dmaSize, DMA_TAG(2), 0, 0);
+ //cellDmaWaitTagStatusAll(DMA_MASK(2));
+ cellDmaWaitTagStatusAll(DMA_MASK(1) | DMA_MASK(2));
+}
+
+void dmaBvhIndexedMesh (btIndexedMesh* IndexMesh, IndexedMeshArray& indexArray, int index, uint32_t dmaTag)
+{
+ cellDmaGet(IndexMesh, (ppu_address_t)&indexArray[index] , sizeof(btIndexedMesh), DMA_TAG(dmaTag), 0, 0);
+
+}
+
+void dmaBvhSubTreeHeaders (btBvhSubtreeInfo* subTreeHeaders, ppu_address_t subTreePtr, int batchSize, uint32_t dmaTag)
+{
+ cellDmaGet(subTreeHeaders, subTreePtr, batchSize * sizeof(btBvhSubtreeInfo), DMA_TAG(dmaTag), 0, 0);
+}
+
+void dmaBvhSubTreeNodes (btQuantizedBvhNode* nodes, const btBvhSubtreeInfo& subtree, QuantizedNodeArray& nodeArray, int dmaTag)
+{
+ cellDmaGet(nodes, reinterpret_cast<ppu_address_t>(&nodeArray[subtree.m_rootNodeIndex]) , subtree.m_subtreeSize* sizeof(btQuantizedBvhNode), DMA_TAG(2), 0, 0);
+}
+
+///getShapeTypeSize could easily be optimized, but it is not likely a bottleneck
+int getShapeTypeSize(int shapeType)
+{
+
+
+ switch (shapeType)
+ {
+ case CYLINDER_SHAPE_PROXYTYPE:
+ {
+ int shapeSize = sizeof(btCylinderShape);
+ btAssert(shapeSize < MAX_SHAPE_SIZE);
+ return shapeSize;
+ }
+ case BOX_SHAPE_PROXYTYPE:
+ {
+ int shapeSize = sizeof(btBoxShape);
+ btAssert(shapeSize < MAX_SHAPE_SIZE);
+ return shapeSize;
+ }
+ case SPHERE_SHAPE_PROXYTYPE:
+ {
+ int shapeSize = sizeof(btSphereShape);
+ btAssert(shapeSize < MAX_SHAPE_SIZE);
+ return shapeSize;
+ }
+ case TRIANGLE_MESH_SHAPE_PROXYTYPE:
+ {
+ int shapeSize = sizeof(btBvhTriangleMeshShape);
+ btAssert(shapeSize < MAX_SHAPE_SIZE);
+ return shapeSize;
+ }
+ case CAPSULE_SHAPE_PROXYTYPE:
+ {
+ int shapeSize = sizeof(btCapsuleShape);
+ btAssert(shapeSize < MAX_SHAPE_SIZE);
+ return shapeSize;
+ }
+
+ case CONVEX_HULL_SHAPE_PROXYTYPE:
+ {
+ int shapeSize = sizeof(btConvexHullShape);
+ btAssert(shapeSize < MAX_SHAPE_SIZE);
+ return shapeSize;
+ }
+
+ case COMPOUND_SHAPE_PROXYTYPE:
+ {
+ int shapeSize = sizeof(btCompoundShape);
+ btAssert(shapeSize < MAX_SHAPE_SIZE);
+ return shapeSize;
+ }
+ case STATIC_PLANE_PROXYTYPE:
+ {
+ int shapeSize = sizeof(btStaticPlaneShape);
+ btAssert(shapeSize < MAX_SHAPE_SIZE);
+ return shapeSize;
+ }
+
+ default:
+ btAssert(0);
+ //unsupported shapetype, please add here
+ return 0;
+ }
+}
+
+void dmaConvexVertexData (SpuConvexPolyhedronVertexData* convexVertexData, btConvexHullShape* convexShapeSPU)
+{
+ convexVertexData->gNumConvexPoints = convexShapeSPU->getNumPoints();
+ if (convexVertexData->gNumConvexPoints>MAX_NUM_SPU_CONVEX_POINTS)
+ {
+ btAssert(0);
+ // spu_printf("SPU: Error: MAX_NUM_SPU_CONVEX_POINTS(%d) exceeded: %d\n",MAX_NUM_SPU_CONVEX_POINTS,convexVertexData->gNumConvexPoints);
+ return;
+ }
+
+ register int dmaSize = convexVertexData->gNumConvexPoints*sizeof(btVector3);
+ ppu_address_t pointsPPU = (ppu_address_t) convexShapeSPU->getUnscaledPoints();
+ cellDmaGet(&convexVertexData->g_convexPointBuffer[0], pointsPPU , dmaSize, DMA_TAG(2), 0, 0);
+}
+
+void dmaCollisionShape (void* collisionShapeLocation, ppu_address_t collisionShapePtr, uint32_t dmaTag, int shapeType)
+{
+ register int dmaSize = getShapeTypeSize(shapeType);
+ cellDmaGet(collisionShapeLocation, collisionShapePtr , dmaSize, DMA_TAG(dmaTag), 0, 0);
+ //cellDmaGetReadOnly(collisionShapeLocation, collisionShapePtr , dmaSize, DMA_TAG(dmaTag), 0, 0);
+ //cellDmaWaitTagStatusAll(DMA_MASK(dmaTag));
+}
+
+void dmaCompoundShapeInfo (CompoundShape_LocalStoreMemory* compoundShapeLocation, btCompoundShape* spuCompoundShape, uint32_t dmaTag)
+{
+ register int dmaSize;
+ register ppu_address_t dmaPpuAddress2;
+ int childShapeCount = spuCompoundShape->getNumChildShapes();
+ dmaSize = childShapeCount * sizeof(btCompoundShapeChild);
+ dmaPpuAddress2 = (ppu_address_t)spuCompoundShape->getChildList();
+ cellDmaGet(&compoundShapeLocation->gSubshapes[0], dmaPpuAddress2, dmaSize, DMA_TAG(dmaTag), 0, 0);
+}
+
+void dmaCompoundSubShapes (CompoundShape_LocalStoreMemory* compoundShapeLocation, btCompoundShape* spuCompoundShape, uint32_t dmaTag)
+{
+ int childShapeCount = spuCompoundShape->getNumChildShapes();
+ int i;
+ // DMA all the subshapes
+ for ( i = 0; i < childShapeCount; ++i)
+ {
+ btCompoundShapeChild& childShape = compoundShapeLocation->gSubshapes[i];
+ dmaCollisionShape (&compoundShapeLocation->gSubshapeShape[i],(ppu_address_t)childShape.m_childShape, dmaTag, childShape.m_childShapeType);
+ }
+}
+
+
+void spuWalkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax,const btQuantizedBvhNode* rootNode,int startNodeIndex,int endNodeIndex)
+{
+
+ int curIndex = startNodeIndex;
+ int walkIterations = 0;
+#ifdef BT_DEBUG
+ int subTreeSize = endNodeIndex - startNodeIndex;
+#endif
+
+ int escapeIndex;
+
+ unsigned int aabbOverlap, isLeafNode;
+
+ while (curIndex < endNodeIndex)
+ {
+ //catch bugs in tree data
+ btAssert (walkIterations < subTreeSize);
+
+ walkIterations++;
+ aabbOverlap = spuTestQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,rootNode->m_quantizedAabbMin,rootNode->m_quantizedAabbMax);
+ isLeafNode = rootNode->isLeafNode();
+
+ if (isLeafNode && aabbOverlap)
+ {
+ //printf("overlap with node %d\n",rootNode->getTriangleIndex());
+ nodeCallback->processNode(0,rootNode->getTriangleIndex());
+ // spu_printf("SPU: overlap detected with triangleIndex:%d\n",rootNode->getTriangleIndex());
+ }
+
+ if (aabbOverlap || isLeafNode)
+ {
+ rootNode++;
+ curIndex++;
+ } else
+ {
+ escapeIndex = rootNode->getEscapeIndex();
+ rootNode += escapeIndex;
+ curIndex += escapeIndex;
+ }
+ }
+
+}
diff --git a/tests/bullet/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuCollisionShapes.h b/tests/bullet/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuCollisionShapes.h
new file mode 100644
index 00000000..aa8a2910
--- /dev/null
+++ b/tests/bullet/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuCollisionShapes.h
@@ -0,0 +1,128 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+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.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+#ifndef __SPU_COLLISION_SHAPES_H
+#define __SPU_COLLISION_SHAPES_H
+
+#include "../SpuDoubleBuffer.h"
+
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/CollisionShapes/btConvexInternalShape.h"
+#include "BulletCollision/CollisionShapes/btCylinderShape.h"
+#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h"
+
+#include "BulletCollision/CollisionShapes/btOptimizedBvh.h"
+#include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h"
+#include "BulletCollision/CollisionShapes/btSphereShape.h"
+
+#include "BulletCollision/CollisionShapes/btCapsuleShape.h"
+
+#include "BulletCollision/CollisionShapes/btConvexShape.h"
+#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h"
+#include "BulletCollision/CollisionShapes/btConvexHullShape.h"
+#include "BulletCollision/CollisionShapes/btCompoundShape.h"
+
+#define MAX_NUM_SPU_CONVEX_POINTS 128 //@fallback to PPU if a btConvexHullShape has more than MAX_NUM_SPU_CONVEX_POINTS points
+#define MAX_SPU_COMPOUND_SUBSHAPES 16 //@fallback on PPU if compound has more than MAX_SPU_COMPOUND_SUBSHAPES child shapes
+#define MAX_SHAPE_SIZE 256 //@todo: assert on this
+
+ATTRIBUTE_ALIGNED16(struct) SpuConvexPolyhedronVertexData
+{
+ void* gSpuConvexShapePtr;
+ btVector3* gConvexPoints;
+ int gNumConvexPoints;
+ int unused;
+ ATTRIBUTE_ALIGNED16(btVector3 g_convexPointBuffer[MAX_NUM_SPU_CONVEX_POINTS]);
+};
+
+
+
+ATTRIBUTE_ALIGNED16(struct) CollisionShape_LocalStoreMemory
+{
+ ATTRIBUTE_ALIGNED16(char collisionShape[MAX_SHAPE_SIZE]);
+};
+
+ATTRIBUTE_ALIGNED16(struct) CompoundShape_LocalStoreMemory
+{
+ // Compound data
+
+ ATTRIBUTE_ALIGNED16(btCompoundShapeChild gSubshapes[MAX_SPU_COMPOUND_SUBSHAPES]);
+ ATTRIBUTE_ALIGNED16(char gSubshapeShape[MAX_SPU_COMPOUND_SUBSHAPES][MAX_SHAPE_SIZE]);
+};
+
+ATTRIBUTE_ALIGNED16(struct) bvhMeshShape_LocalStoreMemory
+{
+ //ATTRIBUTE_ALIGNED16(btOptimizedBvh gOptimizedBvh);
+ ATTRIBUTE_ALIGNED16(char gOptimizedBvh[sizeof(btOptimizedBvh)+16]);
+ btOptimizedBvh* getOptimizedBvh()
+ {
+ return (btOptimizedBvh*) gOptimizedBvh;
+ }
+
+ ATTRIBUTE_ALIGNED16(btTriangleIndexVertexArray gTriangleMeshInterfaceStorage);
+ btTriangleIndexVertexArray* gTriangleMeshInterfacePtr;
+ ///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
+ //1024
+ ATTRIBUTE_ALIGNED16(btBvhSubtreeInfo gSubtreeHeaders[MAX_SPU_SUBTREE_HEADERS]);
+ ATTRIBUTE_ALIGNED16(btQuantizedBvhNode gSubtreeNodes[MAX_SUBTREE_SIZE_IN_BYTES/sizeof(btQuantizedBvhNode)]);
+};
+
+
+void computeAabb (btVector3& aabbMin, btVector3& aabbMax, btConvexInternalShape* convexShape, ppu_address_t convexShapePtr, int shapeType, const btTransform& xform);
+void dmaBvhShapeData (bvhMeshShape_LocalStoreMemory* bvhMeshShape, btBvhTriangleMeshShape* triMeshShape);
+void dmaBvhIndexedMesh (btIndexedMesh* IndexMesh, IndexedMeshArray& indexArray, int index, uint32_t dmaTag);
+void dmaBvhSubTreeHeaders (btBvhSubtreeInfo* subTreeHeaders, ppu_address_t subTreePtr, int batchSize, uint32_t dmaTag);
+void dmaBvhSubTreeNodes (btQuantizedBvhNode* nodes, const btBvhSubtreeInfo& subtree, QuantizedNodeArray& nodeArray, int dmaTag);
+
+int getShapeTypeSize(int shapeType);
+void dmaConvexVertexData (SpuConvexPolyhedronVertexData* convexVertexData, btConvexHullShape* convexShapeSPU);
+void dmaCollisionShape (void* collisionShapeLocation, ppu_address_t collisionShapePtr, uint32_t dmaTag, int shapeType);
+void dmaCompoundShapeInfo (CompoundShape_LocalStoreMemory* compoundShapeLocation, btCompoundShape* spuCompoundShape, uint32_t dmaTag);
+void dmaCompoundSubShapes (CompoundShape_LocalStoreMemory* compoundShapeLocation, btCompoundShape* spuCompoundShape, uint32_t dmaTag);
+
+
+#define USE_BRANCHFREE_TEST 1
+#ifdef USE_BRANCHFREE_TEST
+SIMD_FORCE_INLINE unsigned int spuTestQuantizedAabbAgainstQuantizedAabb(unsigned short int* aabbMin1,unsigned short int* aabbMax1,const unsigned short int* aabbMin2,const unsigned short int* aabbMax2)
+{
+#if defined(__CELLOS_LV2__) && defined (__SPU__)
+ vec_ushort8 vecMin = {aabbMin1[0],aabbMin2[0],aabbMin1[2],aabbMin2[2],aabbMin1[1],aabbMin2[1],0,0};
+ vec_ushort8 vecMax = {aabbMax2[0],aabbMax1[0],aabbMax2[2],aabbMax1[2],aabbMax2[1],aabbMax1[1],0,0};
+ vec_ushort8 isGt = spu_cmpgt(vecMin,vecMax);
+ return spu_extract(spu_gather(isGt),0)==0;
+
+#else
+ return btSelect((unsigned)((aabbMin1[0] <= aabbMax2[0]) & (aabbMax1[0] >= aabbMin2[0])
+ & (aabbMin1[2] <= aabbMax2[2]) & (aabbMax1[2] >= aabbMin2[2])
+ & (aabbMin1[1] <= aabbMax2[1]) & (aabbMax1[1] >= aabbMin2[1])),
+ 1, 0);
+#endif
+}
+#else
+
+SIMD_FORCE_INLINE unsigned int spuTestQuantizedAabbAgainstQuantizedAabb(const unsigned short int* aabbMin1,const unsigned short int* aabbMax1,const unsigned short int* aabbMin2,const unsigned short int* aabbMax2)
+{
+ unsigned int overlap = 1;
+ overlap = (aabbMin1[0] > aabbMax2[0] || aabbMax1[0] < aabbMin2[0]) ? 0 : overlap;
+ overlap = (aabbMin1[2] > aabbMax2[2] || aabbMax1[2] < aabbMin2[2]) ? 0 : overlap;
+ overlap = (aabbMin1[1] > aabbMax2[1] || aabbMax1[1] < aabbMin2[1]) ? 0 : overlap;
+ return overlap;
+}
+#endif
+
+void spuWalkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax,const btQuantizedBvhNode* rootNode,int startNodeIndex,int endNodeIndex);
+
+#endif
diff --git a/tests/bullet/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuContactResult.cpp b/tests/bullet/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuContactResult.cpp
new file mode 100644
index 00000000..bd71373c
--- /dev/null
+++ b/tests/bullet/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuContactResult.cpp
@@ -0,0 +1,248 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+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.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "SpuContactResult.h"
+
+//#define DEBUG_SPU_COLLISION_DETECTION 1
+
+#ifdef DEBUG_SPU_COLLISION_DETECTION
+#ifndef __SPU__
+#include <stdio.h>
+#define spu_printf printf
+#endif
+#endif //DEBUG_SPU_COLLISION_DETECTION
+
+SpuContactResult::SpuContactResult()
+{
+ m_manifoldAddress = 0;
+ m_spuManifold = NULL;
+ m_RequiresWriteBack = false;
+}
+
+ SpuContactResult::~SpuContactResult()
+{
+ g_manifoldDmaExport.swapBuffers();
+}
+
+ ///User can override this material combiner by implementing gContactAddedCallback and setting body0->m_collisionFlags |= btCollisionObject::customMaterialCallback;
+inline btScalar calculateCombinedFriction(btScalar friction0,btScalar friction1)
+{
+ btScalar friction = friction0*friction1;
+
+ const btScalar MAX_FRICTION = btScalar(10.);
+
+ if (friction < -MAX_FRICTION)
+ friction = -MAX_FRICTION;
+ if (friction > MAX_FRICTION)
+ friction = MAX_FRICTION;
+ return friction;
+
+}
+
+inline btScalar calculateCombinedRestitution(btScalar restitution0,btScalar restitution1)
+{
+ return restitution0*restitution1;
+}
+
+
+
+ void SpuContactResult::setContactInfo(btPersistentManifold* spuManifold, ppu_address_t manifoldAddress,const btTransform& worldTrans0,const btTransform& worldTrans1, btScalar restitution0,btScalar restitution1, btScalar friction0,btScalar friction1, bool isSwapped)
+ {
+ //spu_printf("SpuContactResult::setContactInfo ManifoldAddress: %lu\n", manifoldAddress);
+ m_rootWorldTransform0 = worldTrans0;
+ m_rootWorldTransform1 = worldTrans1;
+ m_manifoldAddress = manifoldAddress;
+ m_spuManifold = spuManifold;
+
+ m_combinedFriction = calculateCombinedFriction(friction0,friction1);
+ m_combinedRestitution = calculateCombinedRestitution(restitution0,restitution1);
+ m_isSwapped = isSwapped;
+ }
+
+ void SpuContactResult::setShapeIdentifiersA(int partId0,int index0)
+ {
+
+ }
+
+ void SpuContactResult::setShapeIdentifiersB(int partId1,int index1)
+ {
+
+ }
+
+
+
+ ///return true if it requires a dma transfer back
+bool ManifoldResultAddContactPoint(const btVector3& normalOnBInWorld,
+ const btVector3& pointInWorld,
+ float depth,
+ btPersistentManifold* manifoldPtr,
+ btTransform& transA,
+ btTransform& transB,
+ btScalar combinedFriction,
+ btScalar combinedRestitution,
+ bool isSwapped)
+{
+
+// float contactTreshold = manifoldPtr->getContactBreakingThreshold();
+
+ //spu_printf("SPU: add contactpoint, depth:%f, contactTreshold %f, manifoldPtr %llx\n",depth,contactTreshold,manifoldPtr);
+
+#ifdef DEBUG_SPU_COLLISION_DETECTION
+ spu_printf("SPU: contactTreshold %f\n",contactTreshold);
+#endif //DEBUG_SPU_COLLISION_DETECTION
+ //if (depth > manifoldPtr->getContactBreakingThreshold())
+ // return false;
+
+ if (depth > manifoldPtr->getContactProcessingThreshold())
+ return false;
+
+
+
+ btVector3 pointA;
+ btVector3 localA;
+ btVector3 localB;
+ btVector3 normal;
+
+
+ if (isSwapped)
+ {
+ normal = normalOnBInWorld * -1;
+ pointA = pointInWorld + normal * depth;
+ localA = transA.invXform(pointA );
+ localB = transB.invXform(pointInWorld);
+ }
+ else
+ {
+ normal = normalOnBInWorld;
+ pointA = pointInWorld + normal * depth;
+ localA = transA.invXform(pointA );
+ localB = transB.invXform(pointInWorld);
+ }
+
+ btManifoldPoint newPt(localA,localB,normal,depth);
+ newPt.m_positionWorldOnA = pointA;
+ newPt.m_positionWorldOnB = pointInWorld;
+
+ newPt.m_combinedFriction = combinedFriction;
+ newPt.m_combinedRestitution = combinedRestitution;
+
+
+ int insertIndex = manifoldPtr->getCacheEntry(newPt);
+ if (insertIndex >= 0)
+ {
+ // we need to replace the current contact point, otherwise small errors will accumulate (spheres start rolling etc)
+ manifoldPtr->replaceContactPoint(newPt,insertIndex);
+ return true;
+
+ } else
+ {
+
+ /*
+ ///@todo: SPU callbacks, either immediate (local on the SPU), or deferred
+ //User can override friction and/or restitution
+ if (gContactAddedCallback &&
+ //and if either of the two bodies requires custom material
+ ((m_body0->m_collisionFlags & btCollisionObject::customMaterialCallback) ||
+ (m_body1->m_collisionFlags & btCollisionObject::customMaterialCallback)))
+ {
+ //experimental feature info, for per-triangle material etc.
+ (*gContactAddedCallback)(newPt,m_body0,m_partId0,m_index0,m_body1,m_partId1,m_index1);
+ }
+ */
+
+ manifoldPtr->addManifoldPoint(newPt);
+ return true;
+
+ }
+ return false;
+
+}
+
+
+void SpuContactResult::writeDoubleBufferedManifold(btPersistentManifold* lsManifold, btPersistentManifold* mmManifold)
+{
+ ///only write back the contact information on SPU. Other platforms avoid copying, and use the data in-place
+ ///see SpuFakeDma.cpp 'cellDmaLargeGetReadOnly'
+#if defined (__SPU__) || defined (USE_LIBSPE2)
+ memcpy(g_manifoldDmaExport.getFront(),lsManifold,sizeof(btPersistentManifold));
+
+ g_manifoldDmaExport.swapBuffers();
+ ppu_address_t mmAddr = (ppu_address_t)mmManifold;
+ g_manifoldDmaExport.backBufferDmaPut(mmAddr, sizeof(btPersistentManifold), DMA_TAG(9));
+ // Should there be any kind of wait here? What if somebody tries to use this tag again? What if we call this function again really soon?
+ //no, the swapBuffers does the wait
+#endif
+}
+
+void SpuContactResult::addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth)
+{
+#ifdef DEBUG_SPU_COLLISION_DETECTION
+ spu_printf("*** SpuContactResult::addContactPoint: depth = %f\n",depth);
+ spu_printf("*** normal = %f,%f,%f\n",normalOnBInWorld.getX(),normalOnBInWorld.getY(),normalOnBInWorld.getZ());
+ spu_printf("*** position = %f,%f,%f\n",pointInWorld.getX(),pointInWorld.getY(),pointInWorld.getZ());
+#endif //DEBUG_SPU_COLLISION_DETECTION
+
+
+#ifdef DEBUG_SPU_COLLISION_DETECTION
+ // int sman = sizeof(rage::phManifold);
+// spu_printf("sizeof_manifold = %i\n",sman);
+#endif //DEBUG_SPU_COLLISION_DETECTION
+
+ btPersistentManifold* localManifold = m_spuManifold;
+
+ btVector3 normalB(normalOnBInWorld.getX(),normalOnBInWorld.getY(),normalOnBInWorld.getZ());
+ btVector3 pointWrld(pointInWorld.getX(),pointInWorld.getY(),pointInWorld.getZ());
+
+ //process the contact point
+ const bool retVal = ManifoldResultAddContactPoint(normalB,
+ pointWrld,
+ depth,
+ localManifold,
+ m_rootWorldTransform0,
+ m_rootWorldTransform1,
+ m_combinedFriction,
+ m_combinedRestitution,
+ m_isSwapped);
+ m_RequiresWriteBack = m_RequiresWriteBack || retVal;
+}
+
+void SpuContactResult::flush()
+{
+
+ if (m_spuManifold && m_spuManifold->getNumContacts())
+ {
+ m_spuManifold->refreshContactPoints(m_rootWorldTransform0,m_rootWorldTransform1);
+ m_RequiresWriteBack = true;
+ }
+
+
+ if (m_RequiresWriteBack)
+ {
+#ifdef DEBUG_SPU_COLLISION_DETECTION
+ 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);
+#ifdef DEBUG_SPU_COLLISION_DETECTION
+ spu_printf("SPU: Finished (Put) DMA\n");
+#endif //DEBUG_SPU_COLLISION_DETECTION
+ }