From c6a2461fbd905713e566239e4ab55704c61bed2d Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sat, 1 Nov 2014 20:51:04 +1100 Subject: [PATCH] Delay removing physics until the document is closed. Also other general cleanup. --- apps/opencs/view/doc/viewmanager.cpp | 2 ++ apps/opencs/view/render/worldspacewidget.cpp | 3 +- apps/opencs/view/world/physicsmanager.cpp | 27 ++++++++++---- apps/opencs/view/world/physicsmanager.hpp | 8 ++--- apps/opencs/view/world/physicssystem.cpp | 38 +++++++++++--------- apps/opencs/view/world/physicssystem.hpp | 13 +++---- 6 files changed, 54 insertions(+), 37 deletions(-) diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index 5f6b6b46a..c4fd66884 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -16,6 +16,7 @@ #include "../world/vartypedelegate.hpp" #include "../world/recordstatusdelegate.hpp" #include "../world/idtypedelegate.hpp" +#include "../world/physicsmanager.hpp" #include "../../model/settings/usersettings.hpp" @@ -218,6 +219,7 @@ void CSVDoc::ViewManager::removeDocAndView (CSMDoc::Document *document) mDocumentManager.removeDocument(document); (*iter)->deleteLater(); mViews.erase (iter); + CSVWorld::PhysicsManager::instance()->removeDocument(document); updateIndices(); return; diff --git a/apps/opencs/view/render/worldspacewidget.cpp b/apps/opencs/view/render/worldspacewidget.cpp index 448153d37..fd6a23e2b 100644 --- a/apps/opencs/view/render/worldspacewidget.cpp +++ b/apps/opencs/view/render/worldspacewidget.cpp @@ -927,8 +927,7 @@ void CSVRender::WorldspaceWidget::placeObject(const std::string sceneNode, const // FIXME: adjustRigidBody() seems to lose objects, work around by deleting and recreating objects //mPhysics->moveObject(sceneNode, pos, xr*yr*zr); - std::string mesh = mPhysics->sceneNodeToMesh(sceneNode); - mPhysics->replaceObject(mesh, sceneNode, refId, cellref.mScale, pos, xr*yr*zr); + mPhysics->replaceObject(sceneNode, refId, cellref.mScale, pos, xr*yr*zr); // update all SceneWidgets and their SceneManagers updateSceneWidgets(); diff --git a/apps/opencs/view/world/physicsmanager.cpp b/apps/opencs/view/world/physicsmanager.cpp index ce71ac315..e6ee51da7 100644 --- a/apps/opencs/view/world/physicsmanager.cpp +++ b/apps/opencs/view/world/physicsmanager.cpp @@ -34,11 +34,28 @@ namespace CSVWorld std::map >::iterator iter = mSceneWidgets.find(doc); if(iter == mSceneWidgets.end()) { - mSceneWidgets[doc] = std::list {}; // zero elements + mSceneWidgets[doc] = std::list (); // zero elements mPhysics[doc] = new PhysicsSystem(); } } + // destroy physics, called from CSVDoc::ViewManager + void PhysicsManager::removeDocument(CSMDoc::Document *doc) + { + std::map::iterator iter = mPhysics.find(doc); + if(iter != mPhysics.end()) + { + delete iter->second; + mPhysics.erase(iter); + } + + std::map >::iterator it = mSceneWidgets.find(doc); + if(it != mSceneWidgets.end()) + { + mSceneWidgets.erase(it); + } + } + // called from CSVRender::WorldspaceWidget() to get widgets' association with Document& PhysicsSystem *PhysicsManager::addSceneWidget(CSMDoc::Document &doc, CSVRender::WorldspaceWidget *widget) { @@ -72,12 +89,8 @@ namespace CSVWorld { (*iter).second.erase(itWidget); - if((*iter).second.empty()) // last one for the document - { - delete mPhysics[(*iter).first]; - mPhysics.erase((*iter).first); - mSceneWidgets.erase(iter); - } + //if((*iter).second.empty()) // last one for the document + // NOTE: do not delete physics until the document itself is closed break; } diff --git a/apps/opencs/view/world/physicsmanager.hpp b/apps/opencs/view/world/physicsmanager.hpp index 7bcd5d39d..e17c9ac84 100644 --- a/apps/opencs/view/world/physicsmanager.hpp +++ b/apps/opencs/view/world/physicsmanager.hpp @@ -31,7 +31,6 @@ namespace CSVWorld { static PhysicsManager *mPhysicsManagerInstance; - //std::map mSceneManagers; std::map > mSceneWidgets; std::map mPhysics; @@ -43,15 +42,12 @@ namespace CSVWorld static PhysicsManager *instance(); void setupPhysics(CSMDoc::Document *); -#if 0 - void addSceneManager(CSVRender::SceneWidget *sceneWidget, Ogre::SceneManager *sceneMgr); - - void removeSceneManager(CSVRender::SceneWidget *sceneWidget); -#endif PhysicsSystem *addSceneWidget(CSMDoc::Document &doc, CSVRender::WorldspaceWidget *widget); void removeSceneWidget(CSVRender::WorldspaceWidget *widget); + + void removeDocument(CSMDoc::Document *doc); }; } diff --git a/apps/opencs/view/world/physicssystem.cpp b/apps/opencs/view/world/physicssystem.cpp index 320367906..5776c32e9 100644 --- a/apps/opencs/view/world/physicssystem.cpp +++ b/apps/opencs/view/world/physicssystem.cpp @@ -25,10 +25,10 @@ namespace CSVWorld delete mEngine; } - // FIXME: looks up the scene manager based on the scene node name (highly inefficient) + // looks up the scene manager based on the scene node name (inefficient) // NOTE: referenceId is assumed to be unique per document - // NOTE: searching is done here rather than after rayTest, so slower to load but - // faster to find (not verified w/ perf test) + // NOTE: searching is done here rather than after rayTest, hence slower to load but + // faster to find (guessing, not verified w/ perf test) void PhysicsSystem::addObject(const std::string &mesh, const std::string &sceneNodeName, const std::string &referenceId, float scale, const Ogre::Vector3 &position, const Ogre::Quaternion &rotation, bool placeable) @@ -48,7 +48,12 @@ namespace CSVWorld } if(!foundSceneManager) - return; // FIXME: should this be an exception + { + std::cerr << "Attempt to add an object without a corresponding SceneManager: " + + referenceId + " : " + sceneNodeName << std::endl; + + return; + } // update physics, only one physics model per referenceId if(mEngine->getRigidBody(referenceId, true) == NULL) @@ -61,7 +66,7 @@ namespace CSVWorld placeable); // update other scene managers if they have the referenceId (may have moved) - // FIXME: this bit not needed if object has not moved + // NOTE: this part is not needed if object has not moved iter = mSceneManagers.begin(); for(; iter != mSceneManagers.end(); ++iter) { @@ -99,7 +104,12 @@ namespace CSVWorld } if(!sceneManager) - return; // FIXME: maybe this should be an exception + { + std::cerr << "Attempt to remove an object without a corresponding SceneManager: " + + sceneNodeName << std::endl; + + return; + } // illustration: erase the object "K" from the object map // @@ -123,7 +133,7 @@ namespace CSVWorld } } - // should the physics model be deleted? + // check whether the physics model be deleted if(force || mRefIdToSceneNode.find(referenceId) == mRefIdToSceneNode.end()) { mEngine->removeRigidBody(referenceId); @@ -132,10 +142,11 @@ namespace CSVWorld } } - void PhysicsSystem::replaceObject(const std::string &mesh, - const std::string &sceneNodeName, const std::string &referenceId, float scale, - const Ogre::Vector3 &position, const Ogre::Quaternion &rotation, bool placeable) + void PhysicsSystem::replaceObject(const std::string &sceneNodeName, + const std::string &referenceId, float scale, const Ogre::Vector3 &position, + const Ogre::Quaternion &rotation, bool placeable) { + std::string mesh = mSceneNodeToMesh[sceneNodeName]; removeObject(sceneNodeName, true); // force delete addObject(mesh, sceneNodeName, referenceId, scale, position, rotation, placeable); } @@ -259,11 +270,6 @@ namespace CSVWorld return mSceneNodeToRefId[sceneNodeName]; } - std::string PhysicsSystem::sceneNodeToMesh(std::string sceneNodeName) - { - return mSceneNodeToMesh[sceneNodeName]; - } - void PhysicsSystem::addSceneManager(Ogre::SceneManager *sceneMgr, CSVRender::SceneWidget * sceneWidget) { mSceneManagers.push_back(sceneMgr); @@ -293,7 +299,7 @@ namespace CSVWorld { // FIXME: should check if sceneMgr is in the list if(!sceneMgr) - return; // FIXME: maybe this should be an exception + return; mEngine->setSceneManager(sceneMgr); diff --git a/apps/opencs/view/world/physicssystem.hpp b/apps/opencs/view/world/physicssystem.hpp index 8fadf6c8a..1c2acc6b9 100644 --- a/apps/opencs/view/world/physicssystem.hpp +++ b/apps/opencs/view/world/physicssystem.hpp @@ -42,7 +42,9 @@ namespace CSVWorld PhysicsSystem(); ~PhysicsSystem(); + void addSceneManager(Ogre::SceneManager *sceneMgr, CSVRender::SceneWidget * scene); + void removeSceneManager(Ogre::SceneManager *sceneMgr); void addObject(const std::string &mesh, @@ -52,10 +54,9 @@ namespace CSVWorld void removeObject(const std::string &sceneNodeName, bool force = false); - void replaceObject(const std::string &mesh, - const std::string &sceneNodeName, const std::string &referenceId, float scale, - const Ogre::Vector3 &position, const Ogre::Quaternion &rotation, - bool placeable=false); + void replaceObject(const std::string &sceneNodeName, + const std::string &referenceId, float scale, const Ogre::Vector3 &position, + const Ogre::Quaternion &rotation, bool placeable=false); void moveObject(const std::string &sceneNodeName, const Ogre::Vector3 &position, const Ogre::Quaternion &rotation); @@ -75,8 +76,7 @@ namespace CSVWorld std::string sceneNodeToRefId(std::string sceneNodeName); - std::string sceneNodeToMesh(std::string sceneNodeName); - + // for multi-scene manager per physics engine std::map sceneWidgets(); private: @@ -85,6 +85,7 @@ namespace CSVWorld const std::string referenceId, const Ogre::Vector3 &position); void updateSelectionHighlight(std::string sceneNode, const Ogre::Vector3 &position); + std::string refIdToSceneNode(std::string referenceId, Ogre::SceneManager *sceneMgr); }; }