[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [14033] trunk/blender/source/gameengine: BGE memleak fixed: mesh/material not deleted when switching scene

Benoit Bolsee benoit.bolsee at online.be
Sun Mar 9 22:42:05 CET 2008


Revision: 14033
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=14033
Author:   ben2610
Date:     2008-03-09 22:42:03 +0100 (Sun, 09 Mar 2008)

Log Message:
-----------
BGE memleak fixed: mesh/material not deleted when switching scene

Modified Paths:
--------------
    trunk/blender/source/gameengine/Converter/KX_BlenderSceneConverter.cpp
    trunk/blender/source/gameengine/Converter/KX_BlenderSceneConverter.h
    trunk/blender/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp
    trunk/blender/source/gameengine/Ketsji/KX_ISceneConverter.h
    trunk/blender/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
    trunk/blender/source/gameengine/Ketsji/KX_Scene.cpp
    trunk/blender/source/gameengine/Ketsji/KX_Scene.h

Modified: trunk/blender/source/gameengine/Converter/KX_BlenderSceneConverter.cpp
===================================================================
--- trunk/blender/source/gameengine/Converter/KX_BlenderSceneConverter.cpp	2008-03-09 21:37:01 UTC (rev 14032)
+++ trunk/blender/source/gameengine/Converter/KX_BlenderSceneConverter.cpp	2008-03-09 21:42:03 UTC (rev 14033)
@@ -123,29 +123,29 @@
 		delete (ipoList);
 	}
 
-	vector<KX_WorldInfo*>::iterator itw = m_worldinfos.begin();
+	vector<pair<KX_Scene*,KX_WorldInfo*> >::iterator itw = m_worldinfos.begin();
 	while (itw != m_worldinfos.end()) {
-		delete (*itw);
+		delete (*itw).second;
 		itw++;
 	}
 
-	vector<RAS_IPolyMaterial*>::iterator itp = m_polymaterials.begin();
+	vector<pair<KX_Scene*,RAS_IPolyMaterial*> >::iterator itp = m_polymaterials.begin();
 	while (itp != m_polymaterials.end()) {
-		delete (*itp);
+		delete (*itp).second;
 		itp++;
 	}
 
 	// delete after RAS_IPolyMaterial
-	vector<BL_Material *>::iterator itmat = m_materials.begin();
+	vector<pair<KX_Scene*,BL_Material *> >::iterator itmat = m_materials.begin();
 	while (itmat != m_materials.end()) {
-		delete (*itmat);
+		delete (*itmat).second;
 		itmat++;
 	}	
 
 
-	vector<RAS_MeshObject*>::iterator itm = m_meshobjects.begin();
+	vector<pair<KX_Scene*,RAS_MeshObject*> >::iterator itm = m_meshobjects.begin();
 	while (itm != m_meshobjects.end()) {
-		delete (*itm);
+		delete (*itm).second;
 		itm++;
 	}
 	
@@ -263,6 +263,9 @@
 	Scene *blenderscene = GetSceneForName2(m_maggie, scenename);
 
 	e_PhysicsEngine physics_engine = UseBullet;
+	// hook for registration function during conversion.
+	m_currentScene = destinationscene;
+	destinationscene->SetSceneConverter(this);
 
 	if (blenderscene)
 	{
@@ -360,17 +363,91 @@
 		m_alwaysUseExpandFraming
 		);
 
+	//These lookup are not needed during game
 	m_map_blender_to_gameactuator.clear();
 	m_map_blender_to_gamecontroller.clear();
-	
 	m_map_blender_to_gameobject.clear();
+
+	//Clearing this lookup table has the effect of disabling the cache of meshes
+	//between scenes, even if they are shared in the blend file.
+	//This cache mecanism is buggy so I leave it disable and the memory leak
+	//that would result from this is fixed in RemoveScene()
 	m_map_mesh_to_gamemesh.clear();
-
-	//don't clear it yet, it is needed for the baking physics into ipo animation
+	//Don't clear this lookup, it is needed for the baking physics into ipo animation
+	//To avoid it's infinite grows, object will be unregister when they are deleted 
+	//see KX_Scene::NewRemoveObject
 	//m_map_gameobject_to_blender.clear();
 }
 
+// This function removes all entities stored in the converter for that scene
+// It should be used instead of direct delete scene
+// Note that there was some provision for sharing entities (meshes...) between
+// scenes but that is now disabled so all scene will have their own copy
+// and we can delete them here. If the sharing is reactivated, change this code too..
+// (see KX_BlenderSceneConverter::ConvertScene)
+void KX_BlenderSceneConverter::RemoveScene(KX_Scene *scene)
+{
+	int i, size;
+	// delete the scene first as it will stop the use of entities
+	delete scene;
+	// delete the entities of this scene
+	vector<pair<KX_Scene*,KX_WorldInfo*> >::iterator worldit;
+	size = m_worldinfos.size();
+	for (i=0, worldit=m_worldinfos.begin(); i<size; ) {
+		if ((*worldit).first == scene) {
+			delete (*worldit).second;
+			*worldit = m_worldinfos.back();
+			m_worldinfos.pop_back();
+			size--;
+		} else {
+			i++;
+			worldit++;
+		}
+	}
 
+	vector<pair<KX_Scene*,RAS_IPolyMaterial*> >::iterator polymit;
+	size = m_polymaterials.size();
+	for (i=0, polymit=m_polymaterials.begin(); i<size; ) {
+		if ((*polymit).first == scene) {
+			delete (*polymit).second;
+			*polymit = m_polymaterials.back();
+			m_polymaterials.pop_back();
+			size--;
+		} else {
+			i++;
+			polymit++;
+		}
+	}
+
+	vector<pair<KX_Scene*,BL_Material*> >::iterator matit;
+	size = m_materials.size();
+	for (i=0, matit=m_materials.begin(); i<size; ) {
+		if ((*matit).first == scene) {
+			delete (*matit).second;
+			*matit = m_materials.back();
+			m_materials.pop_back();
+			size--;
+		} else {
+			i++;
+			matit++;
+		}
+	}
+
+	vector<pair<KX_Scene*,RAS_MeshObject*> >::iterator meshit;
+	size = m_meshobjects.size();
+	for (i=0, meshit=m_meshobjects.begin(); i<size; ) {
+		if ((*meshit).first == scene) {
+			delete (*meshit).second;
+			*meshit = m_meshobjects.back();
+			m_meshobjects.pop_back();
+			size--;
+		} else {
+			i++;
+			meshit++;
+		}
+	}
+}
+
 // use blender materials
 void KX_BlenderSceneConverter::SetMaterials(bool val)
 {
@@ -385,7 +462,7 @@
 
 void KX_BlenderSceneConverter::RegisterBlenderMaterial(BL_Material *mat)
 {
-	m_materials.push_back(mat);
+	m_materials.push_back(pair<KX_Scene*,BL_Material *>(m_currentScene,mat));
 }
 
 
@@ -406,6 +483,11 @@
 	m_map_blender_to_gameobject.insert(CHashedPtr(for_blenderobject),gameobject);
 }
 
+void KX_BlenderSceneConverter::UnregisterGameObject(
+									KX_GameObject *gameobject) 
+{
+	m_map_gameobject_to_blender.remove(CHashedPtr(gameobject));
+}
 
 
 KX_GameObject *KX_BlenderSceneConverter::FindGameObject(
@@ -433,7 +515,7 @@
 									struct Mesh *for_blendermesh)
 {
 	m_map_mesh_to_gamemesh.insert(CHashedPtr(for_blendermesh),gamemesh);
-	m_meshobjects.push_back(gamemesh);
+	m_meshobjects.push_back(pair<KX_Scene*,RAS_MeshObject*>(m_currentScene,gamemesh));
 }
 
 
@@ -458,7 +540,7 @@
 
 void KX_BlenderSceneConverter::RegisterPolyMaterial(RAS_IPolyMaterial *polymat)
 {
-	m_polymaterials.push_back(polymat);
+	m_polymaterials.push_back(pair<KX_Scene*,RAS_IPolyMaterial*>(m_currentScene,polymat));
 }
 
 
@@ -523,7 +605,7 @@
 void KX_BlenderSceneConverter::RegisterWorldInfo(
 									KX_WorldInfo *worldinfo)
 {
-	m_worldinfos.push_back(worldinfo);
+	m_worldinfos.push_back(pair<KX_Scene*,KX_WorldInfo*>(m_currentScene,worldinfo));
 }
 
 /*

Modified: trunk/blender/source/gameengine/Converter/KX_BlenderSceneConverter.h
===================================================================
--- trunk/blender/source/gameengine/Converter/KX_BlenderSceneConverter.h	2008-03-09 21:37:01 UTC (rev 14032)
+++ trunk/blender/source/gameengine/Converter/KX_BlenderSceneConverter.h	2008-03-09 21:42:03 UTC (rev 14033)
@@ -51,10 +51,13 @@
 
 class KX_BlenderSceneConverter : public KX_ISceneConverter
 {
-	vector<KX_WorldInfo*>	m_worldinfos;
-	vector<RAS_IPolyMaterial*> m_polymaterials;
-	vector<RAS_MeshObject*> m_meshobjects;
-	vector<BL_Material *>	m_materials;
+	// Use vector of pairs to allow removal of entities between scene switch
+	vector<pair<KX_Scene*,KX_WorldInfo*> >	m_worldinfos;
+	vector<pair<KX_Scene*,RAS_IPolyMaterial*> > m_polymaterials;
+	vector<pair<KX_Scene*,RAS_MeshObject*> > m_meshobjects;
+	vector<pair<KX_Scene*,BL_Material *> >	m_materials;
+	// Should also have a list of collision shapes. 
+	// For the time being this is held in KX_Scene::m_shapes
 
 	GEN_Map<CHashedPtr,struct Object*> m_map_gameobject_to_blender;
 	GEN_Map<CHashedPtr,KX_GameObject*> m_map_blender_to_gameobject;
@@ -72,6 +75,7 @@
 
 	STR_String				m_newfilename;
 	class KX_KetsjiEngine*	m_ketsjiEngine;
+	class KX_Scene*			m_currentScene;	// Scene being converted
 	bool					m_alwaysUseExpandFraming;
 	bool					m_usemat;
 
@@ -99,6 +103,7 @@
 						class RAS_IRenderTools* rendertools,
 						class RAS_ICanvas* canvas
 					);
+	virtual void RemoveScene(class KX_Scene *scene);
 
 	void SetNewFileName(const STR_String& filename);
 	bool TryAndLoadNewFile();
@@ -106,6 +111,7 @@
 	void SetAlwaysUseExpandFraming(bool to_what);
 	
 	void RegisterGameObject(KX_GameObject *gameobject, struct Object *for_blenderobject);
+	void UnregisterGameObject(KX_GameObject *gameobject);
 	KX_GameObject *FindGameObject(struct Object *for_blenderobject);
 	struct Object *FindBlenderObject(KX_GameObject *for_gameobject);
 

Modified: trunk/blender/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp
===================================================================
--- trunk/blender/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp	2008-03-09 21:37:01 UTC (rev 14032)
+++ trunk/blender/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp	2008-03-09 21:42:03 UTC (rev 14033)
@@ -682,8 +682,6 @@
 #endif //WIN32
 
 
-static GEN_Map<GEN_HashedPtr,btCollisionShape*>	map_gamemesh_to_bulletshape;
-
 // forward declarations
 static btCollisionShape* CreateBulletShapeFromMesh(RAS_MeshObject* meshobj, bool polytope)
 {
@@ -701,14 +699,6 @@
 	int numPoints = 0;
 	btVector3* points = 0;
 
-	btCollisionShape** shapeptr = map_gamemesh_to_bulletshape[GEN_HashedPtr(meshobj)];
-
-	// Mesh has already been converted: reuse
-	if (shapeptr)
-	{
-		//return *shapeptr;
-	}
-
 	// Mesh has no polygons!
 	int numpolys = meshobj->NumPolygons();
 	if (!numpolys)
@@ -850,7 +840,6 @@
 	if (numvalidpolys > 0)
 	{
 		
-		//map_gamemesh_to_bulletshape.insert(GEN_HashedPtr(meshobj),collisionMeshShape);
 		if (!polytope)
 		{
 			bool useQuantization = true;
@@ -1200,17 +1189,6 @@
 
 void	KX_ClearBulletSharedShapes()
 {
-	int numshapes = map_gamemesh_to_bulletshape.size();
-	int i;
-	btCollisionShape*shape=0;
-	for (i=0;i<numshapes ;i++)
-	{
-		shape = *map_gamemesh_to_bulletshape.at(i);
-		//delete shape;
-	}
-	
-	map_gamemesh_to_bulletshape.clear();
-	
 }
 
 #endif

Modified: trunk/blender/source/gameengine/Ketsji/KX_ISceneConverter.h
===================================================================
--- trunk/blender/source/gameengine/Ketsji/KX_ISceneConverter.h	2008-03-09 21:37:01 UTC (rev 14032)
+++ trunk/blender/source/gameengine/Ketsji/KX_ISceneConverter.h	2008-03-09 21:42:03 UTC (rev 14033)
@@ -55,6 +55,8 @@
 		class RAS_IRenderTools* rendertools, 
 		class RAS_ICanvas*  canvas)=0;
 	
+	virtual void RemoveScene(class KX_Scene *scene)=0;
+
 	virtual void	SetAlwaysUseExpandFraming(bool to_what) = 0;
 
 	virtual void	SetNewFileName(const STR_String& filename) = 0;

Modified: trunk/blender/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
===================================================================
--- trunk/blender/source/gameengine/Ketsji/KX_KetsjiEngine.cpp	2008-03-09 21:37:01 UTC (rev 14032)
+++ trunk/blender/source/gameengine/Ketsji/KX_KetsjiEngine.cpp	2008-03-09 21:42:03 UTC (rev 14033)
@@ -993,7 +993,7 @@
 		for (sceneit = m_scenes.begin();sceneit != m_scenes.end() ; sceneit++)
 		{
 			KX_Scene* scene = *sceneit;
-			delete scene;
+			m_sceneconverter->RemoveScene(scene);
 		}	
 		m_scenes.clear();
 
@@ -1217,7 +1217,7 @@
 				KX_Scene* scene = *sceneit;

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list