From bd655c20fd2a7c23b83106a5349f718972827883 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 5 Feb 2016 00:39:52 +0100 Subject: [PATCH] Refactor local map updates We don't need the delay any more because the rendering itself is part of the normal rendering traversal - so it's delayed anyway. Don't request maps that we're not actually using (i.e. with cell grid sizes higher than the default 3, we were rendering more maps than the map window could show). --- apps/openmw/mwbase/windowmanager.hpp | 3 +-- apps/openmw/mwgui/mapwindow.cpp | 20 +++++++++++++++++ apps/openmw/mwgui/mapwindow.hpp | 6 +++++ apps/openmw/mwgui/windowmanagerimp.cpp | 20 ++++++++--------- apps/openmw/mwgui/windowmanagerimp.hpp | 3 +-- apps/openmw/mwrender/localmap.cpp | 16 +++++++------ apps/openmw/mwrender/localmap.hpp | 6 ++--- apps/openmw/mwworld/scene.cpp | 31 +------------------------- apps/openmw/mwworld/scene.hpp | 2 -- 9 files changed, 51 insertions(+), 56 deletions(-) diff --git a/apps/openmw/mwbase/windowmanager.hpp b/apps/openmw/mwbase/windowmanager.hpp index f364ada7a..2d4c0e2ca 100644 --- a/apps/openmw/mwbase/windowmanager.hpp +++ b/apps/openmw/mwbase/windowmanager.hpp @@ -176,7 +176,7 @@ namespace MWBase virtual void updateSkillArea() = 0; ///< update display of skills, factions, birth sign, reputation and bounty - virtual void changeCell(MWWorld::CellStore* cell) = 0; + virtual void changeCell(const MWWorld::CellStore* cell) = 0; ///< change the active cell virtual void setFocusObject(const MWWorld::Ptr& focus) = 0; @@ -354,7 +354,6 @@ namespace MWBase virtual std::string correctBookartPath(const std::string& path, int width, int height) = 0; virtual std::string correctTexturePath(const std::string& path) = 0; - virtual void requestMap(std::set cells) = 0; virtual void removeCell(MWWorld::CellStore* cell) = 0; virtual void writeFog(MWWorld::CellStore* cell) = 0; }; diff --git a/apps/openmw/mwgui/mapwindow.cpp b/apps/openmw/mwgui/mapwindow.cpp index 89f4d8cf3..469564d9d 100644 --- a/apps/openmw/mwgui/mapwindow.cpp +++ b/apps/openmw/mwgui/mapwindow.cpp @@ -454,6 +454,26 @@ namespace MWGui updateCustomMarkers(); } + void LocalMapBase::requestMapRender(const MWWorld::CellStore *cell) + { + std::set cells; + if (!cell->isExterior()) + cells.insert(cell); + else + { + for (int dX=-1; dX<2; ++dX) + { + for (int dY=-1; dY<2; ++dY) + { + const MWWorld::CellStore* gridCell = MWBase::Environment::get().getWorld()->getExterior (cell->getCell()->getGridX()+dX, cell->getCell()->getGridY()+dY); + cells.insert(gridCell); + } + } + } + + mLocalMapRender->requestMap(cells); + } + void LocalMapBase::redraw() { // Redraw children in proper order diff --git a/apps/openmw/mwgui/mapwindow.hpp b/apps/openmw/mwgui/mapwindow.hpp index 227a9e3f9..96fd3c994 100644 --- a/apps/openmw/mwgui/mapwindow.hpp +++ b/apps/openmw/mwgui/mapwindow.hpp @@ -23,6 +23,11 @@ namespace ESM class ESMWriter; } +namespace MWWorld +{ + class CellStore; +} + namespace Loading { class Listener; @@ -67,6 +72,7 @@ namespace MWGui void setCellPrefix(const std::string& prefix); void setActiveCell(const int x, const int y, bool interior=false); + void requestMapRender(const MWWorld::CellStore* cell); void setPlayerDir(const float x, const float y); void setPlayerPos(int cellX, int cellY, const float nx, const float ny); diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index f151bee80..90c0494f6 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -926,7 +926,7 @@ namespace MWGui if (!mLocalMapRender) return; - MWWorld::Ptr player = MWMechanics::getPlayer(); + MWWorld::ConstPtr player = MWMechanics::getPlayer(); osg::Vec3f playerPosition = player.getRefData().getPosition().asVec3(); osg::Quat playerOrientation (-player.getRefData().getPosition().rot[2], osg::Vec3(0,0,1)); @@ -938,10 +938,9 @@ namespace MWGui if (!player.getCell()->isExterior()) { - mMap->setActiveCell(x, y, true); - mHud->setActiveCell(x, y, true); + setActiveMap(x, y, true); } - // else: need to know the current grid center, call setActiveCell from MWWorld::Scene + // else: need to know the current grid center, call setActiveMap from changeCell mMap->setPlayerDir(playerdirection.x(), playerdirection.y()); mMap->setPlayerPos(x, y, u, v); @@ -1007,8 +1006,10 @@ namespace MWGui mDebugWindow->onFrame(frameDuration); } - void WindowManager::changeCell(MWWorld::CellStore* cell) + void WindowManager::changeCell(const MWWorld::CellStore* cell) { + mMap->requestMapRender(cell); + std::string name = MWBase::Environment::get().getWorld()->getCellName (cell); mMap->setCellName( name ); @@ -1020,6 +1021,8 @@ namespace MWGui mMap->addVisitedLocation (name, cell->getCell()->getGridX (), cell->getCell()->getGridY ()); mMap->cellExplored (cell->getCell()->getGridX(), cell->getCell()->getGridY()); + + setActiveMap(cell->getCell()->getGridX(), cell->getCell()->getGridY(), false); } else { @@ -1032,6 +1035,8 @@ namespace MWGui else MWBase::Environment::get().getWorld()->getPlayer().setLastKnownExteriorPosition(worldPos); mMap->setGlobalMapPlayerPosition(worldPos.x(), worldPos.y()); + + setActiveMap(0, 0, true); } } @@ -2078,11 +2083,6 @@ namespace MWGui tex->unlock(); } - void WindowManager::requestMap(std::set cells) - { - mLocalMapRender->requestMap(cells); - } - void WindowManager::removeCell(MWWorld::CellStore *cell) { mLocalMapRender->removeCell(cell); diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index 6edb4660c..3cdba8a87 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -204,7 +204,7 @@ namespace MWGui virtual void configureSkills (const SkillList& major, const SkillList& minor); ///< configure skill groups, each set contains the skill ID for that group. virtual void updateSkillArea(); ///< update display of skills, factions, birth sign, reputation and bounty - virtual void changeCell(MWWorld::CellStore* cell); ///< change the active cell + virtual void changeCell(const MWWorld::CellStore* cell); ///< change the active cell virtual void setFocusObject(const MWWorld::Ptr& focus); virtual void setFocusObjectScreenCoords(float min_x, float min_y, float max_x, float max_y); @@ -375,7 +375,6 @@ namespace MWGui virtual std::string correctBookartPath(const std::string& path, int width, int height); virtual std::string correctTexturePath(const std::string& path); - void requestMap(std::set cells); void removeCell(MWWorld::CellStore* cell); void writeFog(MWWorld::CellStore* cell); diff --git a/apps/openmw/mwrender/localmap.cpp b/apps/openmw/mwrender/localmap.cpp index 200f484b5..4efcf5d1b 100644 --- a/apps/openmw/mwrender/localmap.cpp +++ b/apps/openmw/mwrender/localmap.cpp @@ -229,11 +229,11 @@ void LocalMap::setupRenderToTexture(osg::ref_ptr camera, int x, int segment.mMapTexture = texture; } -void LocalMap::requestMap(std::set cells) +void LocalMap::requestMap(std::set cells) { - for (std::set::iterator it = cells.begin(); it != cells.end(); ++it) + for (std::set::iterator it = cells.begin(); it != cells.end(); ++it) { - MWWorld::CellStore* cell = *it; + const MWWorld::CellStore* cell = *it; if (cell->isExterior()) requestExteriorMap(cell); else @@ -296,7 +296,7 @@ void LocalMap::cleanupCameras() mCamerasPendingRemoval.clear(); } -void LocalMap::requestExteriorMap(MWWorld::CellStore* cell) +void LocalMap::requestExteriorMap(const MWWorld::CellStore* cell) { mInterior = false; @@ -321,7 +321,7 @@ void LocalMap::requestExteriorMap(MWWorld::CellStore* cell) } } -void LocalMap::requestInteriorMap(MWWorld::CellStore* cell) +void LocalMap::requestInteriorMap(const MWWorld::CellStore* cell) { osg::ComputeBoundsVisitor computeBoundsVisitor; computeBoundsVisitor.setTraversalMask(Mask_Scene|Mask_Terrain); @@ -375,6 +375,7 @@ void LocalMap::requestInteriorMap(MWWorld::CellStore* cell) // If they changed by too much (for bounds, < padding is considered acceptable) then parts of the interior might not // be covered by the map anymore. // The following code detects this, and discards the CellStore's fog state if it needs to. + bool cellHasValidFog = false; if (cell->getFog()) { ESM::FogState* fog = cell->getFog(); @@ -390,13 +391,14 @@ void LocalMap::requestInteriorMap(MWWorld::CellStore* cell) || std::abs(mAngle - fog->mNorthMarkerAngle) > osg::DegreesToRadians(5.f)) { // Nuke it - cell->setFog(NULL); + cellHasValidFog = false; } else { // Looks sane, use it mBounds = osg::BoundingBox(newMin, newMax); mAngle = fog->mNorthMarkerAngle; + cellHasValidFog = true; } } @@ -434,7 +436,7 @@ void LocalMap::requestInteriorMap(MWWorld::CellStore* cell) MapSegment& segment = mSegments[std::make_pair(x,y)]; if (!segment.mFogOfWarImage) { - if (!cell->getFog()) + if (!cellHasValidFog) segment.initFogOfWar(); else { diff --git a/apps/openmw/mwrender/localmap.hpp b/apps/openmw/mwrender/localmap.hpp index 59165013d..52f570b0b 100644 --- a/apps/openmw/mwrender/localmap.hpp +++ b/apps/openmw/mwrender/localmap.hpp @@ -52,7 +52,7 @@ namespace MWRender /** * Request a map render for the given cells. Render textures will be immediately created and can be retrieved with the getMapTexture function. */ - void requestMap (std::set cells); + void requestMap (std::set cells); /** * Remove map and fog textures for the given cell. @@ -146,8 +146,8 @@ namespace MWRender float mAngle; const osg::Vec2f rotatePoint(const osg::Vec2f& point, const osg::Vec2f& center, const float angle); - void requestExteriorMap(MWWorld::CellStore* cell); - void requestInteriorMap(MWWorld::CellStore* cell); + void requestExteriorMap(const MWWorld::CellStore* cell); + void requestInteriorMap(const MWWorld::CellStore* cell); osg::ref_ptr createOrthographicCamera(float left, float top, float width, float height, const osg::Vec3d& upVector, float zmin, float zmax); void setupRenderToTexture(osg::ref_ptr camera, int x, int y); diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 15b3c057b..dc93c3b1d 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -179,27 +179,6 @@ namespace MWWorld void Scene::update (float duration, bool paused) { - if (mNeedMapUpdate) - { - // Note: exterior cell maps must be updated, even if they were visited before, because the set of surrounding cells might be different - // (and objects in a different cell can "bleed" into another cells map if they cross the border) - std::set cellsToUpdate; - for (CellStoreCollection::iterator active = mActiveCells.begin(); active!=mActiveCells.end(); ++active) - { - cellsToUpdate.insert(*active); - } - MWBase::Environment::get().getWindowManager()->requestMap(cellsToUpdate); - - mNeedMapUpdate = false; - - if (mCurrentCell->isExterior()) - { - int cellX, cellY; - getGridCenter(cellX, cellY); - MWBase::Environment::get().getWindowManager()->setActiveMap(cellX,cellY,false); - } - } - mRendering.update (duration, paused); } @@ -410,10 +389,6 @@ namespace MWWorld mCellChanged = true; - // Delay the map update until scripts have been given a chance to run. - // If we don't do this, objects that should be disabled will still appear on the map. - mNeedMapUpdate = true; - mRendering.getResourceSystem()->clearCache(); } @@ -449,7 +424,7 @@ namespace MWWorld } Scene::Scene (MWRender::RenderingManager& rendering, MWPhysics::PhysicsSystem *physics) - : mCurrentCell (0), mCellChanged (false), mPhysics(physics), mRendering(rendering), mNeedMapUpdate(false) + : mCurrentCell (0), mCellChanged (false), mPhysics(physics), mRendering(rendering) { } @@ -527,10 +502,6 @@ namespace MWWorld MWBase::Environment::get().getWindowManager()->changeCell(mCurrentCell); - // Delay the map update until scripts have been given a chance to run. - // If we don't do this, objects that should be disabled will still appear on the map. - mNeedMapUpdate = true; - mRendering.getResourceSystem()->clearCache(); } diff --git a/apps/openmw/mwworld/scene.hpp b/apps/openmw/mwworld/scene.hpp index 439c8d72c..c6de3ebdf 100644 --- a/apps/openmw/mwworld/scene.hpp +++ b/apps/openmw/mwworld/scene.hpp @@ -58,8 +58,6 @@ namespace MWWorld MWPhysics::PhysicsSystem *mPhysics; MWRender::RenderingManager& mRendering; - bool mNeedMapUpdate; - void insertCell (CellStore &cell, bool rescale, Loading::Listener* loadingListener); // Load and unload cells as necessary to create a cell grid with "X" and "Y" in the center