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:
@@ -33,6 +33,19 @@ m_sharedManifold(ci.m_manifold)
|
|||||||
assert (colObj->getCollisionShape()->isCompound());
|
assert (colObj->getCollisionShape()->isCompound());
|
||||||
|
|
||||||
btCompoundShape* compoundShape = static_cast<btCompoundShape*>(colObj->getCollisionShape());
|
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 numChildren = compoundShape->getNumChildShapes();
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@@ -47,14 +60,13 @@ m_sharedManifold(ci.m_manifold)
|
|||||||
btCollisionShape* tmpShape = colObj->getCollisionShape();
|
btCollisionShape* tmpShape = colObj->getCollisionShape();
|
||||||
btCollisionShape* childShape = compoundShape->getChildShape(i);
|
btCollisionShape* childShape = compoundShape->getChildShape(i);
|
||||||
colObj->internalSetTemporaryCollisionShape( childShape );
|
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 );
|
colObj->internalSetTemporaryCollisionShape( tmpShape );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void btCompoundCollisionAlgorithm::removeChildAlgorithms()
|
||||||
btCompoundCollisionAlgorithm::~btCompoundCollisionAlgorithm()
|
|
||||||
{
|
{
|
||||||
int numChildren = m_childCollisionAlgorithms.size();
|
int numChildren = m_childCollisionAlgorithms.size();
|
||||||
int i;
|
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* colObj = m_isSwapped? body1 : body0;
|
||||||
btCollisionObject* otherObj = m_isSwapped? body0 : body1;
|
btCollisionObject* otherObj = m_isSwapped? body0 : body1;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
assert (colObj->getCollisionShape()->isCompound());
|
assert (colObj->getCollisionShape()->isCompound());
|
||||||
btCompoundShape* compoundShape = static_cast<btCompoundShape*>(colObj->getCollisionShape());
|
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();
|
btDbvt* tree = compoundShape->getDynamicAabbTree();
|
||||||
//use a dynamic aabb tree to cull potential child-overlaps
|
//use a dynamic aabb tree to cull potential child-overlaps
|
||||||
btCompoundLeafCallback callback(colObj,otherObj,m_dispatcher,dispatchInfo,resultOut,&m_childCollisionAlgorithms[0],m_sharedManifold);
|
btCompoundLeafCallback callback(colObj,otherObj,m_dispatcher,dispatchInfo,resultOut,&m_childCollisionAlgorithms[0],m_sharedManifold);
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ class btDispatcher;
|
|||||||
#include "btCollisionCreateFunc.h"
|
#include "btCollisionCreateFunc.h"
|
||||||
#include "LinearMath/btAlignedObjectArray.h"
|
#include "LinearMath/btAlignedObjectArray.h"
|
||||||
class btDispatcher;
|
class btDispatcher;
|
||||||
|
class btCollisionObject;
|
||||||
|
|
||||||
/// btCompoundCollisionAlgorithm supports collision between CompoundCollisionShapes and other collision shapes
|
/// btCompoundCollisionAlgorithm supports collision between CompoundCollisionShapes and other collision shapes
|
||||||
class btCompoundCollisionAlgorithm : public btActivatingCollisionAlgorithm
|
class btCompoundCollisionAlgorithm : public btActivatingCollisionAlgorithm
|
||||||
@@ -36,6 +37,12 @@ class btCompoundCollisionAlgorithm : public btActivatingCollisionAlgorithm
|
|||||||
class btPersistentManifold* m_sharedManifold;
|
class btPersistentManifold* m_sharedManifold;
|
||||||
bool m_ownsManifold;
|
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:
|
public:
|
||||||
|
|
||||||
btCompoundCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped);
|
btCompoundCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped);
|
||||||
|
|||||||
@@ -22,7 +22,8 @@ btCompoundShape::btCompoundShape(bool enableDynamicAabbTree)
|
|||||||
m_localAabbMax(btScalar(-1e30),btScalar(-1e30),btScalar(-1e30)),
|
m_localAabbMax(btScalar(-1e30),btScalar(-1e30),btScalar(-1e30)),
|
||||||
m_collisionMargin(btScalar(0.)),
|
m_collisionMargin(btScalar(0.)),
|
||||||
m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.)),
|
m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.)),
|
||||||
m_dynamicAabbTree(0)
|
m_dynamicAabbTree(0),
|
||||||
|
m_updateRevision(1)
|
||||||
{
|
{
|
||||||
m_shapeType = COMPOUND_SHAPE_PROXYTYPE;
|
m_shapeType = COMPOUND_SHAPE_PROXYTYPE;
|
||||||
|
|
||||||
@@ -46,6 +47,7 @@ btCompoundShape::~btCompoundShape()
|
|||||||
|
|
||||||
void btCompoundShape::addChildShape(const btTransform& localTransform,btCollisionShape* shape)
|
void btCompoundShape::addChildShape(const btTransform& localTransform,btCollisionShape* shape)
|
||||||
{
|
{
|
||||||
|
m_updateRevision++;
|
||||||
//m_childTransforms.push_back(localTransform);
|
//m_childTransforms.push_back(localTransform);
|
||||||
//m_childShapes.push_back(shape);
|
//m_childShapes.push_back(shape);
|
||||||
btCompoundShapeChild child;
|
btCompoundShapeChild child;
|
||||||
@@ -99,6 +101,7 @@ void btCompoundShape::updateChildTransform(int childIndex, const btTransform& ne
|
|||||||
|
|
||||||
void btCompoundShape::removeChildShapeByIndex(int childShapeIndex)
|
void btCompoundShape::removeChildShapeByIndex(int childShapeIndex)
|
||||||
{
|
{
|
||||||
|
m_updateRevision++;
|
||||||
btAssert(childShapeIndex >=0 && childShapeIndex < m_children.size());
|
btAssert(childShapeIndex >=0 && childShapeIndex < m_children.size());
|
||||||
if (m_dynamicAabbTree)
|
if (m_dynamicAabbTree)
|
||||||
{
|
{
|
||||||
@@ -113,6 +116,7 @@ void btCompoundShape::removeChildShapeByIndex(int childShapeIndex)
|
|||||||
|
|
||||||
void btCompoundShape::removeChildShape(btCollisionShape* shape)
|
void btCompoundShape::removeChildShape(btCollisionShape* shape)
|
||||||
{
|
{
|
||||||
|
m_updateRevision++;
|
||||||
// Find the children containing the shape specified, and remove those children.
|
// Find the children containing the shape specified, and remove those children.
|
||||||
//note: there might be multiple children using the same shape!
|
//note: there might be multiple children using the same shape!
|
||||||
for(int i = m_children.size()-1; i >= 0 ; i--)
|
for(int i = m_children.size()-1; i >= 0 ; i--)
|
||||||
@@ -139,6 +143,7 @@ void btCompoundShape::recalculateLocalAabb()
|
|||||||
{
|
{
|
||||||
// Recalculate the local aabb
|
// Recalculate the local aabb
|
||||||
// Brute force, it iterates over all the shapes left.
|
// Brute force, it iterates over all the shapes left.
|
||||||
|
|
||||||
m_localAabbMin = btVector3(btScalar(1e30),btScalar(1e30),btScalar(1e30));
|
m_localAabbMin = btVector3(btScalar(1e30),btScalar(1e30),btScalar(1e30));
|
||||||
m_localAabbMax = 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
|
void btCompoundShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const
|
||||||
{
|
{
|
||||||
btVector3 localHalfExtents = btScalar(0.5)*(m_localAabbMax-m_localAabbMin);
|
btVector3 localHalfExtents = btScalar(0.5)*(m_localAabbMax-m_localAabbMin);
|
||||||
localHalfExtents += btVector3(getMargin(),getMargin(),getMargin());
|
|
||||||
btVector3 localCenter = btScalar(0.5)*(m_localAabbMax+m_localAabbMin);
|
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();
|
btMatrix3x3 abs_b = trans.getBasis().absolute();
|
||||||
|
|
||||||
btVector3 center = trans(localCenter);
|
btVector3 center = trans(localCenter);
|
||||||
|
|||||||
@@ -59,6 +59,9 @@ ATTRIBUTE_ALIGNED16(class) btCompoundShape : public btCollisionShape
|
|||||||
|
|
||||||
btDbvt* m_dynamicAabbTree;
|
btDbvt* m_dynamicAabbTree;
|
||||||
|
|
||||||
|
///increment m_updateRevision when adding/removing/replacing child shapes, so that some caches can be updated
|
||||||
|
int m_updateRevision;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
BT_DECLARE_ALIGNED_ALLOCATOR();
|
BT_DECLARE_ALIGNED_ALLOCATOR();
|
||||||
|
|
||||||
@@ -152,6 +155,10 @@ public:
|
|||||||
///of the collision object by the principal transform.
|
///of the collision object by the principal transform.
|
||||||
void calculatePrincipalAxisTransform(btScalar* masses, btTransform& principal, btVector3& inertia) const;
|
void calculatePrincipalAxisTransform(btScalar* masses, btTransform& principal, btVector3& inertia) const;
|
||||||
|
|
||||||
|
int getUpdateRevision() const
|
||||||
|
{
|
||||||
|
return m_updateRevision;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
btScalar m_collisionMargin;
|
btScalar m_collisionMargin;
|
||||||
|
|||||||
Reference in New Issue
Block a user