Initial work on batch raycast support.
This commit is contained in:
84
Extras/BulletMultiThreaded/SpuBatchRaycaster.cpp
Normal file
84
Extras/BulletMultiThreaded/SpuBatchRaycaster.cpp
Normal file
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com
|
||||
|
||||
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 <new>
|
||||
#include "SpuBatchRaycaster.h"
|
||||
|
||||
SpuBatchRaycaster::SpuBatchRaycaster (class btThreadSupportInterface* threadInterface, int maxNumOutstandingTasks, btCollisionObjectArray& castUponObjects, int numCastUponObjects)
|
||||
{
|
||||
numCastUponObjectWrappers = numCastUponObjects;
|
||||
m_threadInterface = threadInterface;
|
||||
|
||||
castUponObjectWrappers = new SpuCollisionObjectWrapper[numCastUponObjects];
|
||||
|
||||
for (int i = 0; i < numCastUponObjectWrappers; i++)
|
||||
{
|
||||
new (&castUponObjectWrappers[i]) SpuCollisionObjectWrapper(castUponObjects[i]);
|
||||
}
|
||||
|
||||
m_spuRaycastTaskProcess = new SpuRaycastTaskProcess(m_threadInterface,maxNumOutstandingTasks); // FIXME non constant
|
||||
}
|
||||
|
||||
SpuBatchRaycaster::~SpuBatchRaycaster ()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
SpuBatchRaycaster::addRay (const btVector3& rayFrom, const btVector3& rayTo)
|
||||
{
|
||||
SpuRaycastTaskWorkUnitOut workUnitOut;
|
||||
workUnitOut.hitFraction = 0.99;
|
||||
workUnitOut.hitNormal = btVector3(0.0, 1.0, 0.0);
|
||||
|
||||
rayBatchOutput.push_back (workUnitOut);
|
||||
|
||||
SpuRaycastTaskWorkUnit workUnit;
|
||||
workUnit.rayFrom = rayFrom;
|
||||
workUnit.rayTo = rayTo;
|
||||
rayBatch.push_back (workUnit);
|
||||
}
|
||||
|
||||
void
|
||||
SpuBatchRaycaster::clearRays ()
|
||||
{
|
||||
rayBatch.clear ();
|
||||
rayBatchOutput.clear ();
|
||||
}
|
||||
|
||||
void
|
||||
SpuBatchRaycaster::performBatchRaycast ()
|
||||
{
|
||||
m_spuRaycastTaskProcess->initialize2 (castUponObjectWrappers, numCastUponObjectWrappers);
|
||||
|
||||
for (int i = 0; i < rayBatch.size(); i++)
|
||||
{
|
||||
rayBatch[i].output = &rayBatchOutput[i]; // assign output memory location
|
||||
m_spuRaycastTaskProcess->addWorkToTask(rayBatch[i]);
|
||||
}
|
||||
|
||||
m_spuRaycastTaskProcess->flush2 ();
|
||||
}
|
||||
|
||||
const SpuRaycastTaskWorkUnitOut&
|
||||
SpuBatchRaycaster::operator [] (int i) const
|
||||
{
|
||||
return rayBatchOutput[i];
|
||||
}
|
||||
|
||||
int
|
||||
SpuBatchRaycaster::getNumRays () const
|
||||
{
|
||||
return rayBatchOutput.size();
|
||||
}
|
||||
47
Extras/BulletMultiThreaded/SpuBatchRaycaster.h
Normal file
47
Extras/BulletMultiThreaded/SpuBatchRaycaster.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com
|
||||
|
||||
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_BATCH_RAYCASTER_H
|
||||
#define SPU_BATCH_RAYCASTER_H
|
||||
|
||||
#include "LinearMath/btAlignedObjectArray.h"
|
||||
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
|
||||
#include "SpuRaycastTaskProcess.h"
|
||||
#include "SpuRaycastTask/SpuRaycastTask.h"
|
||||
#include "SpuCollisionObjectWrapper.h"
|
||||
|
||||
/* FIXME:
|
||||
* Need to decide how callbacks are performed...
|
||||
*/
|
||||
class SpuBatchRaycaster
|
||||
{
|
||||
protected:
|
||||
SpuCollisionObjectWrapper* castUponObjectWrappers;
|
||||
int numCastUponObjectWrappers;
|
||||
btAlignedObjectArray<SpuRaycastTaskWorkUnit> rayBatch;
|
||||
btAlignedObjectArray<SpuRaycastTaskWorkUnitOut> rayBatchOutput;
|
||||
SpuRaycastTaskProcess* m_spuRaycastTaskProcess;
|
||||
class btThreadSupportInterface* m_threadInterface;
|
||||
public:
|
||||
SpuBatchRaycaster (class btThreadSupportInterface* threadInterface, int maxNumOutstandingTasks, btCollisionObjectArray& castUponObjects, int numCastUponObjects);
|
||||
~SpuBatchRaycaster ();
|
||||
void addRay (const btVector3& rayFrom, const btVector3& rayTo);
|
||||
void clearRays ();
|
||||
void performBatchRaycast ();
|
||||
const SpuRaycastTaskWorkUnitOut& operator [] (int i) const;
|
||||
int getNumRays () const;
|
||||
};
|
||||
|
||||
#endif
|
||||
48
Extras/BulletMultiThreaded/SpuCollisionObjectWrapper.cpp
Normal file
48
Extras/BulletMultiThreaded/SpuCollisionObjectWrapper.cpp
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com
|
||||
|
||||
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 "SpuCollisionObjectWrapper.h"
|
||||
#include "BulletCollision/CollisionShapes/btCollisionShape.h"
|
||||
|
||||
SpuCollisionObjectWrapper::SpuCollisionObjectWrapper ()
|
||||
{
|
||||
}
|
||||
|
||||
#ifndef __SPU__
|
||||
SpuCollisionObjectWrapper::SpuCollisionObjectWrapper (const btCollisionObject* collisionObject)
|
||||
{
|
||||
m_shapeType = collisionObject->getCollisionShape()->getShapeType ();
|
||||
m_collisionObjectPtr = (ppu_address_t)collisionObject;
|
||||
m_margin = collisionObject->getCollisionShape()->getMargin ();
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
SpuCollisionObjectWrapper::getShapeType () const
|
||||
{
|
||||
return m_shapeType;
|
||||
}
|
||||
|
||||
float
|
||||
SpuCollisionObjectWrapper::getCollisionMargin () const
|
||||
{
|
||||
return m_margin;
|
||||
}
|
||||
|
||||
ppu_address_t
|
||||
SpuCollisionObjectWrapper::getCollisionObjectPtr () const
|
||||
{
|
||||
return m_collisionObjectPtr;
|
||||
}
|
||||
35
Extras/BulletMultiThreaded/SpuCollisionObjectWrapper.h
Normal file
35
Extras/BulletMultiThreaded/SpuCollisionObjectWrapper.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com
|
||||
|
||||
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 "PlatformDefinitions.h"
|
||||
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
|
||||
|
||||
class SpuCollisionObjectWrapper
|
||||
{
|
||||
protected:
|
||||
int m_shapeType;
|
||||
float m_margin;
|
||||
ppu_address_t m_collisionObjectPtr;
|
||||
|
||||
public:
|
||||
SpuCollisionObjectWrapper ();
|
||||
|
||||
SpuCollisionObjectWrapper (const btCollisionObject* collisionObject);
|
||||
|
||||
int getShapeType () const;
|
||||
float getCollisionMargin () const;
|
||||
ppu_address_t getCollisionObjectPtr () const;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,464 @@
|
||||
/*
|
||||
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"
|
||||
|
||||
btPoint3 localGetSupportingVertexWithoutMargin(int shapeType, void* shape, btVector3& localDir,struct SpuConvexPolyhedronVertexData* convexVertexData)//, int *featureIndex)
|
||||
{
|
||||
switch (shapeType)
|
||||
{
|
||||
case SPHERE_SHAPE_PROXYTYPE:
|
||||
{
|
||||
return btPoint3(0,0,0);
|
||||
}
|
||||
case BOX_SHAPE_PROXYTYPE:
|
||||
{
|
||||
// spu_printf("SPU: getSupport BOX_SHAPE_PROXYTYPE\n");
|
||||
btConvexInternalShape* convexShape = (btConvexInternalShape*)shape;
|
||||
const btVector3& halfExtents = convexShape->getImplicitShapeDimensions();
|
||||
|
||||
return btPoint3(
|
||||
localDir.getX() < 0.0f ? -halfExtents.x() : halfExtents.x(),
|
||||
localDir.getY() < 0.0f ? -halfExtents.y() : halfExtents.y(),
|
||||
localDir.getZ() < 0.0f ? -halfExtents.z() : halfExtents.z());
|
||||
}
|
||||
|
||||
case TRIANGLE_SHAPE_PROXYTYPE:
|
||||
{
|
||||
|
||||
btVector3 dir(localDir.getX(),localDir.getY(),localDir.getZ());
|
||||
btVector3* vertices = (btVector3*)shape;
|
||||
btVector3 dots(dir.dot(vertices[0]), dir.dot(vertices[1]), dir.dot(vertices[2]));
|
||||
btVector3 sup = vertices[dots.maxAxis()];
|
||||
return btPoint3(sup.getX(),sup.getY(),sup.getZ());
|
||||
break;
|
||||
}
|
||||
|
||||
case CYLINDER_SHAPE_PROXYTYPE:
|
||||
{
|
||||
btCylinderShape* cylShape = (btCylinderShape*)shape;
|
||||
|
||||
//mapping of halfextents/dimension onto radius/height depends on how cylinder local orientation is (upAxis)
|
||||
|
||||
btVector3 halfExtents = cylShape->getImplicitShapeDimensions();
|
||||
btVector3 v(localDir.getX(),localDir.getY(),localDir.getZ());
|
||||
|
||||
int cylinderUpAxis = cylShape->getUpAxis();
|
||||
int XX(1),YY(0),ZZ(2);
|
||||
|
||||
switch (cylinderUpAxis)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
XX = 1;
|
||||
YY = 0;
|
||||
ZZ = 2;
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
XX = 0;
|
||||
YY = 1;
|
||||
ZZ = 2;
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
XX = 0;
|
||||
YY = 2;
|
||||
ZZ = 1;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
btAssert(0);
|
||||
//printf("SPU:localGetSupportingVertexWithoutMargin unknown Cylinder up-axis\n");
|
||||
};
|
||||
|
||||
btScalar radius = halfExtents[XX];
|
||||
btScalar halfHeight = halfExtents[cylinderUpAxis];
|
||||
|
||||
btVector3 tmp;
|
||||
btScalar d ;
|
||||
|
||||
btScalar s = btSqrt(v[XX] * v[XX] + v[ZZ] * v[ZZ]);
|
||||
if (s != btScalar(0.0))
|
||||
{
|
||||
d = radius / s;
|
||||
tmp[XX] = v[XX] * d;
|
||||
tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
|
||||
tmp[ZZ] = v[ZZ] * d;
|
||||
return btPoint3(tmp.getX(),tmp.getY(),tmp.getZ());
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp[XX] = radius;
|
||||
tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
|
||||
tmp[ZZ] = btScalar(0.0);
|
||||
return btPoint3(tmp.getX(),tmp.getY(),tmp.getZ());
|
||||
}
|
||||
}
|
||||
|
||||
case CAPSULE_SHAPE_PROXYTYPE:
|
||||
{
|
||||
//spu_printf("SPU: todo: getSupport CAPSULE_SHAPE_PROXYTYPE\n");
|
||||
btVector3 vec0(localDir.getX(),localDir.getY(),localDir.getZ());
|
||||
|
||||
btConvexInternalShape* cnvxShape = (btConvexInternalShape*)shape;
|
||||
btVector3 halfExtents = cnvxShape->getImplicitShapeDimensions();
|
||||
btScalar halfHeight = halfExtents.getY();
|
||||
btScalar radius = halfExtents.getX();
|
||||
btVector3 supVec(0,0,0);
|
||||
|
||||
btScalar maxDot(btScalar(-1e30));
|
||||
|
||||
btVector3 vec = vec0;
|
||||
btScalar lenSqr = vec.length2();
|
||||
if (lenSqr < btScalar(0.0001))
|
||||
{
|
||||
vec.setValue(1,0,0);
|
||||
} else
|
||||
{
|
||||
btScalar rlen = btScalar(1.) / btSqrt(lenSqr );
|
||||
vec *= rlen;
|
||||
}
|
||||
btVector3 vtx;
|
||||
btScalar newDot;
|
||||
{
|
||||
btVector3 pos(0,halfHeight,0);
|
||||
vtx = pos +vec*(radius);
|
||||
newDot = vec.dot(vtx);
|
||||
if (newDot > maxDot)
|
||||
{
|
||||
maxDot = newDot;
|
||||
supVec = vtx;
|
||||
}
|
||||
}
|
||||
{
|
||||
btVector3 pos(0,-halfHeight,0);
|
||||
vtx = pos +vec*(radius);
|
||||
newDot = vec.dot(vtx);
|
||||
if (newDot > maxDot)
|
||||
{
|
||||
maxDot = newDot;
|
||||
supVec = vtx;
|
||||
}
|
||||
}
|
||||
return btPoint3(supVec.getX(),supVec.getY(),supVec.getZ());
|
||||
break;
|
||||
};
|
||||
|
||||
case CONVEX_HULL_SHAPE_PROXYTYPE:
|
||||
{
|
||||
//spu_printf("SPU: todo: getSupport CONVEX_HULL_SHAPE_PROXYTYPE\n");
|
||||
|
||||
|
||||
|
||||
btPoint3* points = 0;
|
||||
int numPoints = 0;
|
||||
points = convexVertexData->gConvexPoints;
|
||||
numPoints = convexVertexData->gNumConvexPoints;
|
||||
|
||||
// spu_printf("numPoints = %d\n",numPoints);
|
||||
|
||||
btVector3 supVec(btScalar(0.),btScalar(0.),btScalar(0.));
|
||||
btScalar newDot,maxDot = btScalar(-1e30);
|
||||
|
||||
btVector3 vec0(localDir.getX(),localDir.getY(),localDir.getZ());
|
||||
btVector3 vec = vec0;
|
||||
btScalar lenSqr = vec.length2();
|
||||
if (lenSqr < btScalar(0.0001))
|
||||
{
|
||||
vec.setValue(1,0,0);
|
||||
} else
|
||||
{
|
||||
btScalar rlen = btScalar(1.) / btSqrt(lenSqr );
|
||||
vec *= rlen;
|
||||
}
|
||||
|
||||
|
||||
for (int i=0;i<numPoints;i++)
|
||||
{
|
||||
btPoint3 vtx = points[i];// * m_localScaling;
|
||||
|
||||
newDot = vec.dot(vtx);
|
||||
if (newDot > maxDot)
|
||||
{
|
||||
maxDot = newDot;
|
||||
supVec = vtx;
|
||||
}
|
||||
}
|
||||
return btPoint3(supVec.getX(),supVec.getY(),supVec.getZ());
|
||||
|
||||
break;
|
||||
};
|
||||
|
||||
default:
|
||||
|
||||
//spu_printf("SPU:(type %i) missing support function\n",shapeType);
|
||||
|
||||
|
||||
#if __ASSERT
|
||||
spu_printf("localGetSupportingVertexWithoutMargin() - Unsupported bound type: %d.\n", shapeType);
|
||||
#endif // __ASSERT
|
||||
return btPoint3(0.f, 0.f, 0.f);
|
||||
}
|
||||
}
|
||||
|
||||
void computeAabb (btVector3& aabbMin, btVector3& aabbMax, btConvexInternalShape* convexShape, ppu_address_t convexShapePtr, int shapeType, btTransform xform)
|
||||
{
|
||||
//calculate the aabb, given the types...
|
||||
switch (shapeType)
|
||||
{
|
||||
case CYLINDER_SHAPE_PROXYTYPE:
|
||||
/* fall through */
|
||||
case BOX_SHAPE_PROXYTYPE:
|
||||
{
|
||||
float margin=convexShape->getMarginNV();
|
||||
btVector3 halfExtents = convexShape->getImplicitShapeDimensions();
|
||||
btTransform& t = xform;
|
||||
btMatrix3x3 abs_b = t.getBasis().absolute();
|
||||
btPoint3 center = t.getOrigin();
|
||||
btVector3 extent = btVector3(abs_b[0].dot(halfExtents),abs_b[1].dot(halfExtents),abs_b[2].dot(halfExtents));
|
||||
extent += btVector3(margin,margin,margin);
|
||||
aabbMin = center - extent;
|
||||
aabbMax = center + extent;
|
||||
break;
|
||||
}
|
||||
case CAPSULE_SHAPE_PROXYTYPE:
|
||||
{
|
||||
float margin=convexShape->getMarginNV();
|
||||
btVector3 halfExtents = convexShape->getImplicitShapeDimensions();
|
||||
//add the radius to y-axis to get full height
|
||||
btScalar radius = halfExtents[0];
|
||||
halfExtents[1] += radius;
|
||||
btTransform& t = xform;
|
||||
btMatrix3x3 abs_b = t.getBasis().absolute();
|
||||
btPoint3 center = t.getOrigin();
|
||||
btVector3 extent = btVector3(abs_b[0].dot(halfExtents),abs_b[1].dot(halfExtents),abs_b[2].dot(halfExtents));
|
||||
extent += btVector3(margin,margin,margin);
|
||||
aabbMin = center - extent;
|
||||
aabbMax = center + extent;
|
||||
break;
|
||||
}
|
||||
case SPHERE_SHAPE_PROXYTYPE:
|
||||
{
|
||||
float radius = convexShape->getImplicitShapeDimensions().getX();// * convexShape->getLocalScaling().getX();
|
||||
float margin = radius + convexShape->getMarginNV();
|
||||
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;
|
||||
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);
|
||||
bvhMeshShape->gTriangleMeshInterfacePtr = (btTriangleIndexVertexArray*)cellDmaGetReadOnly(&bvhMeshShape->gTriangleMeshInterfaceStorage, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0);
|
||||
//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;
|
||||
}
|
||||
|
||||
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(btPoint3);
|
||||
ppu_address_t pointsPPU = (ppu_address_t) convexShapeSPU->getPoints();
|
||||
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);
|
||||
//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;
|
||||
int subTreeSize = endNodeIndex - startNodeIndex;
|
||||
|
||||
int escapeIndex;
|
||||
|
||||
unsigned int aabbOverlap, isLeafNode;
|
||||
|
||||
while (curIndex < endNodeIndex)
|
||||
{
|
||||
//catch bugs in tree data
|
||||
assert (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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
#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/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
|
||||
|
||||
struct SpuConvexPolyhedronVertexData
|
||||
{
|
||||
void* gSpuConvexShapePtr;
|
||||
btPoint3* gConvexPoints;
|
||||
int gNumConvexPoints;
|
||||
ATTRIBUTE_ALIGNED16(btPoint3 g_convexPointBuffer[MAX_NUM_SPU_CONVEX_POINTS]);
|
||||
};
|
||||
|
||||
#define MAX_SHAPE_SIZE 256
|
||||
|
||||
struct CollisionShape_LocalStoreMemory
|
||||
{
|
||||
ATTRIBUTE_ALIGNED16(char collisionShape[MAX_SHAPE_SIZE]);
|
||||
};
|
||||
|
||||
struct CompoundShape_LocalStoreMemory
|
||||
{
|
||||
// Compound data
|
||||
#define MAX_SPU_COMPOUND_SUBSHAPES 16
|
||||
ATTRIBUTE_ALIGNED16(btCompoundShapeChild gSubshapes[MAX_SPU_COMPOUND_SUBSHAPES]);
|
||||
ATTRIBUTE_ALIGNED16(char gSubshapeShape[MAX_SPU_COMPOUND_SUBSHAPES][MAX_SHAPE_SIZE]);
|
||||
};
|
||||
|
||||
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)]);
|
||||
};
|
||||
|
||||
|
||||
|
||||
btPoint3 localGetSupportingVertexWithoutMargin(int shapeType, void* shape, btVector3& localDir,struct SpuConvexPolyhedronVertexData* convexVertexData);//, int *featureIndex)
|
||||
void computeAabb (btVector3& aabbMin, btVector3& aabbMax, btConvexInternalShape* convexShape, ppu_address_t convexShapePtr, int shapeType, 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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
#else
|
||||
|
||||
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
|
||||
118
Extras/BulletMultiThreaded/SpuRaycastTask/SpuRaycastTask.cpp
Normal file
118
Extras/BulletMultiThreaded/SpuRaycastTask/SpuRaycastTask.cpp
Normal file
@@ -0,0 +1,118 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "SpuRaycastTask.h"
|
||||
#include "SpuCollisionObjectWrapper.h"
|
||||
#include "SpuNarrowPhaseCollisionTask/SpuCollisionShapes.h"
|
||||
|
||||
|
||||
|
||||
struct RaycastTask_LocalStoreMemory
|
||||
{
|
||||
ATTRIBUTE_ALIGNED16(char gColObj [sizeof(btCollisionObject)+16]);
|
||||
btCollisionObject* getColObj()
|
||||
{
|
||||
return (btCollisionObject*) gColObj;
|
||||
}
|
||||
|
||||
SpuCollisionObjectWrapper gCollisionObjectWrapper;
|
||||
SpuCollisionObjectWrapper* getCollisionObjectWrapper ()
|
||||
{
|
||||
return &gCollisionObjectWrapper;
|
||||
}
|
||||
|
||||
CollisionShape_LocalStoreMemory gCollisionShape;
|
||||
ATTRIBUTE_ALIGNED16(int spuIndices[16]);
|
||||
|
||||
bvhMeshShape_LocalStoreMemory bvhShapeData;
|
||||
SpuConvexPolyhedronVertexData convexVertexData;
|
||||
CompoundShape_LocalStoreMemory compoundShapeData;
|
||||
};
|
||||
|
||||
#ifdef WIN32
|
||||
void* createRaycastLocalStoreMemory()
|
||||
{
|
||||
return new RaycastTask_LocalStoreMemory;
|
||||
};
|
||||
#elif defined(__CELLOS_LV2__)
|
||||
ATTRIBUTE_ALIGNED16(RaycastTask_LocalStoreMemory gLocalStoreMemory);
|
||||
void* createRaycastLocalStoreMemory()
|
||||
{
|
||||
return &gLocalStoreMemory;
|
||||
}
|
||||
#endif
|
||||
|
||||
void GatherCollisionObjectAndShapeData (RaycastGatheredObjectData& gatheredObjectData, RaycastTask_LocalStoreMemory& lsMem, ppu_address_t objectWrapper)
|
||||
{
|
||||
register int dmaSize;
|
||||
register ppu_address_t dmaPpuAddress2;
|
||||
|
||||
/* DMA Collision object wrapper into local store */
|
||||
dmaSize = sizeof(SpuCollisionObjectWrapper);
|
||||
dmaPpuAddress2 = objectWrapper;
|
||||
cellDmaGet(&lsMem.gCollisionObjectWrapper, dmaPpuAddress2, dmaSize, DMA_TAG(1), 0, 0);
|
||||
cellDmaWaitTagStatusAll(DMA_MASK(1));
|
||||
|
||||
/* DMA Collision object into local store */
|
||||
dmaSize = sizeof(btCollisionObject);
|
||||
dmaPpuAddress2 = lsMem.getCollisionObjectWrapper()->getCollisionObjectPtr();
|
||||
cellDmaGet(&lsMem.gColObj, dmaPpuAddress2 , dmaSize, DMA_TAG(2), 0, 0);
|
||||
cellDmaWaitTagStatusAll(DMA_MASK(2));
|
||||
|
||||
/* Gather information about collision object and shape */
|
||||
gatheredObjectData.m_worldTransform = lsMem.getColObj()->getWorldTransform();
|
||||
gatheredObjectData.m_collisionMargin = lsMem.getCollisionObjectWrapper()->getCollisionMargin ();
|
||||
gatheredObjectData.m_shapeType = lsMem.getCollisionObjectWrapper()->getShapeType ();
|
||||
gatheredObjectData.m_collisionShape = (ppu_address_t)lsMem.getColObj()->getCollisionShape();
|
||||
gatheredObjectData.m_spuCollisionShape = (void*)&lsMem.gCollisionShape.collisionShape[0];
|
||||
|
||||
/* DMA shape data */
|
||||
dmaCollisionShape (gatheredObjectData.m_spuCollisionShape, gatheredObjectData.m_collisionShape, 1, gatheredObjectData.m_shapeType);
|
||||
cellDmaWaitTagStatusAll(DMA_MASK(1));
|
||||
btConvexInternalShape* spuConvexShape = (btConvexInternalShape*)gatheredObjectData.m_spuCollisionShape;
|
||||
gatheredObjectData.m_primitiveDimensions = spuConvexShape->getImplicitShapeDimensions ();
|
||||
}
|
||||
|
||||
void dmaLoadRayOutput (ppu_address_t rayOutputAddr, SpuRaycastTaskWorkUnitOut* rayOutput, uint32_t dmaTag)
|
||||
{
|
||||
cellDmaGet(rayOutput, rayOutputAddr, sizeof(*rayOutput), DMA_TAG(dmaTag), 0, 0);
|
||||
}
|
||||
|
||||
void dmaStoreRayOutput (ppu_address_t rayOutputAddr, const SpuRaycastTaskWorkUnitOut* rayOutput, uint32_t dmaTag)
|
||||
{
|
||||
cellDmaLargePut (rayOutput, rayOutputAddr, sizeof(*rayOutput), DMA_TAG(dmaTag), 0, 0);
|
||||
}
|
||||
|
||||
void processRaycastTask(void* userPtr, void* lsMemory)
|
||||
{
|
||||
RaycastTask_LocalStoreMemory* localMemory = (RaycastTask_LocalStoreMemory*)lsMemory;
|
||||
|
||||
SpuRaycastTaskDesc* taskDescPtr = (SpuRaycastTaskDesc*)userPtr;
|
||||
SpuRaycastTaskDesc& taskDesc = *taskDescPtr;
|
||||
|
||||
SpuCollisionObjectWrapper* cows = (SpuCollisionObjectWrapper*)taskDesc.spuCollisionObjectsWrappers;
|
||||
|
||||
/* for each object */
|
||||
for (int objectId = 0; objectId < taskDesc.numSpuCollisionObjectWrappers; objectId++)
|
||||
{
|
||||
RaycastGatheredObjectData gatheredObjectData;
|
||||
GatherCollisionObjectAndShapeData (gatheredObjectData, *localMemory, (ppu_address_t)&cows[objectId]);
|
||||
/* load initial collision shape */
|
||||
for (int rayId = 0; rayId < taskDesc.numWorkUnits; rayId++)
|
||||
{
|
||||
SpuRaycastTaskWorkUnitOut rayOut;
|
||||
|
||||
dmaLoadRayOutput ((ppu_address_t)taskDesc.workUnits[rayId].output, &rayOut, 1);
|
||||
cellDmaWaitTagStatusAll(DMA_MASK(1));
|
||||
|
||||
float t = (float)rayId/(float)taskDesc.numWorkUnits;
|
||||
/* performRaycast */
|
||||
rayOut.hitFraction = 0.1f * t;
|
||||
rayOut.hitNormal = btVector3(1.0, 0.0, 0.0);
|
||||
|
||||
/* write ray cast data back */
|
||||
dmaStoreRayOutput ((ppu_address_t)taskDesc.workUnits[rayId].output, &rayOut, 1);
|
||||
cellDmaWaitTagStatusAll(DMA_MASK(1));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
48
Extras/BulletMultiThreaded/SpuRaycastTask/SpuRaycastTask.h
Normal file
48
Extras/BulletMultiThreaded/SpuRaycastTask/SpuRaycastTask.h
Normal file
@@ -0,0 +1,48 @@
|
||||
#ifndef __SPU_RAYCAST_TASK_H
|
||||
#define __SPU_RAYCAST_TASK_H
|
||||
|
||||
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
|
||||
#include "BulletCollision/CollisionDispatch/btCollisionWorld.h"
|
||||
#include "LinearMath/btVector3.h"
|
||||
#include "PlatformDefinitions.h"
|
||||
|
||||
struct RaycastGatheredObjectData
|
||||
{
|
||||
ppu_address_t m_collisionShape;
|
||||
void* m_spuCollisionShape;
|
||||
btVector3 m_primitiveDimensions;
|
||||
int m_shapeType;
|
||||
float m_collisionMargin;
|
||||
btTransform m_worldTransform;
|
||||
};
|
||||
|
||||
struct SpuRaycastTaskWorkUnitOut
|
||||
{
|
||||
btVector3 hitNormal; /* out */
|
||||
btScalar hitFraction; /* out */
|
||||
btCollisionWorld::LocalShapeInfo shapeInfo; /* out */
|
||||
};
|
||||
|
||||
/* Perform a raycast on collision object */
|
||||
struct SpuRaycastTaskWorkUnit
|
||||
{
|
||||
btVector3 rayFrom; /* in */
|
||||
btVector3 rayTo; /* in */
|
||||
SpuRaycastTaskWorkUnitOut* output; /* out */
|
||||
};
|
||||
|
||||
#define SPU_RAYCAST_WORK_UNITS_PER_TASK 16
|
||||
|
||||
struct SpuRaycastTaskDesc
|
||||
{
|
||||
SpuRaycastTaskWorkUnit workUnits[SPU_RAYCAST_WORK_UNITS_PER_TASK];
|
||||
int numWorkUnits;
|
||||
void* spuCollisionObjectsWrappers;
|
||||
int numSpuCollisionObjectWrappers;
|
||||
int taskId;
|
||||
};
|
||||
|
||||
void processRaycastTask (void* userPtr, void* lsMemory);
|
||||
void* createRaycastLocalStoreMemory ();
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
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 "SpuSubSimplexConvexCast.h"
|
||||
#include "SpuNarrowPhaseCollisionTask/SpuCollisionShapes.h"
|
||||
|
||||
#include "BulletCollision/CollisionShapes/btConvexShape.h"
|
||||
#include "BulletCollision/CollisionShapes/btMinkowskiSumShape.h"
|
||||
#include "BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h"
|
||||
|
||||
|
||||
SpuSubsimplexConvexCast::SpuSubsimplexConvexCast (const void* convexA,
|
||||
const void* convexB,
|
||||
SpuVoronoiSimplexSolver* simplexSolver)
|
||||
:m_simplexSolver(simplexSolver), m_convexA(convexA),m_convexB(convexB)
|
||||
{
|
||||
}
|
||||
|
||||
///Typically the conservative advancement reaches solution in a few iterations, clip it to 32 for degenerate cases.
|
||||
///See discussion about this here http://continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=565
|
||||
#ifdef BT_USE_DOUBLE_PRECISION
|
||||
#define MAX_ITERATIONS 64
|
||||
#else
|
||||
#define MAX_ITERATIONS 32
|
||||
#endif
|
||||
|
||||
bool SpuSubsimplexConvexCast::calcTimeOfImpact(const btTransform& fromA,
|
||||
const btTransform& toA,
|
||||
const btTransform& fromB,
|
||||
const btTransform& toB,
|
||||
SpuCastResult& result)
|
||||
{
|
||||
//localGetSupportingVertexWithoutMargin(m_shapeTypeA, m_minkowskiA, seperatingAxisInA,input.m_convexVertexData[0]);
|
||||
#if 0
|
||||
btMinkowskiSumShape combi(m_convexA,m_convexB);
|
||||
btMinkowskiSumShape* convex = &combi;
|
||||
|
||||
btTransform rayFromLocalA;
|
||||
btTransform rayToLocalA;
|
||||
|
||||
rayFromLocalA = fromA.inverse()* fromB;
|
||||
rayToLocalA = toA.inverse()* toB;
|
||||
|
||||
|
||||
m_simplexSolver->reset();
|
||||
|
||||
convex->setTransformB(btTransform(rayFromLocalA.getBasis()));
|
||||
|
||||
//btScalar radius = btScalar(0.01);
|
||||
|
||||
btScalar lambda = btScalar(0.);
|
||||
//todo: need to verify this:
|
||||
//because of minkowski difference, we need the inverse direction
|
||||
|
||||
btVector3 s = -rayFromLocalA.getOrigin();
|
||||
btVector3 r = -(rayToLocalA.getOrigin()-rayFromLocalA.getOrigin());
|
||||
btVector3 x = s;
|
||||
btVector3 v;
|
||||
btVector3 arbitraryPoint = convex->localGetSupportingVertex(r);
|
||||
|
||||
v = x - arbitraryPoint;
|
||||
|
||||
int maxIter = MAX_ITERATIONS;
|
||||
|
||||
btVector3 n;
|
||||
n.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
|
||||
bool hasResult = false;
|
||||
btVector3 c;
|
||||
|
||||
btScalar lastLambda = lambda;
|
||||
|
||||
|
||||
btScalar dist2 = v.length2();
|
||||
#ifdef BT_USE_DOUBLE_PRECISION
|
||||
btScalar epsilon = btScalar(0.0001);
|
||||
#else
|
||||
btScalar epsilon = btScalar(0.0001);
|
||||
#endif //BT_USE_DOUBLE_PRECISION
|
||||
btVector3 w,p;
|
||||
btScalar VdotR;
|
||||
|
||||
while ( (dist2 > epsilon) && maxIter--)
|
||||
{
|
||||
p = convex->localGetSupportingVertex( v);
|
||||
w = x - p;
|
||||
|
||||
btScalar VdotW = v.dot(w);
|
||||
|
||||
if ( VdotW > btScalar(0.))
|
||||
{
|
||||
VdotR = v.dot(r);
|
||||
|
||||
if (VdotR >= -(SIMD_EPSILON*SIMD_EPSILON))
|
||||
return false;
|
||||
else
|
||||
{
|
||||
lambda = lambda - VdotW / VdotR;
|
||||
x = s + lambda * r;
|
||||
m_simplexSolver->reset();
|
||||
//check next line
|
||||
w = x-p;
|
||||
lastLambda = lambda;
|
||||
n = v;
|
||||
hasResult = true;
|
||||
}
|
||||
}
|
||||
m_simplexSolver->addVertex( w, x , p);
|
||||
if (m_simplexSolver->closest(v))
|
||||
{
|
||||
dist2 = v.length2();
|
||||
hasResult = true;
|
||||
//printf("V=%f , %f, %f\n",v[0],v[1],v[2]);
|
||||
//printf("DIST2=%f\n",dist2);
|
||||
//printf("numverts = %i\n",m_simplexSolver->numVertices());
|
||||
} else
|
||||
{
|
||||
dist2 = btScalar(0.);
|
||||
}
|
||||
}
|
||||
|
||||
//int numiter = MAX_ITERATIONS - maxIter;
|
||||
// printf("number of iterations: %d", numiter);
|
||||
result.m_fraction = lambda;
|
||||
result.m_normal = n;
|
||||
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
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_SUBSIMPLEX_CONVEX_CAST_H
|
||||
#define SPU_SUBSIMPLEX_CONVEX_CAST_H
|
||||
|
||||
#include "SpuNarrowPhaseCollisionTask/SpuVoronoiSimplexSolver.h"
|
||||
#include "SpuRaycastTask.h"
|
||||
|
||||
class btConvexShape;
|
||||
|
||||
struct SpuCastResult
|
||||
{
|
||||
};
|
||||
|
||||
/// btSubsimplexConvexCast implements Gino van den Bergens' paper
|
||||
///"Ray Casting against bteral Convex Objects with Application to Continuous Collision Detection"
|
||||
/// GJK based Ray Cast, optimized version
|
||||
/// Objects should not start in overlap, otherwise results are not defined.
|
||||
class SpuSubsimplexConvexCast
|
||||
{
|
||||
SpuVoronoiSimplexSolver* m_simplexSolver;
|
||||
const void* m_convexA;
|
||||
const void* m_convexB;
|
||||
RaycastGatheredObjectData* m_dataB;
|
||||
public:
|
||||
|
||||
SpuSubsimplexConvexCast (const void* shapeA,
|
||||
const void* shapeB,
|
||||
SpuVoronoiSimplexSolver* simplexSolver);
|
||||
|
||||
//virtual ~btSubsimplexConvexCast();
|
||||
///SimsimplexConvexCast calculateTimeOfImpact calculates the time of impact+normal for the linear cast (sweep) between two moving objects.
|
||||
///Precondition is that objects should not penetration/overlap at the start from the interval. Overlap can be tested using btGjkPairDetector.
|
||||
bool calcTimeOfImpact(const btTransform& fromA,
|
||||
const btTransform& toA,
|
||||
const btTransform& fromB,
|
||||
const btTransform& toB,
|
||||
SpuCastResult& result);
|
||||
|
||||
};
|
||||
|
||||
#endif //SUBSIMPLEX_CONVEX_CAST_H
|
||||
172
Extras/BulletMultiThreaded/SpuRaycastTaskProcess.cpp
Normal file
172
Extras/BulletMultiThreaded/SpuRaycastTaskProcess.cpp
Normal file
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com
|
||||
|
||||
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 "SpuRaycastTaskProcess.h"
|
||||
|
||||
SpuRaycastTaskProcess::SpuRaycastTaskProcess(class btThreadSupportInterface* threadInterface, unsigned int maxNumOutstandingTasks)
|
||||
:m_threadInterface(threadInterface),
|
||||
m_maxNumOutstandingTasks(maxNumOutstandingTasks)
|
||||
{
|
||||
m_workUnitTaskBuffers = (unsigned char *)0;
|
||||
m_taskBusy.resize(m_maxNumOutstandingTasks);
|
||||
m_spuRaycastTaskDesc.resize(m_maxNumOutstandingTasks);
|
||||
|
||||
for (int i = 0; i < m_maxNumOutstandingTasks; i++)
|
||||
{
|
||||
m_taskBusy[i] = false;
|
||||
}
|
||||
m_numBusyTasks = 0;
|
||||
m_currentTask = 0;
|
||||
m_currentWorkUnitInTask = 0;
|
||||
|
||||
m_threadInterface->startSPU();
|
||||
|
||||
//printf("sizeof vec_float4: %d\n", sizeof(vec_float4));
|
||||
//printf("sizeof SpuGatherAndProcessWorkUnitInput: %d\n", sizeof(SpuGatherAndProcessWorkUnitInput));
|
||||
|
||||
}
|
||||
|
||||
SpuRaycastTaskProcess::~SpuRaycastTaskProcess()
|
||||
{
|
||||
|
||||
if (m_workUnitTaskBuffers != 0)
|
||||
{
|
||||
btAlignedFree(m_workUnitTaskBuffers);
|
||||
m_workUnitTaskBuffers = 0;
|
||||
}
|
||||
|
||||
m_threadInterface->stopSPU();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void SpuRaycastTaskProcess::initialize2(void* spuCollisionObjectsWrappers, int numSpuCollisionObjectWrappers)
|
||||
{
|
||||
m_spuCollisionObjectWrappers = spuCollisionObjectsWrappers;
|
||||
m_numSpuCollisionObjectWrappers = numSpuCollisionObjectWrappers;
|
||||
for (int i = 0; i < m_maxNumOutstandingTasks; i++)
|
||||
{
|
||||
m_taskBusy[i] = false;
|
||||
}
|
||||
m_numBusyTasks = 0;
|
||||
m_currentTask = 0;
|
||||
m_currentWorkUnitInTask = 0;
|
||||
|
||||
#ifdef DEBUG_SpuRaycastTaskProcess
|
||||
m_initialized = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void SpuRaycastTaskProcess::issueTask2()
|
||||
{
|
||||
m_taskBusy[m_currentTask] = true;
|
||||
m_numBusyTasks++;
|
||||
|
||||
SpuRaycastTaskDesc& taskDesc = m_spuRaycastTaskDesc[m_currentTask];
|
||||
|
||||
taskDesc.taskId = m_currentTask;
|
||||
m_threadInterface->sendRequest(1, (uint32_t) &taskDesc,m_currentTask);
|
||||
//printf("send thread requested for task %d\n", m_currentTask);
|
||||
// if all tasks busy, wait for spu event to clear the task.
|
||||
if (m_numBusyTasks >= m_maxNumOutstandingTasks)
|
||||
{
|
||||
unsigned int taskId;
|
||||
unsigned int outputSize;
|
||||
|
||||
m_threadInterface->waitForResponse(&taskId, &outputSize);
|
||||
|
||||
//printf("PPU: after issue, received event: %u %d\n", taskId, outputSize);
|
||||
|
||||
m_taskBusy[taskId] = false;
|
||||
|
||||
m_numBusyTasks--;
|
||||
} else {
|
||||
//printf("Sent request, not enough busy tasks\n");
|
||||
}
|
||||
}
|
||||
|
||||
void SpuRaycastTaskProcess::addWorkToTask(SpuRaycastTaskWorkUnit workunit)
|
||||
{
|
||||
m_spuRaycastTaskDesc[m_currentTask].workUnits[m_currentWorkUnitInTask] = workunit;
|
||||
m_currentWorkUnitInTask++;
|
||||
if (m_currentWorkUnitInTask == SPU_RAYCAST_WORK_UNITS_PER_TASK)
|
||||
{
|
||||
m_spuRaycastTaskDesc[m_currentTask].numWorkUnits = m_currentWorkUnitInTask;
|
||||
m_spuRaycastTaskDesc[m_currentTask].numSpuCollisionObjectWrappers = m_numSpuCollisionObjectWrappers;
|
||||
m_spuRaycastTaskDesc[m_currentTask].spuCollisionObjectsWrappers = m_spuCollisionObjectWrappers;
|
||||
//printf("Task buffer full, issuing\n");
|
||||
issueTask2 ();
|
||||
//printf("Returned from issueTask2()\n");
|
||||
m_currentWorkUnitInTask = 0;
|
||||
|
||||
// find new task buffer
|
||||
for (unsigned int i = 0; i < m_maxNumOutstandingTasks; i++)
|
||||
{
|
||||
if (!m_taskBusy[i])
|
||||
{
|
||||
m_currentTask = i;
|
||||
//init the task data
|
||||
break;
|
||||
}
|
||||
}
|
||||
//printf("next task = %d\n", m_currentTask);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SpuRaycastTaskProcess::flush2()
|
||||
{
|
||||
#ifdef DEBUG_SPU_TASK_SCHEDULING
|
||||
printf("\nSpuRaycastTaskProcess::flush()\n");
|
||||
#endif //DEBUG_SPU_TASK_SCHEDULING
|
||||
|
||||
// if there's a partially filled task buffer, submit that task
|
||||
//printf("Flushing... %d remaining\n", m_currentWorkUnitInTask);
|
||||
if (m_currentWorkUnitInTask > 0)
|
||||
{
|
||||
m_spuRaycastTaskDesc[m_currentTask].numWorkUnits = m_currentWorkUnitInTask;
|
||||
m_spuRaycastTaskDesc[m_currentTask].numSpuCollisionObjectWrappers = m_numSpuCollisionObjectWrappers;
|
||||
m_spuRaycastTaskDesc[m_currentTask].spuCollisionObjectsWrappers = m_spuCollisionObjectWrappers;
|
||||
issueTask2();
|
||||
m_currentWorkUnitInTask = 0;
|
||||
}
|
||||
|
||||
|
||||
// all tasks are issued, wait for all tasks to be complete
|
||||
while(m_numBusyTasks > 0)
|
||||
{
|
||||
// Consolidating SPU code
|
||||
unsigned int taskId;
|
||||
unsigned int outputSize;
|
||||
|
||||
//printf("Busy tasks... %d\n", m_numBusyTasks);
|
||||
|
||||
{
|
||||
// SPURS support.
|
||||
m_threadInterface->waitForResponse(&taskId, &outputSize);
|
||||
}
|
||||
|
||||
//printf("PPU: flushing, received event: %u %d\n", taskId, outputSize);
|
||||
|
||||
//postProcess(taskId, outputSize);
|
||||
|
||||
m_taskBusy[taskId] = false;
|
||||
|
||||
m_numBusyTasks--;
|
||||
}
|
||||
}
|
||||
72
Extras/BulletMultiThreaded/SpuRaycastTaskProcess.h
Normal file
72
Extras/BulletMultiThreaded/SpuRaycastTaskProcess.h
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com
|
||||
|
||||
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_RAY_TASK_PROCESS_H
|
||||
#define SPU_RAY_TASK_PROCESS_H
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <LinearMath/btScalar.h>
|
||||
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
|
||||
#include <LinearMath/btAlignedAllocator.h>
|
||||
|
||||
#include "PlatformDefinitions.h"
|
||||
#include "LinearMath/btAlignedObjectArray.h"
|
||||
#include "SpuRaycastTask/SpuRaycastTask.h"
|
||||
|
||||
#include "btThreadSupportInterface.h"
|
||||
|
||||
/// SpuRaycastTaskProcess handles SPU processing of raycast requests
|
||||
class SpuRaycastTaskProcess
|
||||
{
|
||||
unsigned char *m_workUnitTaskBuffers;
|
||||
|
||||
// track task buffers that are being used, and total busy tasks
|
||||
btAlignedObjectArray<bool> m_taskBusy;
|
||||
btAlignedObjectArray<SpuRaycastTaskDesc> m_spuRaycastTaskDesc;
|
||||
|
||||
btThreadSupportInterface* m_threadInterface;
|
||||
|
||||
unsigned int m_maxNumOutstandingTasks;
|
||||
|
||||
unsigned int m_numBusyTasks;
|
||||
|
||||
// the current task and the current entry to insert a new work unit
|
||||
unsigned int m_currentTask;
|
||||
unsigned int m_currentWorkUnitInTask;
|
||||
int m_numSpuCollisionObjectWrappers;
|
||||
void* m_spuCollisionObjectWrappers;
|
||||
void issueTask2();
|
||||
//void postProcess(unsigned int taskId, int outputSize);
|
||||
|
||||
public:
|
||||
SpuRaycastTaskProcess(btThreadSupportInterface* threadInterface, unsigned int maxNumOutstandingTasks);
|
||||
|
||||
~SpuRaycastTaskProcess();
|
||||
|
||||
/// call initialize in the beginning of the frame, before addCollisionPairToTask
|
||||
void initialize2(void* spuCollisionObjectsWrappers, int numSpuCollisionObjectWrappers);
|
||||
|
||||
/// batch up additional work to a current task for SPU processing. When batch is full, it issues the task.
|
||||
void addWorkToTask(struct SpuRaycastTaskWorkUnit);
|
||||
|
||||
/// call flush to submit potential outstanding work to SPUs and wait for all involved SPUs to be finished
|
||||
void flush2();
|
||||
};
|
||||
|
||||
|
||||
#endif // SPU_COLLISION_TASK_PROCESS_H
|
||||
|
||||
Reference in New Issue
Block a user