From 9e2f3fd0b496321c412d54daed6a53ab68e3071d Mon Sep 17 00:00:00 2001 From: elsid Date: Sun, 19 May 2024 20:03:34 +0200 Subject: [PATCH 1/6] Report stats for TileCachedRecastMeshManager --- components/detournavigator/navmeshmanager.cpp | 5 ++++- components/detournavigator/stats.cpp | 12 ++++++++++-- components/detournavigator/stats.hpp | 11 ++++++++++- .../tilecachedrecastmeshmanager.cpp | 14 +++++++++++++- .../tilecachedrecastmeshmanager.hpp | 4 +++- components/resource/stats.cpp | 4 ++++ 6 files changed, 44 insertions(+), 6 deletions(-) diff --git a/components/detournavigator/navmeshmanager.cpp b/components/detournavigator/navmeshmanager.cpp index 3b62866ed7..bb0a8e3451 100644 --- a/components/detournavigator/navmeshmanager.cpp +++ b/components/detournavigator/navmeshmanager.cpp @@ -217,7 +217,10 @@ namespace DetourNavigator Stats NavMeshManager::getStats() const { - return Stats{ .mUpdater = mAsyncNavMeshUpdater.getStats() }; + return Stats{ + .mUpdater = mAsyncNavMeshUpdater.getStats(), + .mRecast = mRecastMeshManager.getStats(), + }; } RecastMeshTiles NavMeshManager::getRecastMeshTiles() const diff --git a/components/detournavigator/stats.cpp b/components/detournavigator/stats.cpp index da56f91a38..39251b0f76 100644 --- a/components/detournavigator/stats.cpp +++ b/components/detournavigator/stats.cpp @@ -32,11 +32,19 @@ namespace DetourNavigator out.setAttribute(frameNumber, "NavMesh Cache Get", static_cast(stats.mCache.mGetCount)); out.setAttribute(frameNumber, "NavMesh Cache Hit", static_cast(stats.mCache.mHitCount)); } + + void reportStats(const TileCachedRecastMeshManagerStats& stats, unsigned int frameNumber, osg::Stats& out) + { + out.setAttribute(frameNumber, "NavMesh Recast Tiles", static_cast(stats.mTiles)); + out.setAttribute(frameNumber, "NavMesh Recast Objects", static_cast(stats.mObjects)); + out.setAttribute(frameNumber, "NavMesh Recast Heightfields", static_cast(stats.mHeightfields)); + out.setAttribute(frameNumber, "NavMesh Recast Water", static_cast(stats.mWater)); + } } void reportStats(const Stats& stats, unsigned int frameNumber, osg::Stats& out) { - if (stats.mUpdater.has_value()) - reportStats(*stats.mUpdater, frameNumber, out); + reportStats(stats.mUpdater, frameNumber, out); + reportStats(stats.mRecast, frameNumber, out); } } diff --git a/components/detournavigator/stats.hpp b/components/detournavigator/stats.hpp index 0b62b9e669..38a9febc26 100644 --- a/components/detournavigator/stats.hpp +++ b/components/detournavigator/stats.hpp @@ -50,9 +50,18 @@ namespace DetourNavigator NavMeshTilesCacheStats mCache; }; + struct TileCachedRecastMeshManagerStats + { + std::size_t mTiles = 0; + std::size_t mObjects = 0; + std::size_t mHeightfields = 0; + std::size_t mWater = 0; + }; + struct Stats { - std::optional mUpdater; + AsyncNavMeshUpdaterStats mUpdater; + TileCachedRecastMeshManagerStats mRecast; }; void reportStats(const Stats& stats, unsigned int frameNumber, osg::Stats& out); diff --git a/components/detournavigator/tilecachedrecastmeshmanager.cpp b/components/detournavigator/tilecachedrecastmeshmanager.cpp index 3e3927bf65..51e2087b78 100644 --- a/components/detournavigator/tilecachedrecastmeshmanager.cpp +++ b/components/detournavigator/tilecachedrecastmeshmanager.cpp @@ -1,8 +1,10 @@ #include "tilecachedrecastmeshmanager.hpp" + #include "changetype.hpp" #include "gettilespositions.hpp" #include "recastmeshbuilder.hpp" #include "settingsutils.hpp" +#include "stats.hpp" #include "updateguard.hpp" #include @@ -11,7 +13,6 @@ #include #include -#include namespace DetourNavigator { @@ -429,6 +430,17 @@ namespace DetourNavigator return std::move(mChangedTiles); } + TileCachedRecastMeshManagerStats TileCachedRecastMeshManager::getStats() const + { + const std::lock_guard lock(mMutex); + return TileCachedRecastMeshManagerStats{ + .mTiles = mCache.size(), + .mObjects = mObjects.size(), + .mHeightfields = mHeightfields.size(), + .mWater = mWater.size(), + }; + } + TileCachedRecastMeshManager::IndexPoint TileCachedRecastMeshManager::makeIndexPoint( const TilePosition& tilePosition) { diff --git a/components/detournavigator/tilecachedrecastmeshmanager.hpp b/components/detournavigator/tilecachedrecastmeshmanager.hpp index 12e8ddee2e..553e664a5f 100644 --- a/components/detournavigator/tilecachedrecastmeshmanager.hpp +++ b/components/detournavigator/tilecachedrecastmeshmanager.hpp @@ -28,11 +28,11 @@ #include #include #include -#include namespace DetourNavigator { class RecastMesh; + struct TileCachedRecastMeshManagerStats; class TileCachedRecastMeshManager { @@ -81,6 +81,8 @@ namespace DetourNavigator std::map takeChangedTiles(const UpdateGuard* guard); + TileCachedRecastMeshManagerStats getStats() const; + private: struct Report { diff --git a/components/resource/stats.cpp b/components/resource/stats.cpp index 963a9cf45d..34c3bc560c 100644 --- a/components/resource/stats.cpp +++ b/components/resource/stats.cpp @@ -119,6 +119,10 @@ namespace Resource "NavMesh CachedTiles", "NavMesh Cache Get", "NavMesh Cache Hit", + "NavMesh Recast Tiles", + "NavMesh Recast Objects", + "NavMesh Recast Heightfields", + "NavMesh Recast Water", }; std::vector statNames; From 4f5bdbb4fb1246c7506001d40c84bde54506825a Mon Sep 17 00:00:00 2001 From: elsid Date: Sat, 18 May 2024 02:14:58 +0200 Subject: [PATCH 2/6] Remove recastmesh group for absent tile --- apps/openmw/mwrender/recastmesh.cpp | 18 +++++++++++++----- apps/openmw/mwrender/recastmesh.hpp | 2 -- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/apps/openmw/mwrender/recastmesh.cpp b/apps/openmw/mwrender/recastmesh.cpp index 8edbc8568d..65e7c344d8 100644 --- a/apps/openmw/mwrender/recastmesh.cpp +++ b/apps/openmw/mwrender/recastmesh.cpp @@ -67,14 +67,22 @@ namespace MWRender ++it; } - for (const auto& tile : tiles) + for (const auto& [position, mesh] : tiles) { - if (mGroups.count(tile.first)) - continue; - const auto group = SceneUtil::createRecastMeshGroup(*tile.second, settings.mRecast); + const auto it = mGroups.find(position); + + if (it != mGroups.end()) + { + if (it->second.mVersion == mesh->getVersion()) + continue; + + mRootNode->removeChild(it->second.mValue); + } + + const auto group = SceneUtil::createRecastMeshGroup(*mesh, settings.mRecast); MWBase::Environment::get().getResourceSystem()->getSceneManager()->recreateShaders(group, "debug"); group->setNodeMask(Mask_Debug); - mGroups.emplace(tile.first, Group{ tile.second->getVersion(), group }); + mGroups.insert_or_assign(it, position, Group{ mesh->getVersion(), group }); mRootNode->addChild(group); } } diff --git a/apps/openmw/mwrender/recastmesh.hpp b/apps/openmw/mwrender/recastmesh.hpp index 2a45d67c6f..271f209684 100644 --- a/apps/openmw/mwrender/recastmesh.hpp +++ b/apps/openmw/mwrender/recastmesh.hpp @@ -6,8 +6,6 @@ #include -#include - namespace osg { class Group; From 5d281644163df6a535e6e38e257968c0953a5ef7 Mon Sep 17 00:00:00 2001 From: elsid Date: Sun, 19 May 2024 13:47:58 +0200 Subject: [PATCH 3/6] Remove recast mesh tiles outside active range --- .../tilecachedrecastmeshmanager.cpp | 34 ++++++++++++++++++- .../tilecachedrecastmeshmanager.cpp | 5 +++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/apps/openmw_test_suite/detournavigator/tilecachedrecastmeshmanager.cpp b/apps/openmw_test_suite/detournavigator/tilecachedrecastmeshmanager.cpp index df695ec254..904b6a02f0 100644 --- a/apps/openmw_test_suite/detournavigator/tilecachedrecastmeshmanager.cpp +++ b/apps/openmw_test_suite/detournavigator/tilecachedrecastmeshmanager.cpp @@ -449,7 +449,7 @@ namespace ASSERT_EQ(manager.getMesh("other", TilePosition(x, y)), nullptr); } - TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, set_bounds_should_add_changed_tiles) + TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, set_range_should_add_changed_tiles) { TileCachedRecastMeshManager manager(mSettings); const btBoxShape boxShape(btVector3(20, 20, 100)); @@ -470,4 +470,36 @@ namespace ElementsAre( std::pair(TilePosition(-1, -1), ChangeType::add), std::pair(TilePosition(0, 0), ChangeType::remove))); } + + TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, set_range_should_remove_cached_recast_meshes_outside_range) + { + TileCachedRecastMeshManager manager(mSettings); + + const std::string_view worldspace = "worldspace"; + manager.setWorldspace(worldspace, nullptr); + + const btBoxShape boxShape(btVector3(100, 100, 20)); + const CollisionShape shape(mInstance, boxShape, mObjectTransform); + const TilesPositionsRange range1{ + .mBegin = TilePosition(0, 0), + .mEnd = TilePosition(1, 1), + }; + manager.setRange(range1, nullptr); + manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground, nullptr); + + const TilePosition tilePosition(0, 0); + + ASSERT_EQ(manager.getCachedMesh(worldspace, tilePosition), nullptr); + ASSERT_NE(manager.getMesh(worldspace, tilePosition), nullptr); + ASSERT_NE(manager.getCachedMesh(worldspace, tilePosition), nullptr); + + const TilesPositionsRange range2{ + .mBegin = TilePosition(-1, -1), + .mEnd = TilePosition(0, 0), + }; + manager.takeChangedTiles(nullptr); + manager.setRange(range2, nullptr); + + ASSERT_EQ(manager.getCachedMesh(worldspace, tilePosition), nullptr); + } } diff --git a/components/detournavigator/tilecachedrecastmeshmanager.cpp b/components/detournavigator/tilecachedrecastmeshmanager.cpp index 51e2087b78..a34ac8e795 100644 --- a/components/detournavigator/tilecachedrecastmeshmanager.cpp +++ b/components/detournavigator/tilecachedrecastmeshmanager.cpp @@ -100,6 +100,11 @@ namespace DetourNavigator } }); } + + getTilesPositions(mRange, [&](const TilePosition& v) { + if (!isInTilesPositionsRange(range, v)) + mCache.erase(v); + }); } if (changed) From 9854d42d56e92d550ac07cf5a157fbeafc52db72 Mon Sep 17 00:00:00 2001 From: elsid Date: Sun, 19 May 2024 14:26:28 +0200 Subject: [PATCH 4/6] Use ESM::RefId for worldspace type --- apps/navmeshtool/navmesh.cpp | 14 +-- apps/navmeshtool/worldspacedata.cpp | 9 +- apps/navmeshtool/worldspacedata.hpp | 4 +- apps/openmw/mwworld/scene.cpp | 10 +- .../detournavigator/asyncnavmeshupdater.cpp | 21 ++-- .../detournavigator/navmeshdb.cpp | 17 ++- .../tilecachedrecastmeshmanager.cpp | 117 +++++++++--------- .../detournavigator/asyncnavmeshupdater.cpp | 5 +- .../detournavigator/asyncnavmeshupdater.hpp | 6 +- .../detournavigator/generatenavmeshtile.cpp | 6 +- .../detournavigator/generatenavmeshtile.hpp | 14 +-- components/detournavigator/makenavmesh.cpp | 5 +- components/detournavigator/makenavmesh.hpp | 7 +- components/detournavigator/navigator.hpp | 2 +- components/detournavigator/navigatorimpl.cpp | 2 +- components/detournavigator/navigatorimpl.hpp | 3 +- components/detournavigator/navigatorstub.hpp | 2 +- components/detournavigator/navmeshdb.cpp | 26 ++-- components/detournavigator/navmeshdb.hpp | 23 ++-- components/detournavigator/navmeshmanager.cpp | 2 +- components/detournavigator/navmeshmanager.hpp | 4 +- components/detournavigator/recastcontext.cpp | 4 +- components/detournavigator/recastcontext.hpp | 5 +- .../detournavigator/recastmeshprovider.hpp | 2 +- .../tilecachedrecastmeshmanager.cpp | 8 +- .../tilecachedrecastmeshmanager.hpp | 12 +- 26 files changed, 161 insertions(+), 169 deletions(-) diff --git a/apps/navmeshtool/navmesh.cpp b/apps/navmeshtool/navmesh.cpp index 384c965466..fe03376557 100644 --- a/apps/navmeshtool/navmesh.cpp +++ b/apps/navmeshtool/navmesh.cpp @@ -106,8 +106,8 @@ namespace NavMeshTool return DetourNavigator::resolveMeshSource(mDb, source, mNextShapeId); } - std::optional find(std::string_view worldspace, const TilePosition& tilePosition, - const std::vector& input) override + std::optional find( + ESM::RefId worldspace, const TilePosition& tilePosition, const std::vector& input) override { std::optional result; std::lock_guard lock(mMutex); @@ -121,7 +121,7 @@ namespace NavMeshTool return result; } - void ignore(std::string_view worldspace, const TilePosition& tilePosition) override + void ignore(ESM::RefId worldspace, const TilePosition& tilePosition) override { if (mRemoveUnusedTiles) { @@ -131,7 +131,7 @@ namespace NavMeshTool report(); } - void identity(std::string_view worldspace, const TilePosition& tilePosition, std::int64_t tileId) override + void identity(ESM::RefId worldspace, const TilePosition& tilePosition, std::int64_t tileId) override { if (mRemoveUnusedTiles) { @@ -142,7 +142,7 @@ namespace NavMeshTool report(); } - void insert(std::string_view worldspace, const TilePosition& tilePosition, std::int64_t version, + void insert(ESM::RefId worldspace, const TilePosition& tilePosition, std::int64_t version, const std::vector& input, PreparedNavMeshData& data) override { { @@ -158,7 +158,7 @@ namespace NavMeshTool report(); } - void update(std::string_view worldspace, const TilePosition& tilePosition, std::int64_t tileId, + void update(ESM::RefId worldspace, const TilePosition& tilePosition, std::int64_t tileId, std::int64_t version, PreparedNavMeshData& data) override { data.mUserId = static_cast(tileId); @@ -217,7 +217,7 @@ namespace NavMeshTool mDb.vacuum(); } - void removeTilesOutsideRange(std::string_view worldspace, const TilesPositionsRange& range) + void removeTilesOutsideRange(ESM::RefId worldspace, const TilesPositionsRange& range) { const std::lock_guard lock(mMutex); mTransaction.commit(); diff --git a/apps/navmeshtool/worldspacedata.cpp b/apps/navmeshtool/worldspacedata.cpp index 0b3a1202d0..5c8468d7c6 100644 --- a/apps/navmeshtool/worldspacedata.cpp +++ b/apps/navmeshtool/worldspacedata.cpp @@ -234,8 +234,8 @@ namespace NavMeshTool } WorldspaceNavMeshInput::WorldspaceNavMeshInput( - std::string worldspace, const DetourNavigator::RecastSettings& settings) - : mWorldspace(std::move(worldspace)) + ESM::RefId worldspace, const DetourNavigator::RecastSettings& settings) + : mWorldspace(worldspace) , mTileCachedRecastMeshManager(settings) { mAabb.m_min = btVector3(0, 0, 0); @@ -248,7 +248,7 @@ namespace NavMeshTool { Log(Debug::Info) << "Processing " << esmData.mCells.size() << " cells..."; - std::map> navMeshInputs; + std::unordered_map> navMeshInputs; WorldspaceData data; std::size_t objectsCounter = 0; @@ -276,8 +276,7 @@ namespace NavMeshTool const osg::Vec2i cellPosition(cell.mData.mX, cell.mData.mY); const std::size_t cellObjectsBegin = data.mObjects.size(); - const auto cellWorldspace = Misc::StringUtils::lowerCase( - (cell.isExterior() ? ESM::Cell::sDefaultWorldspaceId : cell.mId).serializeText()); + const ESM::RefId cellWorldspace = cell.isExterior() ? ESM::Cell::sDefaultWorldspaceId : cell.mId; WorldspaceNavMeshInput& navMeshInput = [&]() -> WorldspaceNavMeshInput& { auto it = navMeshInputs.find(cellWorldspace); if (it == navMeshInputs.end()) diff --git a/apps/navmeshtool/worldspacedata.hpp b/apps/navmeshtool/worldspacedata.hpp index b6ccce6733..7096cf95ed 100644 --- a/apps/navmeshtool/worldspacedata.hpp +++ b/apps/navmeshtool/worldspacedata.hpp @@ -48,12 +48,12 @@ namespace NavMeshTool struct WorldspaceNavMeshInput { - std::string mWorldspace; + ESM::RefId mWorldspace; TileCachedRecastMeshManager mTileCachedRecastMeshManager; btAABB mAabb; bool mAabbInitialized = false; - explicit WorldspaceNavMeshInput(std::string worldspace, const DetourNavigator::RecastSettings& settings); + explicit WorldspaceNavMeshInput(ESM::RefId worldspace, const DetourNavigator::RecastSettings& settings); }; class BulletObject diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 169e4bfd21..e3b9419035 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -591,9 +591,7 @@ namespace MWWorld else unloadCell(cell, navigatorUpdateGuard.get()); } - mNavigator.setWorldspace( - mWorld.getWorldModel().getExterior(playerCellIndex).getCell()->getWorldSpace().serializeText(), - navigatorUpdateGuard.get()); + mNavigator.setWorldspace(playerCellIndex.mWorldspace, navigatorUpdateGuard.get()); mNavigator.updateBounds(pos, navigatorUpdateGuard.get()); mCurrentGridCenter = osg::Vec2i(playerCellX, playerCellY); @@ -696,7 +694,7 @@ namespace MWWorld CellStore& cell = mWorld.getWorldModel().getExterior( ESM::ExteriorCellLocation(it->mData.mX, it->mData.mY, ESM::Cell::sDefaultWorldspaceId)); - mNavigator.setWorldspace(cell.getCell()->getWorldSpace().serializeText(), navigatorUpdateGuard.get()); + mNavigator.setWorldspace(cell.getCell()->getWorldSpace(), navigatorUpdateGuard.get()); const osg::Vec3f position = osg::Vec3f(it->mData.mX + 0.5f, it->mData.mY + 0.5f, 0) * Constants::CellSizeInUnits; mNavigator.updateBounds(position, navigatorUpdateGuard.get()); @@ -753,7 +751,7 @@ namespace MWWorld + std::to_string(cells.getIntSize()) + ")..."); CellStore& cell = mWorld.getWorldModel().getInterior(it->mName); - mNavigator.setWorldspace(cell.getCell()->getWorldSpace().serializeText(), navigatorUpdateGuard.get()); + mNavigator.setWorldspace(cell.getCell()->getWorldSpace(), navigatorUpdateGuard.get()); ESM::Position position; mWorld.findInteriorPosition(it->mName, position); mNavigator.updateBounds(position.asVec3(), navigatorUpdateGuard.get()); @@ -906,7 +904,7 @@ namespace MWWorld loadingListener->setProgressRange(cell.count()); - mNavigator.setWorldspace(cell.getCell()->getWorldSpace().serializeText(), navigatorUpdateGuard.get()); + mNavigator.setWorldspace(cell.getCell()->getWorldSpace(), navigatorUpdateGuard.get()); mNavigator.updateBounds(position.asVec3(), navigatorUpdateGuard.get()); // Load cell. diff --git a/apps/openmw_test_suite/detournavigator/asyncnavmeshupdater.cpp b/apps/openmw_test_suite/detournavigator/asyncnavmeshupdater.cpp index 51ab37b123..4eb56d63e0 100644 --- a/apps/openmw_test_suite/detournavigator/asyncnavmeshupdater.cpp +++ b/apps/openmw_test_suite/detournavigator/asyncnavmeshupdater.cpp @@ -52,7 +52,7 @@ namespace OffMeshConnectionsManager mOffMeshConnectionsManager{ mSettings.mRecast }; const AgentBounds mAgentBounds{ CollisionShapeType::Aabb, { 29, 29, 66 } }; const TilePosition mPlayerTile{ 0, 0 }; - const std::string mWorldspace = "sys::default"; + const ESM::RefId mWorldspace = ESM::RefId::stringRefId("sys::default"); const btBoxShape mBox{ btVector3(100, 100, 20) }; Loading::Listener mListener; }; @@ -310,7 +310,7 @@ namespace AsyncNavMeshUpdater updater(mSettings, mRecastMeshManager, mOffMeshConnectionsManager, std::move(db)); const TileId nextTileId(dbPtr->getMaxTileId() + 1); - ASSERT_EQ(dbPtr->insertTile(nextTileId, "worldspace", TilePosition{}, TileVersion{ 1 }, {}, {}), 1); + ASSERT_EQ(dbPtr->insertTile(nextTileId, mWorldspace, TilePosition{}, TileVersion{ 1 }, {}, {}), 1); const auto navMeshCacheItem = std::make_shared(1, mSettings); const TilePosition tilePosition{ 0, 0 }; @@ -385,7 +385,7 @@ namespace const AgentBounds mAgentBounds{ CollisionShapeType::Aabb, osg::Vec3f(1, 1, 1) }; const std::shared_ptr mNavMeshCacheItemPtr; const std::weak_ptr mNavMeshCacheItem = mNavMeshCacheItemPtr; - const std::string_view mWorldspace = "worldspace"; + const ESM::RefId mWorldspace = ESM::RefId::stringRefId("worldspace"); const TilePosition mChangedTile{ 0, 0 }; const std::chrono::steady_clock::time_point mProcessTime{}; const TilePosition mPlayerTile{ 0, 0 }; @@ -397,20 +397,23 @@ namespace std::list jobs; SpatialJobQueue queue; - queue.push(jobs.emplace(jobs.end(), mAgentBounds, mNavMeshCacheItem, "worldspace1", mChangedTile, - ChangeType::remove, mProcessTime)); - queue.push(jobs.emplace(jobs.end(), mAgentBounds, mNavMeshCacheItem, "worldspace2", mChangedTile, - ChangeType::update, mProcessTime)); + const ESM::RefId worldspace1 = ESM::RefId::stringRefId("worldspace1"); + const ESM::RefId worldspace2 = ESM::RefId::stringRefId("worldspace2"); + + queue.push(jobs.emplace( + jobs.end(), mAgentBounds, mNavMeshCacheItem, worldspace1, mChangedTile, ChangeType::remove, mProcessTime)); + queue.push(jobs.emplace( + jobs.end(), mAgentBounds, mNavMeshCacheItem, worldspace2, mChangedTile, ChangeType::update, mProcessTime)); ASSERT_EQ(queue.size(), 2); const auto job1 = queue.pop(mChangedTile); ASSERT_TRUE(job1.has_value()); - EXPECT_EQ((*job1)->mWorldspace, "worldspace1"); + EXPECT_EQ((*job1)->mWorldspace, worldspace1); const auto job2 = queue.pop(mChangedTile); ASSERT_TRUE(job2.has_value()); - EXPECT_EQ((*job2)->mWorldspace, "worldspace2"); + EXPECT_EQ((*job2)->mWorldspace, worldspace2); EXPECT_EQ(queue.size(), 0); } diff --git a/apps/openmw_test_suite/detournavigator/navmeshdb.cpp b/apps/openmw_test_suite/detournavigator/navmeshdb.cpp index 4cf88f5711..cd74983b0e 100644 --- a/apps/openmw_test_suite/detournavigator/navmeshdb.cpp +++ b/apps/openmw_test_suite/detournavigator/navmeshdb.cpp @@ -8,7 +8,6 @@ #include #include -#include #include namespace @@ -19,7 +18,7 @@ namespace struct Tile { - std::string mWorldspace; + ESM::RefId mWorldspace; TilePosition mTilePosition; std::vector mInput; std::vector mData; @@ -39,12 +38,12 @@ namespace Tile insertTile(TileId tileId, TileVersion version) { - std::string worldspace = "sys::default"; + const ESM::RefId worldspace = ESM::RefId::stringRefId("sys::default"); const TilePosition tilePosition{ 3, 4 }; std::vector input = generateData(); std::vector data = generateData(); EXPECT_EQ(mDb.insertTile(tileId, worldspace, tilePosition, version, input, data), 1); - return { std::move(worldspace), tilePosition, std::move(input), std::move(data) }; + return { worldspace, tilePosition, std::move(input), std::move(data) }; } }; @@ -89,7 +88,7 @@ namespace { const TileId tileId{ 53 }; const TileVersion version{ 1 }; - const std::string worldspace = "sys::default"; + const ESM::RefId worldspace = ESM::RefId::stringRefId("sys::default"); const TilePosition tilePosition{ 3, 4 }; const std::vector input = generateData(); const std::vector data = generateData(); @@ -101,7 +100,7 @@ namespace { const TileId tileId{ 53 }; const TileVersion version{ 1 }; - const std::string worldspace = "sys::default"; + const ESM::RefId worldspace = ESM::RefId::stringRefId("sys::default"); const TilePosition tilePosition{ 3, 4 }; const std::vector input = generateData(); const std::vector data = generateData(); @@ -113,7 +112,7 @@ namespace TEST_F(DetourNavigatorNavMeshDbTest, delete_tiles_at_should_remove_all_tiles_with_given_worldspace_and_position) { const TileVersion version{ 1 }; - const std::string worldspace = "sys::default"; + const ESM::RefId worldspace = ESM::RefId::stringRefId("sys::default"); const TilePosition tilePosition{ 3, 4 }; const std::vector input1 = generateData(); const std::vector input2 = generateData(); @@ -130,7 +129,7 @@ namespace const TileId leftTileId{ 53 }; const TileId removedTileId{ 54 }; const TileVersion version{ 1 }; - const std::string worldspace = "sys::default"; + const ESM::RefId worldspace = ESM::RefId::stringRefId("sys::default"); const TilePosition tilePosition{ 3, 4 }; const std::vector leftInput = generateData(); const std::vector removedInput = generateData(); @@ -148,7 +147,7 @@ namespace { TileId tileId{ 1 }; const TileVersion version{ 1 }; - const std::string worldspace = "sys::default"; + const ESM::RefId worldspace = ESM::RefId::stringRefId("sys::default"); const std::vector input = generateData(); const std::vector data = generateData(); for (int x = -2; x <= 2; ++x) diff --git a/apps/openmw_test_suite/detournavigator/tilecachedrecastmeshmanager.cpp b/apps/openmw_test_suite/detournavigator/tilecachedrecastmeshmanager.cpp index 904b6a02f0..7585e405e5 100644 --- a/apps/openmw_test_suite/detournavigator/tilecachedrecastmeshmanager.cpp +++ b/apps/openmw_test_suite/detournavigator/tilecachedrecastmeshmanager.cpp @@ -21,6 +21,7 @@ namespace const ObjectTransform mObjectTransform{ ESM::Position{ { 0, 0, 0 }, { 0, 0, 0 } }, 0.0f }; const osg::ref_ptr mShape = new Resource::BulletShape; const osg::ref_ptr mInstance = new Resource::BulletShapeInstance(mShape); + const ESM::RefId mWorldspace = ESM::RefId::stringRefId("worldspace"); DetourNavigatorTileCachedRecastMeshManagerTest() { @@ -34,7 +35,7 @@ namespace TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, get_mesh_for_empty_should_return_nullptr) { TileCachedRecastMeshManager manager(mSettings); - EXPECT_EQ(manager.getMesh("worldspace", TilePosition(0, 0)), nullptr); + EXPECT_EQ(manager.getMesh(mWorldspace, TilePosition(0, 0)), nullptr); } TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, get_revision_for_empty_should_return_zero) @@ -65,14 +66,14 @@ namespace TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, add_object_should_add_tiles) { TileCachedRecastMeshManager manager(mSettings); - manager.setWorldspace("worldspace", nullptr); + manager.setWorldspace(mWorldspace, nullptr); const btBoxShape boxShape(btVector3(20, 20, 100)); const CollisionShape shape(mInstance, boxShape, mObjectTransform); ASSERT_TRUE(manager.addObject( ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground, nullptr)); for (int x = -1; x < 1; ++x) for (int y = -1; y < 1; ++y) - ASSERT_NE(manager.getMesh("worldspace", TilePosition(x, y)), nullptr); + ASSERT_NE(manager.getMesh(mWorldspace, TilePosition(x, y)), nullptr); } TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, add_object_should_return_add_changed_tiles) @@ -145,25 +146,25 @@ namespace get_mesh_after_add_object_should_return_recast_mesh_for_each_used_tile) { TileCachedRecastMeshManager manager(mSettings); - manager.setWorldspace("worldspace", nullptr); + manager.setWorldspace(mWorldspace, nullptr); const btBoxShape boxShape(btVector3(20, 20, 100)); const CollisionShape shape(mInstance, boxShape, mObjectTransform); manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground, nullptr); - EXPECT_NE(manager.getMesh("worldspace", TilePosition(-1, -1)), nullptr); - EXPECT_NE(manager.getMesh("worldspace", TilePosition(-1, 0)), nullptr); - EXPECT_NE(manager.getMesh("worldspace", TilePosition(0, -1)), nullptr); - EXPECT_NE(manager.getMesh("worldspace", TilePosition(0, 0)), nullptr); + EXPECT_NE(manager.getMesh(mWorldspace, TilePosition(-1, -1)), nullptr); + EXPECT_NE(manager.getMesh(mWorldspace, TilePosition(-1, 0)), nullptr); + EXPECT_NE(manager.getMesh(mWorldspace, TilePosition(0, -1)), nullptr); + EXPECT_NE(manager.getMesh(mWorldspace, TilePosition(0, 0)), nullptr); } TEST_F( DetourNavigatorTileCachedRecastMeshManagerTest, get_mesh_after_add_object_should_return_nullptr_for_unused_tile) { TileCachedRecastMeshManager manager(mSettings); - manager.setWorldspace("worldspace", nullptr); + manager.setWorldspace(mWorldspace, nullptr); const btBoxShape boxShape(btVector3(20, 20, 100)); const CollisionShape shape(mInstance, boxShape, mObjectTransform); manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground, nullptr); - EXPECT_EQ(manager.getMesh("worldspace", TilePosition(1, 0)), nullptr); + EXPECT_EQ(manager.getMesh(mWorldspace, TilePosition(1, 0)), nullptr); } TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, @@ -175,7 +176,7 @@ namespace .mEnd = TilePosition(1, 1), }; manager.setRange(range, nullptr); - manager.setWorldspace("worldspace", nullptr); + manager.setWorldspace(mWorldspace, nullptr); const btBoxShape boxShape(btVector3(20, 20, 100)); const btTransform transform( @@ -183,23 +184,23 @@ namespace const CollisionShape shape(mInstance, boxShape, mObjectTransform); manager.addObject(ObjectId(&boxShape), shape, transform, AreaType::AreaType_ground, nullptr); - EXPECT_NE(manager.getMesh("worldspace", TilePosition(0, -1)), nullptr); - EXPECT_NE(manager.getMesh("worldspace", TilePosition(0, 0)), nullptr); - EXPECT_NE(manager.getMesh("worldspace", TilePosition(1, 0)), nullptr); - EXPECT_NE(manager.getMesh("worldspace", TilePosition(1, -1)), nullptr); + EXPECT_NE(manager.getMesh(mWorldspace, TilePosition(0, -1)), nullptr); + EXPECT_NE(manager.getMesh(mWorldspace, TilePosition(0, 0)), nullptr); + EXPECT_NE(manager.getMesh(mWorldspace, TilePosition(1, 0)), nullptr); + EXPECT_NE(manager.getMesh(mWorldspace, TilePosition(1, -1)), nullptr); manager.updateObject(ObjectId(&boxShape), btTransform::getIdentity(), AreaType::AreaType_ground, nullptr); - EXPECT_NE(manager.getMesh("worldspace", TilePosition(-1, -1)), nullptr); - EXPECT_NE(manager.getMesh("worldspace", TilePosition(-1, 0)), nullptr); - EXPECT_NE(manager.getMesh("worldspace", TilePosition(0, -1)), nullptr); - EXPECT_NE(manager.getMesh("worldspace", TilePosition(0, 0)), nullptr); + EXPECT_NE(manager.getMesh(mWorldspace, TilePosition(-1, -1)), nullptr); + EXPECT_NE(manager.getMesh(mWorldspace, TilePosition(-1, 0)), nullptr); + EXPECT_NE(manager.getMesh(mWorldspace, TilePosition(0, -1)), nullptr); + EXPECT_NE(manager.getMesh(mWorldspace, TilePosition(0, 0)), nullptr); } TEST_F( DetourNavigatorTileCachedRecastMeshManagerTest, get_mesh_for_moved_object_should_return_nullptr_for_unused_tile) { TileCachedRecastMeshManager manager(mSettings); - manager.setWorldspace("worldspace", nullptr); + manager.setWorldspace(mWorldspace, nullptr); const btBoxShape boxShape(btVector3(20, 20, 100)); const btTransform transform( @@ -207,48 +208,48 @@ namespace const CollisionShape shape(mInstance, boxShape, mObjectTransform); manager.addObject(ObjectId(&boxShape), shape, transform, AreaType::AreaType_ground, nullptr); - EXPECT_EQ(manager.getMesh("worldspace", TilePosition(-1, -1)), nullptr); - EXPECT_EQ(manager.getMesh("worldspace", TilePosition(-1, 0)), nullptr); + EXPECT_EQ(manager.getMesh(mWorldspace, TilePosition(-1, -1)), nullptr); + EXPECT_EQ(manager.getMesh(mWorldspace, TilePosition(-1, 0)), nullptr); manager.updateObject(ObjectId(&boxShape), btTransform::getIdentity(), AreaType::AreaType_ground, nullptr); - EXPECT_EQ(manager.getMesh("worldspace", TilePosition(1, 0)), nullptr); - EXPECT_EQ(manager.getMesh("worldspace", TilePosition(1, -1)), nullptr); + EXPECT_EQ(manager.getMesh(mWorldspace, TilePosition(1, 0)), nullptr); + EXPECT_EQ(manager.getMesh(mWorldspace, TilePosition(1, -1)), nullptr); } TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, get_mesh_for_removed_object_should_return_nullptr_for_all_previously_used_tiles) { TileCachedRecastMeshManager manager(mSettings); - manager.setWorldspace("worldspace", nullptr); + manager.setWorldspace(mWorldspace, nullptr); const btBoxShape boxShape(btVector3(20, 20, 100)); const CollisionShape shape(mInstance, boxShape, mObjectTransform); manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground, nullptr); manager.removeObject(ObjectId(&boxShape), nullptr); - EXPECT_EQ(manager.getMesh("worldspace", TilePosition(-1, -1)), nullptr); - EXPECT_EQ(manager.getMesh("worldspace", TilePosition(-1, 0)), nullptr); - EXPECT_EQ(manager.getMesh("worldspace", TilePosition(0, -1)), nullptr); - EXPECT_EQ(manager.getMesh("worldspace", TilePosition(0, 0)), nullptr); + EXPECT_EQ(manager.getMesh(mWorldspace, TilePosition(-1, -1)), nullptr); + EXPECT_EQ(manager.getMesh(mWorldspace, TilePosition(-1, 0)), nullptr); + EXPECT_EQ(manager.getMesh(mWorldspace, TilePosition(0, -1)), nullptr); + EXPECT_EQ(manager.getMesh(mWorldspace, TilePosition(0, 0)), nullptr); } TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, get_mesh_for_not_changed_object_after_update_should_return_recast_mesh_for_same_tiles) { TileCachedRecastMeshManager manager(mSettings); - manager.setWorldspace("worldspace", nullptr); + manager.setWorldspace(mWorldspace, nullptr); const btBoxShape boxShape(btVector3(20, 20, 100)); const CollisionShape shape(mInstance, boxShape, mObjectTransform); manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground, nullptr); - EXPECT_NE(manager.getMesh("worldspace", TilePosition(-1, -1)), nullptr); - EXPECT_NE(manager.getMesh("worldspace", TilePosition(-1, 0)), nullptr); - EXPECT_NE(manager.getMesh("worldspace", TilePosition(0, -1)), nullptr); - EXPECT_NE(manager.getMesh("worldspace", TilePosition(0, 0)), nullptr); + EXPECT_NE(manager.getMesh(mWorldspace, TilePosition(-1, -1)), nullptr); + EXPECT_NE(manager.getMesh(mWorldspace, TilePosition(-1, 0)), nullptr); + EXPECT_NE(manager.getMesh(mWorldspace, TilePosition(0, -1)), nullptr); + EXPECT_NE(manager.getMesh(mWorldspace, TilePosition(0, 0)), nullptr); manager.updateObject(ObjectId(&boxShape), btTransform::getIdentity(), AreaType::AreaType_ground, nullptr); - EXPECT_NE(manager.getMesh("worldspace", TilePosition(-1, -1)), nullptr); - EXPECT_NE(manager.getMesh("worldspace", TilePosition(-1, 0)), nullptr); - EXPECT_NE(manager.getMesh("worldspace", TilePosition(0, -1)), nullptr); - EXPECT_NE(manager.getMesh("worldspace", TilePosition(0, 0)), nullptr); + EXPECT_NE(manager.getMesh(mWorldspace, TilePosition(-1, -1)), nullptr); + EXPECT_NE(manager.getMesh(mWorldspace, TilePosition(-1, 0)), nullptr); + EXPECT_NE(manager.getMesh(mWorldspace, TilePosition(0, -1)), nullptr); + EXPECT_NE(manager.getMesh(mWorldspace, TilePosition(0, 0)), nullptr); } TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, @@ -293,7 +294,7 @@ namespace get_revision_after_update_not_changed_object_should_return_same_value) { TileCachedRecastMeshManager manager(mSettings); - manager.setWorldspace("worldspace", nullptr); + manager.setWorldspace(mWorldspace, nullptr); const btBoxShape boxShape(btVector3(20, 20, 100)); const CollisionShape shape(mInstance, boxShape, mObjectTransform); manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground, nullptr); @@ -339,19 +340,19 @@ namespace TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, add_water_for_not_max_int_should_add_new_tiles) { TileCachedRecastMeshManager manager(mSettings); - manager.setWorldspace("worldspace", nullptr); + manager.setWorldspace(mWorldspace, nullptr); const osg::Vec2i cellPosition(0, 0); const int cellSize = 8192; manager.addWater(cellPosition, cellSize, 0.0f, nullptr); for (int x = -1; x < 12; ++x) for (int y = -1; y < 12; ++y) - ASSERT_NE(manager.getMesh("worldspace", TilePosition(x, y)), nullptr); + ASSERT_NE(manager.getMesh(mWorldspace, TilePosition(x, y)), nullptr); } TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, add_water_for_max_int_should_not_add_new_tiles) { TileCachedRecastMeshManager manager(mSettings); - manager.setWorldspace("worldspace", nullptr); + manager.setWorldspace(mWorldspace, nullptr); const btBoxShape boxShape(btVector3(20, 20, 100)); const CollisionShape shape(mInstance, boxShape, mObjectTransform); ASSERT_TRUE(manager.addObject( @@ -361,7 +362,7 @@ namespace manager.addWater(cellPosition, cellSize, 0.0f, nullptr); for (int x = -6; x < 6; ++x) for (int y = -6; y < 6; ++y) - ASSERT_EQ(manager.getMesh("worldspace", TilePosition(x, y)) != nullptr, + ASSERT_EQ(manager.getMesh(mWorldspace, TilePosition(x, y)) != nullptr, -1 <= x && x <= 0 && -1 <= y && y <= 0); } @@ -390,20 +391,20 @@ namespace TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, remove_water_for_existing_cell_should_remove_empty_tiles) { TileCachedRecastMeshManager manager(mSettings); - manager.setWorldspace("worldspace", nullptr); + manager.setWorldspace(mWorldspace, nullptr); const osg::Vec2i cellPosition(0, 0); const int cellSize = 8192; manager.addWater(cellPosition, cellSize, 0.0f, nullptr); manager.removeWater(cellPosition, nullptr); for (int x = -6; x < 6; ++x) for (int y = -6; y < 6; ++y) - ASSERT_EQ(manager.getMesh("worldspace", TilePosition(x, y)), nullptr); + ASSERT_EQ(manager.getMesh(mWorldspace, TilePosition(x, y)), nullptr); } TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, remove_water_for_existing_cell_should_leave_not_empty_tiles) { TileCachedRecastMeshManager manager(mSettings); - manager.setWorldspace("worldspace", nullptr); + manager.setWorldspace(mWorldspace, nullptr); const btBoxShape boxShape(btVector3(20, 20, 100)); const CollisionShape shape(mInstance, boxShape, mObjectTransform); ASSERT_TRUE(manager.addObject( @@ -414,14 +415,14 @@ namespace manager.removeWater(cellPosition, nullptr); for (int x = -6; x < 6; ++x) for (int y = -6; y < 6; ++y) - ASSERT_EQ(manager.getMesh("worldspace", TilePosition(x, y)) != nullptr, + ASSERT_EQ(manager.getMesh(mWorldspace, TilePosition(x, y)) != nullptr, -1 <= x && x <= 0 && -1 <= y && y <= 0); } TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, remove_object_should_not_remove_tile_with_water) { TileCachedRecastMeshManager manager(mSettings); - manager.setWorldspace("worldspace", nullptr); + manager.setWorldspace(mWorldspace, nullptr); const osg::Vec2i cellPosition(0, 0); const int cellSize = 8192; const btBoxShape boxShape(btVector3(20, 20, 100)); @@ -432,21 +433,22 @@ namespace manager.removeObject(ObjectId(&boxShape), nullptr); for (int x = -1; x < 12; ++x) for (int y = -1; y < 12; ++y) - ASSERT_NE(manager.getMesh("worldspace", TilePosition(x, y)), nullptr); + ASSERT_NE(manager.getMesh(mWorldspace, TilePosition(x, y)), nullptr); } TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, set_new_worldspace_should_remove_tiles) { TileCachedRecastMeshManager manager(mSettings); - manager.setWorldspace("worldspace", nullptr); + manager.setWorldspace(mWorldspace, nullptr); const btBoxShape boxShape(btVector3(20, 20, 100)); const CollisionShape shape(nullptr, boxShape, mObjectTransform); ASSERT_TRUE(manager.addObject( ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground, nullptr)); - manager.setWorldspace("other", nullptr); + const ESM::RefId otherWorldspace(ESM::FormId::fromUint32(0x1)); + manager.setWorldspace(ESM::FormId::fromUint32(0x1), nullptr); for (int x = -1; x < 1; ++x) for (int y = -1; y < 1; ++y) - ASSERT_EQ(manager.getMesh("other", TilePosition(x, y)), nullptr); + ASSERT_EQ(manager.getMesh(otherWorldspace, TilePosition(x, y)), nullptr); } TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, set_range_should_add_changed_tiles) @@ -475,8 +477,7 @@ namespace { TileCachedRecastMeshManager manager(mSettings); - const std::string_view worldspace = "worldspace"; - manager.setWorldspace(worldspace, nullptr); + manager.setWorldspace(mWorldspace, nullptr); const btBoxShape boxShape(btVector3(100, 100, 20)); const CollisionShape shape(mInstance, boxShape, mObjectTransform); @@ -489,9 +490,9 @@ namespace const TilePosition tilePosition(0, 0); - ASSERT_EQ(manager.getCachedMesh(worldspace, tilePosition), nullptr); - ASSERT_NE(manager.getMesh(worldspace, tilePosition), nullptr); - ASSERT_NE(manager.getCachedMesh(worldspace, tilePosition), nullptr); + ASSERT_EQ(manager.getCachedMesh(mWorldspace, tilePosition), nullptr); + ASSERT_NE(manager.getMesh(mWorldspace, tilePosition), nullptr); + ASSERT_NE(manager.getCachedMesh(mWorldspace, tilePosition), nullptr); const TilesPositionsRange range2{ .mBegin = TilePosition(-1, -1), @@ -500,6 +501,6 @@ namespace manager.takeChangedTiles(nullptr); manager.setRange(range2, nullptr); - ASSERT_EQ(manager.getCachedMesh(worldspace, tilePosition), nullptr); + ASSERT_EQ(manager.getCachedMesh(mWorldspace, tilePosition), nullptr); } } diff --git a/components/detournavigator/asyncnavmeshupdater.cpp b/components/detournavigator/asyncnavmeshupdater.cpp index fe6d0625f5..24d7cc0d32 100644 --- a/components/detournavigator/asyncnavmeshupdater.cpp +++ b/components/detournavigator/asyncnavmeshupdater.cpp @@ -91,7 +91,7 @@ namespace DetourNavigator } Job::Job(const AgentBounds& agentBounds, std::weak_ptr navMeshCacheItem, - std::string_view worldspace, const TilePosition& changedTile, ChangeType changeType, + ESM::RefId worldspace, const TilePosition& changedTile, ChangeType changeType, std::chrono::steady_clock::time_point processTime) : mId(getNextJobId()) , mAgentBounds(agentBounds) @@ -261,8 +261,7 @@ namespace DetourNavigator } void AsyncNavMeshUpdater::post(const AgentBounds& agentBounds, const SharedNavMeshCacheItem& navMeshCacheItem, - const TilePosition& playerTile, std::string_view worldspace, - const std::map& changedTiles) + const TilePosition& playerTile, ESM::RefId worldspace, const std::map& changedTiles) { bool playerTileChanged = false; { diff --git a/components/detournavigator/asyncnavmeshupdater.hpp b/components/detournavigator/asyncnavmeshupdater.hpp index f3d624a8a6..a4c446afc9 100644 --- a/components/detournavigator/asyncnavmeshupdater.hpp +++ b/components/detournavigator/asyncnavmeshupdater.hpp @@ -50,7 +50,7 @@ namespace DetourNavigator const std::size_t mId; const AgentBounds mAgentBounds; const std::weak_ptr mNavMeshCacheItem; - const std::string mWorldspace; + const ESM::RefId mWorldspace; const TilePosition mChangedTile; std::chrono::steady_clock::time_point mProcessTime; ChangeType mChangeType; @@ -61,7 +61,7 @@ namespace DetourNavigator std::unique_ptr mGeneratedNavMeshData; Job(const AgentBounds& agentBounds, std::weak_ptr navMeshCacheItem, - std::string_view worldspace, const TilePosition& changedTile, ChangeType changeType, + ESM::RefId worldspace, const TilePosition& changedTile, ChangeType changeType, std::chrono::steady_clock::time_point processTime); }; @@ -199,7 +199,7 @@ namespace DetourNavigator ~AsyncNavMeshUpdater(); void post(const AgentBounds& agentBounds, const SharedNavMeshCacheItem& navMeshCacheItem, - const TilePosition& playerTile, std::string_view worldspace, + const TilePosition& playerTile, ESM::RefId worldspace, const std::map& changedTiles); void wait(WaitConditionType waitConditionType, Loading::Listener* listener); diff --git a/components/detournavigator/generatenavmeshtile.cpp b/components/detournavigator/generatenavmeshtile.cpp index a96a554302..118114181e 100644 --- a/components/detournavigator/generatenavmeshtile.cpp +++ b/components/detournavigator/generatenavmeshtile.cpp @@ -22,7 +22,7 @@ namespace DetourNavigator { struct Ignore { - std::string_view mWorldspace; + ESM::RefId mWorldspace; const TilePosition& mTilePosition; std::shared_ptr mConsumer; @@ -34,10 +34,10 @@ namespace DetourNavigator }; } - GenerateNavMeshTile::GenerateNavMeshTile(std::string worldspace, const TilePosition& tilePosition, + GenerateNavMeshTile::GenerateNavMeshTile(ESM::RefId worldspace, const TilePosition& tilePosition, RecastMeshProvider recastMeshProvider, const AgentBounds& agentBounds, const DetourNavigator::Settings& settings, std::weak_ptr consumer) - : mWorldspace(std::move(worldspace)) + : mWorldspace(worldspace) , mTilePosition(tilePosition) , mRecastMeshProvider(recastMeshProvider) , mAgentBounds(agentBounds) diff --git a/components/detournavigator/generatenavmeshtile.hpp b/components/detournavigator/generatenavmeshtile.hpp index c132ef6160..76ef55ce56 100644 --- a/components/detournavigator/generatenavmeshtile.hpp +++ b/components/detournavigator/generatenavmeshtile.hpp @@ -35,18 +35,18 @@ namespace DetourNavigator virtual std::int64_t resolveMeshSource(const MeshSource& source) = 0; virtual std::optional find( - std::string_view worldspace, const TilePosition& tilePosition, const std::vector& input) + ESM::RefId worldspace, const TilePosition& tilePosition, const std::vector& input) = 0; - virtual void ignore(std::string_view worldspace, const TilePosition& tilePosition) = 0; + virtual void ignore(ESM::RefId worldspace, const TilePosition& tilePosition) = 0; - virtual void identity(std::string_view worldspace, const TilePosition& tilePosition, std::int64_t tileId) = 0; + virtual void identity(ESM::RefId worldspace, const TilePosition& tilePosition, std::int64_t tileId) = 0; - virtual void insert(std::string_view worldspace, const TilePosition& tilePosition, std::int64_t version, + virtual void insert(ESM::RefId worldspace, const TilePosition& tilePosition, std::int64_t version, const std::vector& input, PreparedNavMeshData& data) = 0; - virtual void update(std::string_view worldspace, const TilePosition& tilePosition, std::int64_t tileId, + virtual void update(ESM::RefId worldspace, const TilePosition& tilePosition, std::int64_t tileId, std::int64_t version, PreparedNavMeshData& data) = 0; @@ -56,14 +56,14 @@ namespace DetourNavigator class GenerateNavMeshTile final : public SceneUtil::WorkItem { public: - GenerateNavMeshTile(std::string worldspace, const TilePosition& tilePosition, + GenerateNavMeshTile(ESM::RefId worldspace, const TilePosition& tilePosition, RecastMeshProvider recastMeshProvider, const AgentBounds& agentBounds, const Settings& settings, std::weak_ptr consumer); void doWork() final; private: - const std::string mWorldspace; + const ESM::RefId mWorldspace; const TilePosition mTilePosition; const RecastMeshProvider mRecastMeshProvider; const AgentBounds mAgentBounds; diff --git a/components/detournavigator/makenavmesh.cpp b/components/detournavigator/makenavmesh.cpp index e143bf1837..f037da69f8 100644 --- a/components/detournavigator/makenavmesh.cpp +++ b/components/detournavigator/makenavmesh.cpp @@ -520,9 +520,8 @@ namespace DetourNavigator } } - std::unique_ptr prepareNavMeshTileData(const RecastMesh& recastMesh, - std::string_view worldspace, const TilePosition& tilePosition, const AgentBounds& agentBounds, - const RecastSettings& settings) + std::unique_ptr prepareNavMeshTileData(const RecastMesh& recastMesh, ESM::RefId worldspace, + const TilePosition& tilePosition, const AgentBounds& agentBounds, const RecastSettings& settings) { RecastContext context(worldspace, tilePosition, agentBounds); diff --git a/components/detournavigator/makenavmesh.hpp b/components/detournavigator/makenavmesh.hpp index 25bbca6d3c..d78f946230 100644 --- a/components/detournavigator/makenavmesh.hpp +++ b/components/detournavigator/makenavmesh.hpp @@ -4,6 +4,8 @@ #include "recastmesh.hpp" #include "tileposition.hpp" +#include + #include #include @@ -41,9 +43,8 @@ namespace DetourNavigator && recastMesh.getHeightfields().empty() && recastMesh.getFlatHeightfields().empty(); } - std::unique_ptr prepareNavMeshTileData(const RecastMesh& recastMesh, - std::string_view worldspace, const TilePosition& tilePosition, const AgentBounds& agentBounds, - const RecastSettings& settings); + std::unique_ptr prepareNavMeshTileData(const RecastMesh& recastMesh, ESM::RefId worldspace, + const TilePosition& tilePosition, const AgentBounds& agentBounds, const RecastSettings& settings); NavMeshData makeNavMeshTileData(const PreparedNavMeshData& data, const std::vector& offMeshConnections, const AgentBounds& agentBounds, diff --git a/components/detournavigator/navigator.hpp b/components/detournavigator/navigator.hpp index 378af081d0..7bab0af4d1 100644 --- a/components/detournavigator/navigator.hpp +++ b/components/detournavigator/navigator.hpp @@ -91,7 +91,7 @@ namespace DetourNavigator * @brief setWorldspace should be called before adding object from new worldspace * @param worldspace */ - virtual void setWorldspace(std::string_view worldspace, const UpdateGuard* guard) = 0; + virtual void setWorldspace(ESM::RefId worldspace, const UpdateGuard* guard) = 0; /** * @brief updateBounds should be called before adding object from loading cell diff --git a/components/detournavigator/navigatorimpl.cpp b/components/detournavigator/navigatorimpl.cpp index 514a70b336..443a98a678 100644 --- a/components/detournavigator/navigatorimpl.cpp +++ b/components/detournavigator/navigatorimpl.cpp @@ -33,7 +33,7 @@ namespace DetourNavigator --it->second; } - void NavigatorImpl::setWorldspace(std::string_view worldspace, const UpdateGuard* guard) + void NavigatorImpl::setWorldspace(ESM::RefId worldspace, const UpdateGuard* guard) { mNavMeshManager.setWorldspace(worldspace, guard); } diff --git a/components/detournavigator/navigatorimpl.hpp b/components/detournavigator/navigatorimpl.hpp index 1439a89f28..e9f7276172 100644 --- a/components/detournavigator/navigatorimpl.hpp +++ b/components/detournavigator/navigatorimpl.hpp @@ -8,7 +8,6 @@ #include #include #include -#include #include namespace DetourNavigator @@ -28,7 +27,7 @@ namespace DetourNavigator void removeAgent(const AgentBounds& agentBounds) override; - void setWorldspace(std::string_view worldspace, const UpdateGuard* guard) override; + void setWorldspace(ESM::RefId worldspace, const UpdateGuard* guard) override; void updateBounds(const osg::Vec3f& playerPosition, const UpdateGuard* guard) override; diff --git a/components/detournavigator/navigatorstub.hpp b/components/detournavigator/navigatorstub.hpp index 7b93811c15..bc14e2274c 100644 --- a/components/detournavigator/navigatorstub.hpp +++ b/components/detournavigator/navigatorstub.hpp @@ -24,7 +24,7 @@ namespace DetourNavigator void removeAgent(const AgentBounds& /*agentBounds*/) override {} - void setWorldspace(std::string_view /*worldspace*/, const UpdateGuard* /*guard*/) override {} + void setWorldspace(ESM::RefId /*worldspace*/, const UpdateGuard* /*guard*/) override {} void addObject(const ObjectId /*id*/, const ObjectShapes& /*shapes*/, const btTransform& /*transform*/, const UpdateGuard* /*guard*/) override diff --git a/components/detournavigator/navmeshdb.cpp b/components/detournavigator/navmeshdb.cpp index d5c6fdb46b..76f0811f16 100644 --- a/components/detournavigator/navmeshdb.cpp +++ b/components/detournavigator/navmeshdb.cpp @@ -200,34 +200,35 @@ namespace DetourNavigator } std::optional NavMeshDb::findTile( - std::string_view worldspace, const TilePosition& tilePosition, const std::vector& input) + ESM::RefId worldspace, const TilePosition& tilePosition, const std::vector& input) { Tile result; auto row = std::tie(result.mTileId, result.mVersion); const std::vector compressedInput = Misc::compress(input); - if (&row == request(*mDb, mFindTile, &row, 1, worldspace, tilePosition, compressedInput)) + if (&row == request(*mDb, mFindTile, &row, 1, worldspace.serializeText(), tilePosition, compressedInput)) return {}; return result; } std::optional NavMeshDb::getTileData( - std::string_view worldspace, const TilePosition& tilePosition, const std::vector& input) + ESM::RefId worldspace, const TilePosition& tilePosition, const std::vector& input) { TileData result; auto row = std::tie(result.mTileId, result.mVersion, result.mData); const std::vector compressedInput = Misc::compress(input); - if (&row == request(*mDb, mGetTileData, &row, 1, worldspace, tilePosition, compressedInput)) + if (&row == request(*mDb, mGetTileData, &row, 1, worldspace.serializeText(), tilePosition, compressedInput)) return {}; result.mData = Misc::decompress(result.mData); return result; } - int NavMeshDb::insertTile(TileId tileId, std::string_view worldspace, const TilePosition& tilePosition, + int NavMeshDb::insertTile(TileId tileId, ESM::RefId worldspace, const TilePosition& tilePosition, TileVersion version, const std::vector& input, const std::vector& data) { const std::vector compressedInput = Misc::compress(input); const std::vector compressedData = Misc::compress(data); - return execute(*mDb, mInsertTile, tileId, worldspace, tilePosition, version, compressedInput, compressedData); + return execute(*mDb, mInsertTile, tileId, worldspace.serializeText(), tilePosition, version, compressedInput, + compressedData); } int NavMeshDb::updateTile(TileId tileId, TileVersion version, const std::vector& data) @@ -236,20 +237,19 @@ namespace DetourNavigator return execute(*mDb, mUpdateTile, tileId, version, compressedData); } - int NavMeshDb::deleteTilesAt(std::string_view worldspace, const TilePosition& tilePosition) + int NavMeshDb::deleteTilesAt(ESM::RefId worldspace, const TilePosition& tilePosition) { - return execute(*mDb, mDeleteTilesAt, worldspace, tilePosition); + return execute(*mDb, mDeleteTilesAt, worldspace.serializeText(), tilePosition); } - int NavMeshDb::deleteTilesAtExcept( - std::string_view worldspace, const TilePosition& tilePosition, TileId excludeTileId) + int NavMeshDb::deleteTilesAtExcept(ESM::RefId worldspace, const TilePosition& tilePosition, TileId excludeTileId) { - return execute(*mDb, mDeleteTilesAtExcept, worldspace, tilePosition, excludeTileId); + return execute(*mDb, mDeleteTilesAtExcept, worldspace.serializeText(), tilePosition, excludeTileId); } - int NavMeshDb::deleteTilesOutsideRange(std::string_view worldspace, const TilesPositionsRange& range) + int NavMeshDb::deleteTilesOutsideRange(ESM::RefId worldspace, const TilesPositionsRange& range) { - return execute(*mDb, mDeleteTilesOutsideRange, worldspace, range); + return execute(*mDb, mDeleteTilesOutsideRange, worldspace.serializeText(), range); } ShapeId NavMeshDb::getMaxShapeId() diff --git a/components/detournavigator/navmeshdb.hpp b/components/detournavigator/navmeshdb.hpp index 3cf1bdcdca..9918dca9f5 100644 --- a/components/detournavigator/navmeshdb.hpp +++ b/components/detournavigator/navmeshdb.hpp @@ -2,10 +2,10 @@ #define OPENMW_COMPONENTS_DETOURNAVIGATOR_NAVMESHDB_H #include "tileposition.hpp" +#include "tilespositionsrange.hpp" -#include +#include #include - #include #include #include @@ -13,13 +13,8 @@ #include #include -#include -#include #include -#include #include -#include -#include #include struct sqlite3; @@ -148,21 +143,21 @@ namespace DetourNavigator TileId getMaxTileId(); std::optional findTile( - std::string_view worldspace, const TilePosition& tilePosition, const std::vector& input); + ESM::RefId worldspace, const TilePosition& tilePosition, const std::vector& input); std::optional getTileData( - std::string_view worldspace, const TilePosition& tilePosition, const std::vector& input); + ESM::RefId worldspace, const TilePosition& tilePosition, const std::vector& input); - int insertTile(TileId tileId, std::string_view worldspace, const TilePosition& tilePosition, - TileVersion version, const std::vector& input, const std::vector& data); + int insertTile(TileId tileId, ESM::RefId worldspace, const TilePosition& tilePosition, TileVersion version, + const std::vector& input, const std::vector& data); int updateTile(TileId tileId, TileVersion version, const std::vector& data); - int deleteTilesAt(std::string_view worldspace, const TilePosition& tilePosition); + int deleteTilesAt(ESM::RefId worldspace, const TilePosition& tilePosition); - int deleteTilesAtExcept(std::string_view worldspace, const TilePosition& tilePosition, TileId excludeTileId); + int deleteTilesAtExcept(ESM::RefId worldspace, const TilePosition& tilePosition, TileId excludeTileId); - int deleteTilesOutsideRange(std::string_view worldspace, const TilesPositionsRange& range); + int deleteTilesOutsideRange(ESM::RefId worldspace, const TilesPositionsRange& range); ShapeId getMaxShapeId(); diff --git a/components/detournavigator/navmeshmanager.cpp b/components/detournavigator/navmeshmanager.cpp index bb0a8e3451..7a2fd74714 100644 --- a/components/detournavigator/navmeshmanager.cpp +++ b/components/detournavigator/navmeshmanager.cpp @@ -58,7 +58,7 @@ namespace DetourNavigator { } - void NavMeshManager::setWorldspace(std::string_view worldspace, const UpdateGuard* guard) + void NavMeshManager::setWorldspace(ESM::RefId worldspace, const UpdateGuard* guard) { if (worldspace == mWorldspace) return; diff --git a/components/detournavigator/navmeshmanager.hpp b/components/detournavigator/navmeshmanager.hpp index b50d6fb9f2..6c25cc599f 100644 --- a/components/detournavigator/navmeshmanager.hpp +++ b/components/detournavigator/navmeshmanager.hpp @@ -24,7 +24,7 @@ namespace DetourNavigator ScopedUpdateGuard makeUpdateGuard() { return mRecastMeshManager.makeUpdateGuard(); } - void setWorldspace(std::string_view worldspace, const UpdateGuard* guard); + void setWorldspace(ESM::RefId worldspace, const UpdateGuard* guard); void updateBounds(const osg::Vec3f& playerPosition, const UpdateGuard* guard); @@ -67,7 +67,7 @@ namespace DetourNavigator private: const Settings& mSettings; - std::string mWorldspace; + ESM::RefId mWorldspace; TileCachedRecastMeshManager mRecastMeshManager; OffMeshConnectionsManager mOffMeshConnectionsManager; AsyncNavMeshUpdater mAsyncNavMeshUpdater; diff --git a/components/detournavigator/recastcontext.cpp b/components/detournavigator/recastcontext.cpp index 7ac7bcb66e..225f251f4d 100644 --- a/components/detournavigator/recastcontext.cpp +++ b/components/detournavigator/recastcontext.cpp @@ -24,7 +24,7 @@ namespace DetourNavigator } std::string formatPrefix( - std::string_view worldspace, const TilePosition& tilePosition, const AgentBounds& agentBounds) + ESM::RefId worldspace, const TilePosition& tilePosition, const AgentBounds& agentBounds) { std::ostringstream stream; stream << "Worldspace: " << worldspace << "; tile position: " << tilePosition.x() << ", " @@ -34,7 +34,7 @@ namespace DetourNavigator } RecastContext::RecastContext( - std::string_view worldspace, const TilePosition& tilePosition, const AgentBounds& agentBounds) + ESM::RefId worldspace, const TilePosition& tilePosition, const AgentBounds& agentBounds) : mPrefix(formatPrefix(worldspace, tilePosition, agentBounds)) { } diff --git a/components/detournavigator/recastcontext.hpp b/components/detournavigator/recastcontext.hpp index 3d65bbe95a..8e75f50b34 100644 --- a/components/detournavigator/recastcontext.hpp +++ b/components/detournavigator/recastcontext.hpp @@ -3,6 +3,8 @@ #include "tileposition.hpp" +#include + #include #include @@ -14,8 +16,7 @@ namespace DetourNavigator class RecastContext final : public rcContext { public: - explicit RecastContext( - std::string_view worldspace, const TilePosition& tilePosition, const AgentBounds& agentBounds); + explicit RecastContext(ESM::RefId worldspace, const TilePosition& tilePosition, const AgentBounds& agentBounds); const std::string& getPrefix() const { return mPrefix; } diff --git a/components/detournavigator/recastmeshprovider.hpp b/components/detournavigator/recastmeshprovider.hpp index d0cba1c348..6759daa65a 100644 --- a/components/detournavigator/recastmeshprovider.hpp +++ b/components/detournavigator/recastmeshprovider.hpp @@ -20,7 +20,7 @@ namespace DetourNavigator { } - std::shared_ptr getMesh(std::string_view worldspace, const TilePosition& tilePosition) const + std::shared_ptr getMesh(ESM::RefId worldspace, const TilePosition& tilePosition) const { return mImpl.get().getNewMesh(worldspace, tilePosition); } diff --git a/components/detournavigator/tilecachedrecastmeshmanager.cpp b/components/detournavigator/tilecachedrecastmeshmanager.cpp index a34ac8e795..5cb95fed64 100644 --- a/components/detournavigator/tilecachedrecastmeshmanager.cpp +++ b/components/detournavigator/tilecachedrecastmeshmanager.cpp @@ -142,7 +142,7 @@ namespace DetourNavigator return {}; } - void TileCachedRecastMeshManager::setWorldspace(std::string_view worldspace, const UpdateGuard* guard) + void TileCachedRecastMeshManager::setWorldspace(ESM::RefId worldspace, const UpdateGuard* guard) { const MaybeLockGuard lock(mMutex, guard); if (mWorldspace == worldspace) @@ -351,7 +351,7 @@ namespace DetourNavigator } std::shared_ptr TileCachedRecastMeshManager::getMesh( - std::string_view worldspace, const TilePosition& tilePosition) + ESM::RefId worldspace, const TilePosition& tilePosition) { { const std::lock_guard lock(mMutex); @@ -375,7 +375,7 @@ namespace DetourNavigator } std::shared_ptr TileCachedRecastMeshManager::getCachedMesh( - std::string_view worldspace, const TilePosition& tilePosition) const + ESM::RefId worldspace, const TilePosition& tilePosition) const { const std::lock_guard lock(mMutex); if (mWorldspace != worldspace) @@ -387,7 +387,7 @@ namespace DetourNavigator } std::shared_ptr TileCachedRecastMeshManager::getNewMesh( - std::string_view worldspace, const TilePosition& tilePosition) const + ESM::RefId worldspace, const TilePosition& tilePosition) const { { const std::lock_guard lock(mMutex); diff --git a/components/detournavigator/tilecachedrecastmeshmanager.hpp b/components/detournavigator/tilecachedrecastmeshmanager.hpp index 553e664a5f..fc4ace118d 100644 --- a/components/detournavigator/tilecachedrecastmeshmanager.hpp +++ b/components/detournavigator/tilecachedrecastmeshmanager.hpp @@ -25,8 +25,6 @@ #include #include #include -#include -#include #include namespace DetourNavigator @@ -49,7 +47,7 @@ namespace DetourNavigator TilesPositionsRange getLimitedObjectsRange() const; - void setWorldspace(std::string_view worldspace, const UpdateGuard* guard); + void setWorldspace(ESM::RefId worldspace, const UpdateGuard* guard); bool addObject(ObjectId id, const CollisionShape& shape, const btTransform& transform, AreaType areaType, const UpdateGuard* guard); @@ -67,11 +65,11 @@ namespace DetourNavigator void removeHeightfield(const osg::Vec2i& cellPosition, const UpdateGuard* guard); - std::shared_ptr getMesh(std::string_view worldspace, const TilePosition& tilePosition); + std::shared_ptr getMesh(ESM::RefId worldspace, const TilePosition& tilePosition); - std::shared_ptr getCachedMesh(std::string_view worldspace, const TilePosition& tilePosition) const; + std::shared_ptr getCachedMesh(ESM::RefId worldspace, const TilePosition& tilePosition) const; - std::shared_ptr getNewMesh(std::string_view worldspace, const TilePosition& tilePosition) const; + std::shared_ptr getNewMesh(ESM::RefId worldspace, const TilePosition& tilePosition) const; std::size_t getRevision() const { return mRevision; } @@ -130,7 +128,7 @@ namespace DetourNavigator const RecastSettings& mSettings; TilesPositionsRange mRange; - std::string mWorldspace; + ESM::RefId mWorldspace; std::unordered_map> mObjects; boost::geometry::index::rtree> mObjectIndex; std::map mWater; From 49db37ee292742ae42a951452f28d82b08929351 Mon Sep 17 00:00:00 2001 From: elsid Date: Sun, 19 May 2024 15:38:47 +0200 Subject: [PATCH 5/6] Merge setWorldspace and updateBounds --- apps/openmw/mwworld/scene.cpp | 13 ++++------ .../detournavigator/navigator.cpp | 26 ++++++------------- components/detournavigator/navigator.hpp | 15 +++-------- components/detournavigator/navigatorimpl.cpp | 9 ++----- components/detournavigator/navigatorimpl.hpp | 4 +-- components/detournavigator/navigatorstub.hpp | 7 ++--- components/detournavigator/navmeshmanager.cpp | 18 ++++++------- components/detournavigator/navmeshmanager.hpp | 4 +-- 8 files changed, 33 insertions(+), 63 deletions(-) diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index e3b9419035..2465f165b9 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -591,8 +591,8 @@ namespace MWWorld else unloadCell(cell, navigatorUpdateGuard.get()); } - mNavigator.setWorldspace(playerCellIndex.mWorldspace, navigatorUpdateGuard.get()); - mNavigator.updateBounds(pos, navigatorUpdateGuard.get()); + + mNavigator.updateBounds(playerCellIndex.mWorldspace, pos, navigatorUpdateGuard.get()); mCurrentGridCenter = osg::Vec2i(playerCellX, playerCellY); osg::Vec4i newGrid = gridCenterToBounds(mCurrentGridCenter); @@ -694,10 +694,9 @@ namespace MWWorld CellStore& cell = mWorld.getWorldModel().getExterior( ESM::ExteriorCellLocation(it->mData.mX, it->mData.mY, ESM::Cell::sDefaultWorldspaceId)); - mNavigator.setWorldspace(cell.getCell()->getWorldSpace(), navigatorUpdateGuard.get()); const osg::Vec3f position = osg::Vec3f(it->mData.mX + 0.5f, it->mData.mY + 0.5f, 0) * Constants::CellSizeInUnits; - mNavigator.updateBounds(position, navigatorUpdateGuard.get()); + mNavigator.updateBounds(ESM::Cell::sDefaultWorldspaceId, position, navigatorUpdateGuard.get()); loadCell(cell, nullptr, false, position, navigatorUpdateGuard.get()); mNavigator.update(position, navigatorUpdateGuard.get()); @@ -751,10 +750,9 @@ namespace MWWorld + std::to_string(cells.getIntSize()) + ")..."); CellStore& cell = mWorld.getWorldModel().getInterior(it->mName); - mNavigator.setWorldspace(cell.getCell()->getWorldSpace(), navigatorUpdateGuard.get()); ESM::Position position; mWorld.findInteriorPosition(it->mName, position); - mNavigator.updateBounds(position.asVec3(), navigatorUpdateGuard.get()); + mNavigator.updateBounds(cell.getCell()->getWorldSpace(), position.asVec3(), navigatorUpdateGuard.get()); loadCell(cell, nullptr, false, position.asVec3(), navigatorUpdateGuard.get()); mNavigator.update(position.asVec3(), navigatorUpdateGuard.get()); @@ -904,8 +902,7 @@ namespace MWWorld loadingListener->setProgressRange(cell.count()); - mNavigator.setWorldspace(cell.getCell()->getWorldSpace(), navigatorUpdateGuard.get()); - mNavigator.updateBounds(position.asVec3(), navigatorUpdateGuard.get()); + mNavigator.updateBounds(cell.getCell()->getWorldSpace(), position.asVec3(), navigatorUpdateGuard.get()); // Load cell. mPagedRefs.clear(); diff --git a/apps/openmw_test_suite/detournavigator/navigator.cpp b/apps/openmw_test_suite/detournavigator/navigator.cpp index 6dcade083a..c53ff2cc37 100644 --- a/apps/openmw_test_suite/detournavigator/navigator.cpp +++ b/apps/openmw_test_suite/detournavigator/navigator.cpp @@ -44,31 +44,21 @@ namespace struct DetourNavigatorNavigatorTest : Test { Settings mSettings = makeSettings(); - std::unique_ptr mNavigator; - const osg::Vec3f mPlayerPosition; - const std::string mWorldspace; + std::unique_ptr mNavigator = std::make_unique( + mSettings, std::make_unique(":memory:", std::numeric_limits::max())); + const osg::Vec3f mPlayerPosition{ 256, 256, 0 }; + const ESM::RefId mWorldspace = ESM::RefId::stringRefId("sys::default"); const AgentBounds mAgentBounds{ CollisionShapeType::Aabb, { 29, 29, 66 } }; - osg::Vec3f mStart; - osg::Vec3f mEnd; + osg::Vec3f mStart{ 52, 460, 1 }; + osg::Vec3f mEnd{ 460, 52, 1 }; std::deque mPath; - std::back_insert_iterator> mOut; + std::back_insert_iterator> mOut{ mPath }; AreaCosts mAreaCosts; Loading::Listener mListener; const osg::Vec2i mCellPosition{ 0, 0 }; const float mEndTolerance = 0; const btTransform mTransform{ btMatrix3x3::getIdentity(), btVector3(256, 256, 0) }; const ObjectTransform mObjectTransform{ ESM::Position{ { 256, 256, 0 }, { 0, 0, 0 } }, 0.0f }; - - DetourNavigatorNavigatorTest() - : mPlayerPosition(256, 256, 0) - , mWorldspace("sys::default") - , mStart(52, 460, 1) - , mEnd(460, 52, 1) - , mOut(mPath) - { - mNavigator.reset(new NavigatorImpl( - mSettings, std::make_unique(":memory:", std::numeric_limits::max()))); - } }; constexpr std::array defaultHeightfieldData{ { @@ -878,7 +868,7 @@ namespace .mScale = 1.0f, }; - mNavigator->updateBounds(mPlayerPosition, nullptr); + mNavigator->updateBounds(mWorldspace, mPlayerPosition, nullptr); ASSERT_TRUE(mNavigator->addAgent(mAgentBounds)); mNavigator->addObject(ObjectId(&bigBox.shape()), ObjectShapes(bigBox.instance(), objectTransform), btTransform::getIdentity(), nullptr); diff --git a/components/detournavigator/navigator.hpp b/components/detournavigator/navigator.hpp index 7bab0af4d1..609944b245 100644 --- a/components/detournavigator/navigator.hpp +++ b/components/detournavigator/navigator.hpp @@ -12,6 +12,7 @@ #include "updateguard.hpp" #include "waitconditiontype.hpp" +#include #include namespace ESM @@ -87,17 +88,9 @@ namespace DetourNavigator */ virtual void removeAgent(const AgentBounds& agentBounds) = 0; - /** - * @brief setWorldspace should be called before adding object from new worldspace - * @param worldspace - */ - virtual void setWorldspace(ESM::RefId worldspace, const UpdateGuard* guard) = 0; - - /** - * @brief updateBounds should be called before adding object from loading cell - * @param playerPosition corresponds to the bounds center - */ - virtual void updateBounds(const osg::Vec3f& playerPosition, const UpdateGuard* guard) = 0; + // Updates bounds for recast mesh and navmesh tiles, removes tiles outside the range. + virtual void updateBounds(ESM::RefId worldspace, const osg::Vec3f& playerPosition, const UpdateGuard* guard) + = 0; /** * @brief addObject is used to add complex object with allowed to walk and avoided to walk shapes diff --git a/components/detournavigator/navigatorimpl.cpp b/components/detournavigator/navigatorimpl.cpp index 443a98a678..b14dde20fc 100644 --- a/components/detournavigator/navigatorimpl.cpp +++ b/components/detournavigator/navigatorimpl.cpp @@ -33,14 +33,9 @@ namespace DetourNavigator --it->second; } - void NavigatorImpl::setWorldspace(ESM::RefId worldspace, const UpdateGuard* guard) + void NavigatorImpl::updateBounds(ESM::RefId worldspace, const osg::Vec3f& playerPosition, const UpdateGuard* guard) { - mNavMeshManager.setWorldspace(worldspace, guard); - } - - void NavigatorImpl::updateBounds(const osg::Vec3f& playerPosition, const UpdateGuard* guard) - { - mNavMeshManager.updateBounds(playerPosition, guard); + mNavMeshManager.updateBounds(worldspace, playerPosition, guard); } void NavigatorImpl::addObject( diff --git a/components/detournavigator/navigatorimpl.hpp b/components/detournavigator/navigatorimpl.hpp index e9f7276172..759ddf8d14 100644 --- a/components/detournavigator/navigatorimpl.hpp +++ b/components/detournavigator/navigatorimpl.hpp @@ -27,9 +27,7 @@ namespace DetourNavigator void removeAgent(const AgentBounds& agentBounds) override; - void setWorldspace(ESM::RefId worldspace, const UpdateGuard* guard) override; - - void updateBounds(const osg::Vec3f& playerPosition, const UpdateGuard* guard) override; + void updateBounds(ESM::RefId worldspace, const osg::Vec3f& playerPosition, const UpdateGuard* guard) override; void addObject(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform, const UpdateGuard* guard) override; diff --git a/components/detournavigator/navigatorstub.hpp b/components/detournavigator/navigatorstub.hpp index bc14e2274c..7638faac27 100644 --- a/components/detournavigator/navigatorstub.hpp +++ b/components/detournavigator/navigatorstub.hpp @@ -24,7 +24,10 @@ namespace DetourNavigator void removeAgent(const AgentBounds& /*agentBounds*/) override {} - void setWorldspace(ESM::RefId /*worldspace*/, const UpdateGuard* /*guard*/) override {} + void updateBounds( + ESM::RefId /*worldspace*/, const osg::Vec3f& /*playerPosition*/, const UpdateGuard* /*guard*/) override + { + } void addObject(const ObjectId /*id*/, const ObjectShapes& /*shapes*/, const btTransform& /*transform*/, const UpdateGuard* /*guard*/) override @@ -68,8 +71,6 @@ namespace DetourNavigator void update(const osg::Vec3f& /*playerPosition*/, const UpdateGuard* /*guard*/) override {} - void updateBounds(const osg::Vec3f& /*playerPosition*/, const UpdateGuard* /*guard*/) override {} - void wait(WaitConditionType /*waitConditionType*/, Loading::Listener* /*listener*/) override {} SharedNavMeshCacheItem getNavMesh(const AgentBounds& /*agentBounds*/) const override diff --git a/components/detournavigator/navmeshmanager.cpp b/components/detournavigator/navmeshmanager.cpp index 7a2fd74714..502bda6f66 100644 --- a/components/detournavigator/navmeshmanager.cpp +++ b/components/detournavigator/navmeshmanager.cpp @@ -58,18 +58,16 @@ namespace DetourNavigator { } - void NavMeshManager::setWorldspace(ESM::RefId worldspace, const UpdateGuard* guard) + void NavMeshManager::updateBounds(ESM::RefId worldspace, const osg::Vec3f& playerPosition, const UpdateGuard* guard) { - if (worldspace == mWorldspace) - return; - mRecastMeshManager.setWorldspace(worldspace, guard); - for (auto& [agent, cache] : mCache) - cache = std::make_shared(++mGenerationCounter, mSettings); - mWorldspace = worldspace; - } + if (worldspace != mWorldspace) + { + mRecastMeshManager.setWorldspace(worldspace, guard); + for (auto& [agent, cache] : mCache) + cache = std::make_shared(++mGenerationCounter, mSettings); + mWorldspace = worldspace; + } - void NavMeshManager::updateBounds(const osg::Vec3f& playerPosition, const UpdateGuard* guard) - { const TilePosition playerTile = toNavMeshTilePosition(mSettings.mRecast, playerPosition); const TilesPositionsRange range = makeRange(playerTile, mSettings.mMaxTilesNumber); mRecastMeshManager.setRange(range, guard); diff --git a/components/detournavigator/navmeshmanager.hpp b/components/detournavigator/navmeshmanager.hpp index 6c25cc599f..89ced89f02 100644 --- a/components/detournavigator/navmeshmanager.hpp +++ b/components/detournavigator/navmeshmanager.hpp @@ -24,9 +24,7 @@ namespace DetourNavigator ScopedUpdateGuard makeUpdateGuard() { return mRecastMeshManager.makeUpdateGuard(); } - void setWorldspace(ESM::RefId worldspace, const UpdateGuard* guard); - - void updateBounds(const osg::Vec3f& playerPosition, const UpdateGuard* guard); + void updateBounds(ESM::RefId worldspace, const osg::Vec3f& playerPosition, const UpdateGuard* guard); bool addObject(const ObjectId id, const CollisionShape& shape, const btTransform& transform, const AreaType areaType, const UpdateGuard* guard); From 45d62ee59f7de9a91d7381b132d18584f8c16a86 Mon Sep 17 00:00:00 2001 From: elsid Date: Sun, 19 May 2024 15:59:12 +0200 Subject: [PATCH 6/6] Limit RecastMeshManager range by active cell grid --- apps/openmw/mwworld/scene.cpp | 33 ++++++-- .../detournavigator/navigator.cpp | 79 +++++++++++++++++-- .../detournavigator/settings.hpp | 2 +- .../tilecachedrecastmeshmanager.cpp | 2 +- components/detournavigator/cellgridbounds.hpp | 15 ++++ components/detournavigator/navigator.hpp | 5 +- components/detournavigator/navigatorimpl.cpp | 5 +- components/detournavigator/navigatorimpl.hpp | 3 +- components/detournavigator/navigatorstub.hpp | 4 +- components/detournavigator/navmeshmanager.cpp | 48 +++++++++-- components/detournavigator/navmeshmanager.hpp | 6 +- .../tilecachedrecastmeshmanager.cpp | 9 ++- 12 files changed, 180 insertions(+), 31 deletions(-) create mode 100644 components/detournavigator/cellgridbounds.hpp diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 2465f165b9..4baebf1119 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -572,11 +572,11 @@ namespace MWWorld void Scene::changeCellGrid(const osg::Vec3f& pos, ESM::ExteriorCellLocation playerCellIndex, bool changeEvent) { - mHalfGridSize + const int halfGridSize = isEsm4Ext(playerCellIndex.mWorldspace) ? Constants::ESM4CellGridRadius : Constants::CellGridRadius; auto navigatorUpdateGuard = mNavigator.makeUpdateGuard(); - int playerCellX = playerCellIndex.mX; - int playerCellY = playerCellIndex.mY; + const int playerCellX = playerCellIndex.mX; + const int playerCellY = playerCellIndex.mY; for (auto iter = mActiveCells.begin(); iter != mActiveCells.end();) { @@ -585,15 +585,21 @@ namespace MWWorld { const auto dx = std::abs(playerCellX - cell->getCell()->getGridX()); const auto dy = std::abs(playerCellY - cell->getCell()->getGridY()); - if (dx > mHalfGridSize || dy > mHalfGridSize) + if (dx > halfGridSize || dy > halfGridSize) unloadCell(cell, navigatorUpdateGuard.get()); } else unloadCell(cell, navigatorUpdateGuard.get()); } - mNavigator.updateBounds(playerCellIndex.mWorldspace, pos, navigatorUpdateGuard.get()); + const DetourNavigator::CellGridBounds cellGridBounds{ + .mCenter = osg::Vec2i(playerCellX, playerCellY), + .mHalfSize = halfGridSize, + }; + + mNavigator.updateBounds(playerCellIndex.mWorldspace, cellGridBounds, pos, navigatorUpdateGuard.get()); + mHalfGridSize = halfGridSize; mCurrentGridCenter = osg::Vec2i(playerCellX, playerCellY); osg::Vec4i newGrid = gridCenterToBounds(mCurrentGridCenter); mRendering.setActiveGrid(newGrid); @@ -696,7 +702,16 @@ namespace MWWorld ESM::ExteriorCellLocation(it->mData.mX, it->mData.mY, ESM::Cell::sDefaultWorldspaceId)); const osg::Vec3f position = osg::Vec3f(it->mData.mX + 0.5f, it->mData.mY + 0.5f, 0) * Constants::CellSizeInUnits; - mNavigator.updateBounds(ESM::Cell::sDefaultWorldspaceId, position, navigatorUpdateGuard.get()); + const osg::Vec2i cellPosition(it->mData.mX, it->mData.mY); + + const DetourNavigator::CellGridBounds cellGridBounds{ + .mCenter = osg::Vec2i(it->mData.mX, it->mData.mY), + .mHalfSize = Constants::CellGridRadius, + }; + + mNavigator.updateBounds( + ESM::Cell::sDefaultWorldspaceId, cellGridBounds, position, navigatorUpdateGuard.get()); + loadCell(cell, nullptr, false, position, navigatorUpdateGuard.get()); mNavigator.update(position, navigatorUpdateGuard.get()); @@ -752,7 +767,8 @@ namespace MWWorld CellStore& cell = mWorld.getWorldModel().getInterior(it->mName); ESM::Position position; mWorld.findInteriorPosition(it->mName, position); - mNavigator.updateBounds(cell.getCell()->getWorldSpace(), position.asVec3(), navigatorUpdateGuard.get()); + mNavigator.updateBounds( + cell.getCell()->getWorldSpace(), std::nullopt, position.asVec3(), navigatorUpdateGuard.get()); loadCell(cell, nullptr, false, position.asVec3(), navigatorUpdateGuard.get()); mNavigator.update(position.asVec3(), navigatorUpdateGuard.get()); @@ -902,7 +918,8 @@ namespace MWWorld loadingListener->setProgressRange(cell.count()); - mNavigator.updateBounds(cell.getCell()->getWorldSpace(), position.asVec3(), navigatorUpdateGuard.get()); + mNavigator.updateBounds( + cell.getCell()->getWorldSpace(), std::nullopt, position.asVec3(), navigatorUpdateGuard.get()); // Load cell. mPagedRefs.clear(); diff --git a/apps/openmw_test_suite/detournavigator/navigator.cpp b/apps/openmw_test_suite/detournavigator/navigator.cpp index c53ff2cc37..2927869782 100644 --- a/apps/openmw_test_suite/detournavigator/navigator.cpp +++ b/apps/openmw_test_suite/detournavigator/navigator.cpp @@ -859,6 +859,17 @@ namespace EXPECT_EQ(mNavigator->getNavMesh(mAgentBounds)->lockConst()->getVersion(), version); } + std::pair getMinMax(const RecastMeshTiles& tiles) + { + const auto lessByX = [](const auto& l, const auto& r) { return l.first.x() < r.first.x(); }; + const auto lessByY = [](const auto& l, const auto& r) { return l.first.y() < r.first.y(); }; + + const auto [minX, maxX] = std::ranges::minmax_element(tiles, lessByX); + const auto [minY, maxY] = std::ranges::minmax_element(tiles, lessByY); + + return { TilePosition(minX->first.x(), minY->first.y()), TilePosition(maxX->first.x(), maxY->first.y()) }; + } + TEST_F(DetourNavigatorNavigatorTest, update_for_very_big_object_should_be_limited) { const float size = static_cast((1 << 22) - 1); @@ -867,8 +878,10 @@ namespace .mPosition = ESM::Position{ .pos = { 0, 0, 0 }, .rot{ 0, 0, 0 } }, .mScale = 1.0f, }; + const std::optional cellGridBounds = std::nullopt; + const osg::Vec3f playerPosition(32, 1024, 0); - mNavigator->updateBounds(mWorldspace, mPlayerPosition, nullptr); + mNavigator->updateBounds(mWorldspace, cellGridBounds, playerPosition, nullptr); ASSERT_TRUE(mNavigator->addAgent(mAgentBounds)); mNavigator->addObject(ObjectId(&bigBox.shape()), ObjectShapes(bigBox.instance(), objectTransform), btTransform::getIdentity(), nullptr); @@ -878,7 +891,61 @@ namespace std::mutex mutex; std::thread thread([&] { - mNavigator->update(mPlayerPosition, nullptr); + auto guard = mNavigator->makeUpdateGuard(); + mNavigator->update(playerPosition, guard.get()); + std::lock_guard lock(mutex); + updated = true; + updateFinished.notify_all(); + }); + + { + std::unique_lock lock(mutex); + updateFinished.wait_for(lock, std::chrono::seconds(10), [&] { return updated; }); + ASSERT_TRUE(updated); + } + + thread.join(); + + mNavigator->wait(WaitConditionType::allJobsDone, &mListener); + + const auto recastMeshTiles = mNavigator->getRecastMeshTiles(); + ASSERT_EQ(recastMeshTiles.size(), 1033); + EXPECT_EQ(getMinMax(recastMeshTiles), std::pair(TilePosition(-18, -17), TilePosition(18, 19))); + + const auto navMesh = mNavigator->getNavMesh(mAgentBounds); + ASSERT_NE(navMesh, nullptr); + + std::size_t usedNavMeshTiles = 0; + navMesh->lockConst()->forEachUsedTile([&](const auto&...) { ++usedNavMeshTiles; }); + EXPECT_EQ(usedNavMeshTiles, 1024); + } + + TEST_F(DetourNavigatorNavigatorTest, update_should_be_limited_by_cell_grid_bounds) + { + const float size = static_cast((1 << 22) - 1); + CollisionShapeInstance bigBox(std::make_unique(btVector3(size, size, 1))); + const ObjectTransform objectTransform{ + .mPosition = ESM::Position{ .pos = { 0, 0, 0 }, .rot{ 0, 0, 0 } }, + .mScale = 1.0f, + }; + const CellGridBounds cellGridBounds{ + .mCenter = osg::Vec2i(0, 0), + .mHalfSize = 1, + }; + const osg::Vec3f playerPosition(32, 1024, 0); + + mNavigator->updateBounds(mWorldspace, cellGridBounds, playerPosition, nullptr); + ASSERT_TRUE(mNavigator->addAgent(mAgentBounds)); + mNavigator->addObject(ObjectId(&bigBox.shape()), ObjectShapes(bigBox.instance(), objectTransform), + btTransform::getIdentity(), nullptr); + + bool updated = false; + std::condition_variable updateFinished; + std::mutex mutex; + + std::thread thread([&] { + auto guard = mNavigator->makeUpdateGuard(); + mNavigator->update(playerPosition, guard.get()); std::lock_guard lock(mutex); updated = true; updateFinished.notify_all(); @@ -886,7 +953,7 @@ namespace { std::unique_lock lock(mutex); - updateFinished.wait_for(lock, std::chrono::seconds(3), [&] { return updated; }); + updateFinished.wait_for(lock, std::chrono::seconds(10), [&] { return updated; }); ASSERT_TRUE(updated); } @@ -894,14 +961,16 @@ namespace mNavigator->wait(WaitConditionType::allJobsDone, &mListener); - EXPECT_EQ(mNavigator->getRecastMeshTiles().size(), 509); + const auto recastMeshTiles = mNavigator->getRecastMeshTiles(); + ASSERT_EQ(recastMeshTiles.size(), 854); + EXPECT_EQ(getMinMax(recastMeshTiles), std::pair(TilePosition(-12, -12), TilePosition(18, 19))); const auto navMesh = mNavigator->getNavMesh(mAgentBounds); ASSERT_NE(navMesh, nullptr); std::size_t usedNavMeshTiles = 0; navMesh->lockConst()->forEachUsedTile([&](const auto&...) { ++usedNavMeshTiles; }); - EXPECT_EQ(usedNavMeshTiles, 509); + EXPECT_EQ(usedNavMeshTiles, 854); } struct DetourNavigatorNavigatorNotSupportedAgentBoundsTest : TestWithParam diff --git a/apps/openmw_test_suite/detournavigator/settings.hpp b/apps/openmw_test_suite/detournavigator/settings.hpp index dc37dc7550..1ebbc5ba7b 100644 --- a/apps/openmw_test_suite/detournavigator/settings.hpp +++ b/apps/openmw_test_suite/detournavigator/settings.hpp @@ -39,7 +39,7 @@ namespace DetourNavigator result.mDetour.mMaxPolygonPathSize = 1024; result.mDetour.mMaxSmoothPathSize = 1024; result.mDetour.mMaxPolys = 4096; - result.mMaxTilesNumber = 512; + result.mMaxTilesNumber = 1024; result.mMinUpdateInterval = std::chrono::milliseconds(50); result.mWriteToNavMeshDb = true; return result; diff --git a/apps/openmw_test_suite/detournavigator/tilecachedrecastmeshmanager.cpp b/apps/openmw_test_suite/detournavigator/tilecachedrecastmeshmanager.cpp index 7585e405e5..e1805e993c 100644 --- a/apps/openmw_test_suite/detournavigator/tilecachedrecastmeshmanager.cpp +++ b/apps/openmw_test_suite/detournavigator/tilecachedrecastmeshmanager.cpp @@ -173,7 +173,7 @@ namespace TileCachedRecastMeshManager manager(mSettings); const TilesPositionsRange range{ .mBegin = TilePosition(-1, -1), - .mEnd = TilePosition(1, 1), + .mEnd = TilePosition(2, 2), }; manager.setRange(range, nullptr); manager.setWorldspace(mWorldspace, nullptr); diff --git a/components/detournavigator/cellgridbounds.hpp b/components/detournavigator/cellgridbounds.hpp new file mode 100644 index 0000000000..75d1fce350 --- /dev/null +++ b/components/detournavigator/cellgridbounds.hpp @@ -0,0 +1,15 @@ +#ifndef OPENMW_COMPONENTS_DETOURNAVIGATOR_CELLGRIDBOUNDS_H +#define OPENMW_COMPONENTS_DETOURNAVIGATOR_CELLGRIDBOUNDS_H + +#include + +namespace DetourNavigator +{ + struct CellGridBounds + { + osg::Vec2i mCenter; + int mHalfSize; + }; +} + +#endif diff --git a/components/detournavigator/navigator.hpp b/components/detournavigator/navigator.hpp index 609944b245..3f27bc1479 100644 --- a/components/detournavigator/navigator.hpp +++ b/components/detournavigator/navigator.hpp @@ -3,7 +3,9 @@ #include #include +#include +#include "cellgridbounds.hpp" #include "heightfieldshape.hpp" #include "objectid.hpp" #include "objecttransform.hpp" @@ -89,7 +91,8 @@ namespace DetourNavigator virtual void removeAgent(const AgentBounds& agentBounds) = 0; // Updates bounds for recast mesh and navmesh tiles, removes tiles outside the range. - virtual void updateBounds(ESM::RefId worldspace, const osg::Vec3f& playerPosition, const UpdateGuard* guard) + virtual void updateBounds(ESM::RefId worldspace, const std::optional& cellGridBounds, + const osg::Vec3f& playerPosition, const UpdateGuard* guard) = 0; /** diff --git a/components/detournavigator/navigatorimpl.cpp b/components/detournavigator/navigatorimpl.cpp index b14dde20fc..1cb35a58c6 100644 --- a/components/detournavigator/navigatorimpl.cpp +++ b/components/detournavigator/navigatorimpl.cpp @@ -33,9 +33,10 @@ namespace DetourNavigator --it->second; } - void NavigatorImpl::updateBounds(ESM::RefId worldspace, const osg::Vec3f& playerPosition, const UpdateGuard* guard) + void NavigatorImpl::updateBounds(ESM::RefId worldspace, const std::optional& cellGridBounds, + const osg::Vec3f& playerPosition, const UpdateGuard* guard) { - mNavMeshManager.updateBounds(worldspace, playerPosition, guard); + mNavMeshManager.updateBounds(worldspace, cellGridBounds, playerPosition, guard); } void NavigatorImpl::addObject( diff --git a/components/detournavigator/navigatorimpl.hpp b/components/detournavigator/navigatorimpl.hpp index 759ddf8d14..413fd8ef6b 100644 --- a/components/detournavigator/navigatorimpl.hpp +++ b/components/detournavigator/navigatorimpl.hpp @@ -27,7 +27,8 @@ namespace DetourNavigator void removeAgent(const AgentBounds& agentBounds) override; - void updateBounds(ESM::RefId worldspace, const osg::Vec3f& playerPosition, const UpdateGuard* guard) override; + void updateBounds(ESM::RefId worldspace, const std::optional& cellGridBounds, + const osg::Vec3f& playerPosition, const UpdateGuard* guard) override; void addObject(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform, const UpdateGuard* guard) override; diff --git a/components/detournavigator/navigatorstub.hpp b/components/detournavigator/navigatorstub.hpp index 7638faac27..7102722517 100644 --- a/components/detournavigator/navigatorstub.hpp +++ b/components/detournavigator/navigatorstub.hpp @@ -24,8 +24,8 @@ namespace DetourNavigator void removeAgent(const AgentBounds& /*agentBounds*/) override {} - void updateBounds( - ESM::RefId /*worldspace*/, const osg::Vec3f& /*playerPosition*/, const UpdateGuard* /*guard*/) override + void updateBounds(ESM::RefId /*worldspace*/, const std::optional& /*cellGridBounds*/, + const osg::Vec3f& /*playerPosition*/, const UpdateGuard* /*guard*/) override { } diff --git a/components/detournavigator/navmeshmanager.cpp b/components/detournavigator/navmeshmanager.cpp index 502bda6f66..5db582f152 100644 --- a/components/detournavigator/navmeshmanager.cpp +++ b/components/detournavigator/navmeshmanager.cpp @@ -1,4 +1,5 @@ #include "navmeshmanager.hpp" + #include "debug.hpp" #include "gettilespositions.hpp" #include "makenavmesh.hpp" @@ -8,6 +9,7 @@ #include "waitconditiontype.hpp" #include +#include #include @@ -35,15 +37,46 @@ namespace DetourNavigator { namespace { - TilesPositionsRange makeRange(const TilePosition& center, int maxTiles) + int getMaxRadius(int maxTiles) + { + return static_cast(std::ceil(std::sqrt(static_cast(maxTiles) / osg::PIf) + 1)); + } + + TilesPositionsRange makeRange(const TilePosition& center, int radius) { - const int radius = static_cast(std::ceil(std::sqrt(static_cast(maxTiles) / osg::PIf) + 1)); return TilesPositionsRange{ .mBegin = center - TilePosition(radius, radius), .mEnd = center + TilePosition(radius + 1, radius + 1), }; } + osg::Vec2f getMinCellGridPosition(const osg::Vec2i& center, int offset, float cellSize) + { + const osg::Vec2i cell = center + osg::Vec2i(offset, offset); + return osg::Vec2f(static_cast(cell.x()) * cellSize, static_cast(cell.y()) * cellSize); + } + + TilesPositionsRange makeCellGridRange( + const RecastSettings& settings, ESM::RefId worldspace, const CellGridBounds& bounds) + { + const float floatCellSize = static_cast(ESM::getCellSize(worldspace)); + const osg::Vec2f min = getMinCellGridPosition(bounds.mCenter, -bounds.mHalfSize, floatCellSize); + const osg::Vec2f max = getMinCellGridPosition(bounds.mCenter, bounds.mHalfSize + 1, floatCellSize); + return TilesPositionsRange{ + .mBegin = getTilePosition(settings, toNavMeshCoordinates(settings, min)), + .mEnd = getTilePosition(settings, toNavMeshCoordinates(settings, max)), + }; + } + + TilesPositionsRange makeRange(const Settings& settings, ESM::RefId worldspace, + const std::optional& bounds, int radius, const TilePosition& center) + { + TilesPositionsRange result = makeRange(center, radius); + if (bounds.has_value()) + result = getIntersection(result, makeCellGridRange(settings.mRecast, worldspace, *bounds)); + return result; + } + TilePosition toNavMeshTilePosition(const RecastSettings& settings, const osg::Vec3f& position) { return getTilePosition(settings, toNavMeshCoordinates(settings, position)); @@ -52,13 +85,15 @@ namespace DetourNavigator NavMeshManager::NavMeshManager(const Settings& settings, std::unique_ptr&& db) : mSettings(settings) + , mMaxRadius(getMaxRadius(settings.mMaxTilesNumber)) , mRecastMeshManager(settings.mRecast) , mOffMeshConnectionsManager(settings.mRecast) , mAsyncNavMeshUpdater(settings, mRecastMeshManager, mOffMeshConnectionsManager, std::move(db)) { } - void NavMeshManager::updateBounds(ESM::RefId worldspace, const osg::Vec3f& playerPosition, const UpdateGuard* guard) + void NavMeshManager::updateBounds(ESM::RefId worldspace, const std::optional& cellGridBounds, + const osg::Vec3f& playerPosition, const UpdateGuard* guard) { if (worldspace != mWorldspace) { @@ -69,8 +104,9 @@ namespace DetourNavigator } const TilePosition playerTile = toNavMeshTilePosition(mSettings.mRecast, playerPosition); - const TilesPositionsRange range = makeRange(playerTile, mSettings.mMaxTilesNumber); - mRecastMeshManager.setRange(range, guard); + + mRecastMeshManager.setRange(makeRange(mSettings, worldspace, cellGridBounds, mMaxRadius, playerTile), guard); + mCellGridBounds = cellGridBounds; } bool NavMeshManager::addObject(const ObjectId id, const CollisionShape& shape, const btTransform& transform, @@ -162,7 +198,7 @@ namespace DetourNavigator return; mLastRecastMeshManagerRevision = mRecastMeshManager.getRevision(); mPlayerTile = playerTile; - mRecastMeshManager.setRange(makeRange(playerTile, mSettings.mMaxTilesNumber), guard); + mRecastMeshManager.setRange(makeRange(mSettings, mWorldspace, mCellGridBounds, mMaxRadius, playerTile), guard); const auto changedTiles = mRecastMeshManager.takeChangedTiles(guard); const TilesPositionsRange range = mRecastMeshManager.getLimitedObjectsRange(); for (const auto& [agentBounds, cached] : mCache) diff --git a/components/detournavigator/navmeshmanager.hpp b/components/detournavigator/navmeshmanager.hpp index 89ced89f02..ed4703f4b1 100644 --- a/components/detournavigator/navmeshmanager.hpp +++ b/components/detournavigator/navmeshmanager.hpp @@ -3,6 +3,7 @@ #include "agentbounds.hpp" #include "asyncnavmeshupdater.hpp" +#include "cellgridbounds.hpp" #include "heightfieldshape.hpp" #include "offmeshconnectionsmanager.hpp" #include "recastmeshtiles.hpp" @@ -24,7 +25,8 @@ namespace DetourNavigator ScopedUpdateGuard makeUpdateGuard() { return mRecastMeshManager.makeUpdateGuard(); } - void updateBounds(ESM::RefId worldspace, const osg::Vec3f& playerPosition, const UpdateGuard* guard); + void updateBounds(ESM::RefId worldspace, const std::optional& cellGridBounds, + const osg::Vec3f& playerPosition, const UpdateGuard* guard); bool addObject(const ObjectId id, const CollisionShape& shape, const btTransform& transform, const AreaType areaType, const UpdateGuard* guard); @@ -65,7 +67,9 @@ namespace DetourNavigator private: const Settings& mSettings; + const int mMaxRadius; ESM::RefId mWorldspace; + std::optional mCellGridBounds; TileCachedRecastMeshManager mRecastMeshManager; OffMeshConnectionsManager mOffMeshConnectionsManager; AsyncNavMeshUpdater mAsyncNavMeshUpdater; diff --git a/components/detournavigator/tilecachedrecastmeshmanager.cpp b/components/detournavigator/tilecachedrecastmeshmanager.cpp index 5cb95fed64..cf5a914ceb 100644 --- a/components/detournavigator/tilecachedrecastmeshmanager.cpp +++ b/components/detournavigator/tilecachedrecastmeshmanager.cpp @@ -107,11 +107,10 @@ namespace DetourNavigator }); } + const MaybeLockGuard lock(mMutex, guard); + if (changed) - { - const MaybeLockGuard lock(mMutex, guard); ++mRevision; - } mRange = range; } @@ -357,6 +356,8 @@ namespace DetourNavigator const std::lock_guard lock(mMutex); if (mWorldspace != worldspace) return nullptr; + if (!isInTilesPositionsRange(mRange, tilePosition)) + return nullptr; const auto it = mCache.find(tilePosition); if (it != mCache.end() && it->second.mRecastMesh->getVersion() == it->second.mVersion) return it->second.mRecastMesh; @@ -380,6 +381,8 @@ namespace DetourNavigator const std::lock_guard lock(mMutex); if (mWorldspace != worldspace) return nullptr; + if (!isInTilesPositionsRange(mRange, tilePosition)) + return nullptr; const auto it = mCache.find(tilePosition); if (it == mCache.end()) return nullptr;