BGE: Fix memory leak and crash with certain physic types

Fixing crash if the physic type is set sensor or character. Caused by a790e172d0281e64.
Fixing memory leak, if the constraint is deleted with Python API removeConstraint().
Add RemoveConstraint() method to avoid code duplication.
Rename old RemoveConstraint() to RemoveConstraintById() which is more suitable name for this method.
This commit is contained in:
Thomas Szepe 2015-08-16 11:38:25 +02:00
parent 19cc75d642
commit 9437acb7f3
6 changed files with 32 additions and 28 deletions

@ -583,7 +583,7 @@ static PyObject *gPyRemoveConstraint(PyObject *self,
{ {
if (PHY_GetActiveEnvironment()) if (PHY_GetActiveEnvironment())
{ {
PHY_GetActiveEnvironment()->RemoveConstraint(constraintid); PHY_GetActiveEnvironment()->RemoveConstraintById(constraintid);
} }
} }
else { else {

@ -511,7 +511,26 @@ void CcdPhysicsEnvironment::AddCcdPhysicsController(CcdPhysicsController* ctrl)
assert(obj->getBroadphaseHandle()); assert(obj->getBroadphaseHandle());
} }
void CcdPhysicsEnvironment::RemoveConstraint(btTypedConstraint *con)
{
btRigidBody rbA = con->getRigidBodyA();
btRigidBody rbB = con->getRigidBodyA();
rbA.activate();
rbB.activate();
m_dynamicsWorld->removeConstraint(con);
if (rbA.getUserPointer()) {
((CcdPhysicsController *)rbA.getUserPointer())->removeCcdConstraintRef(con);
}
if (rbB.getUserPointer()) {
((CcdPhysicsController *)rbB.getUserPointer())->removeCcdConstraintRef(con);
}
/* Since we remove the constraint in the onwer and the target, we can delete it,
* KX_ConstraintWrapper keep the constraint id not the pointer, so no problems. */
delete con;
}
bool CcdPhysicsEnvironment::RemoveCcdPhysicsController(CcdPhysicsController* ctrl) bool CcdPhysicsEnvironment::RemoveCcdPhysicsController(CcdPhysicsController* ctrl)
{ {
@ -534,21 +553,7 @@ bool CcdPhysicsEnvironment::RemoveCcdPhysicsController(CcdPhysicsController* ctr
for (int i = ctrl->getNumCcdConstraintRefs() - 1; i >= 0; i--) for (int i = ctrl->getNumCcdConstraintRefs() - 1; i >= 0; i--)
{ {
btTypedConstraint* con = ctrl->getCcdConstraintRef(i); btTypedConstraint* con = ctrl->getCcdConstraintRef(i);
con->getRigidBodyA().activate(); RemoveConstraint(con);
con->getRigidBodyB().activate();
m_dynamicsWorld->removeConstraint(con);
// The other physics controller in the constraint, can't be NULL.
CcdPhysicsController *otherCtrl = (body == &con->getRigidBodyA()) ?
(CcdPhysicsController *)con->getRigidBodyB().getUserPointer() :
(CcdPhysicsController *)con->getRigidBodyA().getUserPointer();
otherCtrl->removeCcdConstraintRef(con);
ctrl->removeCcdConstraintRef(con);
/** Since we remove the constraint in the onwer and the target, we can delete it,
* KX_ConstraintWrapper keep the constraint id not the pointer, so no problems.
*/
delete con;
} }
m_dynamicsWorld->removeRigidBody(ctrl->GetRigidBody()); m_dynamicsWorld->removeRigidBody(ctrl->GetRigidBody());
@ -563,7 +568,7 @@ bool CcdPhysicsEnvironment::RemoveCcdPhysicsController(CcdPhysicsController* ctr
} }
if (vehicle_constraint > 0) if (vehicle_constraint > 0)
RemoveConstraint(vehicle_constraint); RemoveConstraintById(vehicle_constraint);
} else } else
{ {
//if a softbody //if a softbody
@ -1109,9 +1114,7 @@ int CcdPhysicsEnvironment::CreateUniversalD6Constraint(
return 0; return 0;
} }
void CcdPhysicsEnvironment::RemoveConstraintById(int constraintId)
void CcdPhysicsEnvironment::RemoveConstraint(int constraintId)
{ {
// For soft body constraints // For soft body constraints
if (constraintId == 0) if (constraintId == 0)
@ -1124,9 +1127,7 @@ void CcdPhysicsEnvironment::RemoveConstraint(int constraintId)
btTypedConstraint* constraint = m_dynamicsWorld->getConstraint(i); btTypedConstraint* constraint = m_dynamicsWorld->getConstraint(i);
if (constraint->getUserConstraintId() == constraintId) if (constraint->getUserConstraintId() == constraintId)
{ {
constraint->getRigidBodyA().activate(); RemoveConstraint(constraint);
constraint->getRigidBodyB().activate();
m_dynamicsWorld->removeConstraint(constraint);
break; break;
} }
} }

@ -67,6 +67,9 @@ class CcdPhysicsEnvironment : public PHY_IPhysicsEnvironment
friend class CcdOverlapFilterCallBack; friend class CcdOverlapFilterCallBack;
btVector3 m_gravity; btVector3 m_gravity;
// Removes the constraint and his references from the owner and the target.
void RemoveConstraint(btTypedConstraint *con);
protected: protected:
btIDebugDraw* m_debugDrawer; btIDebugDraw* m_debugDrawer;
@ -185,7 +188,7 @@ protected:
virtual float GetConstraintParam(int constraintId,int param); virtual float GetConstraintParam(int constraintId,int param);
virtual void RemoveConstraint(int constraintid); virtual void RemoveConstraintById(int constraintid);
virtual float getAppliedImpulse(int constraintid); virtual float getAppliedImpulse(int constraintid);

@ -106,7 +106,7 @@ int DummyPhysicsEnvironment::CreateConstraint(class PHY_IPhysicsController* ct
} }
void DummyPhysicsEnvironment::RemoveConstraint(int constraintid) void DummyPhysicsEnvironment::RemoveConstraintById(int constraintid)
{ {
if (constraintid) if (constraintid)
{ {

@ -68,7 +68,7 @@ public:
float axis2X=0,float axis2Y=0,float axis2Z=0,int flag=0 float axis2X=0,float axis2Y=0,float axis2Z=0,int flag=0
); );
virtual void RemoveConstraint(int constraintid); virtual void RemoveConstraintById(int constraintid);
//complex constraint for vehicles //complex constraint for vehicles
virtual PHY_IVehicle* GetVehicleConstraint(int constraintId) virtual PHY_IVehicle* GetVehicleConstraint(int constraintId)

@ -168,7 +168,7 @@ class PHY_IPhysicsEnvironment
float axis1X=0,float axis1Y=0,float axis1Z=0, float axis1X=0,float axis1Y=0,float axis1Z=0,
float axis2X=0,float axis2Y=0,float axis2Z=0,int flag=0 float axis2X=0,float axis2Y=0,float axis2Z=0,int flag=0
)=0; )=0;
virtual void RemoveConstraint(int constraintid)=0; virtual void RemoveConstraintById(int constraintid) = 0;
virtual float GetAppliedImpulse(int constraintid) { return 0.0f; } virtual float GetAppliedImpulse(int constraintid) { return 0.0f; }