diff --git a/apps/opencs/view/render/scenewidget.cpp b/apps/opencs/view/render/scenewidget.cpp index 1a11ddad35..aa00de0226 100644 --- a/apps/opencs/view/render/scenewidget.cpp +++ b/apps/opencs/view/render/scenewidget.cpp @@ -66,7 +66,7 @@ namespace CSVRender mOverlaySystem = OverlaySystem::instance().get(); mSceneMgr->addRenderQueueListener(mOverlaySystem); - CSVWorld::PhysicsSystem::instance()->addSceneManager(mSceneMgr, this); + CSVWorld::PhysicsSystem::instance()->addSceneManager(mSceneMgr); QTimer *timer = new QTimer (this); @@ -166,6 +166,8 @@ namespace CSVRender SceneWidget::~SceneWidget() { + CSVWorld::PhysicsSystem::instance()->removeSceneManager(mSceneMgr); + if (mWindow) Ogre::Root::getSingleton().destroyRenderTarget (mWindow); diff --git a/apps/opencs/view/render/worldspacewidget.cpp b/apps/opencs/view/render/worldspacewidget.cpp index a53681404c..4d64c77751 100644 --- a/apps/opencs/view/render/worldspacewidget.cpp +++ b/apps/opencs/view/render/worldspacewidget.cpp @@ -916,8 +916,7 @@ void CSVRender::WorldspaceWidget::placeObject(const std::string sceneNode, const // FIXME: adjustRigidBody() seems to lose objects, work around by deleting and recreating objects //CSVWorld::PhysicsSystem::instance()->moveObject(sceneNode, pos, xr*yr*zr); std::string mesh = CSVWorld::PhysicsSystem::instance()->sceneNodeToMesh(sceneNode); - CSVWorld::PhysicsSystem::instance()->removeObject(sceneNode); - CSVWorld::PhysicsSystem::instance()->addObject(mesh, sceneNode, refId, cellref.mScale, pos, xr*yr*zr); + CSVWorld::PhysicsSystem::instance()->replaceObject(mesh, sceneNode, refId, cellref.mScale, pos, xr*yr*zr); // update all SceneWidgets and their SceneManagers emit signalAsModified(); diff --git a/apps/opencs/view/world/physicssystem.cpp b/apps/opencs/view/world/physicssystem.cpp index a8cf5c37b6..7272552b62 100644 --- a/apps/opencs/view/world/physicssystem.cpp +++ b/apps/opencs/view/world/physicssystem.cpp @@ -65,7 +65,6 @@ namespace CSVWorld // update physics, only one physics model per referenceId if(mEngine->getRigidBody(referenceId, true) == NULL) { - mEngine->createAndAdjustRigidBody(mesh, referenceId, scale, position, rotation, 0, // scaledBoxTranslation @@ -74,27 +73,32 @@ 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 iter = mSceneManagers.begin(); for(; iter != mSceneManagers.end(); ++iter) { std::string name = refIdToSceneNode(referenceId, *iter); if(name != sceneNodeName && (*iter)->hasSceneNode(name)) { - // FIXME: rotation or scale not updated + // FIXME: rotation or scale not updated (*iter)->getSceneNode(name)->setPosition(position); } } } } - void PhysicsSystem::removeObject(const std::string &sceneNodeName) + // normal delete (e.g closing a scene subview) + // TODO: should think about using some kind of reference counting within RigidBody + void PhysicsSystem::removeObject(const std::string &sceneNodeName, bool force) { - std::string referenceId = sceneNodeToRefId(sceneNodeName); + std::string referenceId = mSceneNodeToRefId[sceneNodeName]; + if(referenceId != "") { - mEngine->removeRigidBody(referenceId); - mEngine->deleteRigidBody(referenceId); + mSceneNodeToRefId.erase(sceneNodeName); + mSceneNodeToMesh.erase(sceneNodeName); + // find which SceneManager has this object Ogre::SceneManager *sceneManager = NULL; std::list::const_iterator iter = mSceneManagers.begin(); for(; iter != mSceneManagers.end(); ++iter) @@ -109,6 +113,17 @@ namespace CSVWorld if(!sceneManager) return; // FIXME: maybe this should be an exception + // illustration: erase the object "K" from the object map + // + // RidigBody SubView Ogre + // --------------- -------------- ------------- + // ReferenceId "A" (SceneManager X SceneNode "J") + // (SceneManager Y SceneNode "K") <--- erase + // (SceneManager Z SceneNode "L") + // + // ReferenceId "B" (SceneManager X SceneNode "M") + // (SceneManager Y SceneNode "N") <--- notice not deleted + // (SceneManager Z SceneNode "O") std::map >::iterator itRef = mRefIdToSceneNode.begin(); for(; itRef != mRefIdToSceneNode.end(); ++itRef) @@ -116,12 +131,27 @@ namespace CSVWorld if((*itRef).second.find(sceneManager) != (*itRef).second.end()) { (*itRef).second.erase(sceneManager); - return; + break; } } + + // should the physics model be deleted? + if(force || mRefIdToSceneNode.find(referenceId) == mRefIdToSceneNode.end()) + { + mEngine->removeRigidBody(referenceId); + mEngine->deleteRigidBody(referenceId); + } } } + 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) + { + removeObject(sceneNodeName, true); // force delete + addObject(mesh, sceneNodeName, referenceId, scale, position, rotation, placeable); + } + void PhysicsSystem::moveObject(const std::string &sceneNodeName, const Ogre::Vector3 &position, const Ogre::Quaternion &rotation) { @@ -228,11 +258,24 @@ namespace CSVWorld return mSceneNodeToMesh[sceneNodeName]; } - void PhysicsSystem::addSceneManager(Ogre::SceneManager *sceneMgr, CSVRender::SceneWidget * scene) + void PhysicsSystem::addSceneManager(Ogre::SceneManager *sceneMgr) { mSceneManagers.push_back(sceneMgr); } + void PhysicsSystem::removeSceneManager(Ogre::SceneManager *sceneMgr) + { + std::list::iterator iter = mSceneManagers.begin(); + for(; iter != mSceneManagers.end(); ++iter) + { + if(*iter == sceneMgr) + { + mSceneManagers.erase(iter); + break; + } + } + } + void PhysicsSystem::toggleDebugRendering(Ogre::SceneManager *sceneMgr) { // FIXME: should check if sceneMgr is in the list diff --git a/apps/opencs/view/world/physicssystem.hpp b/apps/opencs/view/world/physicssystem.hpp index c2cb567be5..b5b7658838 100644 --- a/apps/opencs/view/world/physicssystem.hpp +++ b/apps/opencs/view/world/physicssystem.hpp @@ -35,7 +35,6 @@ namespace CSVWorld std::map > mRefIdToSceneNode; std::map mSceneNodeToMesh; std::list mSceneManagers; // FIXME: change to list per OEngine - std::list mSceneWidgets; // FIXME: change to list per OEngine OEngine::Physic::PhysicEngine* mEngine; std::multimap mTerrain; @@ -46,14 +45,20 @@ namespace CSVWorld static PhysicsSystem *instance(); - void addSceneManager(Ogre::SceneManager *sceneMgr, CSVRender::SceneWidget * scene); + void addSceneManager(Ogre::SceneManager *sceneMgr); + void removeSceneManager(Ogre::SceneManager *sceneMgr); void 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=false); - void removeObject(const std::string &sceneNodeName); + 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 moveObject(const std::string &sceneNodeName, const Ogre::Vector3 &position, const Ogre::Quaternion &rotation);