diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp index 804241ac9b9..7fbec8679fb 100644 --- a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp +++ b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp @@ -123,29 +123,29 @@ KX_BlenderSceneConverter::~KX_BlenderSceneConverter() delete (ipoList); } - vector::iterator itw = m_worldinfos.begin(); + vector >::iterator itw = m_worldinfos.begin(); while (itw != m_worldinfos.end()) { - delete (*itw); + delete (*itw).second; itw++; } - vector::iterator itp = m_polymaterials.begin(); + vector >::iterator itp = m_polymaterials.begin(); while (itp != m_polymaterials.end()) { - delete (*itp); + delete (*itp).second; itp++; } // delete after RAS_IPolyMaterial - vector::iterator itmat = m_materials.begin(); + vector >::iterator itmat = m_materials.begin(); while (itmat != m_materials.end()) { - delete (*itmat); + delete (*itmat).second; itmat++; } - vector::iterator itm = m_meshobjects.begin(); + vector >::iterator itm = m_meshobjects.begin(); while (itm != m_meshobjects.end()) { - delete (*itm); + delete (*itm).second; itm++; } @@ -263,6 +263,9 @@ void KX_BlenderSceneConverter::ConvertScene(const STR_String& scenename, 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,16 +363,90 @@ void KX_BlenderSceneConverter::ConvertScene(const STR_String& scenename, 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(); - m_map_mesh_to_gamemesh.clear(); - //don't clear it yet, it is needed for the baking physics into ipo animation + //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 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 >::iterator worldit; + size = m_worldinfos.size(); + for (i=0, worldit=m_worldinfos.begin(); i >::iterator polymit; + size = m_polymaterials.size(); + for (i=0, polymit=m_polymaterials.begin(); i >::iterator matit; + size = m_materials.size(); + for (i=0, matit=m_materials.begin(); i >::iterator meshit; + size = m_meshobjects.size(); + for (i=0, meshit=m_meshobjects.begin(); i(m_currentScene,mat)); } @@ -406,6 +483,11 @@ void KX_BlenderSceneConverter::RegisterGameObject( 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 @@ void KX_BlenderSceneConverter::RegisterGameMesh( struct Mesh *for_blendermesh) { m_map_mesh_to_gamemesh.insert(CHashedPtr(for_blendermesh),gamemesh); - m_meshobjects.push_back(gamemesh); + m_meshobjects.push_back(pair(m_currentScene,gamemesh)); } @@ -458,7 +540,7 @@ RAS_MeshObject *KX_BlenderSceneConverter::FindGameMesh( void KX_BlenderSceneConverter::RegisterPolyMaterial(RAS_IPolyMaterial *polymat) { - m_polymaterials.push_back(polymat); + m_polymaterials.push_back(pair(m_currentScene,polymat)); } @@ -523,7 +605,7 @@ SCA_IController *KX_BlenderSceneConverter::FindGameController( void KX_BlenderSceneConverter::RegisterWorldInfo( KX_WorldInfo *worldinfo) { - m_worldinfos.push_back(worldinfo); + m_worldinfos.push_back(pair(m_currentScene,worldinfo)); } /* diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.h b/source/gameengine/Converter/KX_BlenderSceneConverter.h index a897922d51b..8ac5386d442 100644 --- a/source/gameengine/Converter/KX_BlenderSceneConverter.h +++ b/source/gameengine/Converter/KX_BlenderSceneConverter.h @@ -51,10 +51,13 @@ struct SpaceIpo; class KX_BlenderSceneConverter : public KX_ISceneConverter { - vector m_worldinfos; - vector m_polymaterials; - vector m_meshobjects; - vector m_materials; + // Use vector of pairs to allow removal of entities between scene switch + vector > m_worldinfos; + vector > m_polymaterials; + vector > m_meshobjects; + vector > m_materials; + // Should also have a list of collision shapes. + // For the time being this is held in KX_Scene::m_shapes GEN_Map m_map_gameobject_to_blender; GEN_Map m_map_blender_to_gameobject; @@ -72,6 +75,7 @@ class KX_BlenderSceneConverter : public KX_ISceneConverter 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 @@ public: 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 @@ public: 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); diff --git a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp index 7b2c514db8a..465a021cd43 100644 --- a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp +++ b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp @@ -682,8 +682,6 @@ void KX_ConvertODEEngineObject(KX_GameObject* gameobj, #endif //WIN32 -static GEN_Map map_gamemesh_to_bulletshape; - // forward declarations static btCollisionShape* CreateBulletShapeFromMesh(RAS_MeshObject* meshobj, bool polytope) { @@ -701,14 +699,6 @@ static btCollisionShape* CreateBulletShapeFromMesh(RAS_MeshObject* meshobj, bool 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 @@ static btCollisionShape* CreateBulletShapeFromMesh(RAS_MeshObject* meshobj, bool if (numvalidpolys > 0) { - //map_gamemesh_to_bulletshape.insert(GEN_HashedPtr(meshobj),collisionMeshShape); if (!polytope) { bool useQuantization = true; @@ -1200,17 +1189,6 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj, void KX_ClearBulletSharedShapes() { - int numshapes = map_gamemesh_to_bulletshape.size(); - int i; - btCollisionShape*shape=0; - for (i=0;iRemoveScene(scene); } m_scenes.clear(); @@ -1217,7 +1217,7 @@ void KX_KetsjiEngine::RemoveScheduledScenes() KX_Scene* scene = *sceneit; if (scene->GetName()==scenename) { - delete scene; + m_sceneconverter->RemoveScene(scene); m_scenes.erase(sceneit); break; } @@ -1315,7 +1315,7 @@ void KX_KetsjiEngine::ReplaceScheduledScenes() KX_Scene* scene = *sceneit; if (scene->GetName() == oldscenename) { - delete scene; + m_sceneconverter->RemoveScene(scene); KX_Scene* tmpscene = CreateScene(newscenename); m_scenes[i]=tmpscene; PostProcessScene(tmpscene); diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index f9fc503f406..633b57ef209 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -75,6 +75,7 @@ #include "NG_NetworkScene.h" #include "PHY_IPhysicsEnvironment.h" #include "KX_IPhysicsController.h" +#include "KX_BlenderSceneConverter.h" #include "BL_SkinDeformer.h" #include "BL_DeformableGameObject.h" @@ -120,7 +121,8 @@ KX_Scene::KX_Scene(class SCA_IInputDevice* keyboarddevice, m_adi(adi), m_networkDeviceInterface(ndi), m_active_camera(NULL), - m_ueberExecutionPriority(0) + m_ueberExecutionPriority(0), + m_sceneConverter(NULL) { m_suspendedtime = 0.0; m_suspendeddelta = 0.0; @@ -783,6 +785,8 @@ void KX_Scene::NewRemoveObject(class CValue* gameobj) //m_active_camera->Release(); m_active_camera = NULL; } + if (m_sceneConverter) + m_sceneConverter->UnregisterGameObject(newobj); } @@ -1277,6 +1281,11 @@ void KX_Scene::SetNodeTree(SG_Tree* root) m_objecttree = root; } +void KX_Scene::SetSceneConverter(class KX_BlenderSceneConverter* sceneConverter) +{ + m_sceneConverter = sceneConverter; +} + void KX_Scene::SetPhysicsEnvironment(class PHY_IPhysicsEnvironment* physEnv) { m_physicsEnvironment = physEnv; diff --git a/source/gameengine/Ketsji/KX_Scene.h b/source/gameengine/Ketsji/KX_Scene.h index b857f4f591e..4c3b1d2e558 100644 --- a/source/gameengine/Ketsji/KX_Scene.h +++ b/source/gameengine/Ketsji/KX_Scene.h @@ -86,6 +86,7 @@ class RAS_IRasterizer; class RAS_IRenderTools; class SCA_JoystickManager; class btCollisionShape; +class KX_BlenderSceneConverter; /** * The KX_Scene holds all data for an independent scene. It relates * KX_Objects to the specific objects in the modules. @@ -136,10 +137,12 @@ protected: SCA_MouseManager* m_mousemgr; SCA_TimeEventManager* m_timemgr; + // Scene converter where many scene entities are registered + // Used to deregister objects that are deleted + class KX_BlenderSceneConverter* m_sceneConverter; /** * physics engine abstraction */ - //e_PhysicsEngine m_physicsEngine; //who needs this ? class PHY_IPhysicsEnvironment* m_physicsEnvironment; @@ -517,6 +520,8 @@ public: bool IsClearingZBuffer(); void EnableZBufferClearing(bool isclearingZbuffer); + void SetSceneConverter(class KX_BlenderSceneConverter* sceneConverter); + class PHY_IPhysicsEnvironment* GetPhysicsEnvironment() { return m_physicsEnvironment;