mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-19 21:53:51 +00:00
Merge pull request #2170 from elsid/disable_navigator_option
Add option to disable DetourNavigator component (feature #4833)
This commit is contained in:
commit
09262e0336
17 changed files with 344 additions and 143 deletions
|
@ -57,7 +57,7 @@ namespace MWMechanics
|
|||
|
||||
namespace DetourNavigator
|
||||
{
|
||||
class Navigator;
|
||||
struct Navigator;
|
||||
}
|
||||
|
||||
namespace MWWorld
|
||||
|
|
|
@ -59,7 +59,7 @@ namespace SceneUtil
|
|||
|
||||
namespace DetourNavigator
|
||||
{
|
||||
class Navigator;
|
||||
struct Navigator;
|
||||
struct Settings;
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ namespace Loading
|
|||
|
||||
namespace DetourNavigator
|
||||
{
|
||||
class Navigator;
|
||||
struct Navigator;
|
||||
class Water;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,8 @@
|
|||
#include <components/sceneutil/positionattitudetransform.hpp>
|
||||
|
||||
#include <components/detournavigator/debug.hpp>
|
||||
#include <components/detournavigator/navigator.hpp>
|
||||
#include <components/detournavigator/navigatorimpl.hpp>
|
||||
#include <components/detournavigator/navigatorstub.hpp>
|
||||
#include <components/detournavigator/recastglobalallocator.hpp>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
|
@ -198,40 +199,21 @@ 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");
|
||||
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<std::size_t>(Settings::Manager::getInt("async nav mesh updater threads", "Navigator"));
|
||||
navigatorSettings.mMaxNavMeshTilesCacheSize = static_cast<std::size_t>(Settings::Manager::getInt("max nav mesh tiles cache size", "Navigator"));
|
||||
navigatorSettings.mMaxPolygonPathSize = static_cast<std::size_t>(Settings::Manager::getInt("max polygon path size", "Navigator"));
|
||||
navigatorSettings.mMaxSmoothPathSize = static_cast<std::size_t>(Settings::Manager::getInt("max smooth path size", "Navigator"));
|
||||
navigatorSettings.mTrianglesPerChunk = static_cast<std::size_t>(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<DetourNavigator::FileSink>(
|
||||
new DetourNavigator::FileSink(Settings::Manager::getString("log path", "Navigator"))));
|
||||
DetourNavigator::RecastGlobalAllocator::init();
|
||||
mNavigator.reset(new DetourNavigator::Navigator(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<DetourNavigator::FileSink>(
|
||||
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()));
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#include "operators.hpp"
|
||||
|
||||
#include <components/detournavigator/navigator.hpp>
|
||||
#include <components/detournavigator/navigatorimpl.hpp>
|
||||
#include <components/detournavigator/exceptions.hpp>
|
||||
|
||||
#include <BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h>
|
||||
|
@ -61,13 +61,14 @@ namespace
|
|||
mSettings.mMaxSmoothPathSize = 1024;
|
||||
mSettings.mTrianglesPerChunk = 256;
|
||||
mSettings.mMaxPolys = 4096;
|
||||
mNavigator.reset(new Navigator(mSettings));
|
||||
mNavigator.reset(new NavigatorImpl(mSettings));
|
||||
}
|
||||
};
|
||||
|
||||
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<osg::Vec3f>());
|
||||
}
|
||||
|
||||
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<osg::Vec3f>());
|
||||
}
|
||||
|
||||
TEST_F(DetourNavigatorNavigatorTest, add_agent_should_count_each_agent)
|
||||
|
|
|
@ -164,13 +164,14 @@ add_component_dir(detournavigator
|
|||
recastmeshmanager
|
||||
cachedrecastmeshmanager
|
||||
navmeshmanager
|
||||
navigator
|
||||
navigatorimpl
|
||||
asyncnavmeshupdater
|
||||
chunkytrimesh
|
||||
recastmesh
|
||||
tilecachedrecastmeshmanager
|
||||
recastmeshobject
|
||||
navmeshtilescache
|
||||
settings
|
||||
)
|
||||
|
||||
set (ESM_UI ${CMAKE_SOURCE_DIR}/files/ui/contentselector.ui
|
||||
|
|
|
@ -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<OutputIterator> mImpl;
|
||||
std::reference_wrapper<const Settings> mSettings;
|
||||
};
|
||||
|
||||
inline void initNavMeshQuery(dtNavMeshQuery& value, const dtNavMesh& navMesh, const int maxNodes)
|
||||
|
|
|
@ -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.
|
||||
|
@ -175,30 +170,28 @@ 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);
|
||||
if (!navMesh)
|
||||
return out;
|
||||
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
|
||||
*/
|
||||
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<osg::Vec3f, SharedNavMeshCacheItem> getNavMeshes() const;
|
||||
virtual std::map<osg::Vec3f, SharedNavMeshCacheItem> getNavMeshes() const = 0;
|
||||
|
||||
const Settings& getSettings() const;
|
||||
|
||||
private:
|
||||
Settings mSettings;
|
||||
NavMeshManager mNavMeshManager;
|
||||
std::map<osg::Vec3f, std::size_t> mAgents;
|
||||
std::unordered_map<ObjectId, ObjectId> mAvoidIds;
|
||||
std::unordered_map<ObjectId, ObjectId> 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<ObjectId, ObjectId>& ids);
|
||||
virtual Settings getSettings() const = 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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<const ObjectShapes&>(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<const ObjectShapes&>(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,50 +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();
|
||||
}
|
||||
|
||||
std::map<osg::Vec3f, SharedNavMeshCacheItem> Navigator::getNavMeshes() const
|
||||
SharedNavMeshCacheItem NavigatorImpl::getNavMesh(const osg::Vec3f& agentHalfExtents) const
|
||||
{
|
||||
return mNavMeshManager.getNavMesh(agentHalfExtents);
|
||||
}
|
||||
|
||||
std::map<osg::Vec3f, SharedNavMeshCacheItem> NavigatorImpl::getNavMeshes() const
|
||||
{
|
||||
return mNavMeshManager.getNavMeshes();
|
||||
}
|
||||
|
||||
const 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<ObjectId, ObjectId>& ids)
|
||||
void NavigatorImpl::updateId(const ObjectId id, const ObjectId updateId, std::unordered_map<ObjectId, ObjectId>& ids)
|
||||
{
|
||||
auto inserted = ids.insert(std::make_pair(id, updateId));
|
||||
if (!inserted.second)
|
64
components/detournavigator/navigatorimpl.hpp
Normal file
64
components/detournavigator/navigatorimpl.hpp
Normal file
|
@ -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<osg::Vec3f, SharedNavMeshCacheItem> getNavMeshes() const override;
|
||||
|
||||
Settings getSettings() const override;
|
||||
|
||||
private:
|
||||
Settings mSettings;
|
||||
NavMeshManager mNavMeshManager;
|
||||
std::map<osg::Vec3f, std::size_t> mAgents;
|
||||
std::unordered_map<ObjectId, ObjectId> mAvoidIds;
|
||||
std::unordered_map<ObjectId, ObjectId> 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<ObjectId, ObjectId>& ids);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
83
components/detournavigator/navigatorstub.hpp
Normal file
83
components/detournavigator/navigatorstub.hpp
Normal file
|
@ -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<osg::Vec3f, SharedNavMeshCacheItem> getNavMeshes() const override
|
||||
{
|
||||
return std::map<osg::Vec3f, SharedNavMeshCacheItem>();
|
||||
}
|
||||
|
||||
Settings getSettings() const override
|
||||
{
|
||||
return Settings {};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -135,7 +135,13 @@ namespace DetourNavigator
|
|||
else
|
||||
lastPlayerTile->second = playerTile;
|
||||
std::map<TilePosition, ChangeType> 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();
|
||||
|
@ -220,13 +226,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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
47
components/detournavigator/settings.cpp
Normal file
47
components/detournavigator/settings.cpp
Normal file
|
@ -0,0 +1,47 @@
|
|||
#include "settings.hpp"
|
||||
|
||||
#include <components/settings/settings.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace DetourNavigator
|
||||
{
|
||||
boost::optional<Settings> makeSettingsFromSettingsManager()
|
||||
{
|
||||
if (!::Settings::Manager::getBool("enable", "Navigator"))
|
||||
return boost::optional<Settings>();
|
||||
|
||||
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<std::size_t>(::Settings::Manager::getInt("async nav mesh updater threads", "Navigator"));
|
||||
navigatorSettings.mMaxNavMeshTilesCacheSize = static_cast<std::size_t>(::Settings::Manager::getInt("max nav mesh tiles cache size", "Navigator"));
|
||||
navigatorSettings.mMaxPolygonPathSize = static_cast<std::size_t>(::Settings::Manager::getInt("max polygon path size", "Navigator"));
|
||||
navigatorSettings.mMaxSmoothPathSize = static_cast<std::size_t>(::Settings::Manager::getInt("max smooth path size", "Navigator"));
|
||||
navigatorSettings.mTrianglesPerChunk = static_cast<std::size_t>(::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;
|
||||
}
|
||||
}
|
|
@ -1,41 +1,45 @@
|
|||
#ifndef OPENMW_COMPONENTS_DETOURNAVIGATOR_SETTINGS_H
|
||||
#define OPENMW_COMPONENTS_DETOURNAVIGATOR_SETTINGS_H
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
boost::optional<Settings> makeSettingsFromSettingsManager();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -106,6 +106,11 @@ namespace Misc
|
|||
return Locked<const T>(*mMutex, *mValue);
|
||||
}
|
||||
|
||||
operator bool() const
|
||||
{
|
||||
return static_cast<bool>(mValue);
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<std::mutex> mMutex;
|
||||
std::shared_ptr<T> mValue;
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in a new issue