BulletMultiThreaded (SPU/multi-core): added compound shape support and concave-convex (swapped case). Thanks to Marten Svanfeldt
This commit is contained in:
@@ -1,211 +1,213 @@
|
||||
/*
|
||||
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 "SpuGatheringCollisionDispatcher.h"
|
||||
#include "SpuCollisionTaskProcess.h"
|
||||
|
||||
|
||||
#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
|
||||
#include "BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h"
|
||||
#include "SpuContactManifoldCollisionAlgorithm.h"
|
||||
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
|
||||
#include "BulletCollision/CollisionShapes/btCollisionShape.h"
|
||||
|
||||
|
||||
|
||||
|
||||
SpuGatheringCollisionDispatcher::SpuGatheringCollisionDispatcher(class btThreadSupportInterface* threadInterface, unsigned int maxNumOutstandingTasks)
|
||||
:m_spuCollisionTaskProcess(0),
|
||||
m_threadInterface(threadInterface),
|
||||
m_maxNumOutstandingTasks(maxNumOutstandingTasks)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool SpuGatheringCollisionDispatcher::supportsDispatchPairOnSpu(int proxyType0,int proxyType1)
|
||||
{
|
||||
bool supported0 = (
|
||||
(proxyType0 == BOX_SHAPE_PROXYTYPE) ||
|
||||
(proxyType0 == TRIANGLE_SHAPE_PROXYTYPE) ||
|
||||
(proxyType0 == SPHERE_SHAPE_PROXYTYPE) ||
|
||||
(proxyType0 == CAPSULE_SHAPE_PROXYTYPE) ||
|
||||
(proxyType0 == CYLINDER_SHAPE_PROXYTYPE) ||
|
||||
// (proxyType0 == CONE_SHAPE_PROXYTYPE) ||
|
||||
(proxyType0 == TRIANGLE_MESH_SHAPE_PROXYTYPE) ||
|
||||
(proxyType0 == CONVEX_HULL_SHAPE_PROXYTYPE)
|
||||
);
|
||||
|
||||
bool supported1 = (
|
||||
(proxyType1 == BOX_SHAPE_PROXYTYPE) ||
|
||||
(proxyType1 == TRIANGLE_SHAPE_PROXYTYPE) ||
|
||||
(proxyType1 == SPHERE_SHAPE_PROXYTYPE) ||
|
||||
(proxyType1 == CAPSULE_SHAPE_PROXYTYPE) ||
|
||||
(proxyType1 == CYLINDER_SHAPE_PROXYTYPE) ||
|
||||
// (proxyType1 == CONE_SHAPE_PROXYTYPE) ||
|
||||
(proxyType1 == TRIANGLE_MESH_SHAPE_PROXYTYPE) ||
|
||||
(proxyType1 == CONVEX_HULL_SHAPE_PROXYTYPE)
|
||||
);
|
||||
|
||||
return supported0 && supported1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
SpuGatheringCollisionDispatcher::~SpuGatheringCollisionDispatcher()
|
||||
{
|
||||
if (m_spuCollisionTaskProcess)
|
||||
delete m_spuCollisionTaskProcess;
|
||||
|
||||
}
|
||||
|
||||
#include "stdio.h"
|
||||
|
||||
|
||||
|
||||
///interface for iterating all overlapping collision pairs, no matter how those pairs are stored (array, set, map etc)
|
||||
///this is useful for the collision dispatcher.
|
||||
class btSpuCollisionPairCallback : public btOverlapCallback
|
||||
{
|
||||
btDispatcherInfo& m_dispatchInfo;
|
||||
SpuGatheringCollisionDispatcher* m_dispatcher;
|
||||
|
||||
public:
|
||||
|
||||
btSpuCollisionPairCallback(btDispatcherInfo& dispatchInfo,SpuGatheringCollisionDispatcher* dispatcher)
|
||||
:m_dispatchInfo(dispatchInfo),
|
||||
m_dispatcher(dispatcher)
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool processOverlap(btBroadphasePair& collisionPair)
|
||||
{
|
||||
|
||||
|
||||
//PPU version
|
||||
//(*m_dispatcher->getNearCallback())(collisionPair,*m_dispatcher,m_dispatchInfo);
|
||||
|
||||
//only support discrete collision detection for now, we could fallback on PPU/unoptimized version for TOI/CCD
|
||||
btAssert(m_dispatchInfo.m_dispatchFunc == btDispatcherInfo::DISPATCH_DISCRETE);
|
||||
|
||||
//by default, Bullet will use this near callback
|
||||
{
|
||||
///userInfo is used to determine if the SPU has to handle this case or not (skip PPU tasks)
|
||||
if (!collisionPair.m_userInfo)
|
||||
{
|
||||
collisionPair.m_userInfo = (void*) 1;
|
||||
}
|
||||
if (!collisionPair.m_algorithm)
|
||||
{
|
||||
btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject;
|
||||
btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject;
|
||||
|
||||
btCollisionAlgorithmConstructionInfo ci;
|
||||
ci.m_dispatcher = m_dispatcher;
|
||||
ci.m_manifold = 0;
|
||||
|
||||
if (m_dispatcher->needsCollision(colObj0,colObj1))
|
||||
{
|
||||
int proxyType0 = colObj0->getCollisionShape()->getShapeType();
|
||||
int proxyType1 = colObj1->getCollisionShape()->getShapeType();
|
||||
if (m_dispatcher->supportsDispatchPairOnSpu(proxyType0,proxyType1))
|
||||
{
|
||||
collisionPair.m_algorithm = new SpuContactManifoldCollisionAlgorithm(ci,colObj0,colObj1);
|
||||
collisionPair.m_userInfo = (void*) 2;
|
||||
} else
|
||||
{
|
||||
collisionPair.m_algorithm = m_dispatcher->findAlgorithm(colObj0,colObj1);
|
||||
collisionPair.m_userInfo = (void*)3;
|
||||
}
|
||||
} else
|
||||
{
|
||||
//create an empty algorithm
|
||||
collisionPair.m_algorithm = new btEmptyAlgorithm(ci);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
void SpuGatheringCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,btDispatcherInfo& dispatchInfo)
|
||||
{
|
||||
|
||||
if (dispatchInfo.m_enableSPU)
|
||||
{
|
||||
if (!m_spuCollisionTaskProcess)
|
||||
m_spuCollisionTaskProcess = new SpuCollisionTaskProcess(m_threadInterface,m_maxNumOutstandingTasks);
|
||||
|
||||
m_spuCollisionTaskProcess->initialize2();
|
||||
|
||||
///modified version of btCollisionDispatcher::dispatchAllCollisionPairs:
|
||||
{
|
||||
btSpuCollisionPairCallback collisionCallback(dispatchInfo,this);
|
||||
|
||||
pairCache->processAllOverlappingPairs(&collisionCallback);
|
||||
}
|
||||
|
||||
//send one big batch
|
||||
int numTotalPairs = pairCache->getNumOverlappingPairs();
|
||||
btBroadphasePair* pairPtr = pairCache->getOverlappingPairArrayPtr();
|
||||
int i;
|
||||
for (i=0;i<numTotalPairs;)
|
||||
{
|
||||
//Performance Hint: tweak this number during benchmarking
|
||||
static const int pairRange = SPU_BATCHSIZE_BROADPHASE_PAIRS;
|
||||
int endIndex = (i+pairRange) < numTotalPairs ? i+pairRange : numTotalPairs;
|
||||
m_spuCollisionTaskProcess->addWorkToTask(pairPtr,i,endIndex);
|
||||
i = endIndex;
|
||||
}
|
||||
|
||||
//handle PPU fallback pairs
|
||||
for (i=0;i<numTotalPairs;i++)
|
||||
{
|
||||
btBroadphasePair& collisionPair = pairPtr[i];
|
||||
if (collisionPair.m_userInfo == (void*)3)
|
||||
{
|
||||
if (collisionPair.m_algorithm)
|
||||
{
|
||||
btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject;
|
||||
btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject;
|
||||
btManifoldResult contactPointResult(colObj0,colObj1);
|
||||
|
||||
if (dispatchInfo.m_dispatchFunc == btDispatcherInfo::DISPATCH_DISCRETE)
|
||||
{
|
||||
//discrete collision detection query
|
||||
collisionPair.m_algorithm->processCollision(colObj0,colObj1,dispatchInfo,&contactPointResult);
|
||||
} else
|
||||
{
|
||||
//continuous collision detection query, time of impact (toi)
|
||||
btScalar toi = collisionPair.m_algorithm->calculateTimeOfImpact(colObj0,colObj1,dispatchInfo,&contactPointResult);
|
||||
if (dispatchInfo.m_timeOfImpact > toi)
|
||||
dispatchInfo.m_timeOfImpact = toi;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//make sure all SPU work is done
|
||||
m_spuCollisionTaskProcess->flush2();
|
||||
|
||||
} else
|
||||
{
|
||||
///PPU fallback
|
||||
///!Need to make sure to clear all 'algorithms' when switching between SPU and PPU
|
||||
btCollisionDispatcher::dispatchAllCollisionPairs(pairCache,dispatchInfo);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
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 "SpuGatheringCollisionDispatcher.h"
|
||||
#include "SpuCollisionTaskProcess.h"
|
||||
|
||||
|
||||
#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
|
||||
#include "BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h"
|
||||
#include "SpuContactManifoldCollisionAlgorithm.h"
|
||||
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
|
||||
#include "BulletCollision/CollisionShapes/btCollisionShape.h"
|
||||
|
||||
|
||||
|
||||
|
||||
SpuGatheringCollisionDispatcher::SpuGatheringCollisionDispatcher(class btThreadSupportInterface* threadInterface, unsigned int maxNumOutstandingTasks)
|
||||
:m_spuCollisionTaskProcess(0),
|
||||
m_threadInterface(threadInterface),
|
||||
m_maxNumOutstandingTasks(maxNumOutstandingTasks)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool SpuGatheringCollisionDispatcher::supportsDispatchPairOnSpu(int proxyType0,int proxyType1)
|
||||
{
|
||||
bool supported0 = (
|
||||
(proxyType0 == BOX_SHAPE_PROXYTYPE) ||
|
||||
(proxyType0 == TRIANGLE_SHAPE_PROXYTYPE) ||
|
||||
(proxyType0 == SPHERE_SHAPE_PROXYTYPE) ||
|
||||
(proxyType0 == CAPSULE_SHAPE_PROXYTYPE) ||
|
||||
(proxyType0 == CYLINDER_SHAPE_PROXYTYPE) ||
|
||||
// (proxyType0 == CONE_SHAPE_PROXYTYPE) ||
|
||||
(proxyType0 == TRIANGLE_MESH_SHAPE_PROXYTYPE) ||
|
||||
(proxyType0 == CONVEX_HULL_SHAPE_PROXYTYPE)||
|
||||
(proxyType0 == COMPOUND_SHAPE_PROXYTYPE)
|
||||
);
|
||||
|
||||
bool supported1 = (
|
||||
(proxyType1 == BOX_SHAPE_PROXYTYPE) ||
|
||||
(proxyType1 == TRIANGLE_SHAPE_PROXYTYPE) ||
|
||||
(proxyType1 == SPHERE_SHAPE_PROXYTYPE) ||
|
||||
(proxyType1 == CAPSULE_SHAPE_PROXYTYPE) ||
|
||||
(proxyType1 == CYLINDER_SHAPE_PROXYTYPE) ||
|
||||
// (proxyType1 == CONE_SHAPE_PROXYTYPE) ||
|
||||
(proxyType1 == TRIANGLE_MESH_SHAPE_PROXYTYPE) ||
|
||||
(proxyType1 == CONVEX_HULL_SHAPE_PROXYTYPE) ||
|
||||
(proxyType1 == COMPOUND_SHAPE_PROXYTYPE)
|
||||
);
|
||||
|
||||
return supported0 && supported1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
SpuGatheringCollisionDispatcher::~SpuGatheringCollisionDispatcher()
|
||||
{
|
||||
if (m_spuCollisionTaskProcess)
|
||||
delete m_spuCollisionTaskProcess;
|
||||
|
||||
}
|
||||
|
||||
#include "stdio.h"
|
||||
|
||||
|
||||
|
||||
///interface for iterating all overlapping collision pairs, no matter how those pairs are stored (array, set, map etc)
|
||||
///this is useful for the collision dispatcher.
|
||||
class btSpuCollisionPairCallback : public btOverlapCallback
|
||||
{
|
||||
btDispatcherInfo& m_dispatchInfo;
|
||||
SpuGatheringCollisionDispatcher* m_dispatcher;
|
||||
|
||||
public:
|
||||
|
||||
btSpuCollisionPairCallback(btDispatcherInfo& dispatchInfo,SpuGatheringCollisionDispatcher* dispatcher)
|
||||
:m_dispatchInfo(dispatchInfo),
|
||||
m_dispatcher(dispatcher)
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool processOverlap(btBroadphasePair& collisionPair)
|
||||
{
|
||||
|
||||
|
||||
//PPU version
|
||||
//(*m_dispatcher->getNearCallback())(collisionPair,*m_dispatcher,m_dispatchInfo);
|
||||
|
||||
//only support discrete collision detection for now, we could fallback on PPU/unoptimized version for TOI/CCD
|
||||
btAssert(m_dispatchInfo.m_dispatchFunc == btDispatcherInfo::DISPATCH_DISCRETE);
|
||||
|
||||
//by default, Bullet will use this near callback
|
||||
{
|
||||
///userInfo is used to determine if the SPU has to handle this case or not (skip PPU tasks)
|
||||
if (!collisionPair.m_userInfo)
|
||||
{
|
||||
collisionPair.m_userInfo = (void*) 1;
|
||||
}
|
||||
if (!collisionPair.m_algorithm)
|
||||
{
|
||||
btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject;
|
||||
btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject;
|
||||
|
||||
btCollisionAlgorithmConstructionInfo ci;
|
||||
ci.m_dispatcher = m_dispatcher;
|
||||
ci.m_manifold = 0;
|
||||
|
||||
if (m_dispatcher->needsCollision(colObj0,colObj1))
|
||||
{
|
||||
int proxyType0 = colObj0->getCollisionShape()->getShapeType();
|
||||
int proxyType1 = colObj1->getCollisionShape()->getShapeType();
|
||||
if (m_dispatcher->supportsDispatchPairOnSpu(proxyType0,proxyType1))
|
||||
{
|
||||
collisionPair.m_algorithm = new SpuContactManifoldCollisionAlgorithm(ci,colObj0,colObj1);
|
||||
collisionPair.m_userInfo = (void*) 2;
|
||||
} else
|
||||
{
|
||||
collisionPair.m_algorithm = m_dispatcher->findAlgorithm(colObj0,colObj1);
|
||||
collisionPair.m_userInfo = (void*)3;
|
||||
}
|
||||
} else
|
||||
{
|
||||
//create an empty algorithm
|
||||
collisionPair.m_algorithm = new btEmptyAlgorithm(ci);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
void SpuGatheringCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,btDispatcherInfo& dispatchInfo)
|
||||
{
|
||||
|
||||
if (dispatchInfo.m_enableSPU)
|
||||
{
|
||||
if (!m_spuCollisionTaskProcess)
|
||||
m_spuCollisionTaskProcess = new SpuCollisionTaskProcess(m_threadInterface,m_maxNumOutstandingTasks);
|
||||
|
||||
m_spuCollisionTaskProcess->initialize2();
|
||||
|
||||
///modified version of btCollisionDispatcher::dispatchAllCollisionPairs:
|
||||
{
|
||||
btSpuCollisionPairCallback collisionCallback(dispatchInfo,this);
|
||||
|
||||
pairCache->processAllOverlappingPairs(&collisionCallback);
|
||||
}
|
||||
|
||||
//send one big batch
|
||||
int numTotalPairs = pairCache->getNumOverlappingPairs();
|
||||
btBroadphasePair* pairPtr = pairCache->getOverlappingPairArrayPtr();
|
||||
int i;
|
||||
for (i=0;i<numTotalPairs;)
|
||||
{
|
||||
//Performance Hint: tweak this number during benchmarking
|
||||
static const int pairRange = SPU_BATCHSIZE_BROADPHASE_PAIRS;
|
||||
int endIndex = (i+pairRange) < numTotalPairs ? i+pairRange : numTotalPairs;
|
||||
m_spuCollisionTaskProcess->addWorkToTask(pairPtr,i,endIndex);
|
||||
i = endIndex;
|
||||
}
|
||||
|
||||
//handle PPU fallback pairs
|
||||
for (i=0;i<numTotalPairs;i++)
|
||||
{
|
||||
btBroadphasePair& collisionPair = pairPtr[i];
|
||||
if (collisionPair.m_userInfo == (void*)3)
|
||||
{
|
||||
if (collisionPair.m_algorithm)
|
||||
{
|
||||
btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject;
|
||||
btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject;
|
||||
btManifoldResult contactPointResult(colObj0,colObj1);
|
||||
|
||||
if (dispatchInfo.m_dispatchFunc == btDispatcherInfo::DISPATCH_DISCRETE)
|
||||
{
|
||||
//discrete collision detection query
|
||||
collisionPair.m_algorithm->processCollision(colObj0,colObj1,dispatchInfo,&contactPointResult);
|
||||
} else
|
||||
{
|
||||
//continuous collision detection query, time of impact (toi)
|
||||
btScalar toi = collisionPair.m_algorithm->calculateTimeOfImpact(colObj0,colObj1,dispatchInfo,&contactPointResult);
|
||||
if (dispatchInfo.m_timeOfImpact > toi)
|
||||
dispatchInfo.m_timeOfImpact = toi;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//make sure all SPU work is done
|
||||
m_spuCollisionTaskProcess->flush2();
|
||||
|
||||
} else
|
||||
{
|
||||
///PPU fallback
|
||||
///!Need to make sure to clear all 'algorithms' when switching between SPU and PPU
|
||||
btCollisionDispatcher::dispatchAllCollisionPairs(pairCache,dispatchInfo);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,171 +1,193 @@
|
||||
/*
|
||||
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
|
||||
|
||||
|
||||
#include "SpuContactResult.h"
|
||||
|
||||
|
||||
SpuContactResult::SpuContactResult()
|
||||
{
|
||||
m_manifoldAddress = 0;
|
||||
m_spuManifold = NULL;
|
||||
m_RequiresWriteBack = false;
|
||||
}
|
||||
|
||||
SpuContactResult::~SpuContactResult()
|
||||
{
|
||||
g_manifoldDmaExport.swapBuffers();
|
||||
}
|
||||
|
||||
void SpuContactResult::setContactInfo(btPersistentManifold* spuManifold, uint64_t manifoldAddress,const btTransform& worldTrans0,const btTransform& worldTrans1)
|
||||
{
|
||||
// spu_printf("SpuContactResult::setContactInfo\n");
|
||||
m_rootWorldTransform0 = worldTrans0;
|
||||
m_rootWorldTransform1 = worldTrans1;
|
||||
m_manifoldAddress = manifoldAddress;
|
||||
m_spuManifold = spuManifold;
|
||||
}
|
||||
|
||||
void SpuContactResult::setShapeIdentifiers(int partId0,int index0, 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
|
||||
)
|
||||
{
|
||||
|
||||
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;
|
||||
|
||||
//provide inverses or just calculate?
|
||||
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);
|
||||
|
||||
int insertIndex = manifoldPtr->getCacheEntry(newPt);
|
||||
if (insertIndex >= 0)
|
||||
{
|
||||
// manifoldPtr->replaceContactPoint(newPt,insertIndex);
|
||||
// return true;
|
||||
|
||||
#ifdef DEBUG_SPU_COLLISION_DETECTION
|
||||
spu_printf("SPU: same contact detected, nothing done\n");
|
||||
#endif //DEBUG_SPU_COLLISION_DETECTION
|
||||
// This is not needed, just use the old info! saves a DMA transfer as well
|
||||
} else
|
||||
{
|
||||
|
||||
newPt.m_combinedFriction = 0.25f;//calculateCombinedFriction(m_body0,m_body1);
|
||||
newPt.m_combinedRestitution = 0.0f;//calculateCombinedRestitution(m_body0,m_body1);
|
||||
|
||||
/*
|
||||
//potential 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)
|
||||
{
|
||||
memcpy(g_manifoldDmaExport.getFront(),lsManifold,sizeof(btPersistentManifold));
|
||||
|
||||
g_manifoldDmaExport.swapBuffers();
|
||||
g_manifoldDmaExport.backBufferDmaPut((uint64_t)mmManifold, 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
|
||||
}
|
||||
|
||||
void SpuContactResult::addContactPoint(const btVector3& normalOnBInWorld,const btPoint3& pointInWorld,float depth)
|
||||
{
|
||||
// spu_printf("*** SpuContactResult::addContactPoint: depth = %f\n",depth);
|
||||
|
||||
#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_RequiresWriteBack = m_RequiresWriteBack || retVal;
|
||||
}
|
||||
|
||||
void SpuContactResult::flush()
|
||||
{
|
||||
if (m_RequiresWriteBack)
|
||||
{
|
||||
#ifdef DEBUG_SPU_COLLISION_DETECTION
|
||||
spu_printf("SPU: Start rage::phManifold Write (Put) DMA\n");
|
||||
#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
|
||||
}
|
||||
m_spuManifold = NULL;
|
||||
m_RequiresWriteBack = false;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
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
|
||||
|
||||
|
||||
#include "SpuContactResult.h"
|
||||
|
||||
|
||||
SpuContactResult::SpuContactResult()
|
||||
{
|
||||
m_manifoldAddress = 0;
|
||||
m_spuManifold = NULL;
|
||||
m_RequiresWriteBack = false;
|
||||
}
|
||||
|
||||
SpuContactResult::~SpuContactResult()
|
||||
{
|
||||
g_manifoldDmaExport.swapBuffers();
|
||||
}
|
||||
|
||||
void SpuContactResult::setContactInfo(btPersistentManifold* spuManifold, uint64_t manifoldAddress,const btTransform& worldTrans0,const btTransform& worldTrans1, bool isSwapped)
|
||||
{
|
||||
//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)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
///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,
|
||||
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;
|
||||
|
||||
//provide inverses or just calculate?
|
||||
btTransform transAInv = transA.inverse();//m_body0->m_cachedInvertedWorldTransform;
|
||||
btTransform transBInv= transB.inverse();//m_body1->m_cachedInvertedWorldTransform;
|
||||
|
||||
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)
|
||||
{
|
||||
// manifoldPtr->replaceContactPoint(newPt,insertIndex);
|
||||
// return true;
|
||||
|
||||
#ifdef DEBUG_SPU_COLLISION_DETECTION
|
||||
spu_printf("SPU: same contact detected, nothing done\n");
|
||||
#endif //DEBUG_SPU_COLLISION_DETECTION
|
||||
// This is not needed, just use the old info! saves a DMA transfer as well
|
||||
} else
|
||||
{
|
||||
|
||||
newPt.m_combinedFriction = 0.25f;//calculateCombinedFriction(m_body0,m_body1);
|
||||
newPt.m_combinedRestitution = 0.0f;//calculateCombinedRestitution(m_body0,m_body1);
|
||||
|
||||
/*
|
||||
//potential 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)
|
||||
{
|
||||
memcpy(g_manifoldDmaExport.getFront(),lsManifold,sizeof(btPersistentManifold));
|
||||
|
||||
g_manifoldDmaExport.swapBuffers();
|
||||
g_manifoldDmaExport.backBufferDmaPut((uint64_t)mmManifold, 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
|
||||
}
|
||||
|
||||
void SpuContactResult::addContactPoint(const btVector3& normalOnBInWorld,const btPoint3& pointInWorld,float depth)
|
||||
{
|
||||
//spu_printf("*** SpuContactResult::addContactPoint: depth = %f\n",depth);
|
||||
|
||||
#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_isSwapped);
|
||||
m_RequiresWriteBack = m_RequiresWriteBack || retVal;
|
||||
}
|
||||
|
||||
void SpuContactResult::flush()
|
||||
{
|
||||
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
|
||||
}
|
||||
m_spuManifold = NULL;
|
||||
m_RequiresWriteBack = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,110 +1,111 @@
|
||||
/*
|
||||
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_CONTACT_RESULT2_H
|
||||
#define SPU_CONTACT_RESULT2_H
|
||||
|
||||
|
||||
#ifndef WIN32
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#include "../SpuDoubleBuffer.h"
|
||||
|
||||
|
||||
#include "LinearMath/btTransform.h"
|
||||
#include "LinearMath/btPoint3.h"
|
||||
|
||||
|
||||
#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
|
||||
|
||||
|
||||
struct SpuCollisionPairInput
|
||||
{
|
||||
uint64_t m_collisionShapes[2];
|
||||
void* m_spuCollisionShapes[2];
|
||||
|
||||
uint64_t m_persistentManifoldPtr;
|
||||
btVector3 m_primitiveDimensions0;
|
||||
btVector3 m_primitiveDimensions1;
|
||||
int m_shapeType0;
|
||||
int m_shapeType1;
|
||||
float m_collisionMargin0;
|
||||
float m_collisionMargin1;
|
||||
|
||||
btTransform m_worldTransform0;
|
||||
btTransform m_worldTransform1;
|
||||
|
||||
bool m_isSwapped;
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
struct SpuClosestPointInput
|
||||
{
|
||||
SpuClosestPointInput()
|
||||
:m_maximumDistanceSquared(float(1e30)),
|
||||
m_stackAlloc(0)
|
||||
{
|
||||
}
|
||||
|
||||
btTransform m_transformA;
|
||||
btTransform m_transformB;
|
||||
float m_maximumDistanceSquared;
|
||||
class btStackAlloc* m_stackAlloc;
|
||||
struct SpuConvexPolyhedronVertexData* m_convexVertexData;
|
||||
};
|
||||
|
||||
///SpuContactResult exports the contact points using double-buffered DMA transfers, only when needed
|
||||
///So when an existing contact point is duplicated, no transfer/refresh is performed.
|
||||
class SpuContactResult
|
||||
{
|
||||
btTransform m_rootWorldTransform0;
|
||||
btTransform m_rootWorldTransform1;
|
||||
uint64_t m_manifoldAddress;
|
||||
|
||||
btPersistentManifold* m_spuManifold;
|
||||
bool m_RequiresWriteBack;
|
||||
|
||||
DoubleBuffer<btPersistentManifold, 1> g_manifoldDmaExport;
|
||||
|
||||
public:
|
||||
SpuContactResult();
|
||||
virtual ~SpuContactResult();
|
||||
|
||||
btPersistentManifold* GetSpuManifold() const
|
||||
{
|
||||
return m_spuManifold;
|
||||
}
|
||||
|
||||
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 writeDoubleBufferedManifold(btPersistentManifold* lsManifold, btPersistentManifold* mmManifold);
|
||||
|
||||
virtual void addContactPoint(const btVector3& normalOnBInWorld,const btPoint3& pointInWorld,float depth);
|
||||
|
||||
void flush();
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif //SPU_CONTACT_RESULT2_H
|
||||
|
||||
/*
|
||||
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_CONTACT_RESULT2_H
|
||||
#define SPU_CONTACT_RESULT2_H
|
||||
|
||||
|
||||
#ifndef WIN32
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#include "../SpuDoubleBuffer.h"
|
||||
|
||||
|
||||
#include "LinearMath/btTransform.h"
|
||||
#include "LinearMath/btPoint3.h"
|
||||
|
||||
|
||||
#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
|
||||
|
||||
|
||||
struct SpuCollisionPairInput
|
||||
{
|
||||
uint64_t m_collisionShapes[2];
|
||||
void* m_spuCollisionShapes[2];
|
||||
|
||||
uint64_t m_persistentManifoldPtr;
|
||||
btVector3 m_primitiveDimensions0;
|
||||
btVector3 m_primitiveDimensions1;
|
||||
int m_shapeType0;
|
||||
int m_shapeType1;
|
||||
float m_collisionMargin0;
|
||||
float m_collisionMargin1;
|
||||
|
||||
btTransform m_worldTransform0;
|
||||
btTransform m_worldTransform1;
|
||||
|
||||
bool m_isSwapped;
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
struct SpuClosestPointInput
|
||||
{
|
||||
SpuClosestPointInput()
|
||||
:m_maximumDistanceSquared(float(1e30)),
|
||||
m_stackAlloc(0)
|
||||
{
|
||||
}
|
||||
|
||||
btTransform m_transformA;
|
||||
btTransform m_transformB;
|
||||
float m_maximumDistanceSquared;
|
||||
class btStackAlloc* m_stackAlloc;
|
||||
struct SpuConvexPolyhedronVertexData* m_convexVertexData;
|
||||
};
|
||||
|
||||
///SpuContactResult exports the contact points using double-buffered DMA transfers, only when needed
|
||||
///So when an existing contact point is duplicated, no transfer/refresh is performed.
|
||||
class SpuContactResult
|
||||
{
|
||||
btTransform m_rootWorldTransform0;
|
||||
btTransform m_rootWorldTransform1;
|
||||
uint64_t m_manifoldAddress;
|
||||
|
||||
btPersistentManifold* m_spuManifold;
|
||||
bool m_RequiresWriteBack;
|
||||
bool m_isSwapped;
|
||||
|
||||
DoubleBuffer<btPersistentManifold, 1> g_manifoldDmaExport;
|
||||
|
||||
public:
|
||||
SpuContactResult();
|
||||
virtual ~SpuContactResult();
|
||||
|
||||
btPersistentManifold* GetSpuManifold() const
|
||||
{
|
||||
return m_spuManifold;
|
||||
}
|
||||
|
||||
virtual void setShapeIdentifiers(int partId0,int index0, int partId1,int index1);
|
||||
|
||||
void setContactInfo(btPersistentManifold* spuManifold, uint64_t manifoldAddress,const btTransform& worldTrans0,const btTransform& worldTrans1, bool isSwapped = false);
|
||||
|
||||
void writeDoubleBufferedManifold(btPersistentManifold* lsManifold, btPersistentManifold* mmManifold);
|
||||
|
||||
virtual void addContactPoint(const btVector3& normalOnBInWorld,const btPoint3& pointInWorld,float depth);
|
||||
|
||||
void flush();
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif //SPU_CONTACT_RESULT2_H
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user