Fix issues with btCompoundShape when adding/removing child shapes after construction of a btRigidBody.

Thanks tp for the report:
http://bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=2925&p=11700#p11700
This commit is contained in:
erwin.coumans
2008-12-07 20:57:38 +00:00
parent 06167a0b31
commit f3a70b65eb
4 changed files with 63 additions and 6 deletions

View File

@@ -33,6 +33,19 @@ m_sharedManifold(ci.m_manifold)
assert (colObj->getCollisionShape()->isCompound());
btCompoundShape* compoundShape = static_cast<btCompoundShape*>(colObj->getCollisionShape());
m_compoundShapeRevision = compoundShape->getUpdateRevision();
preallocateChildAlgorithms(body0,body1);
}
void btCompoundCollisionAlgorithm::preallocateChildAlgorithms(btCollisionObject* body0,btCollisionObject* body1)
{
btCollisionObject* colObj = m_isSwapped? body1 : body0;
btCollisionObject* otherObj = m_isSwapped? body0 : body1;
assert (colObj->getCollisionShape()->isCompound());
btCompoundShape* compoundShape = static_cast<btCompoundShape*>(colObj->getCollisionShape());
int numChildren = compoundShape->getNumChildShapes();
int i;
@@ -47,14 +60,13 @@ m_sharedManifold(ci.m_manifold)
btCollisionShape* tmpShape = colObj->getCollisionShape();
btCollisionShape* childShape = compoundShape->getChildShape(i);
colObj->internalSetTemporaryCollisionShape( childShape );
m_childCollisionAlgorithms[i] = ci.m_dispatcher1->findAlgorithm(colObj,otherObj,m_sharedManifold);
m_childCollisionAlgorithms[i] = m_dispatcher->findAlgorithm(colObj,otherObj,m_sharedManifold);
colObj->internalSetTemporaryCollisionShape( tmpShape );
}
}
}
btCompoundCollisionAlgorithm::~btCompoundCollisionAlgorithm()
void btCompoundCollisionAlgorithm::removeChildAlgorithms()
{
int numChildren = m_childCollisionAlgorithms.size();
int i;
@@ -68,6 +80,11 @@ btCompoundCollisionAlgorithm::~btCompoundCollisionAlgorithm()
}
}
btCompoundCollisionAlgorithm::~btCompoundCollisionAlgorithm()
{
removeChildAlgorithms();
}
@@ -168,9 +185,22 @@ void btCompoundCollisionAlgorithm::processCollision (btCollisionObject* body0,bt
btCollisionObject* colObj = m_isSwapped? body1 : body0;
btCollisionObject* otherObj = m_isSwapped? body0 : body1;
assert (colObj->getCollisionShape()->isCompound());
btCompoundShape* compoundShape = static_cast<btCompoundShape*>(colObj->getCollisionShape());
///btCompoundShape might have changed:
////make sure the internal child collision algorithm caches are still valid
if (compoundShape->getUpdateRevision() != m_compoundShapeRevision)
{
///clear and update all
removeChildAlgorithms();
preallocateChildAlgorithms(body0,body1);
}
btDbvt* tree = compoundShape->getDynamicAabbTree();
//use a dynamic aabb tree to cull potential child-overlaps
btCompoundLeafCallback callback(colObj,otherObj,m_dispatcher,dispatchInfo,resultOut,&m_childCollisionAlgorithms[0],m_sharedManifold);

View File

@@ -26,6 +26,7 @@ class btDispatcher;
#include "btCollisionCreateFunc.h"
#include "LinearMath/btAlignedObjectArray.h"
class btDispatcher;
class btCollisionObject;
/// btCompoundCollisionAlgorithm supports collision between CompoundCollisionShapes and other collision shapes
class btCompoundCollisionAlgorithm : public btActivatingCollisionAlgorithm
@@ -36,6 +37,12 @@ class btCompoundCollisionAlgorithm : public btActivatingCollisionAlgorithm
class btPersistentManifold* m_sharedManifold;
bool m_ownsManifold;
int m_compoundShapeRevision;//to keep track of changes, so that childAlgorithm array can be updated
void removeChildAlgorithms();
void preallocateChildAlgorithms(btCollisionObject* body0,btCollisionObject* body1);
public:
btCompoundCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped);

View File

@@ -22,7 +22,8 @@ btCompoundShape::btCompoundShape(bool enableDynamicAabbTree)
m_localAabbMax(btScalar(-1e30),btScalar(-1e30),btScalar(-1e30)),
m_collisionMargin(btScalar(0.)),
m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.)),
m_dynamicAabbTree(0)
m_dynamicAabbTree(0),
m_updateRevision(1)
{
m_shapeType = COMPOUND_SHAPE_PROXYTYPE;
@@ -46,6 +47,7 @@ btCompoundShape::~btCompoundShape()
void btCompoundShape::addChildShape(const btTransform& localTransform,btCollisionShape* shape)
{
m_updateRevision++;
//m_childTransforms.push_back(localTransform);
//m_childShapes.push_back(shape);
btCompoundShapeChild child;
@@ -99,6 +101,7 @@ void btCompoundShape::updateChildTransform(int childIndex, const btTransform& ne
void btCompoundShape::removeChildShapeByIndex(int childShapeIndex)
{
m_updateRevision++;
btAssert(childShapeIndex >=0 && childShapeIndex < m_children.size());
if (m_dynamicAabbTree)
{
@@ -113,6 +116,7 @@ void btCompoundShape::removeChildShapeByIndex(int childShapeIndex)
void btCompoundShape::removeChildShape(btCollisionShape* shape)
{
m_updateRevision++;
// Find the children containing the shape specified, and remove those children.
//note: there might be multiple children using the same shape!
for(int i = m_children.size()-1; i >= 0 ; i--)
@@ -139,6 +143,7 @@ void btCompoundShape::recalculateLocalAabb()
{
// Recalculate the local aabb
// Brute force, it iterates over all the shapes left.
m_localAabbMin = btVector3(btScalar(1e30),btScalar(1e30),btScalar(1e30));
m_localAabbMax = btVector3(btScalar(-1e30),btScalar(-1e30),btScalar(-1e30));
@@ -161,9 +166,17 @@ void btCompoundShape::recalculateLocalAabb()
void btCompoundShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const
{
btVector3 localHalfExtents = btScalar(0.5)*(m_localAabbMax-m_localAabbMin);
localHalfExtents += btVector3(getMargin(),getMargin(),getMargin());
btVector3 localCenter = btScalar(0.5)*(m_localAabbMax+m_localAabbMin);
//avoid an illegal AABB when there are no children
if (!m_children.size())
{
localHalfExtents.setValue(0,0,0);
localCenter.setValue(0,0,0);
}
localHalfExtents += btVector3(getMargin(),getMargin(),getMargin());
btMatrix3x3 abs_b = trans.getBasis().absolute();
btVector3 center = trans(localCenter);

View File

@@ -59,6 +59,9 @@ ATTRIBUTE_ALIGNED16(class) btCompoundShape : public btCollisionShape
btDbvt* m_dynamicAabbTree;
///increment m_updateRevision when adding/removing/replacing child shapes, so that some caches can be updated
int m_updateRevision;
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
@@ -152,6 +155,10 @@ public:
///of the collision object by the principal transform.
void calculatePrincipalAxisTransform(btScalar* masses, btTransform& principal, btVector3& inertia) const;
int getUpdateRevision() const
{
return m_updateRevision;
}
private:
btScalar m_collisionMargin;