From e1bed86d7ec119bd8e86ef2cd2bfd16b82aa6976 Mon Sep 17 00:00:00 2001 From: elsid Date: Sat, 18 Sep 2021 15:52:03 +0200 Subject: [PATCH] Do single navigator update per frame Primarily for crossing cell border case. Each Navigator::update call has a cost. Doing it multiple times per frame increased frame duration on cell loading. Call Navigator::wait only when cell has changed but do not use Scene::hasCellChanged because it doesn't always indicates it. --- .../mwmechanics/mechanicsmanagerimp.cpp | 8 --- apps/openmw/mwworld/scene.cpp | 25 ++----- apps/openmw/mwworld/scene.hpp | 5 ++ apps/openmw/mwworld/worldimp.cpp | 23 +++---- apps/openmw/mwworld/worldimp.hpp | 1 - .../detournavigator/navigator.cpp | 26 +++++-- .../detournavigator/asyncnavmeshupdater.cpp | 37 +++++----- .../detournavigator/asyncnavmeshupdater.hpp | 4 +- components/detournavigator/debug.cpp | 6 ++ components/detournavigator/debug.hpp | 4 ++ components/detournavigator/navigator.hpp | 38 +++------- components/detournavigator/navigatorimpl.cpp | 69 +++++++------------ components/detournavigator/navigatorimpl.hpp | 24 +++---- components/detournavigator/navigatorstub.hpp | 50 +++----------- components/detournavigator/navmeshmanager.cpp | 25 +++---- components/detournavigator/navmeshmanager.hpp | 10 +-- 16 files changed, 140 insertions(+), 215 deletions(-) diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index e0e70348b1..acb03b1504 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -7,8 +7,6 @@ #include #include -#include - #include #include "../mwworld/esmstore.hpp" @@ -813,12 +811,6 @@ namespace MWMechanics bool MechanicsManager::toggleAI() { mAI = !mAI; - - MWBase::World* world = MWBase::Environment::get().getWorld(); - world->getNavigator()->setUpdatesEnabled(mAI); - if (mAI) - world->getNavigator()->update(world->getPlayerPtr().getRefData().getPosition().asVec3()); - return mAI; } diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index d49d6e8fda..82375c8067 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -365,8 +365,6 @@ namespace MWWorld if (const auto pathgrid = mWorld.getStore().get().search(*cell->getCell())) mNavigator.removePathgrid(*pathgrid); - mNavigator.update(mWorld.getPlayerPtr().getRefData().getPosition().asVec3()); - MWBase::Environment::get().getMechanicsManager()->drop (cell); mRendering.removeCell(cell); @@ -514,12 +512,7 @@ namespace MWWorld void Scene::playerMoved(const osg::Vec3f &pos) { - if (mCurrentCell == nullptr) - return; - - mNavigator.updatePlayerPosition(pos); - - if (!mCurrentCell->isExterior()) + if (!mCurrentCell || !mCurrentCell->isExterior()) return; osg::Vec2i newCell = getNewGridCenter(pos, &mCurrentGridCenter); @@ -619,7 +612,7 @@ namespace MWWorld if (changeEvent) mCellChanged = true; - mNavigator.wait(*loadingListener, DetourNavigator::WaitConditionType::requiredTilesPresent); + mCellLoaded = true; } void Scene::addPostponedPhysicsObjects() @@ -868,13 +861,13 @@ namespace MWWorld if (changeEvent) mCellChanged = true; + mCellLoaded = true; + if (useFading) MWBase::Environment::get().getWindowManager()->fadeScreenIn(0.5); MWBase::Environment::get().getWindowManager()->changeCell(mCurrentCell); - mNavigator.wait(*loadingListener, DetourNavigator::WaitConditionType::requiredTilesPresent); - MWBase::Environment::get().getWorld()->getPostProcessor()->setExteriorFlag(cell->getCell()->mData.mFlags & ESM::Cell::QuasiEx); } @@ -921,11 +914,6 @@ namespace MWWorld addObject(ptr, mWorld, mPagedRefs, *mPhysics, mRendering); addObject(ptr, mWorld, *mPhysics, mNavigator); mWorld.scaleObject(ptr, ptr.getCellRef().getScale()); - if (mCurrentCell != nullptr) - { - const auto player = mWorld.getPlayerPtr(); - mNavigator.update(player.getRefData().getPosition().asVec3()); - } } catch (std::exception& e) { @@ -945,11 +933,6 @@ namespace MWWorld if (const auto object = mPhysics->getObject(ptr)) { mNavigator.removeObject(DetourNavigator::ObjectId(object)); - if (mCurrentCell != nullptr) - { - const auto player = mWorld.getPlayerPtr(); - mNavigator.update(player.getRefData().getPosition().asVec3()); - } } else if (mPhysics->getActor(ptr)) { diff --git a/apps/openmw/mwworld/scene.hpp b/apps/openmw/mwworld/scene.hpp index 075213a66a..7e69e8e97d 100644 --- a/apps/openmw/mwworld/scene.hpp +++ b/apps/openmw/mwworld/scene.hpp @@ -85,6 +85,7 @@ namespace MWWorld CellStore* mCurrentCell; // the cell the player is in CellStoreCollection mActiveCells; bool mCellChanged; + bool mCellLoaded = false; MWWorld::World& mWorld; MWPhysics::PhysicsSystem *mPhysics; MWRender::RenderingManager& mRendering; @@ -152,6 +153,10 @@ namespace MWWorld bool hasCellChanged() const; ///< Has the set of active cells changed, since the last frame? + bool hasCellLoaded() const { return mCellLoaded; } + + void resetCellLoaded() { mCellLoaded = false; } + void changeToInteriorCell (const std::string& cellName, const ESM::Position& position, bool adjustPlayerPos, bool changeEvent=true); ///< Move to interior cell. /// @param changeEvent Set cellChanged flag? diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index af5abdd8f3..e212b9ec7e 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -154,7 +154,6 @@ namespace MWWorld mUserDataPath(userDataPath), mDefaultHalfExtents(Settings::Manager::getVector3("default actor pathfind half extents", "Game")), mDefaultActorCollisionShapeType(DetourNavigator::toCollisionShapeType(Settings::Manager::getInt("actor collision shape type", "Game"))), - mShouldUpdateNavigator(false), mActivationDistanceOverride (activationDistanceOverride), mStartCell(startCell), mDistanceToFacedObject(-1.f), mTeleportEnabled(true), mLevitationEnabled(true), mGoToJail(false), mDaysInPrison(0), @@ -1536,12 +1535,7 @@ namespace MWWorld if (const auto object = mPhysics->getObject(door.first)) updateNavigatorObject(*object); - auto player = getPlayerPtr(); - if (mShouldUpdateNavigator && player.getCell() != nullptr) - { - mNavigator->update(player.getRefData().getPosition().asVec3()); - mShouldUpdateNavigator = false; - } + mNavigator->update(getPlayerPtr().getRefData().getPosition().asVec3()); } void World::updateNavigatorObject(const MWPhysics::Object& object) @@ -1549,8 +1543,7 @@ namespace MWWorld const MWWorld::Ptr ptr = object.getPtr(); const DetourNavigator::ObjectShapes shapes(object.getShapeInstance(), DetourNavigator::ObjectTransform {ptr.getRefData().getPosition(), ptr.getCellRef().getScale()}); - mShouldUpdateNavigator = mNavigator->updateObject(DetourNavigator::ObjectId(&object), shapes, object.getTransform()) - || mShouldUpdateNavigator; + mNavigator->updateObject(DetourNavigator::ObjectId(&object), shapes, object.getTransform()); } const MWPhysics::RayCastingInterface* World::getRayCasting() const @@ -1821,10 +1814,7 @@ namespace MWWorld updateWeather(duration, paused); - if (!paused) - { - updateNavigator(); - } + updateNavigator(); mPlayer->update(); @@ -1842,6 +1832,13 @@ namespace MWWorld mSpellPreloadTimer = 0.1f; preloadSpells(); } + + if (mWorldScene->hasCellLoaded()) + { + mNavigator->wait(*MWBase::Environment::get().getWindowManager()->getLoadingScreen(), + DetourNavigator::WaitConditionType::requiredTilesPresent); + mWorldScene->resetCellLoaded(); + } } void World::updatePhysics (float duration, bool paused, osg::Timer_t frameStart, unsigned int frameNumber, osg::Stats& stats) diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index c48504cb05..74e34d5132 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -113,7 +113,6 @@ namespace MWWorld osg::Vec3f mDefaultHalfExtents; DetourNavigator::CollisionShapeType mDefaultActorCollisionShapeType; - bool mShouldUpdateNavigator; int mActivationDistanceOverride; diff --git a/apps/openmw_test_suite/detournavigator/navigator.cpp b/apps/openmw_test_suite/detournavigator/navigator.cpp index f49f3cdc74..57dd50739e 100644 --- a/apps/openmw_test_suite/detournavigator/navigator.cpp +++ b/apps/openmw_test_suite/detournavigator/navigator.cpp @@ -439,8 +439,17 @@ namespace const int cellSize2 = mHeightfieldTileSize * (surface2.mSize - 1); mNavigator->addAgent(mAgentBounds); - EXPECT_TRUE(mNavigator->addHeightfield(mCellPosition, cellSize1, surface1)); - EXPECT_FALSE(mNavigator->addHeightfield(mCellPosition, cellSize2, surface2)); + mNavigator->addHeightfield(mCellPosition, cellSize1, surface1); + mNavigator->update(mPlayerPosition); + mNavigator->wait(mListener, WaitConditionType::allJobsDone); + + const Version version = mNavigator->getNavMesh(mAgentBounds)->lockConst()->getVersion(); + + mNavigator->addHeightfield(mCellPosition, cellSize2, surface2); + mNavigator->update(mPlayerPosition); + mNavigator->wait(mListener, WaitConditionType::allJobsDone); + + EXPECT_EQ(mNavigator->getNavMesh(mAgentBounds)->lockConst()->getVersion(), version); } TEST_F(DetourNavigatorNavigatorTest, path_should_be_around_avoid_shape) @@ -1142,7 +1151,16 @@ namespace const float level2 = 2; mNavigator->addAgent(mAgentBounds); - EXPECT_TRUE(mNavigator->addWater(mCellPosition, cellSize1, level1)); - EXPECT_FALSE(mNavigator->addWater(mCellPosition, cellSize2, level2)); + mNavigator->addWater(mCellPosition, cellSize1, level1); + mNavigator->update(mPlayerPosition); + mNavigator->wait(mListener, WaitConditionType::allJobsDone); + + const Version version = mNavigator->getNavMesh(mAgentBounds)->lockConst()->getVersion(); + + mNavigator->addWater(mCellPosition, cellSize2, level2); + mNavigator->update(mPlayerPosition); + mNavigator->wait(mListener, WaitConditionType::allJobsDone); + + EXPECT_EQ(mNavigator->getNavMesh(mAgentBounds)->lockConst()->getVersion(), version); } } diff --git a/components/detournavigator/asyncnavmeshupdater.cpp b/components/detournavigator/asyncnavmeshupdater.cpp index 3cc19d12ba..f1af3fc614 100644 --- a/components/detournavigator/asyncnavmeshupdater.cpp +++ b/components/detournavigator/asyncnavmeshupdater.cpp @@ -216,27 +216,13 @@ namespace DetourNavigator void AsyncNavMeshUpdater::wait(Loading::Listener& listener, WaitConditionType waitConditionType) { - if (mSettings.get().mWaitUntilMinDistanceToPlayer == 0) - return; - listener.setLabel("#{Navigation:BuildingNavigationMesh}"); - const std::size_t initialJobsLeft = getTotalJobs(); - std::size_t maxProgress = initialJobsLeft + mThreads.size(); - listener.setProgressRange(maxProgress); switch (waitConditionType) { case WaitConditionType::requiredTilesPresent: - { - const int minDistanceToPlayer = waitUntilJobsDoneForNotPresentTiles(initialJobsLeft, maxProgress, listener); - if (minDistanceToPlayer < mSettings.get().mWaitUntilMinDistanceToPlayer) - { - mProcessingTiles.wait(mProcessed, [] (const auto& v) { return v.empty(); }); - listener.setProgress(maxProgress); - } + waitUntilJobsDoneForNotPresentTiles(listener); break; - } case WaitConditionType::allJobsDone: waitUntilAllJobsDone(); - listener.setProgress(maxProgress); break; } } @@ -255,8 +241,10 @@ namespace DetourNavigator thread.join(); } - int AsyncNavMeshUpdater::waitUntilJobsDoneForNotPresentTiles(const std::size_t initialJobsLeft, std::size_t& maxProgress, Loading::Listener& listener) + void AsyncNavMeshUpdater::waitUntilJobsDoneForNotPresentTiles(Loading::Listener& listener) { + const std::size_t initialJobsLeft = getTotalJobs(); + std::size_t maxProgress = initialJobsLeft + mThreads.size(); std::size_t prevJobsLeft = initialJobsLeft; std::size_t jobsDone = 0; std::size_t jobsLeft = 0; @@ -275,7 +263,13 @@ namespace DetourNavigator return minDistanceToPlayer >= maxDistanceToPlayer; }; std::unique_lock lock(mMutex); - while (!mDone.wait_for(lock, std::chrono::milliseconds(250), isDone)) + if (getMinDistanceTo(playerPosition, maxDistanceToPlayer, mPushed, mPresentTiles) >= maxDistanceToPlayer + || (mJobs.empty() && mProcessingTiles.lockConst()->empty())) + return; + Loading::ScopedLoad load(&listener); + listener.setLabel("#{Navigation:BuildingNavigationMesh}"); + listener.setProgressRange(maxProgress); + while (!mDone.wait_for(lock, std::chrono::milliseconds(20), isDone)) { if (maxProgress < jobsLeft) { @@ -291,14 +285,19 @@ namespace DetourNavigator listener.increaseProgress(newJobsDone); } } - return minDistanceToPlayer; + lock.unlock(); + if (minDistanceToPlayer < maxDistanceToPlayer) + { + mProcessingTiles.wait(mProcessed, [] (const auto& v) { return v.empty(); }); + listener.setProgress(maxProgress); + } } void AsyncNavMeshUpdater::waitUntilAllJobsDone() { { std::unique_lock lock(mMutex); - mDone.wait(lock, [this] { return mJobs.size() == 0; }); + mDone.wait(lock, [this] { return mJobs.empty(); }); } mProcessingTiles.wait(mProcessed, [] (const auto& v) { return v.empty(); }); } diff --git a/components/detournavigator/asyncnavmeshupdater.hpp b/components/detournavigator/asyncnavmeshupdater.hpp index 30bbc59ee8..f9fadde4f6 100644 --- a/components/detournavigator/asyncnavmeshupdater.hpp +++ b/components/detournavigator/asyncnavmeshupdater.hpp @@ -223,9 +223,9 @@ namespace DetourNavigator void cleanupLastUpdates(); - int waitUntilJobsDoneForNotPresentTiles(const std::size_t initialJobsLeft, std::size_t& maxJobsLeft, Loading::Listener& listener); + inline void waitUntilJobsDoneForNotPresentTiles(Loading::Listener& listener); - void waitUntilAllJobsDone(); + inline void waitUntilAllJobsDone(); }; void reportStats(const AsyncNavMeshUpdater::Stats& stats, unsigned int frameNumber, osg::Stats& out); diff --git a/components/detournavigator/debug.cpp b/components/detournavigator/debug.cpp index d274023e78..536cad78b2 100644 --- a/components/detournavigator/debug.cpp +++ b/components/detournavigator/debug.cpp @@ -3,6 +3,7 @@ #include "recastmesh.hpp" #include "settings.hpp" #include "settingsutils.hpp" +#include "version.hpp" #include @@ -191,6 +192,11 @@ namespace DetourNavigator return stream << "ChangeType::" << static_cast(value); } + std::ostream& operator<<(std::ostream& stream, const Version& value) + { + return stream << "Version {" << value.mGeneration << ", " << value.mRevision << "}"; + } + void writeToFile(const RecastMesh& recastMesh, const std::string& pathPrefix, const std::string& revision, const RecastSettings& settings) { diff --git a/components/detournavigator/debug.hpp b/components/detournavigator/debug.hpp index 818be0616c..5dcbe55ffb 100644 --- a/components/detournavigator/debug.hpp +++ b/components/detournavigator/debug.hpp @@ -18,6 +18,8 @@ class dtNavMesh; namespace DetourNavigator { + struct Version; + std::ostream& operator<<(std::ostream& stream, const TileBounds& value); std::ostream& operator<<(std::ostream& stream, Status value); @@ -54,6 +56,8 @@ namespace DetourNavigator std::ostream& operator<<(std::ostream& stream, ChangeType value); + std::ostream& operator<<(std::ostream& stream, const Version& value); + class RecastMesh; struct RecastSettings; diff --git a/components/detournavigator/navigator.hpp b/components/detournavigator/navigator.hpp index 1379ebd835..59fa28b908 100644 --- a/components/detournavigator/navigator.hpp +++ b/components/detournavigator/navigator.hpp @@ -100,65 +100,56 @@ namespace DetourNavigator * @param id is used to distinguish different objects * @param shape members must live until object is updated by another shape removed from Navigator * @param transform allows to setup objects geometry according to its world state - * @return true if object is added, false if there is already object with given id */ - virtual bool addObject(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform) = 0; + virtual void addObject(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform) = 0; /** * @brief addObject is used to add doors. * @param id is used to distinguish different objects. * @param shape members must live until object is updated by another shape or removed from Navigator. * @param transform allows to setup objects geometry according to its world state. - * @return true if object is added, false if there is already object with given id. */ - virtual bool addObject(const ObjectId id, const DoorShapes& shapes, const btTransform& transform) = 0; + virtual void addObject(const ObjectId id, const DoorShapes& shapes, const btTransform& transform) = 0; /** * @brief updateObject replace object geometry by given data. * @param id is used to find object. * @param shape members must live until object is updated by another shape removed from Navigator. * @param transform allows to setup objects geometry according to its world state. - * @return true if object is updated, false if there is no object with given id. */ - virtual bool updateObject(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform) = 0; + virtual void updateObject(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform) = 0; /** * @brief updateObject replace object geometry by given data. * @param id is used to find object. * @param shape members must live until object is updated by another shape removed from Navigator. * @param transform allows to setup objects geometry according to its world state. - * @return true if object is updated, false if there is no object with given id. */ - virtual bool updateObject(const ObjectId id, const DoorShapes& shapes, const btTransform& transform) = 0; + virtual void updateObject(const ObjectId id, const DoorShapes& shapes, const btTransform& transform) = 0; /** * @brief removeObject to make it no more available at the scene. * @param id is used to find object. - * @return true if object is removed, false if there is no object with given id. */ - virtual bool removeObject(const ObjectId id) = 0; + virtual void removeObject(const ObjectId id) = 0; /** * @brief addWater is used to set water level at given world cell. * @param cellPosition allows to distinguish cells if there is many in current world. * @param cellSize set cell borders. std::numeric_limits::max() disables cell borders. * @param shift set global shift of cell center. - * @return true if there was no water at given cell if cellSize != std::numeric_limits::max() or there is - * at least single object is added to the scene, false if there is already water for given cell or there is no - * any other objects. */ - virtual bool addWater(const osg::Vec2i& cellPosition, int cellSize, float level) = 0; + virtual void addWater(const osg::Vec2i& cellPosition, int cellSize, float level) = 0; /** * @brief removeWater to make it no more available at the scene. * @param cellPosition allows to find cell. - * @return true if there was water at given cell. */ - virtual bool removeWater(const osg::Vec2i& cellPosition) = 0; + virtual void removeWater(const osg::Vec2i& cellPosition) = 0; - virtual bool addHeightfield(const osg::Vec2i& cellPosition, int cellSize, const HeightfieldShape& shape) = 0; + virtual void addHeightfield(const osg::Vec2i& cellPosition, int cellSize, const HeightfieldShape& shape) = 0; - virtual bool removeHeightfield(const osg::Vec2i& cellPosition) = 0; + virtual void removeHeightfield(const osg::Vec2i& cellPosition) = 0; virtual void addPathgrid(const ESM::Cell& cell, const ESM::Pathgrid& pathgrid) = 0; @@ -170,17 +161,6 @@ namespace DetourNavigator */ virtual void update(const osg::Vec3f& playerPosition) = 0; - /** - * @brief updatePlayerPosition starts background navmesh update using current scene state only when player position has been changed. - * @param playerPosition setup initial point to order build tiles of navmesh. - */ - virtual void updatePlayerPosition(const osg::Vec3f& playerPosition) = 0; - - /** - * @brief disable navigator updates - */ - virtual void setUpdatesEnabled(bool enabled) = 0; - /** * @brief wait locks thread until tiles are updated from last update call based on passed condition type. * @param waitConditionType defines when waiting will stop diff --git a/components/detournavigator/navigatorimpl.cpp b/components/detournavigator/navigatorimpl.cpp index 2738c4a3f6..478451760f 100644 --- a/components/detournavigator/navigatorimpl.cpp +++ b/components/detournavigator/navigatorimpl.cpp @@ -11,7 +11,6 @@ namespace DetourNavigator NavigatorImpl::NavigatorImpl(const Settings& settings, std::unique_ptr&& db) : mSettings(settings) , mNavMeshManager(mSettings, std::move(db)) - , mUpdatesEnabled(true) { } @@ -42,7 +41,12 @@ namespace DetourNavigator mNavMeshManager.updateBounds(playerPosition); } - bool NavigatorImpl::addObject(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform) + void NavigatorImpl::addObject(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform) + { + addObjectImpl(id, shapes, transform); + } + + bool NavigatorImpl::addObjectImpl(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform) { const CollisionShape collisionShape(shapes.mShapeInstance, *shapes.mShapeInstance->mCollisionShape, shapes.mTransform); bool result = mNavMeshManager.addObject(id, collisionShape, transform, AreaType_ground); @@ -59,72 +63,65 @@ namespace DetourNavigator return result; } - bool NavigatorImpl::addObject(const ObjectId id, const DoorShapes& shapes, const btTransform& transform) + void NavigatorImpl::addObject(const ObjectId id, const DoorShapes& shapes, const btTransform& transform) { - if (addObject(id, static_cast(shapes), transform)) + if (addObjectImpl(id, static_cast(shapes), transform)) { const osg::Vec3f start = toNavMeshCoordinates(mSettings.mRecast, shapes.mConnectionStart); const osg::Vec3f end = toNavMeshCoordinates(mSettings.mRecast, shapes.mConnectionEnd); mNavMeshManager.addOffMeshConnection(id, start, end, AreaType_door); mNavMeshManager.addOffMeshConnection(id, end, start, AreaType_door); - return true; } - return false; } - bool NavigatorImpl::updateObject(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform) + void NavigatorImpl::updateObject(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform) { const CollisionShape collisionShape(shapes.mShapeInstance, *shapes.mShapeInstance->mCollisionShape, shapes.mTransform); - bool result = mNavMeshManager.updateObject(id, collisionShape, transform, AreaType_ground); + mNavMeshManager.updateObject(id, collisionShape, transform, AreaType_ground); if (const btCollisionShape* const avoidShape = shapes.mShapeInstance->mAvoidCollisionShape.get()) { const ObjectId avoidId(avoidShape); const CollisionShape avoidCollisionShape(shapes.mShapeInstance, *avoidShape, shapes.mTransform); if (mNavMeshManager.updateObject(avoidId, avoidCollisionShape, transform, AreaType_null)) - { updateAvoidShapeId(id, avoidId); - result = true; - } } - return result; } - bool NavigatorImpl::updateObject(const ObjectId id, const DoorShapes& shapes, const btTransform& transform) + void NavigatorImpl::updateObject(const ObjectId id, const DoorShapes& shapes, const btTransform& transform) { return updateObject(id, static_cast(shapes), transform); } - bool NavigatorImpl::removeObject(const ObjectId id) + void NavigatorImpl::removeObject(const ObjectId id) { - bool result = mNavMeshManager.removeObject(id); + mNavMeshManager.removeObject(id); const auto avoid = mAvoidIds.find(id); if (avoid != mAvoidIds.end()) - result = mNavMeshManager.removeObject(avoid->second) || result; + mNavMeshManager.removeObject(avoid->second); const auto water = mWaterIds.find(id); if (water != mWaterIds.end()) - result = mNavMeshManager.removeObject(water->second) || result; + mNavMeshManager.removeObject(water->second); mNavMeshManager.removeOffMeshConnections(id); - return result; } - bool NavigatorImpl::addWater(const osg::Vec2i& cellPosition, int cellSize, float level) + void NavigatorImpl::addWater(const osg::Vec2i& cellPosition, int cellSize, float level) { - return mNavMeshManager.addWater(cellPosition, cellSize, level); + mNavMeshManager.addWater(cellPosition, cellSize, level); } - bool NavigatorImpl::removeWater(const osg::Vec2i& cellPosition) + void NavigatorImpl::removeWater(const osg::Vec2i& cellPosition) { - return mNavMeshManager.removeWater(cellPosition); + mNavMeshManager.removeWater(cellPosition); } - bool NavigatorImpl::addHeightfield(const osg::Vec2i& cellPosition, int cellSize, const HeightfieldShape& shape) + void NavigatorImpl::addHeightfield(const osg::Vec2i& cellPosition, int cellSize, const HeightfieldShape& shape) { - return mNavMeshManager.addHeightfield(cellPosition, cellSize, shape); + mNavMeshManager.addHeightfield(cellPosition, cellSize, shape); } - bool NavigatorImpl::removeHeightfield(const osg::Vec2i& cellPosition) + void NavigatorImpl::removeHeightfield(const osg::Vec2i& cellPosition) { - return mNavMeshManager.removeHeightfield(cellPosition); + mNavMeshManager.removeHeightfield(cellPosition); } void NavigatorImpl::addPathgrid(const ESM::Cell& cell, const ESM::Pathgrid& pathgrid) @@ -150,31 +147,15 @@ namespace DetourNavigator void NavigatorImpl::update(const osg::Vec3f& playerPosition) { - if (!mUpdatesEnabled) - return; removeUnusedNavMeshes(); for (const auto& v : mAgents) mNavMeshManager.update(playerPosition, v.first); } - void NavigatorImpl::updatePlayerPosition(const osg::Vec3f& playerPosition) - { - const TilePosition tilePosition = getTilePosition(mSettings.mRecast, toNavMeshCoordinates(mSettings.mRecast, playerPosition)); - if (mLastPlayerPosition.has_value() && *mLastPlayerPosition == tilePosition) - return; - mNavMeshManager.updateBounds(playerPosition); - update(playerPosition); - mLastPlayerPosition = tilePosition; - } - - void NavigatorImpl::setUpdatesEnabled(bool enabled) - { - mUpdatesEnabled = enabled; - } - void NavigatorImpl::wait(Loading::Listener& listener, WaitConditionType waitConditionType) { - mNavMeshManager.wait(listener, waitConditionType); + if (mSettings.mWaitUntilMinDistanceToPlayer > 0) + mNavMeshManager.wait(listener, waitConditionType); } SharedNavMeshCacheItem NavigatorImpl::getNavMesh(const AgentBounds& agentBounds) const diff --git a/components/detournavigator/navigatorimpl.hpp b/components/detournavigator/navigatorimpl.hpp index f7b2d6d8c8..ff324280a6 100644 --- a/components/detournavigator/navigatorimpl.hpp +++ b/components/detournavigator/navigatorimpl.hpp @@ -26,23 +26,23 @@ namespace DetourNavigator void updateBounds(const osg::Vec3f& playerPosition) override; - bool addObject(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform) override; + void addObject(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform) override; - bool addObject(const ObjectId id, const DoorShapes& shapes, const btTransform& transform) override; + void addObject(const ObjectId id, const DoorShapes& shapes, const btTransform& transform) override; - bool updateObject(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform) override; + void updateObject(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform) override; - bool updateObject(const ObjectId id, const DoorShapes& shapes, const btTransform& transform) override; + void updateObject(const ObjectId id, const DoorShapes& shapes, const btTransform& transform) override; - bool removeObject(const ObjectId id) override; + void removeObject(const ObjectId id) override; - bool addWater(const osg::Vec2i& cellPosition, int cellSize, float level) override; + void addWater(const osg::Vec2i& cellPosition, int cellSize, float level) override; - bool removeWater(const osg::Vec2i& cellPosition) override; + void removeWater(const osg::Vec2i& cellPosition) override; - bool addHeightfield(const osg::Vec2i& cellPosition, int cellSize, const HeightfieldShape& shape) override; + void addHeightfield(const osg::Vec2i& cellPosition, int cellSize, const HeightfieldShape& shape) override; - bool removeHeightfield(const osg::Vec2i& cellPosition) override; + void removeHeightfield(const osg::Vec2i& cellPosition) override; void addPathgrid(const ESM::Cell& cell, const ESM::Pathgrid& pathgrid) override; @@ -50,10 +50,6 @@ namespace DetourNavigator void update(const osg::Vec3f& playerPosition) override; - void updatePlayerPosition(const osg::Vec3f& playerPosition) override; - - void setUpdatesEnabled(bool enabled) override; - void wait(Loading::Listener& listener, WaitConditionType waitConditionType) override; SharedNavMeshCacheItem getNavMesh(const AgentBounds& agentBounds) const override; @@ -71,12 +67,12 @@ namespace DetourNavigator private: Settings mSettings; NavMeshManager mNavMeshManager; - bool mUpdatesEnabled; std::optional mLastPlayerPosition; std::map mAgents; std::unordered_map mAvoidIds; std::unordered_map mWaterIds; + inline bool addObjectImpl(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform); void updateAvoidShapeId(const ObjectId id, const ObjectId avoidId); void updateWaterShapeId(const ObjectId id, const ObjectId waterId); void updateId(const ObjectId id, const ObjectId waterId, std::unordered_map& ids); diff --git a/components/detournavigator/navigatorstub.hpp b/components/detournavigator/navigatorstub.hpp index 1eb1860217..fec6e8f04c 100644 --- a/components/detournavigator/navigatorstub.hpp +++ b/components/detournavigator/navigatorstub.hpp @@ -22,50 +22,24 @@ namespace DetourNavigator void setWorldspace(std::string_view /*worldspace*/) override {} - bool addObject(const ObjectId /*id*/, const ObjectShapes& /*shapes*/, const btTransform& /*transform*/) override - { - return false; - } + void addObject(const ObjectId /*id*/, const ObjectShapes& /*shapes*/, const btTransform& /*transform*/) override {} - bool addObject(const ObjectId /*id*/, const DoorShapes& /*shapes*/, const btTransform& /*transform*/) override - { - return false; - } + void addObject(const ObjectId /*id*/, const DoorShapes& /*shapes*/, const btTransform& /*transform*/) override {} - bool updateObject(const ObjectId /*id*/, const ObjectShapes& /*shapes*/, const btTransform& /*transform*/) override - { - return false; - } + void updateObject(const ObjectId /*id*/, const ObjectShapes& /*shapes*/, const btTransform& /*transform*/) override {} - bool updateObject(const ObjectId /*id*/, const DoorShapes& /*shapes*/, const btTransform& /*transform*/) override - { - return false; - } + void updateObject(const ObjectId /*id*/, const DoorShapes& /*shapes*/, const btTransform& /*transform*/) override {} - bool removeObject(const ObjectId /*id*/) override - { - return false; - } + void removeObject(const ObjectId /*id*/) override {} - bool addWater(const osg::Vec2i& /*cellPosition*/, int /*cellSize*/, float /*level*/) override - { - return false; - } + void addWater(const osg::Vec2i& /*cellPosition*/, int /*cellSize*/, float /*level*/) override {} - bool removeWater(const osg::Vec2i& /*cellPosition*/) override - { - return false; - } + void removeWater(const osg::Vec2i& /*cellPosition*/) override {} - bool addHeightfield(const osg::Vec2i& /*cellPosition*/, int /*cellSize*/, const HeightfieldShape& /*height*/) override - { - return false; - } + void addHeightfield(const osg::Vec2i& /*cellPosition*/, int /*cellSize*/, const HeightfieldShape& /*height*/) + override {} - bool removeHeightfield(const osg::Vec2i& /*cellPosition*/) override - { - return false; - } + void removeHeightfield(const osg::Vec2i& /*cellPosition*/) override {} void addPathgrid(const ESM::Cell& /*cell*/, const ESM::Pathgrid& /*pathgrid*/) override {} @@ -75,10 +49,6 @@ namespace DetourNavigator void updateBounds(const osg::Vec3f& /*playerPosition*/) override {} - void updatePlayerPosition(const osg::Vec3f& /*playerPosition*/) override {}; - - void setUpdatesEnabled(bool /*enabled*/) override {} - void wait(Loading::Listener& /*listener*/, WaitConditionType /*waitConditionType*/) override {} SharedNavMeshCacheItem getNavMesh(const AgentBounds& /*agentBounds*/) const override diff --git a/components/detournavigator/navmeshmanager.cpp b/components/detournavigator/navmeshmanager.cpp index 50744731b1..0e1dc591a3 100644 --- a/components/detournavigator/navmeshmanager.cpp +++ b/components/detournavigator/navmeshmanager.cpp @@ -107,51 +107,46 @@ namespace DetourNavigator [&] (const TilePosition& tile, ChangeType changeType) { addChangedTile(tile, changeType); }); } - bool NavMeshManager::removeObject(const ObjectId id) + void NavMeshManager::removeObject(const ObjectId id) { const auto object = mRecastMeshManager.removeObject(id); if (!object) - return false; + return; addChangedTiles(object->mShape, object->mTransform, ChangeType::remove); - return true; } - bool NavMeshManager::addWater(const osg::Vec2i& cellPosition, int cellSize, float level) + void NavMeshManager::addWater(const osg::Vec2i& cellPosition, int cellSize, float level) { if (!mRecastMeshManager.addWater(cellPosition, cellSize, level)) - return false; + return; const btVector3 shift = Misc::Convert::toBullet(getWaterShift3d(cellPosition, cellSize, level)); addChangedTiles(cellSize, shift, ChangeType::add); - return true; } - bool NavMeshManager::removeWater(const osg::Vec2i& cellPosition) + void NavMeshManager::removeWater(const osg::Vec2i& cellPosition) { const auto water = mRecastMeshManager.removeWater(cellPosition); if (!water) - return false; + return; const btVector3 shift = Misc::Convert::toBullet(getWaterShift3d(cellPosition, water->mCellSize, water->mLevel)); addChangedTiles(water->mCellSize, shift, ChangeType::remove); - return true; } - bool NavMeshManager::addHeightfield(const osg::Vec2i& cellPosition, int cellSize, const HeightfieldShape& shape) + void NavMeshManager::addHeightfield(const osg::Vec2i& cellPosition, int cellSize, const HeightfieldShape& shape) { if (!mRecastMeshManager.addHeightfield(cellPosition, cellSize, shape)) - return false; + return; const btVector3 shift = getHeightfieldShift(shape, cellPosition, cellSize); addChangedTiles(cellSize, shift, ChangeType::add); - return true; } - bool NavMeshManager::removeHeightfield(const osg::Vec2i& cellPosition) + void NavMeshManager::removeHeightfield(const osg::Vec2i& cellPosition) { const auto heightfield = mRecastMeshManager.removeHeightfield(cellPosition); if (!heightfield) - return false; + return; const btVector3 shift = getHeightfieldShift(heightfield->mShape, cellPosition, heightfield->mCellSize); addChangedTiles(heightfield->mCellSize, shift, ChangeType::remove); - return true; } void NavMeshManager::addAgent(const AgentBounds& agentBounds) diff --git a/components/detournavigator/navmeshmanager.hpp b/components/detournavigator/navmeshmanager.hpp index ade378aeec..7a9a1e2ba4 100644 --- a/components/detournavigator/navmeshmanager.hpp +++ b/components/detournavigator/navmeshmanager.hpp @@ -32,17 +32,17 @@ namespace DetourNavigator bool updateObject(const ObjectId id, const CollisionShape& shape, const btTransform& transform, const AreaType areaType); - bool removeObject(const ObjectId id); + void removeObject(const ObjectId id); void addAgent(const AgentBounds& agentBounds); - bool addWater(const osg::Vec2i& cellPosition, int cellSize, float level); + void addWater(const osg::Vec2i& cellPosition, int cellSize, float level); - bool removeWater(const osg::Vec2i& cellPosition); + void removeWater(const osg::Vec2i& cellPosition); - bool addHeightfield(const osg::Vec2i& cellPosition, int cellSize, const HeightfieldShape& shape); + void addHeightfield(const osg::Vec2i& cellPosition, int cellSize, const HeightfieldShape& shape); - bool removeHeightfield(const osg::Vec2i& cellPosition); + void removeHeightfield(const osg::Vec2i& cellPosition); bool reset(const AgentBounds& agentBounds);