From f3a70b65ebfd8a1a11106c0121bd904fab96e9d1 Mon Sep 17 00:00:00 2001 From: "erwin.coumans" Date: Sun, 7 Dec 2008 20:57:38 +0000 Subject: [PATCH] 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 --- .../btCompoundCollisionAlgorithm.cpp | 36 +++++++++++++++++-- .../btCompoundCollisionAlgorithm.h | 7 ++++ .../CollisionShapes/btCompoundShape.cpp | 19 ++++++++-- .../CollisionShapes/btCompoundShape.h | 7 ++++ 4 files changed, 63 insertions(+), 6 deletions(-) diff --git a/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp b/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp index 1429605bb..b5f6035d7 100644 --- a/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp +++ b/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp @@ -33,6 +33,19 @@ m_sharedManifold(ci.m_manifold) assert (colObj->getCollisionShape()->isCompound()); btCompoundShape* compoundShape = static_cast(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(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(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); diff --git a/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h b/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h index 2bd427fe0..255e0af66 100644 --- a/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h +++ b/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h @@ -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 @@ -35,7 +36,13 @@ 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); diff --git a/src/BulletCollision/CollisionShapes/btCompoundShape.cpp b/src/BulletCollision/CollisionShapes/btCompoundShape.cpp index d10b7d633..167dd12e1 100644 --- a/src/BulletCollision/CollisionShapes/btCompoundShape.cpp +++ b/src/BulletCollision/CollisionShapes/btCompoundShape.cpp @@ -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,8 +166,16 @@ 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(); @@ -173,7 +186,7 @@ void btCompoundShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVect abs_b[2].dot(localHalfExtents)); aabbMin = center-extent; aabbMax = center+extent; - + } void btCompoundShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const diff --git a/src/BulletCollision/CollisionShapes/btCompoundShape.h b/src/BulletCollision/CollisionShapes/btCompoundShape.h index 8883e1f2b..434860c86 100644 --- a/src/BulletCollision/CollisionShapes/btCompoundShape.h +++ b/src/BulletCollision/CollisionShapes/btCompoundShape.h @@ -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;