diff options
author | Benoit Bolsee <benoit.bolsee@online.be> | 2008-03-01 22:46:50 +0300 |
---|---|---|
committer | Benoit Bolsee <benoit.bolsee@online.be> | 2008-03-01 22:46:50 +0300 |
commit | 0db0f5734d358676b11eccc702cf02adb3174b7e (patch) | |
tree | dbed0e86663eeabe8d333892958310878bfbe533 /source/gameengine/Ketsji | |
parent | 44314581dc934dc99c9504edf671118a9f988b68 (diff) |
Various mem leaks related to CValue reference count fixed
Diffstat (limited to 'source/gameengine/Ketsji')
-rw-r--r-- | source/gameengine/Ketsji/KX_Camera.cpp | 4 | ||||
-rw-r--r-- | source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp | 20 | ||||
-rw-r--r-- | source/gameengine/Ketsji/KX_KetsjiEngine.cpp | 2 | ||||
-rw-r--r-- | source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp | 2 | ||||
-rw-r--r-- | source/gameengine/Ketsji/KX_Scene.cpp | 75 | ||||
-rw-r--r-- | source/gameengine/Ketsji/KX_Scene.h | 13 |
6 files changed, 98 insertions, 18 deletions
diff --git a/source/gameengine/Ketsji/KX_Camera.cpp b/source/gameengine/Ketsji/KX_Camera.cpp index bb8ea7f23b3..b75662f01c9 100644 --- a/source/gameengine/Ketsji/KX_Camera.cpp +++ b/source/gameengine/Ketsji/KX_Camera.cpp @@ -58,7 +58,9 @@ KX_Camera::KX_Camera(void* sgReplicationInfo, m_name = "cam"; m_projection_matrix.setIdentity(); m_modelview_matrix.setIdentity(); - SetProperty("camera",new CIntValue(1)); + CValue* val = new CIntValue(1); + SetProperty("camera",val); + val->Release(); } diff --git a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp index 5de2ab1b2dc..7b2c514db8a 100644 --- a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp +++ b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp @@ -858,6 +858,8 @@ static btCollisionShape* CreateBulletShapeFromMesh(RAS_MeshObject* meshobj, bool //concaveShape = new btTriangleMeshShape( collisionMeshData ); concaveShape->recalcLocalAabb(); + if (collisionMeshShape) + delete collisionMeshShape; collisionMeshShape = concaveShape; } @@ -866,8 +868,10 @@ static btCollisionShape* CreateBulletShapeFromMesh(RAS_MeshObject* meshobj, bool return collisionMeshShape; } - - delete collisionMeshShape; + if (collisionMeshShape) + delete collisionMeshShape; + if (collisionMeshData) + delete collisionMeshData; return NULL; } @@ -1021,7 +1025,10 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj, // ci.m_localInertiaTensor.setValue(0.1f,0.1f,0.1f); if (!bm) + { + delete motionstate; return; + } bm->setMargin(0.06); @@ -1057,6 +1064,7 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj, compoundShape->addChildShape(childTrans,bm); + kxscene->AddShape(bm); //do some recalc? //recalc inertia for rigidbody if (!rigidbody->isStaticOrKinematicObject()) @@ -1076,6 +1084,9 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj, btTransform identTrans; identTrans.setIdentity(); compoundShape->addChildShape(identTrans,bm); + //note abount compoundShape: Bullet does not delete the child shapes when + //the compound shape is deleted, so insert also the child shapes + kxscene->AddShape(bm); bm = compoundShape; } @@ -1112,9 +1123,6 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj, ci.m_collisionShape = bm; - - - ci.m_friction = smmaterial->m_friction;//tweak the friction a bit, so the default 0.5 works nice ci.m_restitution = smmaterial->m_restitution; ci.m_physicsEnv = env; @@ -1127,6 +1135,8 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj, ci.m_collisionFilterMask = (isbulletdyna) ? short(CcdConstructionInfo::AllFilter) : short(CcdConstructionInfo::AllFilter ^ CcdConstructionInfo::StaticFilter); KX_BulletPhysicsController* physicscontroller = new KX_BulletPhysicsController(ci,isbulletdyna); + //remember that we created a shape so that we can delete it when the scene is removed (bullet will not delete it) + kxscene->AddShape(bm); if (objprop->m_in_active_layer) { diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp index 8febc0e10cd..9e5efad803b 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp @@ -1047,6 +1047,8 @@ void KX_KetsjiEngine::PostProcessScene(KX_Scene* scene) scene->SetActiveCamera(activecam); scene->GetObjectList()->Add(activecam->AddRef()); scene->GetRootParentList()->Add(activecam->AddRef()); + //done with activecam + activecam->Release(); } scene->UpdateParents(0.0); diff --git a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp index 45b2db10b33..7366e374a10 100644 --- a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp +++ b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp @@ -326,6 +326,8 @@ void KX_SCA_AddObjectActuator::InstantAddObject() m_lastCreatedObject = replica; m_lastCreatedObject->AddRef(); + // finished using replica? then release it + replica->Release(); } } diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index f9c2f8e571b..f9fc503f406 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -35,6 +35,7 @@ #pragma warning (disable : 4786) #endif //WIN32 + #include "KX_Scene.h" #include "MT_assert.h" @@ -78,6 +79,13 @@ #include "BL_SkinDeformer.h" #include "BL_DeformableGameObject.h" +// to get USE_BULLET! +#include "KX_ConvertPhysicsObject.h" + +#ifdef USE_BULLET +#include "CcdPhysicsEnvironment.h" +#include "CcdPhysicsController.h" +#endif void* KX_SceneReplicationFunc(SG_IObject* node,void* gameobj,void* scene) { @@ -124,6 +132,7 @@ KX_Scene::KX_Scene(class SCA_IInputDevice* keyboarddevice, m_objectlist = new CListValue(); m_parentlist = new CListValue(); m_lightlist= new CListValue(); + m_inactivelist = new CListValue(); m_euthanasyobjects = new CListValue(); m_delayReleaseObjects = new CListValue(); @@ -183,6 +192,9 @@ KX_Scene::~KX_Scene() if (m_parentlist) m_parentlist->Release(); + if (m_inactivelist) + m_inactivelist->Release(); + if (m_lightlist) m_lightlist->Release(); @@ -210,11 +222,38 @@ KX_Scene::~KX_Scene() { delete m_bucketmanager; } - +#ifdef USE_BULLET + // This is a fix for memory leaks in bullet: the collision shapes is not destroyed + // when the physical controllers are destroyed. The reason is that shapes are shared + // between replicas of an object. There is no reference count in Bullet so the + // only workaround that does not involve changes in Bullet is to save in this array + // the list of shapes that are created when the scene is created (see KX_ConvertPhysicsObjects.cpp) + class btCollisionShape* shape; + class btTriangleMeshShape* meshShape; + vector<class btCollisionShape*>::iterator it = m_shapes.begin(); + while (it != m_shapes.end()) { + shape = *it; + if (shape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE) + { + meshShape = static_cast<btTriangleMeshShape*>(shape); + // shapes based on meshes use an interface that contains the vertices. + // Again the idea is to be able to share the interface between shapes but + // this is not used in Blender: each base object will have its own interface + btStridingMeshInterface* meshInterface = meshShape->getMeshInterface(); + if (meshInterface) + delete meshInterface; + } + delete shape; + it++; + } +#endif //Py_DECREF(m_attrlist); } - +void KX_Scene::AddShape(class btCollisionShape*shape) +{ + m_shapes.push_back(shape); +} void KX_Scene::SetProjectionMatrix(MT_CmMatrix4x4& pmat) @@ -243,6 +282,11 @@ CListValue* KX_Scene::GetRootParentList() return m_parentlist; } +CListValue* KX_Scene::GetInactiveList() +{ + return m_inactivelist; +} + CListValue* KX_Scene::GetLightList() @@ -415,7 +459,7 @@ KX_GameObject* KX_Scene::AddNodeReplicaObject(class SG_IObject* node, class CVal replicanode->SetSGClientObject(newobj); // this is the list of object that are send to the graphics pipeline - m_objectlist->Add(newobj); + m_objectlist->Add(newobj->AddRef()); newobj->Bucketize(); // logic cannot be replicated, until the whole hierarchy is replicated. @@ -571,7 +615,9 @@ SCA_IObject* KX_Scene::AddReplicaObject(class CValue* originalobject, // add a timebomb to this object // for now, convert between so called frames and realtime m_tempObjectList->Add(replica->AddRef()); - replica->SetProperty("::timebomb",new CFloatValue(lifespan*0.02)); + CValue *fval = new CFloatValue(lifespan*0.02); + replica->SetProperty("::timebomb",fval); + fval->Release(); } // add to 'rootparent' list (this is the list of top hierarchy objects, updated each frame) @@ -634,7 +680,7 @@ SCA_IObject* KX_Scene::AddReplicaObject(class CValue* originalobject, replica->GetSGNode()->UpdateWorldData(0); replica->GetSGNode()->SetBBox(originalobj->GetSGNode()->BBox()); replica->GetSGNode()->SetRadius(originalobj->GetSGNode()->Radius()); - + // don't release replica here because we are returning it, not done with it... return replica; } @@ -654,7 +700,8 @@ void KX_Scene::RemoveObject(class CValue* gameobj) // recursively destruct node->Destruct(); } - newobj->SetSGNode(0); + //no need to do that: the object is destroyed and memory released + //newobj->SetSGNode(0); } void KX_Scene::DelayedReleaseObject(CValue* gameobj) @@ -704,6 +751,7 @@ void KX_Scene::NewRemoveObject(class CValue* gameobj) { m_logicmgr->RemoveDestroyedActuator(*ita); } + // the sensors/controllers/actuators must also be released, this is done in ~SCA_IObject // now remove the timer properties from the time manager int numprops = newobj->GetPropertyCount(); @@ -724,12 +772,15 @@ void KX_Scene::NewRemoveObject(class CValue* gameobj) newobj->Release(); if (m_parentlist->RemoveValue(newobj)) newobj->Release(); + if (m_inactivelist->RemoveValue(newobj)) + newobj->Release(); if (m_euthanasyobjects->RemoveValue(newobj)) newobj->Release(); if (newobj == m_active_camera) { - m_active_camera->Release(); + //no AddRef done on m_active_camera so no Release + //m_active_camera->Release(); m_active_camera = NULL; } } @@ -1108,6 +1159,8 @@ void KX_Scene::LogicEndFrame() for (i = numobj - 1; i >= 0; i--) { KX_GameObject* gameobj = (KX_GameObject*)m_euthanasyobjects->GetValue(i); + // KX_Scene::RemoveObject will also remove the object from this list + // that's why we start from the end this->RemoveObject(gameobj); } @@ -1115,11 +1168,11 @@ void KX_Scene::LogicEndFrame() for (i = numobj-1;i>=0;i--) { KX_GameObject* gameobj = (KX_GameObject*)m_delayReleaseObjects->GetValue(i); - m_delayReleaseObjects->RemoveValue(gameobj); - + // This list is not for object removal, but just object release + gameobj->Release(); } - - + // empty the list as we have removed all references + m_delayReleaseObjects->Resize(0); } diff --git a/source/gameengine/Ketsji/KX_Scene.h b/source/gameengine/Ketsji/KX_Scene.h index 50fcf1a3c40..b857f4f591e 100644 --- a/source/gameengine/Ketsji/KX_Scene.h +++ b/source/gameengine/Ketsji/KX_Scene.h @@ -85,6 +85,7 @@ class RAS_IPolyMaterial; class RAS_IRasterizer; class RAS_IRenderTools; class SCA_JoystickManager; +class btCollisionShape; /** * The KX_Scene holds all data for an independent scene. It relates * KX_Objects to the specific objects in the modules. @@ -111,6 +112,7 @@ protected: CListValue* m_objectlist; CListValue* m_parentlist; // all 'root' parents CListValue* m_lightlist; + CListValue* m_inactivelist; // all objects that are not in the active layer /** * The tree of objects in the scene. @@ -121,7 +123,11 @@ protected: * The set of cameras for this scene */ list<class KX_Camera*> m_cameras; - + /** + * The set of bullet shapes that must be deleted at the end of the scene + * to avoid memory leak (not deleted by bullet because shape are shared between replicas) + */ + vector<class btCollisionShape*> m_shapes; /** * Various SCA managers used by the scene */ @@ -300,6 +306,7 @@ public: void NewRemoveObject(CValue* gameobj); void ReplaceMesh(CValue* gameobj, void* meshobj); + void AddShape(class btCollisionShape* shape); /** * @section Logic stuff * Initiate an update of the logic system. @@ -316,6 +323,10 @@ public: ); CListValue* + GetInactiveList( + ); + + CListValue* GetRootParentList( ); |