From f051fb65ff99707f9443fe1feb52b10a752d70ad Mon Sep 17 00:00:00 2001 From: cc9cii Date: Thu, 6 Nov 2014 08:35:24 +1100 Subject: [PATCH] Fix memory leak when multiple documents in 3D edit. Support multiple physics engine per document. --- apps/opencs/view/world/physicsmanager.cpp | 9 +-- apps/opencs/view/world/physicssystem.cpp | 10 ++- apps/opencs/view/world/physicssystem.hpp | 12 +++- apps/openmw/mwworld/physicssystem.cpp | 2 + libs/openengine/bullet/BtOgreExtras.h | 6 +- libs/openengine/bullet/physic.cpp | 76 ++++++++++++++++++++++- libs/openengine/bullet/physic.hpp | 9 +++ 7 files changed, 106 insertions(+), 18 deletions(-) diff --git a/apps/opencs/view/world/physicsmanager.cpp b/apps/opencs/view/world/physicsmanager.cpp index ce5748e8d..fa8db9e1e 100644 --- a/apps/opencs/view/world/physicsmanager.cpp +++ b/apps/opencs/view/world/physicsmanager.cpp @@ -2,7 +2,6 @@ #include -#include #include #include "../render/worldspacewidget.hpp" @@ -58,15 +57,9 @@ namespace CSVWorld mSceneWidgets.erase(it); } - // cleanup global resources + // cleanup global resources used by OEngine if(mPhysics.empty()) { - // delete the extra resources created in removeDebugDraw - if (Ogre::MaterialManager::getSingleton().resourceExists("BtOgre/DebugLines")) - Ogre::MaterialManager::getSingleton().remove("BtOgre/DebugLines"); - if (Ogre::ResourceGroupManager::getSingleton().resourceGroupExists("BtOgre")) - Ogre::ResourceGroupManager::getSingleton().destroyResourceGroup("BtOgre"); - delete OEngine::Physic::BulletShapeManager::getSingletonPtr(); } } diff --git a/apps/opencs/view/world/physicssystem.cpp b/apps/opencs/view/world/physicssystem.cpp index 98e3a71e9..57909f4d3 100644 --- a/apps/opencs/view/world/physicssystem.cpp +++ b/apps/opencs/view/world/physicssystem.cpp @@ -6,7 +6,7 @@ #include #include -#include "physicsengine.hpp" +#include #include #include "../../model/settings/usersettings.hpp" #include "../render/elements.hpp" @@ -15,7 +15,9 @@ namespace CSVWorld { PhysicsSystem::PhysicsSystem() { - mEngine = new PhysicsEngine(); + // Create physics. shapeLoader is deleted by the physic engine + NifBullet::ManualBulletShapeLoader* shapeLoader = new NifBullet::ManualBulletShapeLoader(); + mEngine = new OEngine::Physic::PhysicEngine(shapeLoader); } PhysicsSystem::~PhysicsSystem() @@ -51,6 +53,8 @@ namespace CSVWorld { mEngine->createAndAdjustRigidBody(mesh, referenceId, scale, position, rotation, + 0, // scaledBoxTranslation + 0, // boxRotation true, // raycasting placeable); } @@ -139,7 +143,7 @@ namespace CSVWorld // create a new physics object mEngine->createAndAdjustRigidBody(mesh, referenceId, scale, position, rotation, - true, placeable); + 0, 0, true, placeable); // update other scene managers if they have the referenceId // FIXME: rotation or scale not updated diff --git a/apps/opencs/view/world/physicssystem.hpp b/apps/opencs/view/world/physicssystem.hpp index 731e527b1..0036bf769 100644 --- a/apps/opencs/view/world/physicssystem.hpp +++ b/apps/opencs/view/world/physicssystem.hpp @@ -12,6 +12,14 @@ namespace Ogre class Camera; } +namespace OEngine +{ + namespace Physic + { + class PhysicEngine; + } +} + namespace CSVRender { class SceneWidget; @@ -19,15 +27,13 @@ namespace CSVRender namespace CSVWorld { - class PhysicsEngine; - class PhysicsSystem { std::map mSceneNodeToRefId; std::map > mRefIdToSceneNode; std::map mSceneNodeToMesh; std::map mSceneWidgets; - PhysicsEngine* mEngine; + OEngine::Physic::PhysicEngine* mEngine; std::multimap mTerrain; public: diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index aba120baa..80cccd063 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include @@ -498,6 +499,7 @@ namespace MWWorld if (mWaterCollisionObject.get()) mEngine->mDynamicsWorld->removeCollisionObject(mWaterCollisionObject.get()); delete mEngine; + delete OEngine::Physic::BulletShapeManager::getSingletonPtr(); } OEngine::Physic::PhysicEngine* PhysicsSystem::getEngine() diff --git a/libs/openengine/bullet/BtOgreExtras.h b/libs/openengine/bullet/BtOgreExtras.h index 9572b8a7b..f8c1fe41d 100644 --- a/libs/openengine/bullet/BtOgreExtras.h +++ b/libs/openengine/bullet/BtOgreExtras.h @@ -212,8 +212,10 @@ public: ~DebugDrawer() { - Ogre::MaterialManager::getSingleton().remove("BtOgre/DebugLines"); - Ogre::ResourceGroupManager::getSingleton().destroyResourceGroup("BtOgre"); + if (Ogre::MaterialManager::getSingleton().resourceExists("BtOgre/DebugLines")) + Ogre::MaterialManager::getSingleton().remove("BtOgre/DebugLines"); + if (Ogre::ResourceGroupManager::getSingleton().resourceGroupExists("BtOgre")) + Ogre::ResourceGroupManager::getSingleton().destroyResourceGroup("BtOgre"); delete mLineDrawer; } diff --git a/libs/openengine/bullet/physic.cpp b/libs/openengine/bullet/physic.cpp index 0c61253bf..d7db81595 100644 --- a/libs/openengine/bullet/physic.cpp +++ b/libs/openengine/bullet/physic.cpp @@ -114,7 +114,7 @@ namespace Physic { mEngine->mDynamicsWorld->removeRigidBody(mBody); delete mBody; - } + } } void PhysicActor::enableCollisionMode(bool collision) @@ -356,7 +356,8 @@ namespace Physic delete broadphase; delete mShapeLoader; - delete BulletShapeManager::getSingletonPtr(); + // Moved the cleanup to mwworld/physicssystem + //delete BulletShapeManager::getSingletonPtr(); } void PhysicEngine::addHeightField(float* heights, @@ -863,5 +864,76 @@ namespace Physic } } + int PhysicEngine::toggleDebugRendering(Ogre::SceneManager *sceneMgr) + { + if(!sceneMgr) + return 0; + + std::map::iterator iter = + mDebugDrawers.find(sceneMgr); + if(iter != mDebugDrawers.end()) // found scene manager + { + if((*iter).second) + { + // set a new drawer each time (maybe with a different scene manager) + mDynamicsWorld->setDebugDrawer(mDebugDrawers[sceneMgr]); + if(!mDebugDrawers[sceneMgr]->getDebugMode()) + mDebugDrawers[sceneMgr]->setDebugMode(1 /*mDebugDrawFlags*/); + else + mDebugDrawers[sceneMgr]->setDebugMode(0); + mDynamicsWorld->debugDrawWorld(); + + return mDebugDrawers[sceneMgr]->getDebugMode(); + } + } + return 0; + } + + void PhysicEngine::stepDebug(Ogre::SceneManager *sceneMgr) + { + if(!sceneMgr) + return; + + std::map::iterator iter = + mDebugDrawers.find(sceneMgr); + if(iter != mDebugDrawers.end()) // found scene manager + { + if((*iter).second) + (*iter).second->step(); + else + return; + } + } + + void PhysicEngine::createDebugDraw(Ogre::SceneManager *sceneMgr) + { + if(mDebugDrawers.find(sceneMgr) == mDebugDrawers.end()) + { + mDebugSceneNodes[sceneMgr] = sceneMgr->getRootSceneNode()->createChildSceneNode(); + mDebugDrawers[sceneMgr] = new BtOgre::DebugDrawer(mDebugSceneNodes[sceneMgr], mDynamicsWorld); + mDebugDrawers[sceneMgr]->setDebugMode(0); + } + } + + void PhysicEngine::removeDebugDraw(Ogre::SceneManager *sceneMgr) + { + std::map::iterator iter = + mDebugDrawers.find(sceneMgr); + if(iter != mDebugDrawers.end()) + { + delete (*iter).second; + mDebugDrawers.erase(iter); + } + + std::map::iterator it = + mDebugSceneNodes.find(sceneMgr); + if(it != mDebugSceneNodes.end()) + { + std::string sceneNodeName = (*it).second->getName(); + if(sceneMgr->hasSceneNode(sceneNodeName)) + sceneMgr->destroySceneNode(sceneNodeName); + } + } + } } diff --git a/libs/openengine/bullet/physic.hpp b/libs/openengine/bullet/physic.hpp index a77b60ab6..fb6ae0ceb 100644 --- a/libs/openengine/bullet/physic.hpp +++ b/libs/openengine/bullet/physic.hpp @@ -348,6 +348,15 @@ namespace Physic bool isDebugCreated; bool mDebugActive; + // for OpenCS with multiple engines per document + std::map mDebugDrawers; + std::map mDebugSceneNodes; + + int toggleDebugRendering(Ogre::SceneManager *sceneMgr); + void stepDebug(Ogre::SceneManager *sceneMgr); + void createDebugDraw(Ogre::SceneManager *sceneMgr); + void removeDebugDraw(Ogre::SceneManager *sceneMgr); + private: PhysicEngine(const PhysicEngine&); PhysicEngine& operator=(const PhysicEngine&);