From 540ee5399c8fc2d48934088b4d39cb7161545346 Mon Sep 17 00:00:00 2001 From: elsid Date: Fri, 17 Feb 2023 13:57:31 +0100 Subject: [PATCH 1/2] Do expensive navmesh calls on timer Reducing the number of them on each frame. --- apps/openmw/mwmechanics/aipackage.cpp | 13 +++++++++++-- apps/openmw/mwmechanics/aiwander.cpp | 14 +++++++------- apps/openmw/mwmechanics/pathfinding.cpp | 11 +++++------ apps/openmw/mwmechanics/pathfinding.hpp | 21 ++++++++++++--------- 4 files changed, 35 insertions(+), 24 deletions(-) diff --git a/apps/openmw/mwmechanics/aipackage.cpp b/apps/openmw/mwmechanics/aipackage.cpp index 4cb4ca6d6e..6c1c4c7118 100644 --- a/apps/openmw/mwmechanics/aipackage.cpp +++ b/apps/openmw/mwmechanics/aipackage.cpp @@ -189,8 +189,17 @@ bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, const osg::Vec3f& = getPointTolerance(actor.getClass().getMaxSpeed(actor), duration, world->getHalfExtents(actor)); static const bool smoothMovement = Settings::Manager::getBool("smooth movement", "Game"); - mPathFinder.update(position, pointTolerance, DEFAULT_TOLERANCE, - /*shortenIfAlmostStraight=*/smoothMovement, actorCanMoveByZ, agentBounds, getNavigatorFlags(actor)); + + PathFinder::UpdateFlags updateFlags{}; + + if (actorCanMoveByZ) + updateFlags |= PathFinder::UpdateFlag_CanMoveByZ; + if (timerStatus == Misc::TimerStatus::Elapsed && smoothMovement) + updateFlags |= PathFinder::UpdateFlag_ShortenIfAlmostStraight; + if (timerStatus == Misc::TimerStatus::Elapsed) + updateFlags |= PathFinder::UpdateFlag_RemoveLoops; + + mPathFinder.update(position, pointTolerance, DEFAULT_TOLERANCE, updateFlags, agentBounds, getNavigatorFlags(actor)); if (isDestReached || mPathFinder.checkPathCompleted()) // if path is finished { diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index 7441bf0c86..54ed2feebe 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -312,6 +312,13 @@ namespace MWMechanics completeManualWalking(actor, storage); } + if (storage.mState == AiWanderStorage::Wander_Walking && mUsePathgrid) + { + const auto agentBounds = MWBase::Environment::get().getWorld()->getPathfindingAgentBounds(actor); + mPathFinder.buildPathByNavMeshToNextPoint( + actor, agentBounds, getNavigatorFlags(actor), getAreaCosts(actor)); + } + if (storage.mState == AiWanderStorage::Wander_MoveNow && storage.mCanWanderAlongPathGrid) { // Construct a new path if there isn't one @@ -560,13 +567,6 @@ namespace MWMechanics void AiWander::evadeObstacles(const MWWorld::Ptr& actor, AiWanderStorage& storage) { - if (mUsePathgrid) - { - const auto agentBounds = MWBase::Environment::get().getWorld()->getPathfindingAgentBounds(actor); - mPathFinder.buildPathByNavMeshToNextPoint( - actor, agentBounds, getNavigatorFlags(actor), getAreaCosts(actor)); - } - if (mObstacleCheck.isEvading()) { // first check if we're walking into a door diff --git a/apps/openmw/mwmechanics/pathfinding.cpp b/apps/openmw/mwmechanics/pathfinding.cpp index 0180323ddd..5b80d90af6 100644 --- a/apps/openmw/mwmechanics/pathfinding.cpp +++ b/apps/openmw/mwmechanics/pathfinding.cpp @@ -313,8 +313,7 @@ namespace MWMechanics } void PathFinder::update(const osg::Vec3f& position, float pointTolerance, float destinationTolerance, - bool shortenIfAlmostStraight, bool canMoveByZ, const DetourNavigator::AgentBounds& agentBounds, - const DetourNavigator::Flags flags) + UpdateFlags updateFlags, const DetourNavigator::AgentBounds& agentBounds, DetourNavigator::Flags pathFlags) { if (mPath.empty()) return; @@ -323,9 +322,9 @@ namespace MWMechanics mPath.pop_front(); const IsValidShortcut isValidShortcut{ MWBase::Environment::get().getWorld()->getNavigator(), agentBounds, - flags }; + pathFlags }; - if (shortenIfAlmostStraight) + if ((updateFlags & UpdateFlag_ShortenIfAlmostStraight) != 0) { while (mPath.size() > 2 && isAlmostStraight(mPath[0], mPath[1], mPath[2], pointTolerance) && isValidShortcut(mPath[0], mPath[2])) @@ -335,7 +334,7 @@ namespace MWMechanics mPath.pop_front(); } - if (mPath.size() > 1) + if ((updateFlags & UpdateFlag_RemoveLoops) != 0 && mPath.size() > 1) { std::size_t begin = 0; for (std::size_t i = 1; i < mPath.size(); ++i) @@ -351,7 +350,7 @@ namespace MWMechanics if (mPath.size() == 1) { float distSqr; - if (canMoveByZ) + if ((updateFlags & UpdateFlag_CanMoveByZ) != 0) distSqr = (mPath.front() - position).length2(); else distSqr = sqrDistanceIgnoreZ(mPath.front(), position); diff --git a/apps/openmw/mwmechanics/pathfinding.hpp b/apps/openmw/mwmechanics/pathfinding.hpp index 330e9fbb0c..c23cf04ade 100644 --- a/apps/openmw/mwmechanics/pathfinding.hpp +++ b/apps/openmw/mwmechanics/pathfinding.hpp @@ -82,11 +82,16 @@ namespace MWMechanics class PathFinder { public: - PathFinder() - : mConstructed(false) - , mCell(nullptr) + using UpdateFlags = unsigned; + + enum UpdateFlag : UpdateFlags { - } + UpdateFlag_CanMoveByZ = 1 << 0, + UpdateFlag_ShortenIfAlmostStraight = 1 << 1, + UpdateFlag_RemoveLoops = 1 << 2, + }; + + PathFinder() = default; void clearPath() { @@ -121,8 +126,7 @@ namespace MWMechanics /// Remove front point if exist and within tolerance void update(const osg::Vec3f& position, float pointTolerance, float destinationTolerance, - bool shortenIfAlmostStraight, bool canMoveByZ, const DetourNavigator::AgentBounds& agentBounds, - const DetourNavigator::Flags flags); + UpdateFlags updateFlags, const DetourNavigator::AgentBounds& agentBounds, DetourNavigator::Flags pathFlags); bool checkPathCompleted() const { return mConstructed && mPath.empty(); } @@ -201,10 +205,9 @@ namespace MWMechanics } private: - bool mConstructed; + bool mConstructed = false; std::deque mPath; - - const MWWorld::CellStore* mCell; + const MWWorld::CellStore* mCell = nullptr; void buildPathByPathgridImpl(const osg::Vec3f& startPoint, const osg::Vec3f& endPoint, const PathgridGraph& pathgridGraph, std::back_insert_iterator> out); From 28f7a8953006aece96a67cd0cff0545dead3b289 Mon Sep 17 00:00:00 2001 From: elsid Date: Fri, 17 Feb 2023 14:55:05 +0100 Subject: [PATCH 2/2] Reuse dtNavMeshQuery To avoid redundant allocations. --- .../detournavigator/asyncnavmeshupdater.cpp | 18 ++++++------ .../findrandompointaroundcircle.cpp | 9 ++---- .../findrandompointaroundcircle.hpp | 6 ++-- components/detournavigator/findsmoothpath.hpp | 10 ++----- components/detournavigator/makenavmesh.cpp | 12 ++------ components/detournavigator/makenavmesh.hpp | 3 +- components/detournavigator/navigatorutils.cpp | 15 +++++----- components/detournavigator/navigatorutils.hpp | 5 ++-- .../detournavigator/navmeshcacheitem.cpp | 28 +++++++++++++++---- .../detournavigator/navmeshcacheitem.hpp | 21 ++++++++------ components/detournavigator/navmeshmanager.cpp | 5 ++-- components/detournavigator/raycast.cpp | 10 ++----- components/detournavigator/raycast.hpp | 6 ++-- components/detournavigator/sharednavmesh.hpp | 13 --------- 14 files changed, 73 insertions(+), 88 deletions(-) delete mode 100644 components/detournavigator/sharednavmesh.hpp diff --git a/apps/openmw_test_suite/detournavigator/asyncnavmeshupdater.cpp b/apps/openmw_test_suite/detournavigator/asyncnavmeshupdater.cpp index 1fa868f133..f51c118a8a 100644 --- a/apps/openmw_test_suite/detournavigator/asyncnavmeshupdater.cpp +++ b/apps/openmw_test_suite/detournavigator/asyncnavmeshupdater.cpp @@ -74,7 +74,7 @@ namespace mRecastMeshManager.setWorldspace(mWorldspace, nullptr); addHeightFieldPlane(mRecastMeshManager); AsyncNavMeshUpdater updater(mSettings, mRecastMeshManager, mOffMeshConnectionsManager, nullptr); - const auto navMeshCacheItem = std::make_shared(makeEmptyNavMesh(mSettings), 1); + const auto navMeshCacheItem = std::make_shared(1, mSettings); const std::map changedTiles{ { TilePosition{ 0, 0 }, ChangeType::add } }; updater.post(mAgentBounds, navMeshCacheItem, mPlayerTile, mWorldspace, changedTiles); updater.wait(WaitConditionType::allJobsDone, &mListener); @@ -86,7 +86,7 @@ namespace mRecastMeshManager.setWorldspace(mWorldspace, nullptr); addHeightFieldPlane(mRecastMeshManager); AsyncNavMeshUpdater updater(mSettings, mRecastMeshManager, mOffMeshConnectionsManager, nullptr); - const auto navMeshCacheItem = std::make_shared(makeEmptyNavMesh(mSettings), 1); + const auto navMeshCacheItem = std::make_shared(1, mSettings); const std::map changedTiles{ { TilePosition{ 0, 0 }, ChangeType::add } }; updater.post(mAgentBounds, navMeshCacheItem, mPlayerTile, mWorldspace, changedTiles); updater.wait(WaitConditionType::allJobsDone, &mListener); @@ -109,7 +109,7 @@ namespace mRecastMeshManager.setWorldspace(mWorldspace, nullptr); addHeightFieldPlane(mRecastMeshManager); AsyncNavMeshUpdater updater(mSettings, mRecastMeshManager, mOffMeshConnectionsManager, nullptr); - const auto navMeshCacheItem = std::make_shared(makeEmptyNavMesh(mSettings), 1); + const auto navMeshCacheItem = std::make_shared(1, mSettings); const std::map changedTiles{ { TilePosition{ 0, 0 }, ChangeType::update } }; updater.post(mAgentBounds, navMeshCacheItem, mPlayerTile, mWorldspace, changedTiles); updater.wait(WaitConditionType::allJobsDone, &mListener); @@ -135,7 +135,7 @@ namespace auto db = std::make_unique(":memory:", std::numeric_limits::max()); NavMeshDb* const dbPtr = db.get(); AsyncNavMeshUpdater updater(mSettings, mRecastMeshManager, mOffMeshConnectionsManager, std::move(db)); - const auto navMeshCacheItem = std::make_shared(makeEmptyNavMesh(mSettings), 1); + const auto navMeshCacheItem = std::make_shared(1, mSettings); const TilePosition tilePosition{ 0, 0 }; const std::map changedTiles{ { tilePosition, ChangeType::add } }; updater.post(mAgentBounds, navMeshCacheItem, mPlayerTile, mWorldspace, changedTiles); @@ -162,7 +162,7 @@ namespace NavMeshDb* const dbPtr = db.get(); mSettings.mWriteToNavMeshDb = false; AsyncNavMeshUpdater updater(mSettings, mRecastMeshManager, mOffMeshConnectionsManager, std::move(db)); - const auto navMeshCacheItem = std::make_shared(makeEmptyNavMesh(mSettings), 1); + const auto navMeshCacheItem = std::make_shared(1, mSettings); const TilePosition tilePosition{ 0, 0 }; const std::map changedTiles{ { tilePosition, ChangeType::add } }; updater.post(mAgentBounds, navMeshCacheItem, mPlayerTile, mWorldspace, changedTiles); @@ -187,7 +187,7 @@ namespace NavMeshDb* const dbPtr = db.get(); mSettings.mWriteToNavMeshDb = false; AsyncNavMeshUpdater updater(mSettings, mRecastMeshManager, mOffMeshConnectionsManager, std::move(db)); - const auto navMeshCacheItem = std::make_shared(makeEmptyNavMesh(mSettings), 1); + const auto navMeshCacheItem = std::make_shared(1, mSettings); const TilePosition tilePosition{ 0, 0 }; const std::map changedTiles{ { tilePosition, ChangeType::add } }; updater.post(mAgentBounds, navMeshCacheItem, mPlayerTile, mWorldspace, changedTiles); @@ -207,7 +207,7 @@ namespace mSettings.mMaxNavMeshTilesCacheSize = 0; AsyncNavMeshUpdater updater(mSettings, mRecastMeshManager, mOffMeshConnectionsManager, std::make_unique(":memory:", std::numeric_limits::max())); - const auto navMeshCacheItem = std::make_shared(makeEmptyNavMesh(mSettings), 1); + const auto navMeshCacheItem = std::make_shared(1, mSettings); const std::map changedTiles{ { TilePosition{ 0, 0 }, ChangeType::add } }; updater.post(mAgentBounds, navMeshCacheItem, mPlayerTile, mWorldspace, changedTiles); updater.wait(WaitConditionType::allJobsDone, &mListener); @@ -236,7 +236,7 @@ namespace mRecastMeshManager.setWorldspace(mWorldspace, nullptr); addHeightFieldPlane(mRecastMeshManager); AsyncNavMeshUpdater updater(mSettings, mRecastMeshManager, mOffMeshConnectionsManager, nullptr); - const auto navMeshCacheItem = std::make_shared(makeEmptyNavMesh(mSettings), 1); + const auto navMeshCacheItem = std::make_shared(1, mSettings); const std::map changedTilesAdd{ { TilePosition{ 0, 0 }, ChangeType::add } }; updater.post(mAgentBounds, navMeshCacheItem, mPlayerTile, mWorldspace, changedTilesAdd); updater.wait(WaitConditionType::allJobsDone, &mListener); @@ -258,7 +258,7 @@ namespace auto db = std::make_unique(":memory:", 4097); NavMeshDb* const dbPtr = db.get(); AsyncNavMeshUpdater updater(mSettings, mRecastMeshManager, mOffMeshConnectionsManager, std::move(db)); - const auto navMeshCacheItem = std::make_shared(makeEmptyNavMesh(mSettings), 1); + const auto navMeshCacheItem = std::make_shared(1, mSettings); std::map changedTiles; for (int x = -5; x <= 5; ++x) for (int y = -5; y <= 5; ++y) diff --git a/components/detournavigator/findrandompointaroundcircle.cpp b/components/detournavigator/findrandompointaroundcircle.cpp index 731b2b9226..5f856915cb 100644 --- a/components/detournavigator/findrandompointaroundcircle.cpp +++ b/components/detournavigator/findrandompointaroundcircle.cpp @@ -1,20 +1,15 @@ #include "findrandompointaroundcircle.hpp" #include "findsmoothpath.hpp" -#include "settings.hpp" #include #include namespace DetourNavigator { - std::optional findRandomPointAroundCircle(const dtNavMesh& navMesh, const osg::Vec3f& halfExtents, - const osg::Vec3f& start, const float maxRadius, const Flags includeFlags, const DetourSettings& settings, + std::optional findRandomPointAroundCircle(const dtNavMeshQuery& navMeshQuery, + const osg::Vec3f& halfExtents, const osg::Vec3f& start, const float maxRadius, const Flags includeFlags, float (*prng)()) { - dtNavMeshQuery navMeshQuery; - if (!initNavMeshQuery(navMeshQuery, navMesh, settings.mMaxNavMeshQueryNodes)) - return std::optional(); - dtQueryFilter queryFilter; queryFilter.setIncludeFlags(includeFlags); diff --git a/components/detournavigator/findrandompointaroundcircle.hpp b/components/detournavigator/findrandompointaroundcircle.hpp index 9374396eb0..eca90617cf 100644 --- a/components/detournavigator/findrandompointaroundcircle.hpp +++ b/components/detournavigator/findrandompointaroundcircle.hpp @@ -6,14 +6,14 @@ #include #include -class dtNavMesh; +class dtNavMeshQuery; namespace DetourNavigator { struct DetourSettings; - std::optional findRandomPointAroundCircle(const dtNavMesh& navMesh, const osg::Vec3f& halfExtents, - const osg::Vec3f& start, const float maxRadius, const Flags includeFlags, const DetourSettings& settings, + std::optional findRandomPointAroundCircle(const dtNavMeshQuery& navMeshQuery, + const osg::Vec3f& halfExtents, const osg::Vec3f& start, const float maxRadius, const Flags includeFlags, float (*prng)()); } diff --git a/components/detournavigator/findsmoothpath.hpp b/components/detournavigator/findsmoothpath.hpp index b96b2a8139..95f84381dd 100644 --- a/components/detournavigator/findsmoothpath.hpp +++ b/components/detournavigator/findsmoothpath.hpp @@ -252,14 +252,10 @@ namespace DetourNavigator } template - Status findSmoothPath(const dtNavMesh& navMesh, const osg::Vec3f& halfExtents, const float stepSize, - const osg::Vec3f& start, const osg::Vec3f& end, const Flags includeFlags, const AreaCosts& areaCosts, - const Settings& settings, float endTolerance, OutputIterator out) + Status findSmoothPath(const dtNavMesh& navMesh, const dtNavMeshQuery& navMeshQuery, const osg::Vec3f& halfExtents, + const float stepSize, const osg::Vec3f& start, const osg::Vec3f& end, const Flags includeFlags, + const AreaCosts& areaCosts, const Settings& settings, float endTolerance, OutputIterator out) { - dtNavMeshQuery navMeshQuery; - if (!initNavMeshQuery(navMeshQuery, navMesh, settings.mDetour.mMaxNavMeshQueryNodes)) - return Status::InitNavMeshQueryFailed; - dtQueryFilter queryFilter; queryFilter.setIncludeFlags(includeFlags); queryFilter.setAreaCost(AreaType_water, areaCosts.mWater); diff --git a/components/detournavigator/makenavmesh.cpp b/components/detournavigator/makenavmesh.cpp index 8616f1a9a6..0837680fc1 100644 --- a/components/detournavigator/makenavmesh.cpp +++ b/components/detournavigator/makenavmesh.cpp @@ -13,7 +13,6 @@ #include "recastparams.hpp" #include "settings.hpp" #include "settingsutils.hpp" -#include "sharednavmesh.hpp" #include "components/debug/debuglog.hpp" @@ -604,7 +603,7 @@ namespace DetourNavigator return NavMeshData(navMeshData, navMeshDataSize); } - NavMeshPtr makeEmptyNavMesh(const Settings& settings) + void initEmptyNavMesh(const Settings& settings, dtNavMesh& navMesh) { // Max tiles and max polys affect how the tile IDs are caculated. // There are 22 bits available for identifying a tile and a polygon. @@ -623,17 +622,10 @@ namespace DetourNavigator params.maxTiles = 1 << tilesBits; params.maxPolys = 1 << polysBits; - NavMeshPtr navMesh(dtAllocNavMesh(), &dtFreeNavMesh); - - if (navMesh == nullptr) - throw NavigatorException("Failed to allocate navmesh"); - - const auto status = navMesh->init(¶ms); + const auto status = navMesh.init(¶ms); if (!dtStatusSucceed(status)) throw NavigatorException("Failed to init navmesh"); - - return navMesh; } bool isSupportedAgentBounds(const RecastSettings& settings, const AgentBounds& agentBounds) diff --git a/components/detournavigator/makenavmesh.hpp b/components/detournavigator/makenavmesh.hpp index 842ef2ab6a..01542d066d 100644 --- a/components/detournavigator/makenavmesh.hpp +++ b/components/detournavigator/makenavmesh.hpp @@ -2,7 +2,6 @@ #define OPENMW_COMPONENTS_DETOURNAVIGATOR_MAKENAVMESH_H #include "recastmesh.hpp" -#include "sharednavmesh.hpp" #include "tileposition.hpp" #include @@ -49,7 +48,7 @@ namespace DetourNavigator const std::vector& offMeshConnections, const AgentBounds& agentBounds, const TilePosition& tile, const RecastSettings& settings); - NavMeshPtr makeEmptyNavMesh(const Settings& settings); + void initEmptyNavMesh(const Settings& settings, dtNavMesh& navMesh); bool isSupportedAgentBounds(const RecastSettings& settings, const AgentBounds& agentBounds); } diff --git a/components/detournavigator/navigatorutils.cpp b/components/detournavigator/navigatorutils.cpp index a939d0b554..cad201825c 100644 --- a/components/detournavigator/navigatorutils.cpp +++ b/components/detournavigator/navigatorutils.cpp @@ -11,11 +11,12 @@ namespace DetourNavigator const auto navMesh = navigator.getNavMesh(agentBounds); if (!navMesh) return std::nullopt; - const auto& settings = navigator.getSettings(); - const auto result = DetourNavigator::findRandomPointAroundCircle(navMesh->lockConst()->getImpl(), + const Settings& settings = navigator.getSettings(); + const auto locked = navMesh->lock(); + const auto result = DetourNavigator::findRandomPointAroundCircle(locked->getQuery(), toNavMeshCoordinates(settings.mRecast, agentBounds.mHalfExtents), toNavMeshCoordinates(settings.mRecast, start), toNavMeshCoordinates(settings.mRecast, maxRadius), - includeFlags, settings.mDetour, prng); + includeFlags, prng); if (!result) return std::nullopt; return std::optional(fromNavMeshCoordinates(settings.mRecast, *result)); @@ -27,11 +28,11 @@ namespace DetourNavigator const auto navMesh = navigator.getNavMesh(agentBounds); if (navMesh == nullptr) return std::nullopt; - const auto& settings = navigator.getSettings(); - const auto result = DetourNavigator::raycast(navMesh->lockConst()->getImpl(), + const Settings& settings = navigator.getSettings(); + const auto locked = navMesh->lock(); + const auto result = DetourNavigator::raycast(locked->getQuery(), toNavMeshCoordinates(settings.mRecast, agentBounds.mHalfExtents), - toNavMeshCoordinates(settings.mRecast, start), toNavMeshCoordinates(settings.mRecast, end), includeFlags, - settings.mDetour); + toNavMeshCoordinates(settings.mRecast, start), toNavMeshCoordinates(settings.mRecast, end), includeFlags); if (!result) return std::nullopt; return fromNavMeshCoordinates(settings.mRecast, *result); diff --git a/components/detournavigator/navigatorutils.hpp b/components/detournavigator/navigatorutils.hpp index f7f5a93194..473c2f11c9 100644 --- a/components/detournavigator/navigatorutils.hpp +++ b/components/detournavigator/navigatorutils.hpp @@ -35,8 +35,9 @@ namespace DetourNavigator const auto navMesh = navigator.getNavMesh(agentBounds); if (navMesh == nullptr) return Status::NavMeshNotFound; - const auto settings = navigator.getSettings(); - return findSmoothPath(navMesh->lockConst()->getImpl(), + const Settings& settings = navigator.getSettings(); + const auto locked = navMesh->lock(); + return findSmoothPath(locked->getImpl(), locked->getQuery(), toNavMeshCoordinates(settings.mRecast, agentBounds.mHalfExtents), toNavMeshCoordinates(settings.mRecast, stepSize), toNavMeshCoordinates(settings.mRecast, start), toNavMeshCoordinates(settings.mRecast, end), includeFlags, areaCosts, settings, endTolerance, out); diff --git a/components/detournavigator/navmeshcacheitem.cpp b/components/detournavigator/navmeshcacheitem.cpp index 388ede272e..8338165db6 100644 --- a/components/detournavigator/navmeshcacheitem.cpp +++ b/components/detournavigator/navmeshcacheitem.cpp @@ -1,12 +1,16 @@ #include "navmeshcacheitem.hpp" +#include "debug.hpp" +#include "makenavmesh.hpp" #include "navmeshdata.hpp" #include "navmeshtilescache.hpp" #include "navmeshtileview.hpp" +#include "settings.hpp" #include "tileposition.hpp" #include #include +#include namespace { @@ -66,18 +70,32 @@ namespace DetourNavigator return navMesh.getTileAt(position.x(), position.y(), layer); } + NavMeshCacheItem::NavMeshCacheItem(std::size_t generation, const Settings& settings) + : mVersion{ generation, 0 } + { + initEmptyNavMesh(settings, mImpl); + + if (const dtStatus status = mQuery.init(&mImpl, settings.mDetour.mMaxNavMeshQueryNodes); + !dtStatusSucceed(status)) + { + std::ostringstream error; + error << "Failed to init navmesh query: " << WriteDtStatus{ status }; + throw std::runtime_error(error.str()); + } + } + UpdateNavMeshStatus NavMeshCacheItem::updateTile( const TilePosition& position, NavMeshTilesCache::Value&& cached, NavMeshData&& navMeshData) { - const dtMeshTile* currentTile = getTile(*mImpl, position); + const dtMeshTile* currentTile = getTile(mImpl, position); if (currentTile != nullptr && asNavMeshTileConstView(*currentTile) == asNavMeshTileConstView(navMeshData.mValue.get())) { return UpdateNavMeshStatus::ignored; } - bool removed = ::removeTile(*mImpl, position); + bool removed = ::removeTile(mImpl, position); removed = mEmptyTiles.erase(position) > 0 || removed; - const auto addStatus = addTile(*mImpl, navMeshData.mValue.get(), navMeshData.mSize); + const auto addStatus = addTile(mImpl, navMeshData.mValue.get(), navMeshData.mSize); if (dtStatusSucceed(addStatus)) { auto tile = mUsedTiles.find(position); @@ -111,7 +129,7 @@ namespace DetourNavigator UpdateNavMeshStatus NavMeshCacheItem::removeTile(const TilePosition& position) { - bool removed = ::removeTile(*mImpl, position); + bool removed = ::removeTile(mImpl, position); removed = mEmptyTiles.erase(position) > 0 || removed; if (removed) { @@ -123,7 +141,7 @@ namespace DetourNavigator UpdateNavMeshStatus NavMeshCacheItem::markAsEmpty(const TilePosition& position) { - bool removed = ::removeTile(*mImpl, position); + bool removed = ::removeTile(mImpl, position); removed = mEmptyTiles.insert(position).second || removed; if (removed) { diff --git a/components/detournavigator/navmeshcacheitem.hpp b/components/detournavigator/navmeshcacheitem.hpp index ddf63368ba..ec76b56a46 100644 --- a/components/detournavigator/navmeshcacheitem.hpp +++ b/components/detournavigator/navmeshcacheitem.hpp @@ -3,10 +3,12 @@ #include "navmeshdata.hpp" #include "navmeshtilescache.hpp" -#include "sharednavmesh.hpp" #include "tileposition.hpp" #include "version.hpp" +#include +#include + #include #include #include @@ -15,6 +17,8 @@ struct dtMeshTile; namespace DetourNavigator { + struct Settings; + enum class UpdateNavMeshStatus : unsigned { ignored = 0, @@ -102,13 +106,11 @@ namespace DetourNavigator class NavMeshCacheItem { public: - NavMeshCacheItem(const NavMeshPtr& impl, std::size_t generation) - : mImpl(impl) - , mVersion{ generation, 0 } - { - } + explicit NavMeshCacheItem(std::size_t generation, const Settings& settings); - const dtNavMesh& getImpl() const { return *mImpl; } + const dtNavMesh& getImpl() const { return mImpl; } + + dtNavMeshQuery& getQuery() { return mQuery; } const Version& getVersion() const { return mVersion; } @@ -125,7 +127,7 @@ namespace DetourNavigator void forEachUsedTile(Function&& function) const { for (const auto& [position, tile] : mUsedTiles) - if (const dtMeshTile* meshTile = getTile(*mImpl, position)) + if (const dtMeshTile* meshTile = getTile(mImpl, position)) function(position, tile.mVersion, *meshTile); } @@ -137,8 +139,9 @@ namespace DetourNavigator NavMeshData mData; }; - NavMeshPtr mImpl; Version mVersion; + dtNavMesh mImpl; + dtNavMeshQuery mQuery; std::map mUsedTiles; std::set mEmptyTiles; }; diff --git a/components/detournavigator/navmeshmanager.cpp b/components/detournavigator/navmeshmanager.cpp index f8d6ce7d79..e237f6c592 100644 --- a/components/detournavigator/navmeshmanager.cpp +++ b/components/detournavigator/navmeshmanager.cpp @@ -69,7 +69,7 @@ namespace DetourNavigator return; mRecastMeshManager.setWorldspace(worldspace, getImpl(guard)); for (auto& [agent, cache] : mCache) - cache = std::make_shared(makeEmptyNavMesh(mSettings), ++mGenerationCounter); + cache = std::make_shared(++mGenerationCounter, mSettings); mWorldspace = worldspace; } @@ -123,8 +123,7 @@ namespace DetourNavigator auto cached = mCache.find(agentBounds); if (cached != mCache.end()) return; - mCache.insert(std::make_pair( - agentBounds, std::make_shared(makeEmptyNavMesh(mSettings), ++mGenerationCounter))); + mCache.emplace(agentBounds, std::make_shared(++mGenerationCounter, mSettings)); mPlayerTile.reset(); Log(Debug::Debug) << "cache add for agent=" << agentBounds; } diff --git a/components/detournavigator/raycast.cpp b/components/detournavigator/raycast.cpp index 665b2433c6..7456912c08 100644 --- a/components/detournavigator/raycast.cpp +++ b/components/detournavigator/raycast.cpp @@ -1,6 +1,4 @@ #include "raycast.hpp" -#include "findsmoothpath.hpp" -#include "settings.hpp" #include #include @@ -9,13 +7,9 @@ namespace DetourNavigator { - std::optional raycast(const dtNavMesh& navMesh, const osg::Vec3f& halfExtents, const osg::Vec3f& start, - const osg::Vec3f& end, const Flags includeFlags, const DetourSettings& settings) + std::optional raycast(const dtNavMeshQuery& navMeshQuery, const osg::Vec3f& halfExtents, + const osg::Vec3f& start, const osg::Vec3f& end, const Flags includeFlags) { - dtNavMeshQuery navMeshQuery; - if (!initNavMeshQuery(navMeshQuery, navMesh, settings.mMaxNavMeshQueryNodes)) - return {}; - dtQueryFilter queryFilter; queryFilter.setIncludeFlags(includeFlags); diff --git a/components/detournavigator/raycast.hpp b/components/detournavigator/raycast.hpp index 9b9125fb71..855c5562fc 100644 --- a/components/detournavigator/raycast.hpp +++ b/components/detournavigator/raycast.hpp @@ -6,14 +6,14 @@ #include #include -class dtNavMesh; +class dtNavMeshQuery; namespace DetourNavigator { struct DetourSettings; - std::optional raycast(const dtNavMesh& navMesh, const osg::Vec3f& halfExtents, const osg::Vec3f& start, - const osg::Vec3f& end, const Flags includeFlags, const DetourSettings& settings); + std::optional raycast(const dtNavMeshQuery& navMeshQuery, const osg::Vec3f& halfExtents, + const osg::Vec3f& start, const osg::Vec3f& end, const Flags includeFlags); } #endif diff --git a/components/detournavigator/sharednavmesh.hpp b/components/detournavigator/sharednavmesh.hpp deleted file mode 100644 index beb0a3c412..0000000000 --- a/components/detournavigator/sharednavmesh.hpp +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef OPENMW_COMPONENTS_DETOURNAVIGATOR_SHAREDNAVMESH_H -#define OPENMW_COMPONENTS_DETOURNAVIGATOR_SHAREDNAVMESH_H - -#include - -class dtNavMesh; - -namespace DetourNavigator -{ - using NavMeshPtr = std::shared_ptr; -} - -#endif