From aa9fb33a185e8a4e895b9b695768ed6740493d7f Mon Sep 17 00:00:00 2001 From: elsid Date: Wed, 10 May 2023 22:26:51 +0200 Subject: [PATCH] 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; }; }