Fix #101877, rigidbodies & constraints causing frequent crashes. #108399

Open
himisa wants to merge 1 commits from himisa/blender:fix_rigid_crash into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
4 changed files with 22 additions and 6 deletions

View File

@ -26,6 +26,7 @@ btTypedConstraint::btTypedConstraint(btTypedConstraintType type, btRigidBody& rb
m_breakingImpulseThreshold(SIMD_INFINITY), m_breakingImpulseThreshold(SIMD_INFINITY),
m_isEnabled(true), m_isEnabled(true),
m_needsFeedback(false), m_needsFeedback(false),
m_isValid(true),
m_overrideNumSolverIterations(-1), m_overrideNumSolverIterations(-1),
m_rbA(rbA), m_rbA(rbA),
m_rbB(getFixedBody()), m_rbB(getFixedBody()),
@ -42,6 +43,7 @@ btTypedConstraint::btTypedConstraint(btTypedConstraintType type, btRigidBody& rb
m_breakingImpulseThreshold(SIMD_INFINITY), m_breakingImpulseThreshold(SIMD_INFINITY),
m_isEnabled(true), m_isEnabled(true),
m_needsFeedback(false), m_needsFeedback(false),
m_isValid(true),
m_overrideNumSolverIterations(-1), m_overrideNumSolverIterations(-1),
m_rbA(rbA), m_rbA(rbA),
m_rbB(rbB), m_rbB(rbB),

View File

@ -84,6 +84,7 @@ btTypedConstraint : public btTypedObject
btScalar m_breakingImpulseThreshold; btScalar m_breakingImpulseThreshold;
bool m_isEnabled; bool m_isEnabled;
bool m_needsFeedback; bool m_needsFeedback;
bool m_isValid;
int m_overrideNumSolverIterations; int m_overrideNumSolverIterations;
btTypedConstraint& operator=(btTypedConstraint& other) btTypedConstraint& operator=(btTypedConstraint& other)
@ -198,6 +199,18 @@ public:
m_breakingImpulseThreshold = threshold; m_breakingImpulseThreshold = threshold;
} }
bool isValid() const{
return m_isValid;
}
void invalidate(){
if(isValid()){
m_rbA.removeConstraintRef(this);
m_rbB.removeConstraintRef(this);
m_isValid = false;
}
}
bool isEnabled() const bool isEnabled() const
{ {
return m_isEnabled; return m_isEnabled;

View File

@ -530,6 +530,10 @@ void btDiscreteDynamicsWorld::removeCollisionObject(btCollisionObject* collision
void btDiscreteDynamicsWorld::removeRigidBody(btRigidBody* body) void btDiscreteDynamicsWorld::removeRigidBody(btRigidBody* body)
{ {
for (int i = body->getNumConstraintRefs() - 1; i >= 0; i--) {
btTypedConstraint *con=body->getConstraintRef(i);
removeConstraint(con);
}
m_nonStaticRigidBodies.remove(body); m_nonStaticRigidBodies.remove(body);
btCollisionWorld::removeCollisionObject(body); btCollisionWorld::removeCollisionObject(body);
} }
@ -644,8 +648,7 @@ void btDiscreteDynamicsWorld::addConstraint(btTypedConstraint* constraint, bool
void btDiscreteDynamicsWorld::removeConstraint(btTypedConstraint* constraint) void btDiscreteDynamicsWorld::removeConstraint(btTypedConstraint* constraint)
{ {
m_constraints.remove(constraint); m_constraints.remove(constraint);
constraint->getRigidBodyA().removeConstraintRef(constraint); constraint->invalidate();
constraint->getRigidBodyB().removeConstraintRef(constraint);
} }
void btDiscreteDynamicsWorld::addAction(btActionInterface* action) void btDiscreteDynamicsWorld::addAction(btActionInterface* action)

View File

@ -353,7 +353,7 @@ void RB_body_delete(rbRigidBody *object)
* but since we delete everything when the world is rebult, we need to do it manually here */ * but since we delete everything when the world is rebult, we need to do it manually here */
for (int i = body->getNumConstraintRefs() - 1; i >= 0; i--) { for (int i = body->getNumConstraintRefs() - 1; i >= 0; i--) {
btTypedConstraint *con = body->getConstraintRef(i); btTypedConstraint *con = body->getConstraintRef(i);
body->removeConstraintRef(con); con->invalidate();
} }
delete body; delete body;
@ -1124,9 +1124,7 @@ void RB_constraint_delete(rbConstraint *con)
/* If the constraint has disabled collisions between the bodies, those bodies /* If the constraint has disabled collisions between the bodies, those bodies
* will have a pointer back to the constraint. We need to remove the constraint * will have a pointer back to the constraint. We need to remove the constraint
* from each body to avoid dereferencing the deleted constraint later (#91369) */ * from each body to avoid dereferencing the deleted constraint later (#91369) */
constraint->getRigidBodyA().removeConstraintRef(constraint); constraint->invalidate();
constraint->getRigidBodyB().removeConstraintRef(constraint);
delete constraint; delete constraint;
} }