From c68e64a2a7c719f8df9d76ce55f0ca64b6966b5e Mon Sep 17 00:00:00 2001 From: elsid Date: Sat, 16 Feb 2019 14:41:11 +0300 Subject: [PATCH 1/7] Make navigator from settings manager setting in separate function --- apps/openmw/mwworld/worldimp.cpp | 27 +-------------- components/CMakeLists.txt | 1 + components/detournavigator/settings.cpp | 44 +++++++++++++++++++++++++ components/detournavigator/settings.hpp | 2 ++ 4 files changed, 48 insertions(+), 26 deletions(-) create mode 100644 components/detournavigator/settings.cpp diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 672e6db24..a6f0616e2 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -198,35 +198,10 @@ namespace MWWorld mPhysics.reset(new MWPhysics::PhysicsSystem(resourceSystem, rootNode)); - DetourNavigator::Settings navigatorSettings; - navigatorSettings.mBorderSize = Settings::Manager::getInt("border size", "Navigator"); - navigatorSettings.mCellHeight = Settings::Manager::getFloat("cell height", "Navigator"); - navigatorSettings.mCellSize = Settings::Manager::getFloat("cell size", "Navigator"); - navigatorSettings.mDetailSampleDist = Settings::Manager::getFloat("detail sample dist", "Navigator"); - navigatorSettings.mDetailSampleMaxError = Settings::Manager::getFloat("detail sample max error", "Navigator"); + auto navigatorSettings = DetourNavigator::makeSettingsFromSettingsManager(); navigatorSettings.mMaxClimb = MWPhysics::sStepSizeUp; - navigatorSettings.mMaxSimplificationError = Settings::Manager::getFloat("max simplification error", "Navigator"); navigatorSettings.mMaxSlope = MWPhysics::sMaxSlope; - navigatorSettings.mRecastScaleFactor = Settings::Manager::getFloat("recast scale factor", "Navigator"); navigatorSettings.mSwimHeightScale = mSwimHeightScale; - navigatorSettings.mMaxEdgeLen = Settings::Manager::getInt("max edge len", "Navigator"); - navigatorSettings.mMaxNavMeshQueryNodes = Settings::Manager::getInt("max nav mesh query nodes", "Navigator"); - navigatorSettings.mMaxPolys = Settings::Manager::getInt("max polygons per tile", "Navigator"); - navigatorSettings.mMaxVertsPerPoly = Settings::Manager::getInt("max verts per poly", "Navigator"); - navigatorSettings.mRegionMergeSize = Settings::Manager::getInt("region merge size", "Navigator"); - navigatorSettings.mRegionMinSize = Settings::Manager::getInt("region min size", "Navigator"); - navigatorSettings.mTileSize = Settings::Manager::getInt("tile size", "Navigator"); - navigatorSettings.mAsyncNavMeshUpdaterThreads = static_cast(Settings::Manager::getInt("async nav mesh updater threads", "Navigator")); - navigatorSettings.mMaxNavMeshTilesCacheSize = static_cast(Settings::Manager::getInt("max nav mesh tiles cache size", "Navigator")); - navigatorSettings.mMaxPolygonPathSize = static_cast(Settings::Manager::getInt("max polygon path size", "Navigator")); - navigatorSettings.mMaxSmoothPathSize = static_cast(Settings::Manager::getInt("max smooth path size", "Navigator")); - navigatorSettings.mTrianglesPerChunk = static_cast(Settings::Manager::getInt("triangles per chunk", "Navigator")); - navigatorSettings.mEnableWriteRecastMeshToFile = Settings::Manager::getBool("enable write recast mesh to file", "Navigator"); - navigatorSettings.mEnableWriteNavMeshToFile = Settings::Manager::getBool("enable write nav mesh to file", "Navigator"); - navigatorSettings.mRecastMeshPathPrefix = Settings::Manager::getString("recast mesh path prefix", "Navigator"); - navigatorSettings.mNavMeshPathPrefix = Settings::Manager::getString("nav mesh path prefix", "Navigator"); - navigatorSettings.mEnableRecastMeshFileNameRevision = Settings::Manager::getBool("enable recast mesh file name revision", "Navigator"); - navigatorSettings.mEnableNavMeshFileNameRevision = Settings::Manager::getBool("enable nav mesh file name revision", "Navigator"); if (Settings::Manager::getBool("enable log", "Navigator")) DetourNavigator::Log::instance().setSink(std::unique_ptr( new DetourNavigator::FileSink(Settings::Manager::getString("log path", "Navigator")))); diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 76641899d..bb45542e4 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -171,6 +171,7 @@ add_component_dir(detournavigator tilecachedrecastmeshmanager recastmeshobject navmeshtilescache + settings ) set (ESM_UI ${CMAKE_SOURCE_DIR}/files/ui/contentselector.ui diff --git a/components/detournavigator/settings.cpp b/components/detournavigator/settings.cpp new file mode 100644 index 000000000..0b9210a90 --- /dev/null +++ b/components/detournavigator/settings.cpp @@ -0,0 +1,44 @@ +#include "settings.hpp" + +#include + +#include + +namespace DetourNavigator +{ + Settings makeSettingsFromSettingsManager() + { + Settings navigatorSettings; + + navigatorSettings.mBorderSize = ::Settings::Manager::getInt("border size", "Navigator"); + navigatorSettings.mCellHeight = ::Settings::Manager::getFloat("cell height", "Navigator"); + navigatorSettings.mCellSize = ::Settings::Manager::getFloat("cell size", "Navigator"); + navigatorSettings.mDetailSampleDist = ::Settings::Manager::getFloat("detail sample dist", "Navigator"); + navigatorSettings.mDetailSampleMaxError = ::Settings::Manager::getFloat("detail sample max error", "Navigator"); + navigatorSettings.mMaxClimb = 0; + navigatorSettings.mMaxSimplificationError = ::Settings::Manager::getFloat("max simplification error", "Navigator"); + navigatorSettings.mMaxSlope = 0; + navigatorSettings.mRecastScaleFactor = ::Settings::Manager::getFloat("recast scale factor", "Navigator"); + navigatorSettings.mSwimHeightScale = 0; + navigatorSettings.mMaxEdgeLen = ::Settings::Manager::getInt("max edge len", "Navigator"); + navigatorSettings.mMaxNavMeshQueryNodes = ::Settings::Manager::getInt("max nav mesh query nodes", "Navigator"); + navigatorSettings.mMaxPolys = ::Settings::Manager::getInt("max polygons per tile", "Navigator"); + navigatorSettings.mMaxVertsPerPoly = ::Settings::Manager::getInt("max verts per poly", "Navigator"); + navigatorSettings.mRegionMergeSize = ::Settings::Manager::getInt("region merge size", "Navigator"); + navigatorSettings.mRegionMinSize = ::Settings::Manager::getInt("region min size", "Navigator"); + navigatorSettings.mTileSize = ::Settings::Manager::getInt("tile size", "Navigator"); + navigatorSettings.mAsyncNavMeshUpdaterThreads = static_cast(::Settings::Manager::getInt("async nav mesh updater threads", "Navigator")); + navigatorSettings.mMaxNavMeshTilesCacheSize = static_cast(::Settings::Manager::getInt("max nav mesh tiles cache size", "Navigator")); + navigatorSettings.mMaxPolygonPathSize = static_cast(::Settings::Manager::getInt("max polygon path size", "Navigator")); + navigatorSettings.mMaxSmoothPathSize = static_cast(::Settings::Manager::getInt("max smooth path size", "Navigator")); + navigatorSettings.mTrianglesPerChunk = static_cast(::Settings::Manager::getInt("triangles per chunk", "Navigator")); + navigatorSettings.mEnableWriteRecastMeshToFile = ::Settings::Manager::getBool("enable write recast mesh to file", "Navigator"); + navigatorSettings.mEnableWriteNavMeshToFile = ::Settings::Manager::getBool("enable write nav mesh to file", "Navigator"); + navigatorSettings.mRecastMeshPathPrefix = ::Settings::Manager::getString("recast mesh path prefix", "Navigator"); + navigatorSettings.mNavMeshPathPrefix = ::Settings::Manager::getString("nav mesh path prefix", "Navigator"); + navigatorSettings.mEnableRecastMeshFileNameRevision = ::Settings::Manager::getBool("enable recast mesh file name revision", "Navigator"); + navigatorSettings.mEnableNavMeshFileNameRevision = ::Settings::Manager::getBool("enable nav mesh file name revision", "Navigator"); + + return navigatorSettings; + } +} diff --git a/components/detournavigator/settings.hpp b/components/detournavigator/settings.hpp index 3e537c2fb..f4073b24b 100644 --- a/components/detournavigator/settings.hpp +++ b/components/detournavigator/settings.hpp @@ -36,6 +36,8 @@ namespace DetourNavigator std::string mRecastMeshPathPrefix; std::string mNavMeshPathPrefix; }; + + Settings makeSettingsFromSettingsManager(); } #endif From a0ed981a7c235fb7535f2d6806697ef11fc765e9 Mon Sep 17 00:00:00 2001 From: elsid Date: Sat, 16 Feb 2019 15:09:57 +0300 Subject: [PATCH 2/7] Fix operator ++ for OutputTransformIterator --- components/detournavigator/findsmoothpath.hpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/components/detournavigator/findsmoothpath.hpp b/components/detournavigator/findsmoothpath.hpp index 81b732b74..c02e3315b 100644 --- a/components/detournavigator/findsmoothpath.hpp +++ b/components/detournavigator/findsmoothpath.hpp @@ -81,21 +81,28 @@ namespace DetourNavigator return *this; } - OutputTransformIterator& operator ++(int) + OutputTransformIterator& operator ++() { - mImpl++; + ++mImpl.get(); return *this; } + OutputTransformIterator operator ++(int) + { + const auto copy = *this; + ++(*this); + return copy; + } + OutputTransformIterator& operator =(const osg::Vec3f& value) { - *mImpl = fromNavMeshCoordinates(mSettings, value); + *mImpl.get() = fromNavMeshCoordinates(mSettings, value); return *this; } private: - OutputIterator& mImpl; - const Settings& mSettings; + std::reference_wrapper mImpl; + std::reference_wrapper mSettings; }; inline void initNavMeshQuery(dtNavMeshQuery& value, const dtNavMesh& navMesh, const int maxNodes) From d63881e054324f26da77c2c710aba71c46d88ed1 Mon Sep 17 00:00:00 2001 From: elsid Date: Sat, 16 Feb 2019 15:14:05 +0300 Subject: [PATCH 3/7] Make Navigator::findPath independent from class fields --- components/detournavigator/navigator.cpp | 7 ++++++- components/detournavigator/navigator.hpp | 17 ++++++++++++----- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/components/detournavigator/navigator.cpp b/components/detournavigator/navigator.cpp index 73537ff6f..ddd985021 100644 --- a/components/detournavigator/navigator.cpp +++ b/components/detournavigator/navigator.cpp @@ -122,12 +122,17 @@ namespace DetourNavigator mNavMeshManager.wait(); } + SharedNavMeshCacheItem Navigator::getNavMesh(const osg::Vec3f& agentHalfExtents) const + { + return mNavMeshManager.getNavMesh(agentHalfExtents); + } + std::map Navigator::getNavMeshes() const { return mNavMeshManager.getNavMeshes(); } - const Settings& Navigator::getSettings() const + Settings Navigator::getSettings() const { return mSettings; } diff --git a/components/detournavigator/navigator.hpp b/components/detournavigator/navigator.hpp index 351e0f9f8..0bdc79e8a 100644 --- a/components/detournavigator/navigator.hpp +++ b/components/detournavigator/navigator.hpp @@ -175,19 +175,26 @@ namespace DetourNavigator >::value, "out is not an OutputIterator" ); - const auto navMesh = mNavMeshManager.getNavMesh(agentHalfExtents); - return findSmoothPath(navMesh.lock()->getValue(), toNavMeshCoordinates(mSettings, agentHalfExtents), - toNavMeshCoordinates(mSettings, start), toNavMeshCoordinates(mSettings, end), includeFlags, - mSettings, out); + const auto navMesh = getNavMesh(agentHalfExtents); + const auto settings = getSettings(); + return findSmoothPath(navMesh.lock()->getValue(), toNavMeshCoordinates(settings, agentHalfExtents), + toNavMeshCoordinates(settings, start), toNavMeshCoordinates(settings, end), includeFlags, + settings, out); } + /** + * @brief getNavMesh returns navmesh for specific agent half extents + * @return navmesh + */ + SharedNavMeshCacheItem getNavMesh(const osg::Vec3f& agentHalfExtents) const; + /** * @brief getNavMeshes returns all current navmeshes * @return map of agent half extents to navmesh */ std::map getNavMeshes() const; - const Settings& getSettings() const; + Settings getSettings() const; private: Settings mSettings; From 1d3668cd2298f2120310aa5b871589f17fe19f6d Mon Sep 17 00:00:00 2001 From: elsid Date: Sat, 16 Feb 2019 15:27:02 +0300 Subject: [PATCH 4/7] Add Navigator interface --- apps/openmw/mwbase/world.hpp | 2 +- apps/openmw/mwrender/renderingmanager.hpp | 2 +- apps/openmw/mwworld/scene.hpp | 2 +- apps/openmw/mwworld/worldimp.cpp | 4 +- .../detournavigator/navigator.cpp | 4 +- components/CMakeLists.txt | 2 +- components/detournavigator/navigator.hpp | 60 +++++++---------- .../{navigator.cpp => navigatorimpl.cpp} | 42 ++++++------ components/detournavigator/navigatorimpl.hpp | 64 +++++++++++++++++++ 9 files changed, 115 insertions(+), 67 deletions(-) rename components/detournavigator/{navigator.cpp => navigatorimpl.cpp} (66%) create mode 100644 components/detournavigator/navigatorimpl.hpp diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index 1728af659..217e6d367 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -57,7 +57,7 @@ namespace MWMechanics namespace DetourNavigator { - class Navigator; + struct Navigator; } namespace MWWorld diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index 2a48097bd..e04404f2b 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -59,7 +59,7 @@ namespace SceneUtil namespace DetourNavigator { - class Navigator; + struct Navigator; struct Settings; } diff --git a/apps/openmw/mwworld/scene.hpp b/apps/openmw/mwworld/scene.hpp index 00f5f98b8..0f1ae7298 100644 --- a/apps/openmw/mwworld/scene.hpp +++ b/apps/openmw/mwworld/scene.hpp @@ -30,7 +30,7 @@ namespace Loading namespace DetourNavigator { - class Navigator; + struct Navigator; class Water; } diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index a6f0616e2..65d629384 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -24,7 +24,7 @@ #include #include -#include +#include #include #include "../mwbase/environment.hpp" @@ -206,7 +206,7 @@ namespace MWWorld DetourNavigator::Log::instance().setSink(std::unique_ptr( new DetourNavigator::FileSink(Settings::Manager::getString("log path", "Navigator")))); DetourNavigator::RecastGlobalAllocator::init(); - mNavigator.reset(new DetourNavigator::Navigator(navigatorSettings)); + mNavigator.reset(new DetourNavigator::NavigatorImpl(navigatorSettings)); mRendering.reset(new MWRender::RenderingManager(viewer, rootNode, resourceSystem, workQueue, &mFallback, resourcePath, *mNavigator)); mProjectileManager.reset(new ProjectileManager(mRendering->getLightRoot(), resourceSystem, mRendering.get(), mPhysics.get())); diff --git a/apps/openmw_test_suite/detournavigator/navigator.cpp b/apps/openmw_test_suite/detournavigator/navigator.cpp index febbc0387..288392143 100644 --- a/apps/openmw_test_suite/detournavigator/navigator.cpp +++ b/apps/openmw_test_suite/detournavigator/navigator.cpp @@ -1,6 +1,6 @@ #include "operators.hpp" -#include +#include #include #include @@ -61,7 +61,7 @@ namespace mSettings.mMaxSmoothPathSize = 1024; mSettings.mTrianglesPerChunk = 256; mSettings.mMaxPolys = 4096; - mNavigator.reset(new Navigator(mSettings)); + mNavigator.reset(new NavigatorImpl(mSettings)); } }; diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index bb45542e4..50fd59006 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -164,7 +164,7 @@ add_component_dir(detournavigator recastmeshmanager cachedrecastmeshmanager navmeshmanager - navigator + navigatorimpl asyncnavmeshupdater chunkytrimesh recastmesh diff --git a/components/detournavigator/navigator.hpp b/components/detournavigator/navigator.hpp index 0bdc79e8a..529b539c8 100644 --- a/components/detournavigator/navigator.hpp +++ b/components/detournavigator/navigator.hpp @@ -3,9 +3,9 @@ #include "findsmoothpath.hpp" #include "flags.hpp" -#include "navmeshmanager.hpp" #include "settings.hpp" -#include "settingsutils.hpp" +#include "objectid.hpp" +#include "navmeshcacheitem.hpp" namespace DetourNavigator { @@ -33,33 +33,28 @@ namespace DetourNavigator }; /** - * @brief Top level class of detournavigator componenet. Navigator allows to build a scene with navmesh and find + * @brief Top level interface of detournavigator component. Navigator allows to build a scene with navmesh and find * a path for an agent there. Scene contains agents, geometry objects and water. Agent are distinguished only by * half extents. Each object has unique identifier and could be added, updated or removed. Water could be added once * for each world cell at given level of height. Navmesh builds asynchronously in separate threads. To start build * navmesh call update method. */ - class Navigator + struct Navigator { - public: - /** - * @brief Navigator constructor initializes all internal data. Constructed object is ready to build a scene. - * @param settings allows to customize navigator work. Constructor is only place to set navigator settings. - */ - Navigator(const Settings& settings); + virtual ~Navigator() = default; /** * @brief addAgent should be called for each agent even if all of them has same half extents. * @param agentHalfExtents allows to setup bounding cylinder for each agent, for each different half extents * there is different navmesh. */ - void addAgent(const osg::Vec3f& agentHalfExtents); + virtual void addAgent(const osg::Vec3f& agentHalfExtents) = 0; /** * @brief removeAgent should be called for each agent even if all of them has same half extents * @param agentHalfExtents allows determine which agent to remove */ - void removeAgent(const osg::Vec3f& agentHalfExtents); + virtual void removeAgent(const osg::Vec3f& agentHalfExtents) = 0; /** * @brief addObject is used to add object represented by single btCollisionShape and btTransform. @@ -68,7 +63,7 @@ namespace DetourNavigator * @param transform allows to setup object geometry according to its world state. * @return true if object is added, false if there is already object with given id. */ - bool addObject(const ObjectId id, const btCollisionShape& shape, const btTransform& transform); + virtual bool addObject(const ObjectId id, const btCollisionShape& shape, const btTransform& transform) = 0; /** * @brief addObject is used to add complex object with allowed to walk and avoided to walk shapes @@ -77,7 +72,7 @@ namespace DetourNavigator * @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 */ - bool addObject(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform); + virtual bool addObject(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform) = 0; /** * @brief addObject is used to add doors. @@ -86,7 +81,7 @@ namespace DetourNavigator * @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. */ - bool addObject(const ObjectId id, const DoorShapes& shapes, const btTransform& transform); + virtual bool addObject(const ObjectId id, const DoorShapes& shapes, const btTransform& transform) = 0; /** * @brief updateObject replace object geometry by given data. @@ -95,7 +90,7 @@ namespace DetourNavigator * @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. */ - bool updateObject(const ObjectId id, const btCollisionShape& shape, const btTransform& transform); + virtual bool updateObject(const ObjectId id, const btCollisionShape& shape, const btTransform& transform) = 0; /** * @brief updateObject replace object geometry by given data. @@ -104,7 +99,7 @@ namespace DetourNavigator * @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. */ - bool updateObject(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform); + virtual bool updateObject(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform) = 0; /** * @brief updateObject replace object geometry by given data. @@ -113,14 +108,14 @@ namespace DetourNavigator * @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. */ - bool updateObject(const ObjectId id, const DoorShapes& shapes, const btTransform& transform); + virtual bool 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. */ - bool removeObject(const ObjectId id); + virtual bool removeObject(const ObjectId id) = 0; /** * @brief addWater is used to set water level at given world cell. @@ -132,26 +127,26 @@ namespace DetourNavigator * 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. */ - bool addWater(const osg::Vec2i& cellPosition, const int cellSize, const btScalar level, - const btTransform& transform); + virtual bool addWater(const osg::Vec2i& cellPosition, const int cellSize, const btScalar level, + const btTransform& transform) = 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. */ - bool removeWater(const osg::Vec2i& cellPosition); + virtual bool removeWater(const osg::Vec2i& cellPosition) = 0; /** * @brief update start background navmesh update using current scene state. * @param playerPosition setup initial point to order build tiles of navmesh. */ - void update(const osg::Vec3f& playerPosition); + virtual void update(const osg::Vec3f& playerPosition) = 0; /** * @brief wait locks thread until all tiles are updated from last update call. */ - void wait(); + virtual void wait() = 0; /** * @brief findPath fills output iterator with points of scene surfaces to be used for actor to walk through. @@ -186,26 +181,15 @@ namespace DetourNavigator * @brief getNavMesh returns navmesh for specific agent half extents * @return navmesh */ - SharedNavMeshCacheItem getNavMesh(const osg::Vec3f& agentHalfExtents) const; + virtual SharedNavMeshCacheItem getNavMesh(const osg::Vec3f& agentHalfExtents) const = 0; /** * @brief getNavMeshes returns all current navmeshes * @return map of agent half extents to navmesh */ - std::map getNavMeshes() const; - - Settings getSettings() const; - - private: - Settings mSettings; - NavMeshManager mNavMeshManager; - std::map mAgents; - std::unordered_map mAvoidIds; - std::unordered_map mWaterIds; + virtual std::map getNavMeshes() const = 0; - 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); + virtual Settings getSettings() const = 0; }; } diff --git a/components/detournavigator/navigator.cpp b/components/detournavigator/navigatorimpl.cpp similarity index 66% rename from components/detournavigator/navigator.cpp rename to components/detournavigator/navigatorimpl.cpp index ddd985021..1b83769f4 100644 --- a/components/detournavigator/navigator.cpp +++ b/components/detournavigator/navigatorimpl.cpp @@ -1,4 +1,4 @@ -#include "navigator.hpp" +#include "navigatorimpl.hpp" #include "debug.hpp" #include "settingsutils.hpp" @@ -6,19 +6,19 @@ namespace DetourNavigator { - Navigator::Navigator(const Settings& settings) + NavigatorImpl::NavigatorImpl(const Settings& settings) : mSettings(settings) , mNavMeshManager(mSettings) { } - void Navigator::addAgent(const osg::Vec3f& agentHalfExtents) + void NavigatorImpl::addAgent(const osg::Vec3f& agentHalfExtents) { ++mAgents[agentHalfExtents]; mNavMeshManager.addAgent(agentHalfExtents); } - void Navigator::removeAgent(const osg::Vec3f& agentHalfExtents) + void NavigatorImpl::removeAgent(const osg::Vec3f& agentHalfExtents) { const auto it = mAgents.find(agentHalfExtents); if (it == mAgents.end() || --it->second) @@ -27,12 +27,12 @@ namespace DetourNavigator mNavMeshManager.reset(agentHalfExtents); } - bool Navigator::addObject(const ObjectId id, const btCollisionShape& shape, const btTransform& transform) + bool NavigatorImpl::addObject(const ObjectId id, const btCollisionShape& shape, const btTransform& transform) { return mNavMeshManager.addObject(id, shape, transform, AreaType_ground); } - bool Navigator::addObject(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform) + bool NavigatorImpl::addObject(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform) { bool result = addObject(id, shapes.mShape, transform); if (shapes.mAvoid) @@ -47,7 +47,7 @@ namespace DetourNavigator return result; } - bool Navigator::addObject(const ObjectId id, const DoorShapes& shapes, const btTransform& transform) + bool NavigatorImpl::addObject(const ObjectId id, const DoorShapes& shapes, const btTransform& transform) { if (addObject(id, static_cast(shapes), transform)) { @@ -61,12 +61,12 @@ namespace DetourNavigator return false; } - bool Navigator::updateObject(const ObjectId id, const btCollisionShape& shape, const btTransform& transform) + bool NavigatorImpl::updateObject(const ObjectId id, const btCollisionShape& shape, const btTransform& transform) { return mNavMeshManager.updateObject(id, shape, transform, AreaType_ground); } - bool Navigator::updateObject(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform) + bool NavigatorImpl::updateObject(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform) { bool result = updateObject(id, shapes.mShape, transform); if (shapes.mAvoid) @@ -81,12 +81,12 @@ namespace DetourNavigator return result; } - bool Navigator::updateObject(const ObjectId id, const DoorShapes& shapes, const btTransform& transform) + bool NavigatorImpl::updateObject(const ObjectId id, const DoorShapes& shapes, const btTransform& transform) { return updateObject(id, static_cast(shapes), transform); } - bool Navigator::removeObject(const ObjectId id) + bool NavigatorImpl::removeObject(const ObjectId id) { bool result = mNavMeshManager.removeObject(id); const auto avoid = mAvoidIds.find(id); @@ -99,55 +99,55 @@ namespace DetourNavigator return result; } - bool Navigator::addWater(const osg::Vec2i& cellPosition, const int cellSize, const btScalar level, + bool NavigatorImpl::addWater(const osg::Vec2i& cellPosition, const int cellSize, const btScalar level, const btTransform& transform) { return mNavMeshManager.addWater(cellPosition, cellSize, btTransform(transform.getBasis(), btVector3(transform.getOrigin().x(), transform.getOrigin().y(), level))); } - bool Navigator::removeWater(const osg::Vec2i& cellPosition) + bool NavigatorImpl::removeWater(const osg::Vec2i& cellPosition) { return mNavMeshManager.removeWater(cellPosition); } - void Navigator::update(const osg::Vec3f& playerPosition) + void NavigatorImpl::update(const osg::Vec3f& playerPosition) { for (const auto& v : mAgents) mNavMeshManager.update(playerPosition, v.first); } - void Navigator::wait() + void NavigatorImpl::wait() { mNavMeshManager.wait(); } - SharedNavMeshCacheItem Navigator::getNavMesh(const osg::Vec3f& agentHalfExtents) const + SharedNavMeshCacheItem NavigatorImpl::getNavMesh(const osg::Vec3f& agentHalfExtents) const { return mNavMeshManager.getNavMesh(agentHalfExtents); } - std::map Navigator::getNavMeshes() const + std::map NavigatorImpl::getNavMeshes() const { return mNavMeshManager.getNavMeshes(); } - Settings Navigator::getSettings() const + Settings NavigatorImpl::getSettings() const { return mSettings; } - void Navigator::updateAvoidShapeId(const ObjectId id, const ObjectId avoidId) + void NavigatorImpl::updateAvoidShapeId(const ObjectId id, const ObjectId avoidId) { updateId(id, avoidId, mWaterIds); } - void Navigator::updateWaterShapeId(const ObjectId id, const ObjectId waterId) + void NavigatorImpl::updateWaterShapeId(const ObjectId id, const ObjectId waterId) { updateId(id, waterId, mWaterIds); } - void Navigator::updateId(const ObjectId id, const ObjectId updateId, std::unordered_map& ids) + void NavigatorImpl::updateId(const ObjectId id, const ObjectId updateId, std::unordered_map& ids) { auto inserted = ids.insert(std::make_pair(id, updateId)); if (!inserted.second) diff --git a/components/detournavigator/navigatorimpl.hpp b/components/detournavigator/navigatorimpl.hpp new file mode 100644 index 000000000..975055984 --- /dev/null +++ b/components/detournavigator/navigatorimpl.hpp @@ -0,0 +1,64 @@ +#ifndef OPENMW_COMPONENTS_DETOURNAVIGATOR_NAVIGATORIMPL_H +#define OPENMW_COMPONENTS_DETOURNAVIGATOR_NAVIGATORIMPL_H + +#include "navigator.hpp" +#include "navmeshmanager.hpp" + +namespace DetourNavigator +{ + class NavigatorImpl final : public Navigator + { + public: + /** + * @brief Navigator constructor initializes all internal data. Constructed object is ready to build a scene. + * @param settings allows to customize navigator work. Constructor is only place to set navigator settings. + */ + NavigatorImpl(const Settings& settings); + + void addAgent(const osg::Vec3f& agentHalfExtents) override; + + void removeAgent(const osg::Vec3f& agentHalfExtents) override; + + bool addObject(const ObjectId id, const btCollisionShape& shape, const btTransform& transform) override; + + bool addObject(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform) override; + + bool addObject(const ObjectId id, const DoorShapes& shapes, const btTransform& transform) override; + + bool updateObject(const ObjectId id, const btCollisionShape& shape, const btTransform& transform) override; + + bool updateObject(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform) override; + + bool updateObject(const ObjectId id, const DoorShapes& shapes, const btTransform& transform) override; + + bool removeObject(const ObjectId id) override; + + bool addWater(const osg::Vec2i& cellPosition, const int cellSize, const btScalar level, + const btTransform& transform) override; + + bool removeWater(const osg::Vec2i& cellPosition) override; + + void update(const osg::Vec3f& playerPosition) override; + + void wait() override; + + SharedNavMeshCacheItem getNavMesh(const osg::Vec3f& agentHalfExtents) const override; + + std::map getNavMeshes() const override; + + Settings getSettings() const override; + + private: + Settings mSettings; + NavMeshManager mNavMeshManager; + std::map mAgents; + std::unordered_map mAvoidIds; + std::unordered_map mWaterIds; + + 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); + }; +} + +#endif From 16675fd25495bd390b2e7018bde147877878d112 Mon Sep 17 00:00:00 2001 From: elsid Date: Sat, 16 Feb 2019 15:32:47 +0300 Subject: [PATCH 5/7] Return empty path when navmesh is not found for agent --- .../detournavigator/navigator.cpp | 10 ++++++---- components/detournavigator/navigator.hpp | 2 ++ components/detournavigator/navmeshmanager.cpp | 14 +++++++++----- components/detournavigator/navmeshmanager.hpp | 2 +- components/misc/guarded.hpp | 5 +++++ 5 files changed, 23 insertions(+), 10 deletions(-) diff --git a/apps/openmw_test_suite/detournavigator/navigator.cpp b/apps/openmw_test_suite/detournavigator/navigator.cpp index 288392143..8e76b3154 100644 --- a/apps/openmw_test_suite/detournavigator/navigator.cpp +++ b/apps/openmw_test_suite/detournavigator/navigator.cpp @@ -65,9 +65,10 @@ namespace } }; - TEST_F(DetourNavigatorNavigatorTest, find_path_for_empty_should_throw_exception) + TEST_F(DetourNavigatorNavigatorTest, find_path_for_empty_should_return_empty) { - EXPECT_THROW(mNavigator->findPath(mAgentHalfExtents, mStart, mEnd, Flag_walk, mOut), InvalidArgument); + mNavigator->findPath(mAgentHalfExtents, mStart, mEnd, Flag_walk, mOut); + EXPECT_EQ(mPath, std::deque()); } TEST_F(DetourNavigatorNavigatorTest, find_path_for_existing_agent_with_no_navmesh_should_throw_exception) @@ -76,11 +77,12 @@ namespace EXPECT_THROW(mNavigator->findPath(mAgentHalfExtents, mStart, mEnd, Flag_walk, mOut), NavigatorException); } - TEST_F(DetourNavigatorNavigatorTest, find_path_for_removed_agent_should_throw_exception) + TEST_F(DetourNavigatorNavigatorTest, find_path_for_removed_agent_should_return_empty) { mNavigator->addAgent(mAgentHalfExtents); mNavigator->removeAgent(mAgentHalfExtents); - EXPECT_THROW(mNavigator->findPath(mAgentHalfExtents, mStart, mEnd, Flag_walk, mOut), InvalidArgument); + mNavigator->findPath(mAgentHalfExtents, mStart, mEnd, Flag_walk, mOut); + EXPECT_EQ(mPath, std::deque()); } TEST_F(DetourNavigatorNavigatorTest, add_agent_should_count_each_agent) diff --git a/components/detournavigator/navigator.hpp b/components/detournavigator/navigator.hpp index 529b539c8..a06d97c56 100644 --- a/components/detournavigator/navigator.hpp +++ b/components/detournavigator/navigator.hpp @@ -171,6 +171,8 @@ namespace DetourNavigator "out is not an OutputIterator" ); const auto navMesh = getNavMesh(agentHalfExtents); + if (!navMesh) + return out; const auto settings = getSettings(); return findSmoothPath(navMesh.lock()->getValue(), toNavMeshCoordinates(settings, agentHalfExtents), toNavMeshCoordinates(settings, start), toNavMeshCoordinates(settings, end), includeFlags, diff --git a/components/detournavigator/navmeshmanager.cpp b/components/detournavigator/navmeshmanager.cpp index 66bf39aaf..ddf0045a2 100644 --- a/components/detournavigator/navmeshmanager.cpp +++ b/components/detournavigator/navmeshmanager.cpp @@ -133,7 +133,13 @@ namespace DetourNavigator else lastPlayerTile->second = playerTile; std::map tilesToPost; - const auto& cached = getCached(agentHalfExtents); + const auto cached = getCached(agentHalfExtents); + if (!cached) + { + std::ostringstream stream; + stream << "Agent with half extents is not found: " << agentHalfExtents; + throw InvalidArgument(stream.str()); + } const auto changedTiles = mChangedTiles.find(agentHalfExtents); { const auto locked = cached.lock(); @@ -218,13 +224,11 @@ namespace DetourNavigator } } - const SharedNavMeshCacheItem& NavMeshManager::getCached(const osg::Vec3f& agentHalfExtents) const + SharedNavMeshCacheItem NavMeshManager::getCached(const osg::Vec3f& agentHalfExtents) const { const auto cached = mCache.find(agentHalfExtents); if (cached != mCache.end()) return cached->second; - std::ostringstream stream; - stream << "Agent with half extents is not found: " << agentHalfExtents; - throw InvalidArgument(stream.str()); + return SharedNavMeshCacheItem(); } } diff --git a/components/detournavigator/navmeshmanager.hpp b/components/detournavigator/navmeshmanager.hpp index f44cdd251..ae006da73 100644 --- a/components/detournavigator/navmeshmanager.hpp +++ b/components/detournavigator/navmeshmanager.hpp @@ -67,7 +67,7 @@ namespace DetourNavigator void addChangedTile(const TilePosition& tilePosition, const ChangeType changeType); - const SharedNavMeshCacheItem& getCached(const osg::Vec3f& agentHalfExtents) const; + SharedNavMeshCacheItem getCached(const osg::Vec3f& agentHalfExtents) const; }; } diff --git a/components/misc/guarded.hpp b/components/misc/guarded.hpp index 4cb0564b1..114a77b10 100644 --- a/components/misc/guarded.hpp +++ b/components/misc/guarded.hpp @@ -106,6 +106,11 @@ namespace Misc return Locked(*mMutex, *mValue); } + operator bool() const + { + return static_cast(mValue); + } + private: std::shared_ptr mMutex; std::shared_ptr mValue; From 34c594f01e1f647a96f5814408a0b25cb9d22ceb Mon Sep 17 00:00:00 2001 From: elsid Date: Sat, 16 Feb 2019 15:39:06 +0300 Subject: [PATCH 6/7] Add default initializators for settings fields --- components/detournavigator/settings.hpp | 52 ++++++++++++------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/components/detournavigator/settings.hpp b/components/detournavigator/settings.hpp index f4073b24b..dda193fff 100644 --- a/components/detournavigator/settings.hpp +++ b/components/detournavigator/settings.hpp @@ -7,32 +7,32 @@ namespace DetourNavigator { struct Settings { - bool mEnableWriteRecastMeshToFile; - bool mEnableWriteNavMeshToFile; - bool mEnableRecastMeshFileNameRevision; - bool mEnableNavMeshFileNameRevision; - float mCellHeight; - float mCellSize; - float mDetailSampleDist; - float mDetailSampleMaxError; - float mMaxClimb; - float mMaxSimplificationError; - float mMaxSlope; - float mRecastScaleFactor; - float mSwimHeightScale; - int mBorderSize; - int mMaxEdgeLen; - int mMaxNavMeshQueryNodes; - int mMaxPolys; - int mMaxVertsPerPoly; - int mRegionMergeSize; - int mRegionMinSize; - int mTileSize; - std::size_t mAsyncNavMeshUpdaterThreads; - std::size_t mMaxNavMeshTilesCacheSize; - std::size_t mMaxPolygonPathSize; - std::size_t mMaxSmoothPathSize; - std::size_t mTrianglesPerChunk; + bool mEnableWriteRecastMeshToFile = false; + bool mEnableWriteNavMeshToFile = false; + bool mEnableRecastMeshFileNameRevision = false; + bool mEnableNavMeshFileNameRevision = false; + float mCellHeight = 0; + float mCellSize = 0; + float mDetailSampleDist = 0; + float mDetailSampleMaxError = 0; + float mMaxClimb = 0; + float mMaxSimplificationError = 0; + float mMaxSlope = 0; + float mRecastScaleFactor = 0; + float mSwimHeightScale = 0; + int mBorderSize = 0; + int mMaxEdgeLen = 0; + int mMaxNavMeshQueryNodes = 0; + int mMaxPolys = 0; + int mMaxVertsPerPoly = 0; + int mRegionMergeSize = 0; + int mRegionMinSize = 0; + int mTileSize = 0; + std::size_t mAsyncNavMeshUpdaterThreads = 0; + std::size_t mMaxNavMeshTilesCacheSize = 0; + std::size_t mMaxPolygonPathSize = 0; + std::size_t mMaxSmoothPathSize = 0; + std::size_t mTrianglesPerChunk = 0; std::string mRecastMeshPathPrefix; std::string mNavMeshPathPrefix; }; From 9626b6ec422ffbc0b264e98031eac78340725736 Mon Sep 17 00:00:00 2001 From: elsid Date: Sat, 16 Feb 2019 15:50:58 +0300 Subject: [PATCH 7/7] Add option to disable DetourNavigator component to find paths --- apps/openmw/mwworld/worldimp.cpp | 25 +++--- components/detournavigator/navigatorstub.hpp | 83 ++++++++++++++++++++ components/detournavigator/settings.cpp | 5 +- components/detournavigator/settings.hpp | 4 +- files/settings-default.cfg | 4 + 5 files changed, 110 insertions(+), 11 deletions(-) create mode 100644 components/detournavigator/navigatorstub.hpp diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 65d629384..d7963fae1 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -25,6 +25,7 @@ #include #include +#include #include #include "../mwbase/environment.hpp" @@ -198,15 +199,21 @@ namespace MWWorld mPhysics.reset(new MWPhysics::PhysicsSystem(resourceSystem, rootNode)); - auto navigatorSettings = DetourNavigator::makeSettingsFromSettingsManager(); - navigatorSettings.mMaxClimb = MWPhysics::sStepSizeUp; - navigatorSettings.mMaxSlope = MWPhysics::sMaxSlope; - navigatorSettings.mSwimHeightScale = mSwimHeightScale; - if (Settings::Manager::getBool("enable log", "Navigator")) - DetourNavigator::Log::instance().setSink(std::unique_ptr( - new DetourNavigator::FileSink(Settings::Manager::getString("log path", "Navigator")))); - DetourNavigator::RecastGlobalAllocator::init(); - mNavigator.reset(new DetourNavigator::NavigatorImpl(navigatorSettings)); + if (auto navigatorSettings = DetourNavigator::makeSettingsFromSettingsManager()) + { + navigatorSettings->mMaxClimb = MWPhysics::sStepSizeUp; + navigatorSettings->mMaxSlope = MWPhysics::sMaxSlope; + navigatorSettings->mSwimHeightScale = mSwimHeightScale; + if (Settings::Manager::getBool("enable log", "Navigator")) + DetourNavigator::Log::instance().setSink(std::unique_ptr( + new DetourNavigator::FileSink(Settings::Manager::getString("log path", "Navigator")))); + DetourNavigator::RecastGlobalAllocator::init(); + mNavigator.reset(new DetourNavigator::NavigatorImpl(*navigatorSettings)); + } + else + { + mNavigator.reset(new DetourNavigator::NavigatorStub()); + } mRendering.reset(new MWRender::RenderingManager(viewer, rootNode, resourceSystem, workQueue, &mFallback, resourcePath, *mNavigator)); mProjectileManager.reset(new ProjectileManager(mRendering->getLightRoot(), resourceSystem, mRendering.get(), mPhysics.get())); diff --git a/components/detournavigator/navigatorstub.hpp b/components/detournavigator/navigatorstub.hpp new file mode 100644 index 000000000..5d82d2f59 --- /dev/null +++ b/components/detournavigator/navigatorstub.hpp @@ -0,0 +1,83 @@ +#ifndef OPENMW_COMPONENTS_DETOURNAVIGATOR_NAVIGATORSTUB_H +#define OPENMW_COMPONENTS_DETOURNAVIGATOR_NAVIGATORSTUB_H + +#include "navigator.hpp" + +namespace DetourNavigator +{ + struct NavigatorStub final : public Navigator + { + NavigatorStub() = default; + + void addAgent(const osg::Vec3f& /*agentHalfExtents*/) override {} + + void removeAgent(const osg::Vec3f& /*agentHalfExtents*/) override {} + + bool addObject(const ObjectId /*id*/, const btCollisionShape& /*shape*/, const btTransform& /*transform*/) override + { + return false; + } + + bool addObject(const ObjectId /*id*/, const ObjectShapes& /*shapes*/, const btTransform& /*transform*/) override + { + return false; + } + + bool addObject(const ObjectId /*id*/, const DoorShapes& /*shapes*/, const btTransform& /*transform*/) override + { + return false; + } + + bool updateObject(const ObjectId /*id*/, const btCollisionShape& /*shape*/, const btTransform& /*transform*/) override + { + return false; + } + + bool updateObject(const ObjectId /*id*/, const ObjectShapes& /*shapes*/, const btTransform& /*transform*/) override + { + return false; + } + + bool updateObject(const ObjectId /*id*/, const DoorShapes& /*shapes*/, const btTransform& /*transform*/) override + { + return false; + } + + bool removeObject(const ObjectId /*id*/) override + { + return false; + } + + bool addWater(const osg::Vec2i& /*cellPosition*/, const int /*cellSize*/, const btScalar /*level*/, + const btTransform& /*transform*/) override + { + return false; + } + + bool removeWater(const osg::Vec2i& /*cellPosition*/) override + { + return false; + } + + void update(const osg::Vec3f& /*playerPosition*/) override {} + + void wait() override {} + + SharedNavMeshCacheItem getNavMesh(const osg::Vec3f& /*agentHalfExtents*/) const override + { + return SharedNavMeshCacheItem(); + } + + std::map getNavMeshes() const override + { + return std::map(); + } + + Settings getSettings() const override + { + return Settings {}; + } + }; +} + +#endif diff --git a/components/detournavigator/settings.cpp b/components/detournavigator/settings.cpp index 0b9210a90..f584e48f9 100644 --- a/components/detournavigator/settings.cpp +++ b/components/detournavigator/settings.cpp @@ -6,8 +6,11 @@ namespace DetourNavigator { - Settings makeSettingsFromSettingsManager() + boost::optional makeSettingsFromSettingsManager() { + if (!::Settings::Manager::getBool("enable", "Navigator")) + return boost::optional(); + Settings navigatorSettings; navigatorSettings.mBorderSize = ::Settings::Manager::getInt("border size", "Navigator"); diff --git a/components/detournavigator/settings.hpp b/components/detournavigator/settings.hpp index dda193fff..0316092a0 100644 --- a/components/detournavigator/settings.hpp +++ b/components/detournavigator/settings.hpp @@ -1,6 +1,8 @@ #ifndef OPENMW_COMPONENTS_DETOURNAVIGATOR_SETTINGS_H #define OPENMW_COMPONENTS_DETOURNAVIGATOR_SETTINGS_H +#include + #include namespace DetourNavigator @@ -37,7 +39,7 @@ namespace DetourNavigator std::string mNavMeshPathPrefix; }; - Settings makeSettingsFromSettingsManager(); + boost::optional makeSettingsFromSettingsManager(); } #endif diff --git a/files/settings-default.cfg b/files/settings-default.cfg index 71a93d1a2..81df700cc 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -542,6 +542,10 @@ companion h = 0.63 [Navigator] +# Enable navigator (true, false). When enabled background threads are started to build navmesh for world geometry. +# Pathfinding system uses navmesh to build paths. When disabled only pathgrid is used to build paths. +enable = true + # Scale of NavMesh coordinates to world coordinates (value > 0.0). Recastnavigation builds voxels for world geometry. # Basically voxel size is 1 / "cell size". To reduce amount of voxels we apply scale factor, to make voxel size # "recast scale factor" / "cell size". Default value calculates by this equation: