From 624ffef4fea88e4f5ddba8b3b9504094a0a75392 Mon Sep 17 00:00:00 2001 From: elsid Date: Wed, 10 May 2023 20:10:05 +0200 Subject: [PATCH 1/7] Reduce block nesting --- apps/openmw/mwrender/localmap.cpp | 41 +++++++++++++++---------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/apps/openmw/mwrender/localmap.cpp b/apps/openmw/mwrender/localmap.cpp index f9c7e02e44..929b46ee8d 100644 --- a/apps/openmw/mwrender/localmap.cpp +++ b/apps/openmw/mwrender/localmap.cpp @@ -182,22 +182,20 @@ namespace MWRender void LocalMap::requestMap(const MWWorld::CellStore* cell) { - if (cell->isExterior()) + if (!cell->isExterior()) { - int cellX = cell->getCell()->getGridX(); - int cellY = cell->getCell()->getGridY(); - - MapSegment& segment = mExteriorSegments[std::make_pair(cellX, cellY)]; - if (!segment.needUpdate) - return; - else - { - requestExteriorMap(cell); - segment.needUpdate = false; - } - } - else requestInteriorMap(cell); + return; + } + + int cellX = cell->getCell()->getGridX(); + int cellY = cell->getCell()->getGridY(); + + MapSegment& segment = mExteriorSegments[std::make_pair(cellX, cellY)]; + if (!segment.needUpdate) + return; + requestExteriorMap(cell); + segment.needUpdate = false; } void LocalMap::addCell(MWWorld::CellStore* cell) @@ -272,13 +270,14 @@ namespace MWRender MapSegment& segment = mExteriorSegments[std::make_pair(cell->getCell()->getGridX(), cell->getCell()->getGridY())]; - if (!segment.mFogOfWarImage) - { - if (cell->getFog()) - segment.loadFogOfWar(cell->getFog()->mFogTextures.back()); - else - segment.initFogOfWar(); - } + + if (segment.mFogOfWarImage != nullptr) + return; + + if (cell->getFog()) + segment.loadFogOfWar(cell->getFog()->mFogTextures.back()); + else + segment.initFogOfWar(); } static osg::Vec2f getNorthVector(const MWWorld::CellStore* cell) From 13242564401f4ce21bebf248dc8cac0ceda7a4bc Mon Sep 17 00:00:00 2001 From: elsid Date: Wed, 10 May 2023 20:13:47 +0200 Subject: [PATCH 2/7] Avoid redundant lookup --- apps/openmw/mwrender/localmap.cpp | 7 ++----- apps/openmw/mwrender/localmap.hpp | 2 +- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/apps/openmw/mwrender/localmap.cpp b/apps/openmw/mwrender/localmap.cpp index 929b46ee8d..f3a8791cd3 100644 --- a/apps/openmw/mwrender/localmap.cpp +++ b/apps/openmw/mwrender/localmap.cpp @@ -194,7 +194,7 @@ namespace MWRender MapSegment& segment = mExteriorSegments[std::make_pair(cellX, cellY)]; if (!segment.needUpdate) return; - requestExteriorMap(cell); + requestExteriorMap(cell, segment); segment.needUpdate = false; } @@ -253,7 +253,7 @@ namespace MWRender } } - void LocalMap::requestExteriorMap(const MWWorld::CellStore* cell) + void LocalMap::requestExteriorMap(const MWWorld::CellStore* cell, MapSegment& segment) { mInterior = false; @@ -268,9 +268,6 @@ namespace MWRender x * mMapWorldSize + mMapWorldSize / 2.f, y * mMapWorldSize + mMapWorldSize / 2.f, osg::Vec3d(0, 1, 0), zmin, zmax); - MapSegment& segment - = mExteriorSegments[std::make_pair(cell->getCell()->getGridX(), cell->getCell()->getGridY())]; - if (segment.mFogOfWarImage != nullptr) return; diff --git a/apps/openmw/mwrender/localmap.hpp b/apps/openmw/mwrender/localmap.hpp index f4a856606e..da81cb7cd3 100644 --- a/apps/openmw/mwrender/localmap.hpp +++ b/apps/openmw/mwrender/localmap.hpp @@ -143,7 +143,7 @@ namespace MWRender float mAngle; const osg::Vec2f rotatePoint(const osg::Vec2f& point, const osg::Vec2f& center, const float angle); - void requestExteriorMap(const MWWorld::CellStore* cell); + void requestExteriorMap(const MWWorld::CellStore* cell, MapSegment& segment); void requestInteriorMap(const MWWorld::CellStore* cell); void setupRenderToTexture( From d927aaad14d3ce7efd8b3cc7043423450cc03915 Mon Sep 17 00:00:00 2001 From: elsid Date: Wed, 10 May 2023 20:15:04 +0200 Subject: [PATCH 3/7] Avoid redundant getCell()->getGrid* calls --- apps/openmw/mwrender/localmap.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwrender/localmap.cpp b/apps/openmw/mwrender/localmap.cpp index f3a8791cd3..433f8092b3 100644 --- a/apps/openmw/mwrender/localmap.cpp +++ b/apps/openmw/mwrender/localmap.cpp @@ -257,16 +257,15 @@ namespace MWRender { mInterior = false; - int x = cell->getCell()->getGridX(); - int y = cell->getCell()->getGridY(); + const int x = cell->getCell()->getGridX(); + const int y = cell->getCell()->getGridY(); osg::BoundingSphere bound = mSceneRoot->getBound(); float zmin = bound.center().z() - bound.radius(); float zmax = bound.center().z() + bound.radius(); - setupRenderToTexture(cell->getCell()->getGridX(), cell->getCell()->getGridY(), - x * mMapWorldSize + mMapWorldSize / 2.f, y * mMapWorldSize + mMapWorldSize / 2.f, osg::Vec3d(0, 1, 0), zmin, - zmax); + setupRenderToTexture(x, y, x * mMapWorldSize + mMapWorldSize / 2.f, y * mMapWorldSize + mMapWorldSize / 2.f, + osg::Vec3d(0, 1, 0), zmin, zmax); if (segment.mFogOfWarImage != nullptr) return; From b2f7fc70a65856d1aeaaa196ce00ae8be10d3669 Mon Sep 17 00:00:00 2001 From: elsid Date: Wed, 10 May 2023 20:25:30 +0200 Subject: [PATCH 4/7] Remove redundant MapSegment constructor and destructor --- apps/openmw/mwrender/localmap.cpp | 5 ----- apps/openmw/mwrender/localmap.hpp | 6 +----- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/apps/openmw/mwrender/localmap.cpp b/apps/openmw/mwrender/localmap.cpp index 433f8092b3..9e9580fcaa 100644 --- a/apps/openmw/mwrender/localmap.cpp +++ b/apps/openmw/mwrender/localmap.cpp @@ -571,11 +571,6 @@ namespace MWRender } } - LocalMap::MapSegment::MapSegment() - : mHasFogState(false) - { - } - void LocalMap::MapSegment::createFogOfWarTexture() { if (mFogOfWarTexture) diff --git a/apps/openmw/mwrender/localmap.hpp b/apps/openmw/mwrender/localmap.hpp index da81cb7cd3..6b1513cf8a 100644 --- a/apps/openmw/mwrender/localmap.hpp +++ b/apps/openmw/mwrender/localmap.hpp @@ -109,9 +109,6 @@ namespace MWRender struct MapSegment { - MapSegment(); - ~MapSegment() = default; - void initFogOfWar(); void loadFogOfWar(const ESM::FogTexture& fog); void saveFogOfWar(ESM::FogTexture& fog) const; @@ -122,8 +119,7 @@ namespace MWRender osg::ref_ptr mFogOfWarImage; bool needUpdate = true; - - bool mHasFogState; + bool mHasFogState = false; }; typedef std::map, MapSegment> SegmentMap; From fd249b46c0c6ebb46330ce3334b50c6dd6997b34 Mon Sep 17 00:00:00 2001 From: elsid Date: Wed, 10 May 2023 22:46:21 +0200 Subject: [PATCH 5/7] Remove redundant member function mActive is public. --- apps/openmw/mwrender/localmap.cpp | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/apps/openmw/mwrender/localmap.cpp b/apps/openmw/mwrender/localmap.cpp index 9e9580fcaa..a71ab61f3c 100644 --- a/apps/openmw/mwrender/localmap.cpp +++ b/apps/openmw/mwrender/localmap.cpp @@ -61,9 +61,6 @@ namespace MWRender void setDefaults(osg::Camera* camera) override; - bool isActive() { return mActive; } - void setIsActive(bool active) { mActive = active; } - osg::Node* mSceneRoot; osg::Matrix mProjectionMatrix; osg::Matrix mViewMatrix; @@ -243,7 +240,7 @@ namespace MWRender auto it = mLocalMapRTTs.begin(); while (it != mLocalMapRTTs.end()) { - if (!(*it)->isActive()) + if (!(*it)->mActive) { mRoot->removeChild(*it); it = mLocalMapRTTs.erase(it); @@ -758,13 +755,10 @@ namespace MWRender void CameraLocalUpdateCallback::operator()(LocalMapRenderToTexture* node, osg::NodeVisitor* nv) { - if (!node->isActive()) + if (!node->mActive) node->setNodeMask(0); - if (node->isActive()) - { - node->setIsActive(false); - } + node->mActive = false; // Rtt-nodes do not forward update traversal to their cameras so we can traverse safely. // Traverse in case there are nested callbacks. From f7ebd9b9b48fc2dc236824a582555d280299cbdc Mon Sep 17 00:00:00 2001 From: elsid Date: Wed, 10 May 2023 22:52:59 +0200 Subject: [PATCH 6/7] Avoid old C-style cast --- apps/openmw/mwrender/localmap.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/openmw/mwrender/localmap.cpp b/apps/openmw/mwrender/localmap.cpp index a71ab61f3c..98f39603d5 100644 --- a/apps/openmw/mwrender/localmap.cpp +++ b/apps/openmw/mwrender/localmap.cpp @@ -468,7 +468,8 @@ namespace MWRender int texU = static_cast((sFogOfWarResolution - 1) * nX); int texV = static_cast((sFogOfWarResolution - 1) * nY); - uint32_t clr = ((const uint32_t*)segment.mFogOfWarImage->data())[texV * sFogOfWarResolution + texU]; + const std::uint32_t clr + = reinterpret_cast(segment.mFogOfWarImage->data())[texV * sFogOfWarResolution + texU]; uint8_t alpha = (clr >> 24); return alpha < 200; } @@ -536,7 +537,7 @@ namespace MWRender if (!segment.mFogOfWarImage || !segment.mMapTexture) continue; - uint32_t* data = (uint32_t*)segment.mFogOfWarImage->data(); + std::uint32_t* data = reinterpret_cast(segment.mFogOfWarImage->data()); bool changed = false; for (int texV = 0; texV < sFogOfWarResolution; ++texV) { @@ -545,10 +546,9 @@ namespace MWRender float sqrDist = square((texU + mx * (sFogOfWarResolution - 1)) - u * (sFogOfWarResolution - 1)) + square((texV + my * (sFogOfWarResolution - 1)) - v * (sFogOfWarResolution - 1)); - uint32_t clr = *(uint32_t*)data; - uint8_t alpha = (clr >> 24); - alpha = std::min(alpha, (uint8_t)(std::clamp(sqrDist / sqrExploreRadius, 0.f, 1.f) * 255)); - uint32_t val = (uint32_t)(alpha << 24); + const std::uint8_t alpha = std::min( + *data >> 24, std::clamp(sqrDist / sqrExploreRadius, 0.f, 1.f) * 255); + std::uint32_t val = static_cast(alpha << 24); if (*data != val) { *data = val; From aa9fb33a185e8a4e895b9b695768ed6740493d7f Mon Sep 17 00:00:00 2001 From: elsid Date: Wed, 10 May 2023 22:26:51 +0200 Subject: [PATCH 7/7] Update cell local map on different neighbour cells Save which neighbour cells were active when local map for a cell is rendered. Update when intersection of currently loaded cells is different from stored. If map was rendered when all neighbours were loaded no more updates will happen. --- apps/openmw/mwrender/localmap.cpp | 32 ++++++++++++++++++++++++++----- apps/openmw/mwrender/localmap.hpp | 20 ++++++++++++++++--- 2 files changed, 44 insertions(+), 8 deletions(-) diff --git a/apps/openmw/mwrender/localmap.cpp b/apps/openmw/mwrender/localmap.cpp index 98f39603d5..937aa91161 100644 --- a/apps/openmw/mwrender/localmap.cpp +++ b/apps/openmw/mwrender/localmap.cpp @@ -189,17 +189,18 @@ namespace MWRender int cellY = cell->getCell()->getGridY(); MapSegment& segment = mExteriorSegments[std::make_pair(cellX, cellY)]; - if (!segment.needUpdate) + const std::uint8_t neighbourFlags = getExteriorNeighbourFlags(cellX, cellY); + if ((segment.mLastRenderNeighbourFlags & neighbourFlags) == neighbourFlags) return; requestExteriorMap(cell, segment); - segment.needUpdate = false; + segment.mLastRenderNeighbourFlags = neighbourFlags; } void LocalMap::addCell(MWWorld::CellStore* cell) { if (cell->isExterior()) - mExteriorSegments[std::make_pair(cell->getCell()->getGridX(), cell->getCell()->getGridY())].needUpdate - = true; + mExteriorSegments.emplace( + std::make_pair(cell->getCell()->getGridX(), cell->getCell()->getGridY()), MapSegment{}); } void LocalMap::removeExteriorCell(int x, int y) @@ -211,7 +212,9 @@ namespace MWRender { saveFogOfWar(cell); - if (!cell->isExterior()) + if (cell->isExterior()) + mExteriorSegments.erase({ cell->getCell()->getGridX(), cell->getCell()->getGridY() }); + else mInteriorSegments.clear(); } @@ -568,6 +571,25 @@ namespace MWRender } } + std::uint8_t LocalMap::getExteriorNeighbourFlags(int cellX, int cellY) const + { + constexpr std::tuple flags[] = { + { NeighbourCellTopLeft, -1, -1 }, + { NeighbourCellTopCenter, 0, -1 }, + { NeighbourCellTopRight, 1, -1 }, + { NeighbourCellMiddleLeft, -1, 0 }, + { NeighbourCellMiddleRight, 1, 0 }, + { NeighbourCellBottomLeft, -1, 1 }, + { NeighbourCellBottomCenter, 0, 1 }, + { NeighbourCellBottomRight, 1, 1 }, + }; + std::uint8_t result = 0; + for (const auto& [flag, dx, dy] : flags) + if (mExteriorSegments.contains(std::pair(cellX + dx, cellY + dy))) + result |= flag; + return result; + } + void LocalMap::MapSegment::createFogOfWarTexture() { if (mFogOfWarTexture) diff --git a/apps/openmw/mwrender/localmap.hpp b/apps/openmw/mwrender/localmap.hpp index 6b1513cf8a..9fd101c45f 100644 --- a/apps/openmw/mwrender/localmap.hpp +++ b/apps/openmw/mwrender/localmap.hpp @@ -1,6 +1,7 @@ #ifndef GAME_RENDER_LOCALMAP_H #define GAME_RENDER_LOCALMAP_H +#include #include #include #include @@ -107,6 +108,18 @@ namespace MWRender typedef std::set> Grid; Grid mCurrentGrid; + enum NeighbourCellFlag : std::uint8_t + { + NeighbourCellTopLeft = 1, + NeighbourCellTopCenter = 1 << 1, + NeighbourCellTopRight = 1 << 2, + NeighbourCellMiddleLeft = 1 << 3, + NeighbourCellMiddleRight = 1 << 4, + NeighbourCellBottomLeft = 1 << 5, + NeighbourCellBottomCenter = 1 << 6, + NeighbourCellBottomRight = 1 << 7, + }; + struct MapSegment { void initFogOfWar(); @@ -114,12 +127,11 @@ namespace MWRender void saveFogOfWar(ESM::FogTexture& fog) const; void createFogOfWarTexture(); + std::uint8_t mLastRenderNeighbourFlags = 0; + bool mHasFogState = false; osg::ref_ptr mMapTexture; osg::ref_ptr mFogOfWarTexture; osg::ref_ptr mFogOfWarImage; - - bool needUpdate = true; - bool mHasFogState = false; }; typedef std::map, MapSegment> SegmentMap; @@ -147,6 +159,8 @@ namespace MWRender bool mInterior; osg::BoundingBox mBounds; + + std::uint8_t getExteriorNeighbourFlags(int cellX, int cellY) const; }; }