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
|
Bullet Continuous Collision Detection and Physics Library
|
||||||
Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com
|
Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied warranty.
|
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.
|
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,
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
including commercial applications, and to alter it and redistribute it freely,
|
including commercial applications, and to alter it and redistribute it freely,
|
||||||
subject to the following restrictions:
|
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.
|
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.
|
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.
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "SpuGatheringCollisionDispatcher.h"
|
#include "SpuGatheringCollisionDispatcher.h"
|
||||||
#include "SpuCollisionTaskProcess.h"
|
#include "SpuCollisionTaskProcess.h"
|
||||||
|
|
||||||
|
|
||||||
#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
|
#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
|
||||||
#include "BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h"
|
#include "BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h"
|
||||||
#include "SpuContactManifoldCollisionAlgorithm.h"
|
#include "SpuContactManifoldCollisionAlgorithm.h"
|
||||||
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
|
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
|
||||||
#include "BulletCollision/CollisionShapes/btCollisionShape.h"
|
#include "BulletCollision/CollisionShapes/btCollisionShape.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
SpuGatheringCollisionDispatcher::SpuGatheringCollisionDispatcher(class btThreadSupportInterface* threadInterface, unsigned int maxNumOutstandingTasks)
|
SpuGatheringCollisionDispatcher::SpuGatheringCollisionDispatcher(class btThreadSupportInterface* threadInterface, unsigned int maxNumOutstandingTasks)
|
||||||
:m_spuCollisionTaskProcess(0),
|
:m_spuCollisionTaskProcess(0),
|
||||||
m_threadInterface(threadInterface),
|
m_threadInterface(threadInterface),
|
||||||
m_maxNumOutstandingTasks(maxNumOutstandingTasks)
|
m_maxNumOutstandingTasks(maxNumOutstandingTasks)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool SpuGatheringCollisionDispatcher::supportsDispatchPairOnSpu(int proxyType0,int proxyType1)
|
bool SpuGatheringCollisionDispatcher::supportsDispatchPairOnSpu(int proxyType0,int proxyType1)
|
||||||
{
|
{
|
||||||
bool supported0 = (
|
bool supported0 = (
|
||||||
(proxyType0 == BOX_SHAPE_PROXYTYPE) ||
|
(proxyType0 == BOX_SHAPE_PROXYTYPE) ||
|
||||||
(proxyType0 == TRIANGLE_SHAPE_PROXYTYPE) ||
|
(proxyType0 == TRIANGLE_SHAPE_PROXYTYPE) ||
|
||||||
(proxyType0 == SPHERE_SHAPE_PROXYTYPE) ||
|
(proxyType0 == SPHERE_SHAPE_PROXYTYPE) ||
|
||||||
(proxyType0 == CAPSULE_SHAPE_PROXYTYPE) ||
|
(proxyType0 == CAPSULE_SHAPE_PROXYTYPE) ||
|
||||||
(proxyType0 == CYLINDER_SHAPE_PROXYTYPE) ||
|
(proxyType0 == CYLINDER_SHAPE_PROXYTYPE) ||
|
||||||
// (proxyType0 == CONE_SHAPE_PROXYTYPE) ||
|
// (proxyType0 == CONE_SHAPE_PROXYTYPE) ||
|
||||||
(proxyType0 == TRIANGLE_MESH_SHAPE_PROXYTYPE) ||
|
(proxyType0 == TRIANGLE_MESH_SHAPE_PROXYTYPE) ||
|
||||||
(proxyType0 == CONVEX_HULL_SHAPE_PROXYTYPE)
|
(proxyType0 == CONVEX_HULL_SHAPE_PROXYTYPE)||
|
||||||
);
|
(proxyType0 == COMPOUND_SHAPE_PROXYTYPE)
|
||||||
|
);
|
||||||
bool supported1 = (
|
|
||||||
(proxyType1 == BOX_SHAPE_PROXYTYPE) ||
|
bool supported1 = (
|
||||||
(proxyType1 == TRIANGLE_SHAPE_PROXYTYPE) ||
|
(proxyType1 == BOX_SHAPE_PROXYTYPE) ||
|
||||||
(proxyType1 == SPHERE_SHAPE_PROXYTYPE) ||
|
(proxyType1 == TRIANGLE_SHAPE_PROXYTYPE) ||
|
||||||
(proxyType1 == CAPSULE_SHAPE_PROXYTYPE) ||
|
(proxyType1 == SPHERE_SHAPE_PROXYTYPE) ||
|
||||||
(proxyType1 == CYLINDER_SHAPE_PROXYTYPE) ||
|
(proxyType1 == CAPSULE_SHAPE_PROXYTYPE) ||
|
||||||
// (proxyType1 == CONE_SHAPE_PROXYTYPE) ||
|
(proxyType1 == CYLINDER_SHAPE_PROXYTYPE) ||
|
||||||
(proxyType1 == TRIANGLE_MESH_SHAPE_PROXYTYPE) ||
|
// (proxyType1 == CONE_SHAPE_PROXYTYPE) ||
|
||||||
(proxyType1 == CONVEX_HULL_SHAPE_PROXYTYPE)
|
(proxyType1 == TRIANGLE_MESH_SHAPE_PROXYTYPE) ||
|
||||||
);
|
(proxyType1 == CONVEX_HULL_SHAPE_PROXYTYPE) ||
|
||||||
|
(proxyType1 == COMPOUND_SHAPE_PROXYTYPE)
|
||||||
return supported0 && supported1;
|
);
|
||||||
}
|
|
||||||
|
return supported0 && supported1;
|
||||||
|
}
|
||||||
|
|
||||||
SpuGatheringCollisionDispatcher::~SpuGatheringCollisionDispatcher()
|
|
||||||
{
|
|
||||||
if (m_spuCollisionTaskProcess)
|
SpuGatheringCollisionDispatcher::~SpuGatheringCollisionDispatcher()
|
||||||
delete m_spuCollisionTaskProcess;
|
{
|
||||||
|
if (m_spuCollisionTaskProcess)
|
||||||
}
|
delete m_spuCollisionTaskProcess;
|
||||||
|
|
||||||
#include "stdio.h"
|
}
|
||||||
|
|
||||||
|
#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
|
///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.
|
||||||
btDispatcherInfo& m_dispatchInfo;
|
class btSpuCollisionPairCallback : public btOverlapCallback
|
||||||
SpuGatheringCollisionDispatcher* m_dispatcher;
|
{
|
||||||
|
btDispatcherInfo& m_dispatchInfo;
|
||||||
public:
|
SpuGatheringCollisionDispatcher* m_dispatcher;
|
||||||
|
|
||||||
btSpuCollisionPairCallback(btDispatcherInfo& dispatchInfo,SpuGatheringCollisionDispatcher* dispatcher)
|
public:
|
||||||
:m_dispatchInfo(dispatchInfo),
|
|
||||||
m_dispatcher(dispatcher)
|
btSpuCollisionPairCallback(btDispatcherInfo& dispatchInfo,SpuGatheringCollisionDispatcher* dispatcher)
|
||||||
{
|
:m_dispatchInfo(dispatchInfo),
|
||||||
}
|
m_dispatcher(dispatcher)
|
||||||
|
{
|
||||||
virtual bool processOverlap(btBroadphasePair& collisionPair)
|
}
|
||||||
{
|
|
||||||
|
virtual bool processOverlap(btBroadphasePair& collisionPair)
|
||||||
|
{
|
||||||
//PPU version
|
|
||||||
//(*m_dispatcher->getNearCallback())(collisionPair,*m_dispatcher,m_dispatchInfo);
|
|
||||||
|
//PPU version
|
||||||
//only support discrete collision detection for now, we could fallback on PPU/unoptimized version for TOI/CCD
|
//(*m_dispatcher->getNearCallback())(collisionPair,*m_dispatcher,m_dispatchInfo);
|
||||||
btAssert(m_dispatchInfo.m_dispatchFunc == btDispatcherInfo::DISPATCH_DISCRETE);
|
|
||||||
|
//only support discrete collision detection for now, we could fallback on PPU/unoptimized version for TOI/CCD
|
||||||
//by default, Bullet will use this near callback
|
btAssert(m_dispatchInfo.m_dispatchFunc == btDispatcherInfo::DISPATCH_DISCRETE);
|
||||||
{
|
|
||||||
///userInfo is used to determine if the SPU has to handle this case or not (skip PPU tasks)
|
//by default, Bullet will use this near callback
|
||||||
if (!collisionPair.m_userInfo)
|
{
|
||||||
{
|
///userInfo is used to determine if the SPU has to handle this case or not (skip PPU tasks)
|
||||||
collisionPair.m_userInfo = (void*) 1;
|
if (!collisionPair.m_userInfo)
|
||||||
}
|
{
|
||||||
if (!collisionPair.m_algorithm)
|
collisionPair.m_userInfo = (void*) 1;
|
||||||
{
|
}
|
||||||
btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject;
|
if (!collisionPair.m_algorithm)
|
||||||
btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject;
|
{
|
||||||
|
btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject;
|
||||||
btCollisionAlgorithmConstructionInfo ci;
|
btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject;
|
||||||
ci.m_dispatcher = m_dispatcher;
|
|
||||||
ci.m_manifold = 0;
|
btCollisionAlgorithmConstructionInfo ci;
|
||||||
|
ci.m_dispatcher = m_dispatcher;
|
||||||
if (m_dispatcher->needsCollision(colObj0,colObj1))
|
ci.m_manifold = 0;
|
||||||
{
|
|
||||||
int proxyType0 = colObj0->getCollisionShape()->getShapeType();
|
if (m_dispatcher->needsCollision(colObj0,colObj1))
|
||||||
int proxyType1 = colObj1->getCollisionShape()->getShapeType();
|
{
|
||||||
if (m_dispatcher->supportsDispatchPairOnSpu(proxyType0,proxyType1))
|
int proxyType0 = colObj0->getCollisionShape()->getShapeType();
|
||||||
{
|
int proxyType1 = colObj1->getCollisionShape()->getShapeType();
|
||||||
collisionPair.m_algorithm = new SpuContactManifoldCollisionAlgorithm(ci,colObj0,colObj1);
|
if (m_dispatcher->supportsDispatchPairOnSpu(proxyType0,proxyType1))
|
||||||
collisionPair.m_userInfo = (void*) 2;
|
{
|
||||||
} else
|
collisionPair.m_algorithm = new SpuContactManifoldCollisionAlgorithm(ci,colObj0,colObj1);
|
||||||
{
|
collisionPair.m_userInfo = (void*) 2;
|
||||||
collisionPair.m_algorithm = m_dispatcher->findAlgorithm(colObj0,colObj1);
|
} else
|
||||||
collisionPair.m_userInfo = (void*)3;
|
{
|
||||||
}
|
collisionPair.m_algorithm = m_dispatcher->findAlgorithm(colObj0,colObj1);
|
||||||
} else
|
collisionPair.m_userInfo = (void*)3;
|
||||||
{
|
}
|
||||||
//create an empty algorithm
|
} else
|
||||||
collisionPair.m_algorithm = new btEmptyAlgorithm(ci);
|
{
|
||||||
}
|
//create an empty algorithm
|
||||||
}
|
collisionPair.m_algorithm = new btEmptyAlgorithm(ci);
|
||||||
}
|
}
|
||||||
return false;
|
}
|
||||||
}
|
}
|
||||||
};
|
return false;
|
||||||
|
}
|
||||||
void SpuGatheringCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,btDispatcherInfo& dispatchInfo)
|
};
|
||||||
{
|
|
||||||
|
void SpuGatheringCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,btDispatcherInfo& dispatchInfo)
|
||||||
if (dispatchInfo.m_enableSPU)
|
{
|
||||||
{
|
|
||||||
if (!m_spuCollisionTaskProcess)
|
if (dispatchInfo.m_enableSPU)
|
||||||
m_spuCollisionTaskProcess = new SpuCollisionTaskProcess(m_threadInterface,m_maxNumOutstandingTasks);
|
{
|
||||||
|
if (!m_spuCollisionTaskProcess)
|
||||||
m_spuCollisionTaskProcess->initialize2();
|
m_spuCollisionTaskProcess = new SpuCollisionTaskProcess(m_threadInterface,m_maxNumOutstandingTasks);
|
||||||
|
|
||||||
///modified version of btCollisionDispatcher::dispatchAllCollisionPairs:
|
m_spuCollisionTaskProcess->initialize2();
|
||||||
{
|
|
||||||
btSpuCollisionPairCallback collisionCallback(dispatchInfo,this);
|
///modified version of btCollisionDispatcher::dispatchAllCollisionPairs:
|
||||||
|
{
|
||||||
pairCache->processAllOverlappingPairs(&collisionCallback);
|
btSpuCollisionPairCallback collisionCallback(dispatchInfo,this);
|
||||||
}
|
|
||||||
|
pairCache->processAllOverlappingPairs(&collisionCallback);
|
||||||
//send one big batch
|
}
|
||||||
int numTotalPairs = pairCache->getNumOverlappingPairs();
|
|
||||||
btBroadphasePair* pairPtr = pairCache->getOverlappingPairArrayPtr();
|
//send one big batch
|
||||||
int i;
|
int numTotalPairs = pairCache->getNumOverlappingPairs();
|
||||||
for (i=0;i<numTotalPairs;)
|
btBroadphasePair* pairPtr = pairCache->getOverlappingPairArrayPtr();
|
||||||
{
|
int i;
|
||||||
//Performance Hint: tweak this number during benchmarking
|
for (i=0;i<numTotalPairs;)
|
||||||
static const int pairRange = SPU_BATCHSIZE_BROADPHASE_PAIRS;
|
{
|
||||||
int endIndex = (i+pairRange) < numTotalPairs ? i+pairRange : numTotalPairs;
|
//Performance Hint: tweak this number during benchmarking
|
||||||
m_spuCollisionTaskProcess->addWorkToTask(pairPtr,i,endIndex);
|
static const int pairRange = SPU_BATCHSIZE_BROADPHASE_PAIRS;
|
||||||
i = endIndex;
|
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++)
|
|
||||||
{
|
//handle PPU fallback pairs
|
||||||
btBroadphasePair& collisionPair = pairPtr[i];
|
for (i=0;i<numTotalPairs;i++)
|
||||||
if (collisionPair.m_userInfo == (void*)3)
|
{
|
||||||
{
|
btBroadphasePair& collisionPair = pairPtr[i];
|
||||||
if (collisionPair.m_algorithm)
|
if (collisionPair.m_userInfo == (void*)3)
|
||||||
{
|
{
|
||||||
btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject;
|
if (collisionPair.m_algorithm)
|
||||||
btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject;
|
{
|
||||||
btManifoldResult contactPointResult(colObj0,colObj1);
|
btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject;
|
||||||
|
btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject;
|
||||||
if (dispatchInfo.m_dispatchFunc == btDispatcherInfo::DISPATCH_DISCRETE)
|
btManifoldResult contactPointResult(colObj0,colObj1);
|
||||||
{
|
|
||||||
//discrete collision detection query
|
if (dispatchInfo.m_dispatchFunc == btDispatcherInfo::DISPATCH_DISCRETE)
|
||||||
collisionPair.m_algorithm->processCollision(colObj0,colObj1,dispatchInfo,&contactPointResult);
|
{
|
||||||
} else
|
//discrete collision detection query
|
||||||
{
|
collisionPair.m_algorithm->processCollision(colObj0,colObj1,dispatchInfo,&contactPointResult);
|
||||||
//continuous collision detection query, time of impact (toi)
|
} else
|
||||||
btScalar toi = collisionPair.m_algorithm->calculateTimeOfImpact(colObj0,colObj1,dispatchInfo,&contactPointResult);
|
{
|
||||||
if (dispatchInfo.m_timeOfImpact > toi)
|
//continuous collision detection query, time of impact (toi)
|
||||||
dispatchInfo.m_timeOfImpact = 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();
|
|
||||||
|
//make sure all SPU work is done
|
||||||
} else
|
m_spuCollisionTaskProcess->flush2();
|
||||||
{
|
|
||||||
///PPU fallback
|
} else
|
||||||
///!Need to make sure to clear all 'algorithms' when switching between SPU and PPU
|
{
|
||||||
btCollisionDispatcher::dispatchAllCollisionPairs(pairCache,dispatchInfo);
|
///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
|
Bullet Continuous Collision Detection and Physics Library
|
||||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied warranty.
|
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.
|
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,
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
including commercial applications, and to alter it and redistribute it freely,
|
including commercial applications, and to alter it and redistribute it freely,
|
||||||
subject to the following restrictions:
|
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.
|
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.
|
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.
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "SpuContactResult.h"
|
#include "SpuContactResult.h"
|
||||||
|
|
||||||
|
|
||||||
//#define DEBUG_SPU_COLLISION_DETECTION 1
|
//#define DEBUG_SPU_COLLISION_DETECTION 1
|
||||||
|
|
||||||
|
|
||||||
#include "SpuContactResult.h"
|
#include "SpuContactResult.h"
|
||||||
|
|
||||||
|
|
||||||
SpuContactResult::SpuContactResult()
|
SpuContactResult::SpuContactResult()
|
||||||
{
|
{
|
||||||
m_manifoldAddress = 0;
|
m_manifoldAddress = 0;
|
||||||
m_spuManifold = NULL;
|
m_spuManifold = NULL;
|
||||||
m_RequiresWriteBack = false;
|
m_RequiresWriteBack = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
SpuContactResult::~SpuContactResult()
|
SpuContactResult::~SpuContactResult()
|
||||||
{
|
{
|
||||||
g_manifoldDmaExport.swapBuffers();
|
g_manifoldDmaExport.swapBuffers();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpuContactResult::setContactInfo(btPersistentManifold* spuManifold, uint64_t manifoldAddress,const btTransform& worldTrans0,const btTransform& worldTrans1)
|
void SpuContactResult::setContactInfo(btPersistentManifold* spuManifold, uint64_t manifoldAddress,const btTransform& worldTrans0,const btTransform& worldTrans1, bool isSwapped)
|
||||||
{
|
{
|
||||||
// spu_printf("SpuContactResult::setContactInfo\n");
|
//spu_printf("SpuContactResult::setContactInfo ManifoldAddress: %lu\n", manifoldAddress);
|
||||||
m_rootWorldTransform0 = worldTrans0;
|
m_rootWorldTransform0 = worldTrans0;
|
||||||
m_rootWorldTransform1 = worldTrans1;
|
m_rootWorldTransform1 = worldTrans1;
|
||||||
m_manifoldAddress = manifoldAddress;
|
m_manifoldAddress = manifoldAddress;
|
||||||
m_spuManifold = spuManifold;
|
m_spuManifold = spuManifold;
|
||||||
}
|
m_isSwapped = isSwapped;
|
||||||
|
}
|
||||||
void SpuContactResult::setShapeIdentifiers(int partId0,int index0, int partId1,int index1)
|
|
||||||
{
|
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,
|
///return true if it requires a dma transfer back
|
||||||
const btVector3& pointInWorld,
|
bool ManifoldResultAddContactPoint(const btVector3& normalOnBInWorld,
|
||||||
float depth,
|
const btVector3& pointInWorld,
|
||||||
btPersistentManifold* manifoldPtr,
|
float depth,
|
||||||
btTransform& transA,
|
btPersistentManifold* manifoldPtr,
|
||||||
btTransform& transB
|
btTransform& transA,
|
||||||
)
|
btTransform& transB,
|
||||||
{
|
bool isSwapped)
|
||||||
|
{
|
||||||
float contactTreshold = manifoldPtr->getContactBreakingThreshold();
|
|
||||||
|
float contactTreshold = manifoldPtr->getContactBreakingThreshold();
|
||||||
//spu_printf("SPU: add contactpoint, depth:%f, contactTreshold %f, manifoldPtr %llx\n",depth,contactTreshold,manifoldPtr);
|
|
||||||
|
//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);
|
#ifdef DEBUG_SPU_COLLISION_DETECTION
|
||||||
#endif //DEBUG_SPU_COLLISION_DETECTION
|
spu_printf("SPU: contactTreshold %f\n",contactTreshold);
|
||||||
if (depth > manifoldPtr->getContactBreakingThreshold())
|
#endif //DEBUG_SPU_COLLISION_DETECTION
|
||||||
return false;
|
if (depth > manifoldPtr->getContactBreakingThreshold())
|
||||||
|
return false;
|
||||||
//provide inverses or just calculate?
|
|
||||||
btTransform transAInv = transA.inverse();//m_body0->m_cachedInvertedWorldTransform;
|
//provide inverses or just calculate?
|
||||||
btTransform transBInv= transB.inverse();//m_body1->m_cachedInvertedWorldTransform;
|
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 pointA;
|
||||||
btVector3 localB = transBInv(pointInWorld);
|
btVector3 localA;
|
||||||
btManifoldPoint newPt(localA,localB,normalOnBInWorld,depth);
|
btVector3 localB;
|
||||||
|
btVector3 normal;
|
||||||
int insertIndex = manifoldPtr->getCacheEntry(newPt);
|
|
||||||
if (insertIndex >= 0)
|
if (isSwapped)
|
||||||
{
|
{
|
||||||
// manifoldPtr->replaceContactPoint(newPt,insertIndex);
|
normal = normalOnBInWorld * -1;
|
||||||
// return true;
|
pointA = pointInWorld + normal * depth;
|
||||||
|
localA = transAInv(pointA );
|
||||||
#ifdef DEBUG_SPU_COLLISION_DETECTION
|
localB = transBInv(pointInWorld);
|
||||||
spu_printf("SPU: same contact detected, nothing done\n");
|
/*localA = transBInv(pointA );
|
||||||
#endif //DEBUG_SPU_COLLISION_DETECTION
|
localB = transAInv(pointInWorld);*/
|
||||||
// This is not needed, just use the old info! saves a DMA transfer as well
|
}
|
||||||
} else
|
else
|
||||||
{
|
{
|
||||||
|
normal = normalOnBInWorld;
|
||||||
newPt.m_combinedFriction = 0.25f;//calculateCombinedFriction(m_body0,m_body1);
|
pointA = pointInWorld + normal * depth;
|
||||||
newPt.m_combinedRestitution = 0.0f;//calculateCombinedRestitution(m_body0,m_body1);
|
localA = transAInv(pointA );
|
||||||
|
localB = transBInv(pointInWorld);
|
||||||
/*
|
}
|
||||||
//potential TODO: SPU callbacks, either immediate (local on the SPU), or deferred
|
|
||||||
//User can override friction and/or restitution
|
btManifoldPoint newPt(localA,localB,normal,depth);
|
||||||
if (gContactAddedCallback &&
|
|
||||||
//and if either of the two bodies requires custom material
|
int insertIndex = manifoldPtr->getCacheEntry(newPt);
|
||||||
((m_body0->m_collisionFlags & btCollisionObject::customMaterialCallback) ||
|
if (insertIndex >= 0)
|
||||||
(m_body1->m_collisionFlags & btCollisionObject::customMaterialCallback)))
|
{
|
||||||
{
|
// manifoldPtr->replaceContactPoint(newPt,insertIndex);
|
||||||
//experimental feature info, for per-triangle material etc.
|
// return true;
|
||||||
(*gContactAddedCallback)(newPt,m_body0,m_partId0,m_index0,m_body1,m_partId1,m_index1);
|
|
||||||
}
|
#ifdef DEBUG_SPU_COLLISION_DETECTION
|
||||||
*/
|
spu_printf("SPU: same contact detected, nothing done\n");
|
||||||
manifoldPtr->AddManifoldPoint(newPt);
|
#endif //DEBUG_SPU_COLLISION_DETECTION
|
||||||
return true;
|
// This is not needed, just use the old info! saves a DMA transfer as well
|
||||||
|
} else
|
||||||
}
|
{
|
||||||
return false;
|
|
||||||
|
newPt.m_combinedFriction = 0.25f;//calculateCombinedFriction(m_body0,m_body1);
|
||||||
}
|
newPt.m_combinedRestitution = 0.0f;//calculateCombinedRestitution(m_body0,m_body1);
|
||||||
|
|
||||||
|
/*
|
||||||
void SpuContactResult::writeDoubleBufferedManifold(btPersistentManifold* lsManifold, btPersistentManifold* mmManifold)
|
//potential TODO: SPU callbacks, either immediate (local on the SPU), or deferred
|
||||||
{
|
//User can override friction and/or restitution
|
||||||
memcpy(g_manifoldDmaExport.getFront(),lsManifold,sizeof(btPersistentManifold));
|
if (gContactAddedCallback &&
|
||||||
|
//and if either of the two bodies requires custom material
|
||||||
g_manifoldDmaExport.swapBuffers();
|
((m_body0->m_collisionFlags & btCollisionObject::customMaterialCallback) ||
|
||||||
g_manifoldDmaExport.backBufferDmaPut((uint64_t)mmManifold, sizeof(btPersistentManifold), DMA_TAG(9));
|
(m_body1->m_collisionFlags & btCollisionObject::customMaterialCallback)))
|
||||||
// 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
|
//experimental feature info, for per-triangle material etc.
|
||||||
}
|
(*gContactAddedCallback)(newPt,m_body0,m_partId0,m_index0,m_body1,m_partId1,m_index1);
|
||||||
|
}
|
||||||
void SpuContactResult::addContactPoint(const btVector3& normalOnBInWorld,const btPoint3& pointInWorld,float depth)
|
*/
|
||||||
{
|
manifoldPtr->AddManifoldPoint(newPt);
|
||||||
// spu_printf("*** SpuContactResult::addContactPoint: depth = %f\n",depth);
|
return true;
|
||||||
|
|
||||||
#ifdef DEBUG_SPU_COLLISION_DETECTION
|
}
|
||||||
// int sman = sizeof(rage::phManifold);
|
return false;
|
||||||
// spu_printf("sizeof_manifold = %i\n",sman);
|
|
||||||
#endif //DEBUG_SPU_COLLISION_DETECTION
|
}
|
||||||
|
|
||||||
btPersistentManifold* localManifold = m_spuManifold;
|
|
||||||
|
void SpuContactResult::writeDoubleBufferedManifold(btPersistentManifold* lsManifold, btPersistentManifold* mmManifold)
|
||||||
btVector3 normalB(normalOnBInWorld.getX(),normalOnBInWorld.getY(),normalOnBInWorld.getZ());
|
{
|
||||||
btVector3 pointWrld(pointInWorld.getX(),pointInWorld.getY(),pointInWorld.getZ());
|
memcpy(g_manifoldDmaExport.getFront(),lsManifold,sizeof(btPersistentManifold));
|
||||||
|
|
||||||
//process the contact point
|
g_manifoldDmaExport.swapBuffers();
|
||||||
const bool retVal = ManifoldResultAddContactPoint(normalB,
|
g_manifoldDmaExport.backBufferDmaPut((uint64_t)mmManifold, sizeof(btPersistentManifold), DMA_TAG(9));
|
||||||
pointWrld,
|
// 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?
|
||||||
depth,
|
//no, the swapBuffers does the wait
|
||||||
localManifold,
|
}
|
||||||
m_rootWorldTransform0,
|
|
||||||
m_rootWorldTransform1
|
void SpuContactResult::addContactPoint(const btVector3& normalOnBInWorld,const btPoint3& pointInWorld,float depth)
|
||||||
);
|
{
|
||||||
m_RequiresWriteBack = m_RequiresWriteBack || retVal;
|
//spu_printf("*** SpuContactResult::addContactPoint: depth = %f\n",depth);
|
||||||
}
|
|
||||||
|
#ifdef DEBUG_SPU_COLLISION_DETECTION
|
||||||
void SpuContactResult::flush()
|
// int sman = sizeof(rage::phManifold);
|
||||||
{
|
// spu_printf("sizeof_manifold = %i\n",sman);
|
||||||
if (m_RequiresWriteBack)
|
#endif //DEBUG_SPU_COLLISION_DETECTION
|
||||||
{
|
|
||||||
#ifdef DEBUG_SPU_COLLISION_DETECTION
|
btPersistentManifold* localManifold = m_spuManifold;
|
||||||
spu_printf("SPU: Start rage::phManifold Write (Put) DMA\n");
|
|
||||||
#endif //DEBUG_SPU_COLLISION_DETECTION
|
btVector3 normalB(normalOnBInWorld.getX(),normalOnBInWorld.getY(),normalOnBInWorld.getZ());
|
||||||
// spu_printf("writeDoubleBufferedManifold\n");
|
btVector3 pointWrld(pointInWorld.getX(),pointInWorld.getY(),pointInWorld.getZ());
|
||||||
writeDoubleBufferedManifold(m_spuManifold, (btPersistentManifold*)m_manifoldAddress);
|
|
||||||
#ifdef DEBUG_SPU_COLLISION_DETECTION
|
//process the contact point
|
||||||
spu_printf("SPU: Finished (Put) DMA\n");
|
const bool retVal = ManifoldResultAddContactPoint(normalB,
|
||||||
#endif //DEBUG_SPU_COLLISION_DETECTION
|
pointWrld,
|
||||||
}
|
depth,
|
||||||
m_spuManifold = NULL;
|
localManifold,
|
||||||
m_RequiresWriteBack = false;
|
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
|
Bullet Continuous Collision Detection and Physics Library
|
||||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied warranty.
|
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.
|
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,
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
including commercial applications, and to alter it and redistribute it freely,
|
including commercial applications, and to alter it and redistribute it freely,
|
||||||
subject to the following restrictions:
|
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.
|
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.
|
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.
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef SPU_CONTACT_RESULT2_H
|
#ifndef SPU_CONTACT_RESULT2_H
|
||||||
#define SPU_CONTACT_RESULT2_H
|
#define SPU_CONTACT_RESULT2_H
|
||||||
|
|
||||||
|
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include "../SpuDoubleBuffer.h"
|
#include "../SpuDoubleBuffer.h"
|
||||||
|
|
||||||
|
|
||||||
#include "LinearMath/btTransform.h"
|
#include "LinearMath/btTransform.h"
|
||||||
#include "LinearMath/btPoint3.h"
|
#include "LinearMath/btPoint3.h"
|
||||||
|
|
||||||
|
|
||||||
#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
|
#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
|
||||||
|
|
||||||
|
|
||||||
struct SpuCollisionPairInput
|
struct SpuCollisionPairInput
|
||||||
{
|
{
|
||||||
uint64_t m_collisionShapes[2];
|
uint64_t m_collisionShapes[2];
|
||||||
void* m_spuCollisionShapes[2];
|
void* m_spuCollisionShapes[2];
|
||||||
|
|
||||||
uint64_t m_persistentManifoldPtr;
|
uint64_t m_persistentManifoldPtr;
|
||||||
btVector3 m_primitiveDimensions0;
|
btVector3 m_primitiveDimensions0;
|
||||||
btVector3 m_primitiveDimensions1;
|
btVector3 m_primitiveDimensions1;
|
||||||
int m_shapeType0;
|
int m_shapeType0;
|
||||||
int m_shapeType1;
|
int m_shapeType1;
|
||||||
float m_collisionMargin0;
|
float m_collisionMargin0;
|
||||||
float m_collisionMargin1;
|
float m_collisionMargin1;
|
||||||
|
|
||||||
btTransform m_worldTransform0;
|
btTransform m_worldTransform0;
|
||||||
btTransform m_worldTransform1;
|
btTransform m_worldTransform1;
|
||||||
|
|
||||||
bool m_isSwapped;
|
bool m_isSwapped;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct SpuClosestPointInput
|
struct SpuClosestPointInput
|
||||||
{
|
{
|
||||||
SpuClosestPointInput()
|
SpuClosestPointInput()
|
||||||
:m_maximumDistanceSquared(float(1e30)),
|
:m_maximumDistanceSquared(float(1e30)),
|
||||||
m_stackAlloc(0)
|
m_stackAlloc(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
btTransform m_transformA;
|
btTransform m_transformA;
|
||||||
btTransform m_transformB;
|
btTransform m_transformB;
|
||||||
float m_maximumDistanceSquared;
|
float m_maximumDistanceSquared;
|
||||||
class btStackAlloc* m_stackAlloc;
|
class btStackAlloc* m_stackAlloc;
|
||||||
struct SpuConvexPolyhedronVertexData* m_convexVertexData;
|
struct SpuConvexPolyhedronVertexData* m_convexVertexData;
|
||||||
};
|
};
|
||||||
|
|
||||||
///SpuContactResult exports the contact points using double-buffered DMA transfers, only when needed
|
///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.
|
///So when an existing contact point is duplicated, no transfer/refresh is performed.
|
||||||
class SpuContactResult
|
class SpuContactResult
|
||||||
{
|
{
|
||||||
btTransform m_rootWorldTransform0;
|
btTransform m_rootWorldTransform0;
|
||||||
btTransform m_rootWorldTransform1;
|
btTransform m_rootWorldTransform1;
|
||||||
uint64_t m_manifoldAddress;
|
uint64_t m_manifoldAddress;
|
||||||
|
|
||||||
btPersistentManifold* m_spuManifold;
|
btPersistentManifold* m_spuManifold;
|
||||||
bool m_RequiresWriteBack;
|
bool m_RequiresWriteBack;
|
||||||
|
bool m_isSwapped;
|
||||||
DoubleBuffer<btPersistentManifold, 1> g_manifoldDmaExport;
|
|
||||||
|
DoubleBuffer<btPersistentManifold, 1> g_manifoldDmaExport;
|
||||||
public:
|
|
||||||
SpuContactResult();
|
public:
|
||||||
virtual ~SpuContactResult();
|
SpuContactResult();
|
||||||
|
virtual ~SpuContactResult();
|
||||||
btPersistentManifold* GetSpuManifold() const
|
|
||||||
{
|
btPersistentManifold* GetSpuManifold() const
|
||||||
return m_spuManifold;
|
{
|
||||||
}
|
return m_spuManifold;
|
||||||
|
}
|
||||||
virtual void setShapeIdentifiers(int partId0,int index0, int partId1,int index1);
|
|
||||||
|
virtual void setShapeIdentifiers(int partId0,int index0, int partId1,int index1);
|
||||||
void setContactInfo(btPersistentManifold* spuManifold, uint64_t manifoldAddress,const btTransform& worldTrans0,const btTransform& worldTrans1);
|
|
||||||
|
void setContactInfo(btPersistentManifold* spuManifold, uint64_t manifoldAddress,const btTransform& worldTrans0,const btTransform& worldTrans1, bool isSwapped = false);
|
||||||
void writeDoubleBufferedManifold(btPersistentManifold* lsManifold, btPersistentManifold* mmManifold);
|
|
||||||
|
void writeDoubleBufferedManifold(btPersistentManifold* lsManifold, btPersistentManifold* mmManifold);
|
||||||
virtual void addContactPoint(const btVector3& normalOnBInWorld,const btPoint3& pointInWorld,float depth);
|
|
||||||
|
virtual void addContactPoint(const btVector3& normalOnBInWorld,const btPoint3& pointInWorld,float depth);
|
||||||
void flush();
|
|
||||||
};
|
void flush();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif //SPU_CONTACT_RESULT2_H
|
|
||||||
|
#endif //SPU_CONTACT_RESULT2_H
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -35,8 +35,15 @@ btCompoundShape::~btCompoundShape()
|
|||||||
|
|
||||||
void btCompoundShape::addChildShape(const btTransform& localTransform,btCollisionShape* shape)
|
void btCompoundShape::addChildShape(const btTransform& localTransform,btCollisionShape* shape)
|
||||||
{
|
{
|
||||||
m_childTransforms.push_back(localTransform);
|
//m_childTransforms.push_back(localTransform);
|
||||||
m_childShapes.push_back(shape);
|
//m_childShapes.push_back(shape);
|
||||||
|
btCompoundShapeChild child;
|
||||||
|
child.m_transform = localTransform;
|
||||||
|
child.m_childShape = shape;
|
||||||
|
child.m_childShapeType = shape->getShapeType();
|
||||||
|
child.m_childMargin = shape->getMargin();
|
||||||
|
|
||||||
|
m_children.push_back(child);
|
||||||
|
|
||||||
//extend the local aabbMin/aabbMax
|
//extend the local aabbMin/aabbMax
|
||||||
btVector3 localAabbMin,localAabbMax;
|
btVector3 localAabbMin,localAabbMax;
|
||||||
|
|||||||
@@ -26,12 +26,21 @@ subject to the following restrictions:
|
|||||||
|
|
||||||
class btOptimizedBvh;
|
class btOptimizedBvh;
|
||||||
|
|
||||||
|
ATTRIBUTE_ALIGNED16(struct) btCompoundShapeChild
|
||||||
|
{
|
||||||
|
btTransform m_transform;
|
||||||
|
btCollisionShape* m_childShape;
|
||||||
|
int m_childShapeType;
|
||||||
|
btScalar m_childMargin;
|
||||||
|
};
|
||||||
|
|
||||||
/// btCompoundShape allows to store multiple other btCollisionShapes
|
/// btCompoundShape allows to store multiple other btCollisionShapes
|
||||||
/// This allows for concave collision objects. This is more general then the Static Concave btTriangleMeshShape.
|
/// This allows for concave collision objects. This is more general then the Static Concave btTriangleMeshShape.
|
||||||
class btCompoundShape : public btCollisionShape
|
ATTRIBUTE_ALIGNED16(class) btCompoundShape : public btCollisionShape
|
||||||
{
|
{
|
||||||
btAlignedObjectArray<btTransform> m_childTransforms;
|
//btAlignedObjectArray<btTransform> m_childTransforms;
|
||||||
btAlignedObjectArray<btCollisionShape*> m_childShapes;
|
//btAlignedObjectArray<btCollisionShape*> m_childShapes;
|
||||||
|
btAlignedObjectArray<btCompoundShapeChild> m_children;
|
||||||
btVector3 m_localAabbMin;
|
btVector3 m_localAabbMin;
|
||||||
btVector3 m_localAabbMax;
|
btVector3 m_localAabbMax;
|
||||||
|
|
||||||
@@ -46,25 +55,31 @@ public:
|
|||||||
|
|
||||||
int getNumChildShapes() const
|
int getNumChildShapes() const
|
||||||
{
|
{
|
||||||
return int (m_childShapes.size());
|
return int (m_children.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
btCollisionShape* getChildShape(int index)
|
btCollisionShape* getChildShape(int index)
|
||||||
{
|
{
|
||||||
return m_childShapes[index];
|
return m_children[index].m_childShape;
|
||||||
}
|
}
|
||||||
const btCollisionShape* getChildShape(int index) const
|
const btCollisionShape* getChildShape(int index) const
|
||||||
{
|
{
|
||||||
return m_childShapes[index];
|
return m_children[index].m_childShape;
|
||||||
}
|
}
|
||||||
|
|
||||||
btTransform& getChildTransform(int index)
|
btTransform getChildTransform(int index)
|
||||||
{
|
{
|
||||||
return m_childTransforms[index];
|
return m_children[index].m_transform;
|
||||||
}
|
}
|
||||||
const btTransform& getChildTransform(int index) const
|
const btTransform getChildTransform(int index) const
|
||||||
{
|
{
|
||||||
return m_childTransforms[index];
|
return m_children[index].m_transform;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
btCompoundShapeChild* getChildList()
|
||||||
|
{
|
||||||
|
return &m_children[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
|
///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
|
||||||
|
|||||||
Reference in New Issue
Block a user