mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-04-29 05:17:58 +03:00
Split navigator settings into subtypes
Mostly to distinguish settings that affect properties of the generated navmesh.
This commit is contained in:
parent
33bb18850d
commit
01c712d5f1
38 changed files with 327 additions and 304 deletions
|
@ -4,6 +4,7 @@
|
||||||
#include <components/sceneutil/agentpath.hpp>
|
#include <components/sceneutil/agentpath.hpp>
|
||||||
#include <components/resource/resourcesystem.hpp>
|
#include <components/resource/resourcesystem.hpp>
|
||||||
#include <components/resource/scenemanager.hpp>
|
#include <components/resource/scenemanager.hpp>
|
||||||
|
#include <components/detournavigator/settings.hpp>
|
||||||
|
|
||||||
#include <osg/PositionAttitudeTransform>
|
#include <osg/PositionAttitudeTransform>
|
||||||
|
|
||||||
|
@ -47,7 +48,7 @@ namespace MWRender
|
||||||
if (group != mGroups.end())
|
if (group != mGroups.end())
|
||||||
mRootNode->removeChild(group->second);
|
mRootNode->removeChild(group->second);
|
||||||
|
|
||||||
const auto newGroup = SceneUtil::createAgentPathGroup(path, halfExtents, start, end, settings);
|
const auto newGroup = SceneUtil::createAgentPathGroup(path, halfExtents, start, end, settings.mRecast);
|
||||||
if (newGroup)
|
if (newGroup)
|
||||||
{
|
{
|
||||||
MWBase::Environment::get().getResourceSystem()->getSceneManager()->recreateShaders(newGroup, "debug");
|
MWBase::Environment::get().getResourceSystem()->getSceneManager()->recreateShaders(newGroup, "debug");
|
||||||
|
|
|
@ -54,7 +54,7 @@ namespace MWRender
|
||||||
if (it->second.mGeneration != tile->second->getGeneration()
|
if (it->second.mGeneration != tile->second->getGeneration()
|
||||||
|| it->second.mRevision != tile->second->getRevision())
|
|| it->second.mRevision != tile->second->getRevision())
|
||||||
{
|
{
|
||||||
const auto group = SceneUtil::createRecastMeshGroup(*tile->second, settings);
|
const auto group = SceneUtil::createRecastMeshGroup(*tile->second, settings.mRecast);
|
||||||
MWBase::Environment::get().getResourceSystem()->getSceneManager()->recreateShaders(group, "debug");
|
MWBase::Environment::get().getResourceSystem()->getSceneManager()->recreateShaders(group, "debug");
|
||||||
group->setNodeMask(Mask_Debug);
|
group->setNodeMask(Mask_Debug);
|
||||||
mRootNode->removeChild(it->second.mValue);
|
mRootNode->removeChild(it->second.mValue);
|
||||||
|
@ -71,7 +71,7 @@ namespace MWRender
|
||||||
{
|
{
|
||||||
if (mGroups.count(tile.first))
|
if (mGroups.count(tile.first))
|
||||||
continue;
|
continue;
|
||||||
const auto group = SceneUtil::createRecastMeshGroup(*tile.second, settings);
|
const auto group = SceneUtil::createRecastMeshGroup(*tile.second, settings.mRecast);
|
||||||
MWBase::Environment::get().getResourceSystem()->getSceneManager()->recreateShaders(group, "debug");
|
MWBase::Environment::get().getResourceSystem()->getSceneManager()->recreateShaders(group, "debug");
|
||||||
group->setNodeMask(Mask_Debug);
|
group->setNodeMask(Mask_Debug);
|
||||||
mGroups.emplace(tile.first, Group {tile.second->getGeneration(), tile.second->getRevision(), group});
|
mGroups.emplace(tile.first, Group {tile.second->getGeneration(), tile.second->getRevision(), group});
|
||||||
|
|
|
@ -186,7 +186,7 @@ namespace MWWorld
|
||||||
if (Settings::Manager::getBool("enable", "Navigator"))
|
if (Settings::Manager::getBool("enable", "Navigator"))
|
||||||
{
|
{
|
||||||
auto navigatorSettings = DetourNavigator::makeSettingsFromSettingsManager();
|
auto navigatorSettings = DetourNavigator::makeSettingsFromSettingsManager();
|
||||||
navigatorSettings.mSwimHeightScale = mSwimHeightScale;
|
navigatorSettings.mRecast.mSwimHeightScale = mSwimHeightScale;
|
||||||
mNavigator = DetourNavigator::makeNavigator(navigatorSettings);
|
mNavigator = DetourNavigator::makeNavigator(navigatorSettings);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -21,7 +21,7 @@ namespace
|
||||||
|
|
||||||
struct DetourNavigatorGetTilesPositionsTest : Test
|
struct DetourNavigatorGetTilesPositionsTest : Test
|
||||||
{
|
{
|
||||||
Settings mSettings;
|
RecastSettings mSettings;
|
||||||
std::vector<TilePosition> mTilesPositions;
|
std::vector<TilePosition> mTilesPositions;
|
||||||
CollectTilesPositions mCollect {mTilesPositions};
|
CollectTilesPositions mCollect {mTilesPositions};
|
||||||
|
|
||||||
|
|
|
@ -63,28 +63,28 @@ namespace
|
||||||
mSettings.mEnableWriteNavMeshToFile = false;
|
mSettings.mEnableWriteNavMeshToFile = false;
|
||||||
mSettings.mEnableRecastMeshFileNameRevision = false;
|
mSettings.mEnableRecastMeshFileNameRevision = false;
|
||||||
mSettings.mEnableNavMeshFileNameRevision = false;
|
mSettings.mEnableNavMeshFileNameRevision = false;
|
||||||
mSettings.mBorderSize = 16;
|
mSettings.mRecast.mBorderSize = 16;
|
||||||
mSettings.mCellHeight = 0.2f;
|
mSettings.mRecast.mCellHeight = 0.2f;
|
||||||
mSettings.mCellSize = 0.2f;
|
mSettings.mRecast.mCellSize = 0.2f;
|
||||||
mSettings.mDetailSampleDist = 6;
|
mSettings.mRecast.mDetailSampleDist = 6;
|
||||||
mSettings.mDetailSampleMaxError = 1;
|
mSettings.mRecast.mDetailSampleMaxError = 1;
|
||||||
mSettings.mMaxClimb = 34;
|
mSettings.mRecast.mMaxClimb = 34;
|
||||||
mSettings.mMaxSimplificationError = 1.3f;
|
mSettings.mRecast.mMaxSimplificationError = 1.3f;
|
||||||
mSettings.mMaxSlope = 49;
|
mSettings.mRecast.mMaxSlope = 49;
|
||||||
mSettings.mRecastScaleFactor = 0.017647058823529415f;
|
mSettings.mRecast.mRecastScaleFactor = 0.017647058823529415f;
|
||||||
mSettings.mSwimHeightScale = 0.89999997615814208984375f;
|
mSettings.mRecast.mSwimHeightScale = 0.89999997615814208984375f;
|
||||||
mSettings.mMaxEdgeLen = 12;
|
mSettings.mRecast.mMaxEdgeLen = 12;
|
||||||
mSettings.mMaxNavMeshQueryNodes = 2048;
|
mSettings.mDetour.mMaxNavMeshQueryNodes = 2048;
|
||||||
mSettings.mMaxVertsPerPoly = 6;
|
mSettings.mRecast.mMaxVertsPerPoly = 6;
|
||||||
mSettings.mRegionMergeSize = 20;
|
mSettings.mRecast.mRegionMergeArea = 400;
|
||||||
mSettings.mRegionMinSize = 8;
|
mSettings.mRecast.mRegionMinArea = 64;
|
||||||
mSettings.mTileSize = 64;
|
mSettings.mRecast.mTileSize = 64;
|
||||||
mSettings.mWaitUntilMinDistanceToPlayer = std::numeric_limits<int>::max();
|
mSettings.mWaitUntilMinDistanceToPlayer = std::numeric_limits<int>::max();
|
||||||
mSettings.mAsyncNavMeshUpdaterThreads = 1;
|
mSettings.mAsyncNavMeshUpdaterThreads = 1;
|
||||||
mSettings.mMaxNavMeshTilesCacheSize = 1024 * 1024;
|
mSettings.mMaxNavMeshTilesCacheSize = 1024 * 1024;
|
||||||
mSettings.mMaxPolygonPathSize = 1024;
|
mSettings.mDetour.mMaxPolygonPathSize = 1024;
|
||||||
mSettings.mMaxSmoothPathSize = 1024;
|
mSettings.mDetour.mMaxSmoothPathSize = 1024;
|
||||||
mSettings.mMaxPolys = 4096;
|
mSettings.mDetour.mMaxPolys = 4096;
|
||||||
mSettings.mMaxTilesNumber = 512;
|
mSettings.mMaxTilesNumber = 512;
|
||||||
mSettings.mMinUpdateInterval = std::chrono::milliseconds(50);
|
mSettings.mMinUpdateInterval = std::chrono::milliseconds(50);
|
||||||
mNavigator.reset(new NavigatorImpl(mSettings));
|
mNavigator.reset(new NavigatorImpl(mSettings));
|
||||||
|
|
|
@ -11,7 +11,7 @@ namespace
|
||||||
|
|
||||||
struct DetourNavigatorGetTilePositionTest : Test
|
struct DetourNavigatorGetTilePositionTest : Test
|
||||||
{
|
{
|
||||||
Settings mSettings;
|
RecastSettings mSettings;
|
||||||
|
|
||||||
DetourNavigatorGetTilePositionTest()
|
DetourNavigatorGetTilePositionTest()
|
||||||
{
|
{
|
||||||
|
@ -47,7 +47,7 @@ namespace
|
||||||
|
|
||||||
struct DetourNavigatorMakeTileBoundsTest : Test
|
struct DetourNavigatorMakeTileBoundsTest : Test
|
||||||
{
|
{
|
||||||
Settings mSettings;
|
RecastSettings mSettings;
|
||||||
|
|
||||||
DetourNavigatorMakeTileBoundsTest()
|
DetourNavigatorMakeTileBoundsTest()
|
||||||
{
|
{
|
||||||
|
|
|
@ -15,7 +15,7 @@ namespace
|
||||||
|
|
||||||
struct DetourNavigatorTileCachedRecastMeshManagerTest : Test
|
struct DetourNavigatorTileCachedRecastMeshManagerTest : Test
|
||||||
{
|
{
|
||||||
Settings mSettings;
|
RecastSettings mSettings;
|
||||||
std::vector<TilePosition> mChangedTiles;
|
std::vector<TilePosition> mChangedTiles;
|
||||||
const ObjectTransform mObjectTransform {ESM::Position {{0, 0, 0}, {0, 0, 0}}, 0.0f};
|
const ObjectTransform mObjectTransform {ESM::Position {{0, 0, 0}, {0, 0, 0}}, 0.0f};
|
||||||
const osg::ref_ptr<const Resource::BulletShape> mShape = new Resource::BulletShape;
|
const osg::ref_ptr<const Resource::BulletShape> mShape = new Resource::BulletShape;
|
||||||
|
|
|
@ -404,7 +404,7 @@ namespace DetourNavigator
|
||||||
}
|
}
|
||||||
if (recastMesh && mSettings.get().mEnableWriteRecastMeshToFile)
|
if (recastMesh && mSettings.get().mEnableWriteRecastMeshToFile)
|
||||||
writeToFile(*recastMesh, mSettings.get().mRecastMeshPathPrefix + std::to_string(job.mChangedTile.x())
|
writeToFile(*recastMesh, mSettings.get().mRecastMeshPathPrefix + std::to_string(job.mChangedTile.x())
|
||||||
+ "_" + std::to_string(job.mChangedTile.y()) + "_", recastMeshRevision, mSettings);
|
+ "_" + std::to_string(job.mChangedTile.y()) + "_", recastMeshRevision, mSettings.get().mRecast);
|
||||||
if (mSettings.get().mEnableWriteNavMeshToFile)
|
if (mSettings.get().mEnableWriteNavMeshToFile)
|
||||||
if (const auto shared = job.mNavMeshCacheItem.lock())
|
if (const auto shared = job.mNavMeshCacheItem.lock())
|
||||||
writeToFile(shared->lockConst()->getImpl(), mSettings.get().mNavMeshPathPrefix, navMeshRevision);
|
writeToFile(shared->lockConst()->getImpl(), mSettings.get().mNavMeshPathPrefix, navMeshRevision);
|
||||||
|
|
|
@ -11,7 +11,8 @@
|
||||||
|
|
||||||
namespace DetourNavigator
|
namespace DetourNavigator
|
||||||
{
|
{
|
||||||
void writeToFile(const RecastMesh& recastMesh, const std::string& pathPrefix, const std::string& revision, const Settings& settings)
|
void writeToFile(const RecastMesh& recastMesh, const std::string& pathPrefix,
|
||||||
|
const std::string& revision, const RecastSettings& settings)
|
||||||
{
|
{
|
||||||
const auto path = pathPrefix + "recastmesh" + revision + ".obj";
|
const auto path = pathPrefix + "recastmesh" + revision + ".obj";
|
||||||
boost::filesystem::ofstream file(boost::filesystem::path(path), std::ios::out);
|
boost::filesystem::ofstream file(boost::filesystem::path(path), std::ios::out);
|
||||||
|
|
|
@ -70,9 +70,10 @@ namespace DetourNavigator
|
||||||
}
|
}
|
||||||
|
|
||||||
class RecastMesh;
|
class RecastMesh;
|
||||||
struct Settings;
|
struct RecastSettings;
|
||||||
|
|
||||||
void writeToFile(const RecastMesh& recastMesh, const std::string& pathPrefix, const std::string& revision, const Settings& settings);
|
void writeToFile(const RecastMesh& recastMesh, const std::string& pathPrefix,
|
||||||
|
const std::string& revision, const RecastSettings& settings);
|
||||||
void writeToFile(const dtNavMesh& navMesh, const std::string& pathPrefix, const std::string& revision);
|
void writeToFile(const dtNavMesh& navMesh, const std::string& pathPrefix, const std::string& revision);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
namespace DetourNavigator
|
namespace DetourNavigator
|
||||||
{
|
{
|
||||||
std::optional<osg::Vec3f> findRandomPointAroundCircle(const dtNavMesh& navMesh, const osg::Vec3f& halfExtents,
|
std::optional<osg::Vec3f> findRandomPointAroundCircle(const dtNavMesh& navMesh, const osg::Vec3f& halfExtents,
|
||||||
const osg::Vec3f& start, const float maxRadius, const Flags includeFlags, const Settings& settings)
|
const osg::Vec3f& start, const float maxRadius, const Flags includeFlags, const DetourSettings& settings)
|
||||||
{
|
{
|
||||||
dtNavMeshQuery navMeshQuery;
|
dtNavMeshQuery navMeshQuery;
|
||||||
if (!initNavMeshQuery(navMeshQuery, navMesh, settings.mMaxNavMeshQueryNodes))
|
if (!initNavMeshQuery(navMeshQuery, navMesh, settings.mMaxNavMeshQueryNodes))
|
||||||
|
|
|
@ -10,10 +10,10 @@ class dtNavMesh;
|
||||||
|
|
||||||
namespace DetourNavigator
|
namespace DetourNavigator
|
||||||
{
|
{
|
||||||
struct Settings;
|
struct DetourSettings;
|
||||||
|
|
||||||
std::optional<osg::Vec3f> findRandomPointAroundCircle(const dtNavMesh& navMesh, const osg::Vec3f& halfExtents,
|
std::optional<osg::Vec3f> findRandomPointAroundCircle(const dtNavMesh& navMesh, const osg::Vec3f& halfExtents,
|
||||||
const osg::Vec3f& start, const float maxRadius, const Flags includeFlags, const Settings& settings);
|
const osg::Vec3f& start, const float maxRadius, const Flags includeFlags, const DetourSettings& settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -60,7 +60,7 @@ namespace DetourNavigator
|
||||||
class OutputTransformIterator
|
class OutputTransformIterator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
OutputTransformIterator(OutputIterator& impl, const Settings& settings)
|
explicit OutputTransformIterator(OutputIterator& impl, const RecastSettings& settings)
|
||||||
: mImpl(impl), mSettings(settings)
|
: mImpl(impl), mSettings(settings)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -91,7 +91,7 @@ namespace DetourNavigator
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::reference_wrapper<OutputIterator> mImpl;
|
std::reference_wrapper<OutputIterator> mImpl;
|
||||||
std::reference_wrapper<const Settings> mSettings;
|
std::reference_wrapper<const RecastSettings> mSettings;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline bool initNavMeshQuery(dtNavMeshQuery& value, const dtNavMesh& navMesh, const int maxNodes)
|
inline bool initNavMeshQuery(dtNavMeshQuery& value, const dtNavMesh& navMesh, const int maxNodes)
|
||||||
|
@ -261,7 +261,7 @@ namespace DetourNavigator
|
||||||
const Settings& settings, float endTolerance, OutputIterator& out)
|
const Settings& settings, float endTolerance, OutputIterator& out)
|
||||||
{
|
{
|
||||||
dtNavMeshQuery navMeshQuery;
|
dtNavMeshQuery navMeshQuery;
|
||||||
if (!initNavMeshQuery(navMeshQuery, navMesh, settings.mMaxNavMeshQueryNodes))
|
if (!initNavMeshQuery(navMeshQuery, navMesh, settings.mDetour.mMaxNavMeshQueryNodes))
|
||||||
return Status::InitNavMeshQueryFailed;
|
return Status::InitNavMeshQueryFailed;
|
||||||
|
|
||||||
dtQueryFilter queryFilter;
|
dtQueryFilter queryFilter;
|
||||||
|
@ -283,7 +283,7 @@ namespace DetourNavigator
|
||||||
if (endRef == 0)
|
if (endRef == 0)
|
||||||
return Status::EndPolygonNotFound;
|
return Status::EndPolygonNotFound;
|
||||||
|
|
||||||
std::vector<dtPolyRef> polygonPath(settings.mMaxPolygonPathSize);
|
std::vector<dtPolyRef> polygonPath(settings.mDetour.mMaxPolygonPathSize);
|
||||||
const auto polygonPathSize = findPath(navMeshQuery, startRef, endRef, start, end, queryFilter,
|
const auto polygonPathSize = findPath(navMeshQuery, startRef, endRef, start, end, queryFilter,
|
||||||
polygonPath.data(), polygonPath.size());
|
polygonPath.data(), polygonPath.size());
|
||||||
|
|
||||||
|
@ -294,9 +294,9 @@ namespace DetourNavigator
|
||||||
return Status::Success;
|
return Status::Success;
|
||||||
|
|
||||||
const bool partialPath = polygonPath[*polygonPathSize - 1] != endRef;
|
const bool partialPath = polygonPath[*polygonPathSize - 1] != endRef;
|
||||||
auto outTransform = OutputTransformIterator<OutputIterator>(out, settings);
|
auto outTransform = OutputTransformIterator<OutputIterator>(out, settings.mRecast);
|
||||||
const Status smoothStatus = makeSmoothPath(navMesh, navMeshQuery, queryFilter, start, end, stepSize,
|
const Status smoothStatus = makeSmoothPath(navMesh, navMeshQuery, queryFilter, start, end, stepSize,
|
||||||
polygonPath, *polygonPathSize, settings.mMaxSmoothPathSize, outTransform);
|
polygonPath, *polygonPathSize, settings.mDetour.mMaxSmoothPathSize, outTransform);
|
||||||
|
|
||||||
if (smoothStatus != Status::Success)
|
if (smoothStatus != Status::Success)
|
||||||
return smoothStatus;
|
return smoothStatus;
|
||||||
|
|
|
@ -15,7 +15,7 @@ namespace DetourNavigator
|
||||||
{
|
{
|
||||||
template <class Callback>
|
template <class Callback>
|
||||||
void getTilesPositions(const osg::Vec3f& aabbMin, const osg::Vec3f& aabbMax,
|
void getTilesPositions(const osg::Vec3f& aabbMin, const osg::Vec3f& aabbMax,
|
||||||
const Settings& settings, Callback&& callback)
|
const RecastSettings& settings, Callback&& callback)
|
||||||
{
|
{
|
||||||
auto min = toNavMeshCoordinates(settings, aabbMin);
|
auto min = toNavMeshCoordinates(settings, aabbMin);
|
||||||
auto max = toNavMeshCoordinates(settings, aabbMax);
|
auto max = toNavMeshCoordinates(settings, aabbMax);
|
||||||
|
@ -40,7 +40,7 @@ namespace DetourNavigator
|
||||||
|
|
||||||
template <class Callback>
|
template <class Callback>
|
||||||
void getTilesPositions(const btCollisionShape& shape, const btTransform& transform,
|
void getTilesPositions(const btCollisionShape& shape, const btTransform& transform,
|
||||||
const Settings& settings, Callback&& callback)
|
const RecastSettings& settings, Callback&& callback)
|
||||||
{
|
{
|
||||||
btVector3 aabbMin;
|
btVector3 aabbMin;
|
||||||
btVector3 aabbMax;
|
btVector3 aabbMax;
|
||||||
|
@ -51,7 +51,7 @@ namespace DetourNavigator
|
||||||
|
|
||||||
template <class Callback>
|
template <class Callback>
|
||||||
void getTilesPositions(const int cellSize, const btVector3& shift,
|
void getTilesPositions(const int cellSize, const btVector3& shift,
|
||||||
const Settings& settings, Callback&& callback)
|
const RecastSettings& settings, Callback&& callback)
|
||||||
{
|
{
|
||||||
using Misc::Convert::toOsg;
|
using Misc::Convert::toOsg;
|
||||||
|
|
||||||
|
|
|
@ -36,32 +36,6 @@ namespace
|
||||||
float mHeight;
|
float mHeight;
|
||||||
};
|
};
|
||||||
|
|
||||||
Rectangle getSwimRectangle(const CellWater& water, const Settings& settings, const osg::Vec3f& agentHalfExtents)
|
|
||||||
{
|
|
||||||
if (water.mWater.mCellSize == std::numeric_limits<int>::max())
|
|
||||||
{
|
|
||||||
return Rectangle {
|
|
||||||
TileBounds {
|
|
||||||
osg::Vec2f(-std::numeric_limits<float>::max(), -std::numeric_limits<float>::max()),
|
|
||||||
osg::Vec2f(std::numeric_limits<float>::max(), std::numeric_limits<float>::max())
|
|
||||||
},
|
|
||||||
toNavMeshCoordinates(settings, getSwimLevel(settings, water.mWater.mLevel, agentHalfExtents.z()))
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const osg::Vec2f shift = getWaterShift2d(water.mCellPosition, water.mWater.mCellSize);
|
|
||||||
const float halfCellSize = water.mWater.mCellSize / 2.0f;
|
|
||||||
return Rectangle {
|
|
||||||
TileBounds{
|
|
||||||
toNavMeshCoordinates(settings, shift + osg::Vec2f(-halfCellSize, -halfCellSize)),
|
|
||||||
toNavMeshCoordinates(settings, shift + osg::Vec2f(halfCellSize, halfCellSize))
|
|
||||||
},
|
|
||||||
toNavMeshCoordinates(settings, getSwimLevel(settings, water.mWater.mLevel, agentHalfExtents.z()))
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<float> getOffMeshVerts(const std::vector<OffMeshConnection>& connections)
|
std::vector<float> getOffMeshVerts(const std::vector<OffMeshConnection>& connections)
|
||||||
{
|
{
|
||||||
std::vector<float> result;
|
std::vector<float> result;
|
||||||
|
@ -120,52 +94,46 @@ namespace
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
rcConfig makeConfig(const osg::Vec3f& agentHalfExtents, const TilePosition& tile, float minZ, float maxZ,
|
float getHeight(const RecastSettings& settings,const osg::Vec3f& agentHalfExtents)
|
||||||
const Settings& settings)
|
|
||||||
{
|
{
|
||||||
rcConfig config;
|
return 2.0f * agentHalfExtents.z() * settings.mRecastScaleFactor;
|
||||||
|
|
||||||
config.cs = settings.mCellSize;
|
|
||||||
config.ch = settings.mCellHeight;
|
|
||||||
config.walkableSlopeAngle = settings.mMaxSlope;
|
|
||||||
config.walkableHeight = static_cast<int>(std::ceil(getHeight(settings, agentHalfExtents) / config.ch));
|
|
||||||
config.walkableClimb = static_cast<int>(std::floor(getMaxClimb(settings) / config.ch));
|
|
||||||
config.walkableRadius = static_cast<int>(std::ceil(getRadius(settings, agentHalfExtents) / config.cs));
|
|
||||||
config.maxEdgeLen = static_cast<int>(std::round(settings.mMaxEdgeLen / config.cs));
|
|
||||||
config.maxSimplificationError = settings.mMaxSimplificationError;
|
|
||||||
config.minRegionArea = settings.mRegionMinSize * settings.mRegionMinSize;
|
|
||||||
config.mergeRegionArea = settings.mRegionMergeSize * settings.mRegionMergeSize;
|
|
||||||
config.maxVertsPerPoly = settings.mMaxVertsPerPoly;
|
|
||||||
config.detailSampleDist = settings.mDetailSampleDist < 0.9f ? 0 : config.cs * settings.mDetailSampleDist;
|
|
||||||
config.detailSampleMaxError = config.ch * settings.mDetailSampleMaxError;
|
|
||||||
config.borderSize = settings.mBorderSize;
|
|
||||||
config.tileSize = settings.mTileSize;
|
|
||||||
const int size = config.tileSize + config.borderSize * 2;
|
|
||||||
config.width = size;
|
|
||||||
config.height = size;
|
|
||||||
const float halfBoundsSize = size * config.cs * 0.5f;
|
|
||||||
const osg::Vec2f shift = osg::Vec2f(tile.x() + 0.5f, tile.y() + 0.5f) * getTileSize(settings);
|
|
||||||
config.bmin[0] = shift.x() - halfBoundsSize;
|
|
||||||
config.bmin[1] = minZ;
|
|
||||||
config.bmin[2] = shift.y() - halfBoundsSize;
|
|
||||||
config.bmax[0] = shift.x() + halfBoundsSize;
|
|
||||||
config.bmax[1] = maxZ;
|
|
||||||
config.bmax[2] = shift.y() + halfBoundsSize;
|
|
||||||
|
|
||||||
return config;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void createHeightfield(rcContext& context, rcHeightfield& solid, int width, int height, const float* bmin,
|
float getMaxClimb(const RecastSettings& settings)
|
||||||
const float* bmax, const float cs, const float ch)
|
|
||||||
{
|
{
|
||||||
const auto result = rcCreateHeightfield(&context, solid, width, height, bmin, bmax, cs, ch);
|
return settings.mMaxClimb * settings.mRecastScaleFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
float getRadius(const RecastSettings& settings, const osg::Vec3f& agentHalfExtents)
|
||||||
|
{
|
||||||
|
return std::max(agentHalfExtents.x(), agentHalfExtents.y()) * std::sqrt(2) * settings.mRecastScaleFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
float getSwimLevel(const RecastSettings& settings, const float waterLevel, const float agentHalfExtentsZ)
|
||||||
|
{
|
||||||
|
return waterLevel - settings.mSwimHeightScale * agentHalfExtentsZ - agentHalfExtentsZ;;
|
||||||
|
}
|
||||||
|
|
||||||
|
void initHeightfield(rcContext& context, const TilePosition& tilePosition, float minZ, float maxZ,
|
||||||
|
const RecastSettings& settings, rcHeightfield& solid)
|
||||||
|
{
|
||||||
|
const int size = settings.mTileSize + settings.mBorderSize * 2;
|
||||||
|
const int width = size;
|
||||||
|
const int height = size;
|
||||||
|
const float halfBoundsSize = size * settings.mCellSize * 0.5f;
|
||||||
|
const osg::Vec2f shift = osg::Vec2f(tilePosition.x() + 0.5f, tilePosition.y() + 0.5f) * getTileSize(settings);
|
||||||
|
const osg::Vec3f bmin(shift.x() - halfBoundsSize, minZ, shift.y() - halfBoundsSize);
|
||||||
|
const osg::Vec3f bmax(shift.x() + halfBoundsSize, maxZ, shift.y() + halfBoundsSize);
|
||||||
|
|
||||||
|
const auto result = rcCreateHeightfield(&context, solid, width, height, bmin.ptr(), bmax.ptr(),
|
||||||
|
settings.mCellSize, settings.mCellHeight);
|
||||||
|
|
||||||
if (!result)
|
if (!result)
|
||||||
throw NavigatorException("Failed to create heightfield for navmesh");
|
throw NavigatorException("Failed to create heightfield for navmesh");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool rasterizeTriangles(rcContext& context, const Mesh& mesh, const Settings& settings, const rcConfig& config,
|
bool rasterizeTriangles(rcContext& context, const Mesh& mesh, const RecastSettings& settings,
|
||||||
rcHeightfield& solid)
|
const RecastParams& params, rcHeightfield& solid)
|
||||||
{
|
{
|
||||||
std::vector<unsigned char> areas(mesh.getAreaTypes().begin(), mesh.getAreaTypes().end());
|
std::vector<unsigned char> areas(mesh.getAreaTypes().begin(), mesh.getAreaTypes().end());
|
||||||
std::vector<float> vertices = mesh.getVertices();
|
std::vector<float> vertices = mesh.getVertices();
|
||||||
|
@ -179,7 +147,7 @@ namespace
|
||||||
|
|
||||||
rcClearUnwalkableTriangles(
|
rcClearUnwalkableTriangles(
|
||||||
&context,
|
&context,
|
||||||
config.walkableSlopeAngle,
|
settings.mMaxSlope,
|
||||||
vertices.data(),
|
vertices.data(),
|
||||||
static_cast<int>(mesh.getVerticesCount()),
|
static_cast<int>(mesh.getVerticesCount()),
|
||||||
mesh.getIndices().data(),
|
mesh.getIndices().data(),
|
||||||
|
@ -195,30 +163,18 @@ namespace
|
||||||
areas.data(),
|
areas.data(),
|
||||||
static_cast<int>(areas.size()),
|
static_cast<int>(areas.size()),
|
||||||
solid,
|
solid,
|
||||||
config.walkableClimb
|
params.mWalkableClimb
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool rasterizeTriangles(rcContext& context, const Rectangle& rectangle, const rcConfig& config,
|
bool rasterizeTriangles(rcContext& context, const Rectangle& rectangle, AreaType areaType,
|
||||||
AreaType areaType, rcHeightfield& solid)
|
const RecastParams& params, rcHeightfield& solid)
|
||||||
{
|
{
|
||||||
const osg::Vec2f tileBoundsMin(
|
|
||||||
std::clamp(rectangle.mBounds.mMin.x(), config.bmin[0], config.bmax[0]),
|
|
||||||
std::clamp(rectangle.mBounds.mMin.y(), config.bmin[2], config.bmax[2])
|
|
||||||
);
|
|
||||||
const osg::Vec2f tileBoundsMax(
|
|
||||||
std::clamp(rectangle.mBounds.mMax.x(), config.bmin[0], config.bmax[0]),
|
|
||||||
std::clamp(rectangle.mBounds.mMax.y(), config.bmin[2], config.bmax[2])
|
|
||||||
);
|
|
||||||
|
|
||||||
if (tileBoundsMax == tileBoundsMin)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
const std::array vertices {
|
const std::array vertices {
|
||||||
tileBoundsMin.x(), rectangle.mHeight, tileBoundsMin.y(),
|
rectangle.mBounds.mMin.x(), rectangle.mHeight, rectangle.mBounds.mMin.y(),
|
||||||
tileBoundsMin.x(), rectangle.mHeight, tileBoundsMax.y(),
|
rectangle.mBounds.mMin.x(), rectangle.mHeight, rectangle.mBounds.mMax.y(),
|
||||||
tileBoundsMax.x(), rectangle.mHeight, tileBoundsMax.y(),
|
rectangle.mBounds.mMax.x(), rectangle.mHeight, rectangle.mBounds.mMax.y(),
|
||||||
tileBoundsMax.x(), rectangle.mHeight, tileBoundsMin.y(),
|
rectangle.mBounds.mMax.x(), rectangle.mHeight, rectangle.mBounds.mMin.y(),
|
||||||
};
|
};
|
||||||
|
|
||||||
const std::array indices {
|
const std::array indices {
|
||||||
|
@ -236,31 +192,42 @@ namespace
|
||||||
areas.data(),
|
areas.data(),
|
||||||
static_cast<int>(areas.size()),
|
static_cast<int>(areas.size()),
|
||||||
solid,
|
solid,
|
||||||
config.walkableClimb
|
params.mWalkableClimb
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool rasterizeTriangles(rcContext& context, const osg::Vec3f& agentHalfExtents, const std::vector<CellWater>& water,
|
bool rasterizeTriangles(rcContext& context, const osg::Vec3f& agentHalfExtents, const std::vector<CellWater>& water,
|
||||||
const Settings& settings, const rcConfig& config, rcHeightfield& solid)
|
const RecastSettings& settings, const RecastParams& params, const TileBounds& realTileBounds, rcHeightfield& solid)
|
||||||
{
|
{
|
||||||
for (const CellWater& cellWater : water)
|
for (const CellWater& cellWater : water)
|
||||||
{
|
{
|
||||||
const Rectangle rectangle = getSwimRectangle(cellWater, settings, agentHalfExtents);
|
const TileBounds cellTileBounds = maxCellTileBounds(cellWater.mCellPosition, cellWater.mWater.mCellSize);
|
||||||
if (!rasterizeTriangles(context, rectangle, config, AreaType_water, solid))
|
if (auto intersection = getIntersection(realTileBounds, cellTileBounds))
|
||||||
|
{
|
||||||
|
const Rectangle rectangle {
|
||||||
|
toNavMeshCoordinates(settings, *intersection),
|
||||||
|
toNavMeshCoordinates(settings, getSwimLevel(settings, cellWater.mWater.mLevel, agentHalfExtents.z()))
|
||||||
|
};
|
||||||
|
if (!rasterizeTriangles(context, rectangle, AreaType_water, params, solid))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool rasterizeTriangles(rcContext& context, const TileBounds& tileBounds, const std::vector<FlatHeightfield>& heightfields,
|
bool rasterizeTriangles(rcContext& context, const TileBounds& realTileBounds, const std::vector<FlatHeightfield>& heightfields,
|
||||||
const Settings& settings, const rcConfig& config, rcHeightfield& solid)
|
const RecastSettings& settings, const RecastParams& params, rcHeightfield& solid)
|
||||||
{
|
{
|
||||||
for (const FlatHeightfield& heightfield : heightfields)
|
for (const FlatHeightfield& heightfield : heightfields)
|
||||||
{
|
{
|
||||||
if (auto intersection = getIntersection(tileBounds, maxCellTileBounds(heightfield.mCellPosition, heightfield.mCellSize)))
|
const TileBounds cellTileBounds = maxCellTileBounds(heightfield.mCellPosition, heightfield.mCellSize);
|
||||||
|
if (auto intersection = getIntersection(realTileBounds, cellTileBounds))
|
||||||
{
|
{
|
||||||
const Rectangle rectangle {*intersection, toNavMeshCoordinates(settings, heightfield.mHeight)};
|
const Rectangle rectangle {
|
||||||
if (!rasterizeTriangles(context, rectangle, config, AreaType_ground, solid))
|
toNavMeshCoordinates(settings, *intersection),
|
||||||
|
toNavMeshCoordinates(settings, heightfield.mHeight)
|
||||||
|
};
|
||||||
|
if (!rasterizeTriangles(context, rectangle, AreaType_ground, params, solid))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -268,27 +235,25 @@ namespace
|
||||||
}
|
}
|
||||||
|
|
||||||
bool rasterizeTriangles(rcContext& context, const std::vector<Heightfield>& heightfields,
|
bool rasterizeTriangles(rcContext& context, const std::vector<Heightfield>& heightfields,
|
||||||
const Settings& settings, const rcConfig& config, rcHeightfield& solid)
|
const RecastSettings& settings, const RecastParams& params, rcHeightfield& solid)
|
||||||
{
|
{
|
||||||
using BulletHelpers::makeProcessTriangleCallback;
|
|
||||||
|
|
||||||
for (const Heightfield& heightfield : heightfields)
|
for (const Heightfield& heightfield : heightfields)
|
||||||
{
|
{
|
||||||
const Mesh mesh = makeMesh(heightfield);
|
const Mesh mesh = makeMesh(heightfield);
|
||||||
if (!rasterizeTriangles(context, mesh, settings, config, solid))
|
if (!rasterizeTriangles(context, mesh, settings, params, solid))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool rasterizeTriangles(rcContext& context, const TilePosition& tilePosition, const osg::Vec3f& agentHalfExtents,
|
bool rasterizeTriangles(rcContext& context, const TilePosition& tilePosition, const osg::Vec3f& agentHalfExtents,
|
||||||
const RecastMesh& recastMesh, const rcConfig& config, const Settings& settings, rcHeightfield& solid)
|
const RecastMesh& recastMesh, const RecastSettings& settings, const RecastParams& params, rcHeightfield& solid)
|
||||||
{
|
{
|
||||||
return rasterizeTriangles(context, recastMesh.getMesh(), settings, config, solid)
|
const TileBounds realTileBounds = makeRealTileBoundsWithBorder(settings, tilePosition);
|
||||||
&& rasterizeTriangles(context, agentHalfExtents, recastMesh.getWater(), settings, config, solid)
|
return rasterizeTriangles(context, recastMesh.getMesh(), settings, params, solid)
|
||||||
&& rasterizeTriangles(context, recastMesh.getHeightfields(), settings, config, solid)
|
&& rasterizeTriangles(context, agentHalfExtents, recastMesh.getWater(), settings, params, realTileBounds, solid)
|
||||||
&& rasterizeTriangles(context, makeRealTileBoundsWithBorder(settings, tilePosition),
|
&& rasterizeTriangles(context, recastMesh.getHeightfields(), settings, params, solid)
|
||||||
recastMesh.getFlatHeightfields(), settings, config, solid);
|
&& rasterizeTriangles(context, realTileBounds, recastMesh.getFlatHeightfields(), settings, params, solid);
|
||||||
}
|
}
|
||||||
|
|
||||||
void buildCompactHeightfield(rcContext& context, const int walkableHeight, const int walkableClimb,
|
void buildCompactHeightfield(rcContext& context, const int walkableHeight, const int walkableClimb,
|
||||||
|
@ -359,27 +324,25 @@ namespace
|
||||||
polyMesh.flags[i] = getFlag(static_cast<AreaType>(polyMesh.areas[i]));
|
polyMesh.flags[i] = getFlag(static_cast<AreaType>(polyMesh.areas[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool fillPolyMesh(rcContext& context, const rcConfig& config, rcHeightfield& solid, rcPolyMesh& polyMesh,
|
bool fillPolyMesh(rcContext& context, const RecastSettings& settings, const RecastParams& params,
|
||||||
rcPolyMeshDetail& polyMeshDetail)
|
rcHeightfield& solid, rcPolyMesh& polyMesh, rcPolyMeshDetail& polyMeshDetail)
|
||||||
{
|
{
|
||||||
rcCompactHeightfield compact;
|
rcCompactHeightfield compact;
|
||||||
compact.dist = nullptr;
|
buildCompactHeightfield(context, params.mWalkableHeight, params.mWalkableClimb, solid, compact);
|
||||||
buildCompactHeightfield(context, config.walkableHeight, config.walkableClimb, solid, compact);
|
|
||||||
|
|
||||||
erodeWalkableArea(context, config.walkableRadius, compact);
|
erodeWalkableArea(context, params.mWalkableRadius, compact);
|
||||||
buildDistanceField(context, compact);
|
buildDistanceField(context, compact);
|
||||||
buildRegions(context, compact, config.borderSize, config.minRegionArea, config.mergeRegionArea);
|
buildRegions(context, compact, settings.mBorderSize, settings.mRegionMinArea, settings.mRegionMergeArea);
|
||||||
|
|
||||||
rcContourSet contourSet;
|
rcContourSet contourSet;
|
||||||
buildContours(context, compact, config.maxSimplificationError, config.maxEdgeLen, contourSet);
|
buildContours(context, compact, settings.mMaxSimplificationError, params.mMaxEdgeLen, contourSet);
|
||||||
|
|
||||||
if (contourSet.nconts == 0)
|
if (contourSet.nconts == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
buildPolyMesh(context, contourSet, config.maxVertsPerPoly, polyMesh);
|
buildPolyMesh(context, contourSet, settings.mMaxVertsPerPoly, polyMesh);
|
||||||
|
|
||||||
buildPolyMeshDetail(context, polyMesh, compact, config.detailSampleDist, config.detailSampleMaxError,
|
buildPolyMeshDetail(context, polyMesh, compact, params.mSampleDist, params.mSampleMaxError, polyMeshDetail);
|
||||||
polyMeshDetail);
|
|
||||||
|
|
||||||
setPolyMeshFlags(polyMesh);
|
setPolyMeshFlags(polyMesh);
|
||||||
|
|
||||||
|
@ -395,7 +358,7 @@ namespace
|
||||||
return power;
|
return power;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<float, float> getBoundsByZ(const RecastMesh& recastMesh, const osg::Vec3f& agentHalfExtents, const Settings& settings)
|
std::pair<float, float> getBoundsByZ(const RecastMesh& recastMesh, const osg::Vec3f& agentHalfExtents, const RecastSettings& settings)
|
||||||
{
|
{
|
||||||
float minZ = 0;
|
float minZ = 0;
|
||||||
float maxZ = 0;
|
float maxZ = 0;
|
||||||
|
@ -436,39 +399,54 @@ namespace
|
||||||
|
|
||||||
namespace DetourNavigator
|
namespace DetourNavigator
|
||||||
{
|
{
|
||||||
|
RecastParams makeRecastParams(const RecastSettings& settings, const osg::Vec3f& agentHalfExtents)
|
||||||
|
{
|
||||||
|
RecastParams result;
|
||||||
|
|
||||||
|
result.mWalkableHeight = static_cast<int>(std::ceil(getHeight(settings, agentHalfExtents) / settings.mCellHeight));
|
||||||
|
result.mWalkableClimb = static_cast<int>(std::floor(getMaxClimb(settings) / settings.mCellHeight));
|
||||||
|
result.mWalkableRadius = static_cast<int>(std::ceil(getRadius(settings, agentHalfExtents) / settings.mCellSize));
|
||||||
|
result.mMaxEdgeLen = static_cast<int>(std::round(static_cast<float>(settings.mMaxEdgeLen) / settings.mCellSize));
|
||||||
|
result.mSampleDist = settings.mDetailSampleDist < 0.9f ? 0 : settings.mCellSize * settings.mDetailSampleDist;
|
||||||
|
result.mSampleMaxError = settings.mCellHeight * settings.mDetailSampleMaxError;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_ptr<PreparedNavMeshData> prepareNavMeshTileData(const RecastMesh& recastMesh,
|
std::unique_ptr<PreparedNavMeshData> prepareNavMeshTileData(const RecastMesh& recastMesh,
|
||||||
const TilePosition& tilePosition, const osg::Vec3f& agentHalfExtents, const Settings& settings)
|
const TilePosition& tilePosition, const osg::Vec3f& agentHalfExtents, const RecastSettings& settings)
|
||||||
{
|
{
|
||||||
const auto [minZ, maxZ] = getBoundsByZ(recastMesh, agentHalfExtents, settings);
|
const auto [minZ, maxZ] = getBoundsByZ(recastMesh, agentHalfExtents, settings);
|
||||||
|
|
||||||
rcContext context;
|
rcContext context;
|
||||||
const auto config = makeConfig(agentHalfExtents, tilePosition, toNavMeshCoordinates(settings, minZ),
|
|
||||||
toNavMeshCoordinates(settings, maxZ), settings);
|
|
||||||
|
|
||||||
rcHeightfield solid;
|
rcHeightfield solid;
|
||||||
createHeightfield(context, solid, config.width, config.height, config.bmin, config.bmax, config.cs, config.ch);
|
initHeightfield(context, tilePosition, toNavMeshCoordinates(settings, minZ),
|
||||||
|
toNavMeshCoordinates(settings, maxZ), settings, solid);
|
||||||
|
|
||||||
if (!rasterizeTriangles(context, tilePosition, agentHalfExtents, recastMesh, config, settings, solid))
|
const RecastParams params = makeRecastParams(settings, agentHalfExtents);
|
||||||
|
|
||||||
|
if (!rasterizeTriangles(context, tilePosition, agentHalfExtents, recastMesh, settings, params, solid))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
rcFilterLowHangingWalkableObstacles(&context, config.walkableClimb, solid);
|
rcFilterLowHangingWalkableObstacles(&context, params.mWalkableClimb, solid);
|
||||||
rcFilterLedgeSpans(&context, config.walkableHeight, config.walkableClimb, solid);
|
rcFilterLedgeSpans(&context, params.mWalkableHeight, params.mWalkableClimb, solid);
|
||||||
rcFilterWalkableLowHeightSpans(&context, config.walkableHeight, solid);
|
rcFilterWalkableLowHeightSpans(&context, params.mWalkableHeight, solid);
|
||||||
|
|
||||||
std::unique_ptr<PreparedNavMeshData> result = std::make_unique<PreparedNavMeshData>();
|
std::unique_ptr<PreparedNavMeshData> result = std::make_unique<PreparedNavMeshData>();
|
||||||
|
|
||||||
if (!fillPolyMesh(context, config, solid, result->mPolyMesh, result->mPolyMeshDetail))
|
if (!fillPolyMesh(context, settings, params, solid, result->mPolyMesh, result->mPolyMeshDetail))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
result->mCellSize = config.cs;
|
result->mCellSize = settings.mCellSize;
|
||||||
result->mCellHeight = config.ch;
|
result->mCellHeight = settings.mCellHeight;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
NavMeshData makeNavMeshTileData(const PreparedNavMeshData& data,
|
NavMeshData makeNavMeshTileData(const PreparedNavMeshData& data,
|
||||||
const std::vector<OffMeshConnection>& offMeshConnections, const osg::Vec3f& agentHalfExtents,
|
const std::vector<OffMeshConnection>& offMeshConnections, const osg::Vec3f& agentHalfExtents,
|
||||||
const TilePosition& tile, const Settings& settings)
|
const TilePosition& tile, const RecastSettings& settings)
|
||||||
{
|
{
|
||||||
const auto offMeshConVerts = getOffMeshVerts(offMeshConnections);
|
const auto offMeshConVerts = getOffMeshVerts(offMeshConnections);
|
||||||
const std::vector<float> offMeshConRad(offMeshConnections.size(), getRadius(settings, agentHalfExtents));
|
const std::vector<float> offMeshConRad(offMeshConnections.size(), getRadius(settings, agentHalfExtents));
|
||||||
|
@ -524,7 +502,7 @@ namespace DetourNavigator
|
||||||
// Max tiles and max polys affect how the tile IDs are caculated.
|
// Max tiles and max polys affect how the tile IDs are caculated.
|
||||||
// There are 22 bits available for identifying a tile and a polygon.
|
// There are 22 bits available for identifying a tile and a polygon.
|
||||||
const int polysAndTilesBits = 22;
|
const int polysAndTilesBits = 22;
|
||||||
const auto polysBits = getMinValuableBitsNumber(settings.mMaxPolys);
|
const auto polysBits = getMinValuableBitsNumber(settings.mDetour.mMaxPolys);
|
||||||
|
|
||||||
if (polysBits >= polysAndTilesBits)
|
if (polysBits >= polysAndTilesBits)
|
||||||
throw InvalidArgument("Too many polygons per tile");
|
throw InvalidArgument("Too many polygons per tile");
|
||||||
|
@ -533,8 +511,8 @@ namespace DetourNavigator
|
||||||
|
|
||||||
dtNavMeshParams params;
|
dtNavMeshParams params;
|
||||||
std::fill_n(params.orig, 3, 0.0f);
|
std::fill_n(params.orig, 3, 0.0f);
|
||||||
params.tileWidth = settings.mTileSize * settings.mCellSize;
|
params.tileWidth = settings.mRecast.mTileSize * settings.mRecast.mCellSize;
|
||||||
params.tileHeight = settings.mTileSize * settings.mCellSize;
|
params.tileHeight = settings.mRecast.mTileSize * settings.mRecast.mCellSize;
|
||||||
params.maxTiles = 1 << tilesBits;
|
params.maxTiles = 1 << tilesBits;
|
||||||
params.maxPolys = 1 << polysBits;
|
params.maxPolys = 1 << polysBits;
|
||||||
|
|
||||||
|
@ -558,9 +536,9 @@ namespace DetourNavigator
|
||||||
{
|
{
|
||||||
Log(Debug::Debug) << std::fixed << std::setprecision(2) <<
|
Log(Debug::Debug) << std::fixed << std::setprecision(2) <<
|
||||||
"Update NavMesh with multiple tiles:" <<
|
"Update NavMesh with multiple tiles:" <<
|
||||||
" agentHeight=" << getHeight(settings, agentHalfExtents) <<
|
" agentHeight=" << getHeight(settings.mRecast, agentHalfExtents) <<
|
||||||
" agentMaxClimb=" << getMaxClimb(settings) <<
|
" agentMaxClimb=" << getMaxClimb(settings.mRecast) <<
|
||||||
" agentRadius=" << getRadius(settings, agentHalfExtents) <<
|
" agentRadius=" << getRadius(settings.mRecast, agentHalfExtents) <<
|
||||||
" changedTile=(" << changedTile << ")" <<
|
" changedTile=(" << changedTile << ")" <<
|
||||||
" playerTile=(" << playerTile << ")" <<
|
" playerTile=(" << playerTile << ")" <<
|
||||||
" changedTileDistance=" << getDistance(changedTile, playerTile);
|
" changedTileDistance=" << getDistance(changedTile, playerTile);
|
||||||
|
@ -591,7 +569,7 @@ namespace DetourNavigator
|
||||||
|
|
||||||
if (!cachedNavMeshData)
|
if (!cachedNavMeshData)
|
||||||
{
|
{
|
||||||
auto prepared = prepareNavMeshTileData(*recastMesh, changedTile, agentHalfExtents, settings);
|
auto prepared = prepareNavMeshTileData(*recastMesh, changedTile, agentHalfExtents, settings.mRecast);
|
||||||
|
|
||||||
if (prepared == nullptr)
|
if (prepared == nullptr)
|
||||||
{
|
{
|
||||||
|
@ -601,7 +579,7 @@ namespace DetourNavigator
|
||||||
|
|
||||||
if (updateType == UpdateType::Temporary)
|
if (updateType == UpdateType::Temporary)
|
||||||
return navMeshCacheItem->lock()->updateTile(changedTile, NavMeshTilesCache::Value(),
|
return navMeshCacheItem->lock()->updateTile(changedTile, NavMeshTilesCache::Value(),
|
||||||
makeNavMeshTileData(*prepared, offMeshConnections, agentHalfExtents, changedTile, settings));
|
makeNavMeshTileData(*prepared, offMeshConnections, agentHalfExtents, changedTile, settings.mRecast));
|
||||||
|
|
||||||
cachedNavMeshData = navMeshTilesCache.set(agentHalfExtents, changedTile, *recastMesh, std::move(prepared));
|
cachedNavMeshData = navMeshTilesCache.set(agentHalfExtents, changedTile, *recastMesh, std::move(prepared));
|
||||||
|
|
||||||
|
@ -609,12 +587,12 @@ namespace DetourNavigator
|
||||||
{
|
{
|
||||||
Log(Debug::Debug) << "Navigator cache overflow";
|
Log(Debug::Debug) << "Navigator cache overflow";
|
||||||
return navMeshCacheItem->lock()->updateTile(changedTile, NavMeshTilesCache::Value(),
|
return navMeshCacheItem->lock()->updateTile(changedTile, NavMeshTilesCache::Value(),
|
||||||
makeNavMeshTileData(*prepared, offMeshConnections, agentHalfExtents, changedTile, settings));
|
makeNavMeshTileData(*prepared, offMeshConnections, agentHalfExtents, changedTile, settings.mRecast));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto updateStatus = navMeshCacheItem->lock()->updateTile(changedTile, std::move(cachedNavMeshData),
|
const auto updateStatus = navMeshCacheItem->lock()->updateTile(changedTile, std::move(cachedNavMeshData),
|
||||||
makeNavMeshTileData(cachedNavMeshData.get(), offMeshConnections, agentHalfExtents, changedTile, settings));
|
makeNavMeshTileData(cachedNavMeshData.get(), offMeshConnections, agentHalfExtents, changedTile, settings.mRecast));
|
||||||
|
|
||||||
return UpdateNavMeshStatusBuilder(updateStatus).cached(cached).getResult();
|
return UpdateNavMeshStatusBuilder(updateStatus).cached(cached).getResult();
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,16 @@ namespace DetourNavigator
|
||||||
struct PreparedNavMeshData;
|
struct PreparedNavMeshData;
|
||||||
struct NavMeshData;
|
struct NavMeshData;
|
||||||
|
|
||||||
|
struct RecastParams
|
||||||
|
{
|
||||||
|
float mSampleDist = 0;
|
||||||
|
float mSampleMaxError = 0;
|
||||||
|
int mMaxEdgeLen = 0;
|
||||||
|
int mWalkableClimb = 0;
|
||||||
|
int mWalkableHeight = 0;
|
||||||
|
int mWalkableRadius = 0;
|
||||||
|
};
|
||||||
|
|
||||||
inline float getLength(const osg::Vec2i& value)
|
inline float getLength(const osg::Vec2i& value)
|
||||||
{
|
{
|
||||||
return std::sqrt(float(osg::square(value.x()) + osg::square(value.y())));
|
return std::sqrt(float(osg::square(value.x()) + osg::square(value.y())));
|
||||||
|
@ -38,12 +48,14 @@ namespace DetourNavigator
|
||||||
return expectedTilesCount <= maxTiles;
|
return expectedTilesCount <= maxTiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RecastParams makeRecastParams(const RecastSettings& settings, const osg::Vec3f& agentHalfExtents);
|
||||||
|
|
||||||
std::unique_ptr<PreparedNavMeshData> prepareNavMeshTileData(const RecastMesh& recastMesh, const TilePosition& tile,
|
std::unique_ptr<PreparedNavMeshData> prepareNavMeshTileData(const RecastMesh& recastMesh, const TilePosition& tile,
|
||||||
const Bounds& bounds, const osg::Vec3f& agentHalfExtents, const Settings& settings);
|
const Bounds& bounds, const osg::Vec3f& agentHalfExtents, const Settings& settings);
|
||||||
|
|
||||||
NavMeshData makeNavMeshTileData(const PreparedNavMeshData& data,
|
NavMeshData makeNavMeshTileData(const PreparedNavMeshData& data,
|
||||||
const std::vector<OffMeshConnection>& offMeshConnections, const osg::Vec3f& agentHalfExtents,
|
const std::vector<OffMeshConnection>& offMeshConnections, const osg::Vec3f& agentHalfExtents,
|
||||||
const TilePosition& tile, const Settings& settings);
|
const TilePosition& tile, const RecastSettings& settings);
|
||||||
|
|
||||||
NavMeshPtr makeEmptyNavMesh(const Settings& settings);
|
NavMeshPtr makeEmptyNavMesh(const Settings& settings);
|
||||||
|
|
||||||
|
|
|
@ -53,8 +53,8 @@ namespace DetourNavigator
|
||||||
{
|
{
|
||||||
if (addObject(id, static_cast<const ObjectShapes&>(shapes), transform))
|
if (addObject(id, static_cast<const ObjectShapes&>(shapes), transform))
|
||||||
{
|
{
|
||||||
const osg::Vec3f start = toNavMeshCoordinates(mSettings, shapes.mConnectionStart);
|
const osg::Vec3f start = toNavMeshCoordinates(mSettings.mRecast, shapes.mConnectionStart);
|
||||||
const osg::Vec3f end = toNavMeshCoordinates(mSettings, shapes.mConnectionEnd);
|
const osg::Vec3f end = toNavMeshCoordinates(mSettings.mRecast, shapes.mConnectionEnd);
|
||||||
mNavMeshManager.addOffMeshConnection(id, start, end, AreaType_door);
|
mNavMeshManager.addOffMeshConnection(id, start, end, AreaType_door);
|
||||||
mNavMeshManager.addOffMeshConnection(id, end, start, AreaType_door);
|
mNavMeshManager.addOffMeshConnection(id, end, start, AreaType_door);
|
||||||
return true;
|
return true;
|
||||||
|
@ -126,8 +126,8 @@ namespace DetourNavigator
|
||||||
const auto dst = Misc::Convert::makeOsgVec3f(converter.toWorldPoint(pathgrid.mPoints[edge.mV1]));
|
const auto dst = Misc::Convert::makeOsgVec3f(converter.toWorldPoint(pathgrid.mPoints[edge.mV1]));
|
||||||
mNavMeshManager.addOffMeshConnection(
|
mNavMeshManager.addOffMeshConnection(
|
||||||
ObjectId(&pathgrid),
|
ObjectId(&pathgrid),
|
||||||
toNavMeshCoordinates(mSettings, src),
|
toNavMeshCoordinates(mSettings.mRecast, src),
|
||||||
toNavMeshCoordinates(mSettings, dst),
|
toNavMeshCoordinates(mSettings.mRecast, dst),
|
||||||
AreaType_pathgrid
|
AreaType_pathgrid
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -149,7 +149,7 @@ namespace DetourNavigator
|
||||||
|
|
||||||
void NavigatorImpl::updatePlayerPosition(const osg::Vec3f& playerPosition)
|
void NavigatorImpl::updatePlayerPosition(const osg::Vec3f& playerPosition)
|
||||||
{
|
{
|
||||||
const TilePosition tilePosition = getTilePosition(mSettings, toNavMeshCoordinates(mSettings, playerPosition));
|
const TilePosition tilePosition = getTilePosition(mSettings.mRecast, toNavMeshCoordinates(mSettings.mRecast, playerPosition));
|
||||||
if (mLastPlayerPosition.has_value() && *mLastPlayerPosition == tilePosition)
|
if (mLastPlayerPosition.has_value() && *mLastPlayerPosition == tilePosition)
|
||||||
return;
|
return;
|
||||||
update(playerPosition);
|
update(playerPosition);
|
||||||
|
@ -225,6 +225,6 @@ namespace DetourNavigator
|
||||||
float NavigatorImpl::getMaxNavmeshAreaRealRadius() const
|
float NavigatorImpl::getMaxNavmeshAreaRealRadius() const
|
||||||
{
|
{
|
||||||
const auto& settings = getSettings();
|
const auto& settings = getSettings();
|
||||||
return getRealTileSize(settings) * getMaxNavmeshAreaRadius(settings);
|
return getRealTileSize(settings.mRecast) * getMaxNavmeshAreaRadius(settings);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,11 +13,11 @@ namespace DetourNavigator
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
const auto settings = navigator.getSettings();
|
const auto settings = navigator.getSettings();
|
||||||
const auto result = DetourNavigator::findRandomPointAroundCircle(navMesh->lockConst()->getImpl(),
|
const auto result = DetourNavigator::findRandomPointAroundCircle(navMesh->lockConst()->getImpl(),
|
||||||
toNavMeshCoordinates(settings, agentHalfExtents), toNavMeshCoordinates(settings, start),
|
toNavMeshCoordinates(settings.mRecast, agentHalfExtents), toNavMeshCoordinates(settings.mRecast, start),
|
||||||
toNavMeshCoordinates(settings, maxRadius), includeFlags, settings);
|
toNavMeshCoordinates(settings.mRecast, maxRadius), includeFlags, settings.mDetour);
|
||||||
if (!result)
|
if (!result)
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
return std::optional<osg::Vec3f>(fromNavMeshCoordinates(settings, *result));
|
return std::optional<osg::Vec3f>(fromNavMeshCoordinates(settings.mRecast, *result));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<osg::Vec3f> raycast(const Navigator& navigator, const osg::Vec3f& agentHalfExtents, const osg::Vec3f& start,
|
std::optional<osg::Vec3f> raycast(const Navigator& navigator, const osg::Vec3f& agentHalfExtents, const osg::Vec3f& start,
|
||||||
|
@ -28,10 +28,10 @@ namespace DetourNavigator
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
const auto settings = navigator.getSettings();
|
const auto settings = navigator.getSettings();
|
||||||
const auto result = DetourNavigator::raycast(navMesh->lockConst()->getImpl(),
|
const auto result = DetourNavigator::raycast(navMesh->lockConst()->getImpl(),
|
||||||
toNavMeshCoordinates(settings, agentHalfExtents), toNavMeshCoordinates(settings, start),
|
toNavMeshCoordinates(settings.mRecast, agentHalfExtents), toNavMeshCoordinates(settings.mRecast, start),
|
||||||
toNavMeshCoordinates(settings, end), includeFlags, settings);
|
toNavMeshCoordinates(settings.mRecast, end), includeFlags, settings.mDetour);
|
||||||
if (!result)
|
if (!result)
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
return fromNavMeshCoordinates(settings, *result);
|
return fromNavMeshCoordinates(settings.mRecast, *result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,9 +37,9 @@ namespace DetourNavigator
|
||||||
if (navMesh == nullptr)
|
if (navMesh == nullptr)
|
||||||
return Status::NavMeshNotFound;
|
return Status::NavMeshNotFound;
|
||||||
const auto settings = navigator.getSettings();
|
const auto settings = navigator.getSettings();
|
||||||
return findSmoothPath(navMesh->lockConst()->getImpl(), toNavMeshCoordinates(settings, agentHalfExtents),
|
return findSmoothPath(navMesh->lockConst()->getImpl(), toNavMeshCoordinates(settings.mRecast, agentHalfExtents),
|
||||||
toNavMeshCoordinates(settings, stepSize), toNavMeshCoordinates(settings, start),
|
toNavMeshCoordinates(settings.mRecast, stepSize), toNavMeshCoordinates(settings.mRecast, start),
|
||||||
toNavMeshCoordinates(settings, end), includeFlags, areaCosts, settings, endTolerance, out);
|
toNavMeshCoordinates(settings.mRecast, end), includeFlags, areaCosts, settings, endTolerance, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -43,8 +43,8 @@ namespace DetourNavigator
|
||||||
{
|
{
|
||||||
NavMeshManager::NavMeshManager(const Settings& settings)
|
NavMeshManager::NavMeshManager(const Settings& settings)
|
||||||
: mSettings(settings)
|
: mSettings(settings)
|
||||||
, mRecastMeshManager(settings)
|
, mRecastMeshManager(mSettings.mRecast)
|
||||||
, mOffMeshConnectionsManager(settings)
|
, mOffMeshConnectionsManager(mSettings.mRecast)
|
||||||
, mAsyncNavMeshUpdater(settings, mRecastMeshManager, mOffMeshConnectionsManager)
|
, mAsyncNavMeshUpdater(settings, mRecastMeshManager, mOffMeshConnectionsManager)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
@ -140,8 +140,8 @@ namespace DetourNavigator
|
||||||
{
|
{
|
||||||
mOffMeshConnectionsManager.add(id, OffMeshConnection {start, end, areaType});
|
mOffMeshConnectionsManager.add(id, OffMeshConnection {start, end, areaType});
|
||||||
|
|
||||||
const auto startTilePosition = getTilePosition(mSettings, start);
|
const auto startTilePosition = getTilePosition(mSettings.mRecast, start);
|
||||||
const auto endTilePosition = getTilePosition(mSettings, end);
|
const auto endTilePosition = getTilePosition(mSettings.mRecast, end);
|
||||||
|
|
||||||
addChangedTile(startTilePosition, ChangeType::add);
|
addChangedTile(startTilePosition, ChangeType::add);
|
||||||
|
|
||||||
|
@ -158,7 +158,7 @@ namespace DetourNavigator
|
||||||
|
|
||||||
void NavMeshManager::update(const osg::Vec3f& playerPosition, const osg::Vec3f& agentHalfExtents)
|
void NavMeshManager::update(const osg::Vec3f& playerPosition, const osg::Vec3f& agentHalfExtents)
|
||||||
{
|
{
|
||||||
const auto playerTile = getTilePosition(mSettings, toNavMeshCoordinates(mSettings, playerPosition));
|
const auto playerTile = getTilePosition(mSettings.mRecast, toNavMeshCoordinates(mSettings.mRecast, playerPosition));
|
||||||
auto& lastRevision = mLastRecastMeshManagerRevision[agentHalfExtents];
|
auto& lastRevision = mLastRecastMeshManagerRevision[agentHalfExtents];
|
||||||
auto lastPlayerTile = mPlayerTile.find(agentHalfExtents);
|
auto lastPlayerTile = mPlayerTile.find(agentHalfExtents);
|
||||||
if (lastRevision == mRecastMeshManager.getRevision() && lastPlayerTile != mPlayerTile.end()
|
if (lastRevision == mRecastMeshManager.getRevision() && lastPlayerTile != mPlayerTile.end()
|
||||||
|
@ -251,7 +251,7 @@ namespace DetourNavigator
|
||||||
void NavMeshManager::addChangedTiles(const btCollisionShape& shape, const btTransform& transform,
|
void NavMeshManager::addChangedTiles(const btCollisionShape& shape, const btTransform& transform,
|
||||||
const ChangeType changeType)
|
const ChangeType changeType)
|
||||||
{
|
{
|
||||||
getTilesPositions(shape, transform, mSettings,
|
getTilesPositions(shape, transform, mSettings.mRecast,
|
||||||
[&] (const TilePosition& v) { addChangedTile(v, changeType); });
|
[&] (const TilePosition& v) { addChangedTile(v, changeType); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -261,7 +261,7 @@ namespace DetourNavigator
|
||||||
if (cellSize == std::numeric_limits<int>::max())
|
if (cellSize == std::numeric_limits<int>::max())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
getTilesPositions(cellSize, shift, mSettings,
|
getTilesPositions(cellSize, shift, mSettings.mRecast,
|
||||||
[&] (const TilePosition& v) { addChangedTile(v, changeType); });
|
[&] (const TilePosition& v) { addChangedTile(v, changeType); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
namespace DetourNavigator
|
namespace DetourNavigator
|
||||||
{
|
{
|
||||||
OffMeshConnectionsManager::OffMeshConnectionsManager(const Settings& settings)
|
OffMeshConnectionsManager::OffMeshConnectionsManager(const RecastSettings& settings)
|
||||||
: mSettings(settings)
|
: mSettings(settings)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ namespace DetourNavigator
|
||||||
class OffMeshConnectionsManager
|
class OffMeshConnectionsManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
OffMeshConnectionsManager(const Settings& settings);
|
explicit OffMeshConnectionsManager(const RecastSettings& settings);
|
||||||
|
|
||||||
void add(const ObjectId id, const OffMeshConnection& value);
|
void add(const ObjectId id, const OffMeshConnection& value);
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ namespace DetourNavigator
|
||||||
std::map<TilePosition, std::unordered_set<ObjectId>> mByTilePosition;
|
std::map<TilePosition, std::unordered_set<ObjectId>> mByTilePosition;
|
||||||
};
|
};
|
||||||
|
|
||||||
const Settings& mSettings;
|
const RecastSettings& mSettings;
|
||||||
Misc::ScopeGuarded<Values> mValues;
|
Misc::ScopeGuarded<Values> mValues;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
namespace DetourNavigator
|
namespace DetourNavigator
|
||||||
{
|
{
|
||||||
std::optional<osg::Vec3f> raycast(const dtNavMesh& navMesh, const osg::Vec3f& halfExtents,
|
std::optional<osg::Vec3f> raycast(const dtNavMesh& navMesh, const osg::Vec3f& halfExtents,
|
||||||
const osg::Vec3f& start, const osg::Vec3f& end, const Flags includeFlags, const Settings& settings)
|
const osg::Vec3f& start, const osg::Vec3f& end, const Flags includeFlags, const DetourSettings& settings)
|
||||||
{
|
{
|
||||||
dtNavMeshQuery navMeshQuery;
|
dtNavMeshQuery navMeshQuery;
|
||||||
if (!initNavMeshQuery(navMeshQuery, navMesh, settings.mMaxNavMeshQueryNodes))
|
if (!initNavMeshQuery(navMeshQuery, navMesh, settings.mMaxNavMeshQueryNodes))
|
||||||
|
|
|
@ -10,10 +10,10 @@ class dtNavMesh;
|
||||||
|
|
||||||
namespace DetourNavigator
|
namespace DetourNavigator
|
||||||
{
|
{
|
||||||
struct Settings;
|
struct DetourSettings;
|
||||||
|
|
||||||
std::optional<osg::Vec3f> raycast(const dtNavMesh& navMesh, const osg::Vec3f& halfExtents,
|
std::optional<osg::Vec3f> raycast(const dtNavMesh& navMesh, const osg::Vec3f& halfExtents,
|
||||||
const osg::Vec3f& start, const osg::Vec3f& end, const Flags includeFlags, const Settings& settings);
|
const osg::Vec3f& start, const osg::Vec3f& end, const Flags includeFlags, const DetourSettings& settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -3,43 +3,65 @@
|
||||||
#include <components/settings/settings.hpp>
|
#include <components/settings/settings.hpp>
|
||||||
#include <components/misc/constants.hpp>
|
#include <components/misc/constants.hpp>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
namespace DetourNavigator
|
namespace DetourNavigator
|
||||||
{
|
{
|
||||||
|
RecastSettings makeRecastSettingsFromSettingsManager()
|
||||||
|
{
|
||||||
|
constexpr float epsilon = std::numeric_limits<float>::epsilon();
|
||||||
|
|
||||||
|
RecastSettings result;
|
||||||
|
|
||||||
|
result.mBorderSize = std::max(0, ::Settings::Manager::getInt("border size", "Navigator"));
|
||||||
|
result.mCellHeight = std::max(epsilon, ::Settings::Manager::getFloat("cell height", "Navigator"));
|
||||||
|
result.mCellSize = std::max(epsilon, ::Settings::Manager::getFloat("cell size", "Navigator"));
|
||||||
|
result.mDetailSampleDist = std::max(0.0f, ::Settings::Manager::getFloat("detail sample dist", "Navigator"));
|
||||||
|
result.mDetailSampleMaxError = std::max(0.0f, ::Settings::Manager::getFloat("detail sample max error", "Navigator"));
|
||||||
|
result.mMaxClimb = Constants::sStepSizeUp;
|
||||||
|
result.mMaxSimplificationError = std::max(0.0f, ::Settings::Manager::getFloat("max simplification error", "Navigator"));
|
||||||
|
result.mMaxSlope = Constants::sMaxSlope;
|
||||||
|
result.mRecastScaleFactor = std::max(epsilon, ::Settings::Manager::getFloat("recast scale factor", "Navigator"));
|
||||||
|
result.mSwimHeightScale = 0;
|
||||||
|
result.mMaxEdgeLen = std::max(0, ::Settings::Manager::getInt("max edge len", "Navigator"));
|
||||||
|
result.mMaxVertsPerPoly = std::max(3, ::Settings::Manager::getInt("max verts per poly", "Navigator"));
|
||||||
|
result.mRegionMergeArea = std::max(0, ::Settings::Manager::getInt("region merge area", "Navigator"));
|
||||||
|
result.mRegionMinArea = std::max(0, ::Settings::Manager::getInt("region min area", "Navigator"));
|
||||||
|
result.mTileSize = std::max(1, ::Settings::Manager::getInt("tile size", "Navigator"));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
DetourSettings makeDetourSettingsFromSettingsManager()
|
||||||
|
{
|
||||||
|
DetourSettings result;
|
||||||
|
|
||||||
|
result.mMaxNavMeshQueryNodes = std::clamp(::Settings::Manager::getInt("max nav mesh query nodes", "Navigator"), 1, 65535);
|
||||||
|
result.mMaxPolys = std::clamp(::Settings::Manager::getInt("max polygons per tile", "Navigator"), 1, (1 << 22) - 1);
|
||||||
|
result.mMaxPolygonPathSize = static_cast<std::size_t>(std::max(0, ::Settings::Manager::getInt("max polygon path size", "Navigator")));
|
||||||
|
result.mMaxSmoothPathSize = static_cast<std::size_t>(std::max(0, ::Settings::Manager::getInt("max smooth path size", "Navigator")));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
Settings makeSettingsFromSettingsManager()
|
Settings makeSettingsFromSettingsManager()
|
||||||
{
|
{
|
||||||
Settings navigatorSettings;
|
Settings result;
|
||||||
|
|
||||||
navigatorSettings.mBorderSize = ::Settings::Manager::getInt("border size", "Navigator");
|
result.mRecast = makeRecastSettingsFromSettingsManager();
|
||||||
navigatorSettings.mCellHeight = ::Settings::Manager::getFloat("cell height", "Navigator");
|
result.mDetour = makeDetourSettingsFromSettingsManager();
|
||||||
navigatorSettings.mCellSize = ::Settings::Manager::getFloat("cell size", "Navigator");
|
result.mMaxTilesNumber = std::max(0, ::Settings::Manager::getInt("max tiles number", "Navigator"));
|
||||||
navigatorSettings.mDetailSampleDist = ::Settings::Manager::getFloat("detail sample dist", "Navigator");
|
result.mWaitUntilMinDistanceToPlayer = ::Settings::Manager::getInt("wait until min distance to player", "Navigator");
|
||||||
navigatorSettings.mDetailSampleMaxError = ::Settings::Manager::getFloat("detail sample max error", "Navigator");
|
result.mAsyncNavMeshUpdaterThreads = static_cast<std::size_t>(std::max(0, ::Settings::Manager::getInt("async nav mesh updater threads", "Navigator")));
|
||||||
navigatorSettings.mMaxClimb = Constants::sStepSizeUp;
|
result.mMaxNavMeshTilesCacheSize = static_cast<std::size_t>(std::max(std::int64_t {0}, ::Settings::Manager::getInt64("max nav mesh tiles cache size", "Navigator")));
|
||||||
navigatorSettings.mMaxSimplificationError = ::Settings::Manager::getFloat("max simplification error", "Navigator");
|
result.mEnableWriteRecastMeshToFile = ::Settings::Manager::getBool("enable write recast mesh to file", "Navigator");
|
||||||
navigatorSettings.mMaxSlope = Constants::sMaxSlope;
|
result.mEnableWriteNavMeshToFile = ::Settings::Manager::getBool("enable write nav mesh to file", "Navigator");
|
||||||
navigatorSettings.mRecastScaleFactor = ::Settings::Manager::getFloat("recast scale factor", "Navigator");
|
result.mRecastMeshPathPrefix = ::Settings::Manager::getString("recast mesh path prefix", "Navigator");
|
||||||
navigatorSettings.mSwimHeightScale = 0;
|
result.mNavMeshPathPrefix = ::Settings::Manager::getString("nav mesh path prefix", "Navigator");
|
||||||
navigatorSettings.mMaxEdgeLen = ::Settings::Manager::getInt("max edge len", "Navigator");
|
result.mEnableRecastMeshFileNameRevision = ::Settings::Manager::getBool("enable recast mesh file name revision", "Navigator");
|
||||||
navigatorSettings.mMaxNavMeshQueryNodes = ::Settings::Manager::getInt("max nav mesh query nodes", "Navigator");
|
result.mEnableNavMeshFileNameRevision = ::Settings::Manager::getBool("enable nav mesh file name revision", "Navigator");
|
||||||
navigatorSettings.mMaxPolys = ::Settings::Manager::getInt("max polygons per tile", "Navigator");
|
result.mMinUpdateInterval = std::chrono::milliseconds(::Settings::Manager::getInt("min update interval ms", "Navigator"));
|
||||||
navigatorSettings.mMaxTilesNumber = ::Settings::Manager::getInt("max tiles number", "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.mWaitUntilMinDistanceToPlayer = ::Settings::Manager::getInt("wait until min distance to player", "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.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");
|
|
||||||
navigatorSettings.mMinUpdateInterval = std::chrono::milliseconds(::Settings::Manager::getInt("min update interval ms", "Navigator"));
|
|
||||||
|
|
||||||
return navigatorSettings;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,12 +6,8 @@
|
||||||
|
|
||||||
namespace DetourNavigator
|
namespace DetourNavigator
|
||||||
{
|
{
|
||||||
struct Settings
|
struct RecastSettings
|
||||||
{
|
{
|
||||||
bool mEnableWriteRecastMeshToFile = false;
|
|
||||||
bool mEnableWriteNavMeshToFile = false;
|
|
||||||
bool mEnableRecastMeshFileNameRevision = false;
|
|
||||||
bool mEnableNavMeshFileNameRevision = false;
|
|
||||||
float mCellHeight = 0;
|
float mCellHeight = 0;
|
||||||
float mCellSize = 0;
|
float mCellSize = 0;
|
||||||
float mDetailSampleDist = 0;
|
float mDetailSampleDist = 0;
|
||||||
|
@ -23,23 +19,41 @@ namespace DetourNavigator
|
||||||
float mSwimHeightScale = 0;
|
float mSwimHeightScale = 0;
|
||||||
int mBorderSize = 0;
|
int mBorderSize = 0;
|
||||||
int mMaxEdgeLen = 0;
|
int mMaxEdgeLen = 0;
|
||||||
int mMaxNavMeshQueryNodes = 0;
|
|
||||||
int mMaxPolys = 0;
|
|
||||||
int mMaxTilesNumber = 0;
|
|
||||||
int mMaxVertsPerPoly = 0;
|
int mMaxVertsPerPoly = 0;
|
||||||
int mRegionMergeSize = 0;
|
int mRegionMergeArea = 0;
|
||||||
int mRegionMinSize = 0;
|
int mRegionMinArea = 0;
|
||||||
int mTileSize = 0;
|
int mTileSize = 0;
|
||||||
int mWaitUntilMinDistanceToPlayer = 0;
|
};
|
||||||
std::size_t mAsyncNavMeshUpdaterThreads = 0;
|
|
||||||
std::size_t mMaxNavMeshTilesCacheSize = 0;
|
struct DetourSettings
|
||||||
|
{
|
||||||
|
int mMaxPolys = 0;
|
||||||
|
int mMaxNavMeshQueryNodes = 0;
|
||||||
std::size_t mMaxPolygonPathSize = 0;
|
std::size_t mMaxPolygonPathSize = 0;
|
||||||
std::size_t mMaxSmoothPathSize = 0;
|
std::size_t mMaxSmoothPathSize = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Settings
|
||||||
|
{
|
||||||
|
bool mEnableWriteRecastMeshToFile = false;
|
||||||
|
bool mEnableWriteNavMeshToFile = false;
|
||||||
|
bool mEnableRecastMeshFileNameRevision = false;
|
||||||
|
bool mEnableNavMeshFileNameRevision = false;
|
||||||
|
RecastSettings mRecast;
|
||||||
|
DetourSettings mDetour;
|
||||||
|
int mWaitUntilMinDistanceToPlayer = 0;
|
||||||
|
int mMaxTilesNumber = 0;
|
||||||
|
std::size_t mAsyncNavMeshUpdaterThreads = 0;
|
||||||
|
std::size_t mMaxNavMeshTilesCacheSize = 0;
|
||||||
std::string mRecastMeshPathPrefix;
|
std::string mRecastMeshPathPrefix;
|
||||||
std::string mNavMeshPathPrefix;
|
std::string mNavMeshPathPrefix;
|
||||||
std::chrono::milliseconds mMinUpdateInterval;
|
std::chrono::milliseconds mMinUpdateInterval;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
RecastSettings makeRecastSettingsFromSettingsManager();
|
||||||
|
|
||||||
|
DetourSettings makeDetourSettingsFromSettingsManager();
|
||||||
|
|
||||||
Settings makeSettingsFromSettingsManager();
|
Settings makeSettingsFromSettingsManager();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,12 +4,8 @@
|
||||||
#include "settings.hpp"
|
#include "settings.hpp"
|
||||||
#include "tilebounds.hpp"
|
#include "tilebounds.hpp"
|
||||||
#include "tileposition.hpp"
|
#include "tileposition.hpp"
|
||||||
#include "tilebounds.hpp"
|
|
||||||
|
|
||||||
#include <LinearMath/btTransform.h>
|
|
||||||
|
|
||||||
#include <osg/Vec2f>
|
#include <osg/Vec2f>
|
||||||
#include <osg/Vec2i>
|
|
||||||
#include <osg/Vec3f>
|
#include <osg/Vec3f>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
@ -17,38 +13,31 @@
|
||||||
|
|
||||||
namespace DetourNavigator
|
namespace DetourNavigator
|
||||||
{
|
{
|
||||||
inline float getHeight(const Settings& settings,const osg::Vec3f& agentHalfExtents)
|
inline float toNavMeshCoordinates(const RecastSettings& settings, float value)
|
||||||
{
|
|
||||||
return 2.0f * agentHalfExtents.z() * settings.mRecastScaleFactor;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline float getMaxClimb(const Settings& settings)
|
|
||||||
{
|
|
||||||
return settings.mMaxClimb * settings.mRecastScaleFactor;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline float getRadius(const Settings& settings, const osg::Vec3f& agentHalfExtents)
|
|
||||||
{
|
|
||||||
return std::max(agentHalfExtents.x(), agentHalfExtents.y()) * std::sqrt(2) * settings.mRecastScaleFactor;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline float toNavMeshCoordinates(const Settings& settings, float value)
|
|
||||||
{
|
{
|
||||||
return value * settings.mRecastScaleFactor;
|
return value * settings.mRecastScaleFactor;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline osg::Vec2f toNavMeshCoordinates(const Settings& settings, osg::Vec2f position)
|
inline osg::Vec2f toNavMeshCoordinates(const RecastSettings& settings, osg::Vec2f position)
|
||||||
{
|
{
|
||||||
return position * settings.mRecastScaleFactor;
|
return position * settings.mRecastScaleFactor;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline osg::Vec3f toNavMeshCoordinates(const Settings& settings, osg::Vec3f position)
|
inline osg::Vec3f toNavMeshCoordinates(const RecastSettings& settings, osg::Vec3f position)
|
||||||
{
|
{
|
||||||
std::swap(position.y(), position.z());
|
std::swap(position.y(), position.z());
|
||||||
return position * settings.mRecastScaleFactor;
|
return position * settings.mRecastScaleFactor;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline osg::Vec3f fromNavMeshCoordinates(const Settings& settings, osg::Vec3f position)
|
inline TileBounds toNavMeshCoordinates(const RecastSettings& settings, const TileBounds& value)
|
||||||
|
{
|
||||||
|
return TileBounds {
|
||||||
|
toNavMeshCoordinates(settings, value.mMin),
|
||||||
|
toNavMeshCoordinates(settings, value.mMax)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
inline osg::Vec3f fromNavMeshCoordinates(const RecastSettings& settings, osg::Vec3f position)
|
||||||
{
|
{
|
||||||
const auto factor = 1.0f / settings.mRecastScaleFactor;
|
const auto factor = 1.0f / settings.mRecastScaleFactor;
|
||||||
position *= factor;
|
position *= factor;
|
||||||
|
@ -56,12 +45,12 @@ namespace DetourNavigator
|
||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline float getTileSize(const Settings& settings)
|
inline float getTileSize(const RecastSettings& settings)
|
||||||
{
|
{
|
||||||
return static_cast<float>(settings.mTileSize) * settings.mCellSize;
|
return static_cast<float>(settings.mTileSize) * settings.mCellSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline TilePosition getTilePosition(const Settings& settings, const osg::Vec3f& position)
|
inline TilePosition getTilePosition(const RecastSettings& settings, const osg::Vec3f& position)
|
||||||
{
|
{
|
||||||
return TilePosition(
|
return TilePosition(
|
||||||
static_cast<int>(std::floor(position.x() / getTileSize(settings))),
|
static_cast<int>(std::floor(position.x() / getTileSize(settings))),
|
||||||
|
@ -69,7 +58,7 @@ namespace DetourNavigator
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline TileBounds makeTileBounds(const Settings& settings, const TilePosition& tilePosition)
|
inline TileBounds makeTileBounds(const RecastSettings& settings, const TilePosition& tilePosition)
|
||||||
{
|
{
|
||||||
return TileBounds {
|
return TileBounds {
|
||||||
osg::Vec2f(tilePosition.x(), tilePosition.y()) * getTileSize(settings),
|
osg::Vec2f(tilePosition.x(), tilePosition.y()) * getTileSize(settings),
|
||||||
|
@ -77,17 +66,12 @@ namespace DetourNavigator
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
inline float getBorderSize(const Settings& settings)
|
inline float getBorderSize(const RecastSettings& settings)
|
||||||
{
|
{
|
||||||
return static_cast<float>(settings.mBorderSize) * settings.mCellSize;
|
return static_cast<float>(settings.mBorderSize) * settings.mCellSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline float getSwimLevel(const Settings& settings, const float waterLevel, const float agentHalfExtentsZ)
|
inline float getRealTileSize(const RecastSettings& settings)
|
||||||
{
|
|
||||||
return waterLevel - settings.mSwimHeightScale * agentHalfExtentsZ - agentHalfExtentsZ;;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline float getRealTileSize(const Settings& settings)
|
|
||||||
{
|
{
|
||||||
return settings.mTileSize * settings.mCellSize / settings.mRecastScaleFactor;
|
return settings.mTileSize * settings.mCellSize / settings.mRecastScaleFactor;
|
||||||
}
|
}
|
||||||
|
@ -97,7 +81,7 @@ namespace DetourNavigator
|
||||||
return std::floor(std::sqrt(settings.mMaxTilesNumber / osg::PI)) - 1;
|
return std::floor(std::sqrt(settings.mMaxTilesNumber / osg::PI)) - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline TileBounds makeRealTileBoundsWithBorder(const Settings& settings, const TilePosition& tilePosition)
|
inline TileBounds makeRealTileBoundsWithBorder(const RecastSettings& settings, const TilePosition& tilePosition)
|
||||||
{
|
{
|
||||||
TileBounds result = makeTileBounds(settings, tilePosition);
|
TileBounds result = makeTileBounds(settings, tilePosition);
|
||||||
const float border = getBorderSize(settings);
|
const float border = getBorderSize(settings);
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
namespace DetourNavigator
|
namespace DetourNavigator
|
||||||
{
|
{
|
||||||
TileCachedRecastMeshManager::TileCachedRecastMeshManager(const Settings& settings)
|
TileCachedRecastMeshManager::TileCachedRecastMeshManager(const RecastSettings& settings)
|
||||||
: mSettings(settings)
|
: mSettings(settings)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ namespace DetourNavigator
|
||||||
class TileCachedRecastMeshManager
|
class TileCachedRecastMeshManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TileCachedRecastMeshManager(const Settings& settings);
|
explicit TileCachedRecastMeshManager(const RecastSettings& settings);
|
||||||
|
|
||||||
bool addObject(const ObjectId id, const CollisionShape& shape, const btTransform& transform,
|
bool addObject(const ObjectId id, const CollisionShape& shape, const btTransform& transform,
|
||||||
const AreaType areaType);
|
const AreaType areaType);
|
||||||
|
@ -102,7 +102,7 @@ namespace DetourNavigator
|
||||||
private:
|
private:
|
||||||
using TilesMap = std::map<TilePosition, std::shared_ptr<CachedRecastMeshManager>>;
|
using TilesMap = std::map<TilePosition, std::shared_ptr<CachedRecastMeshManager>>;
|
||||||
|
|
||||||
const Settings& mSettings;
|
const RecastSettings& mSettings;
|
||||||
Misc::ScopeGuarded<TilesMap> mTiles;
|
Misc::ScopeGuarded<TilesMap> mTiles;
|
||||||
std::unordered_map<ObjectId, std::vector<TilePosition>> mObjectsTilesPositions;
|
std::unordered_map<ObjectId, std::vector<TilePosition>> mObjectsTilesPositions;
|
||||||
std::map<osg::Vec2i, std::vector<TilePosition>> mWaterTilesPositions;
|
std::map<osg::Vec2i, std::vector<TilePosition>> mWaterTilesPositions;
|
||||||
|
|
|
@ -37,7 +37,7 @@ namespace SceneUtil
|
||||||
{
|
{
|
||||||
osg::ref_ptr<osg::Group> createAgentPathGroup(const std::deque<osg::Vec3f>& path,
|
osg::ref_ptr<osg::Group> createAgentPathGroup(const std::deque<osg::Vec3f>& path,
|
||||||
const osg::Vec3f& halfExtents, const osg::Vec3f& start, const osg::Vec3f& end,
|
const osg::Vec3f& halfExtents, const osg::Vec3f& start, const osg::Vec3f& end,
|
||||||
const DetourNavigator::Settings& settings)
|
const DetourNavigator::RecastSettings& settings)
|
||||||
{
|
{
|
||||||
using namespace DetourNavigator;
|
using namespace DetourNavigator;
|
||||||
|
|
||||||
|
|
|
@ -13,14 +13,14 @@ namespace osg
|
||||||
|
|
||||||
namespace DetourNavigator
|
namespace DetourNavigator
|
||||||
{
|
{
|
||||||
struct Settings;
|
struct RecastSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace SceneUtil
|
namespace SceneUtil
|
||||||
{
|
{
|
||||||
osg::ref_ptr<osg::Group> createAgentPathGroup(const std::deque<osg::Vec3f>& path,
|
osg::ref_ptr<osg::Group> createAgentPathGroup(const std::deque<osg::Vec3f>& path,
|
||||||
const osg::Vec3f& halfExtents, const osg::Vec3f& start, const osg::Vec3f& end,
|
const osg::Vec3f& halfExtents, const osg::Vec3f& start, const osg::Vec3f& end,
|
||||||
const DetourNavigator::Settings& settings);
|
const DetourNavigator::RecastSettings& settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -254,9 +254,9 @@ namespace SceneUtil
|
||||||
osg::ref_ptr<osg::Group> group(new osg::Group);
|
osg::ref_ptr<osg::Group> group(new osg::Group);
|
||||||
group->setStateSet(groupStateSet);
|
group->setStateSet(groupStateSet);
|
||||||
constexpr float shift = 10.0f;
|
constexpr float shift = 10.0f;
|
||||||
DebugDraw debugDraw(*group, debugDrawStateSet, osg::Vec3f(0, 0, shift), 1.0f / settings.mRecastScaleFactor);
|
DebugDraw debugDraw(*group, debugDrawStateSet, osg::Vec3f(0, 0, shift), 1.0f / settings.mRecast.mRecastScaleFactor);
|
||||||
dtNavMeshQuery navMeshQuery;
|
dtNavMeshQuery navMeshQuery;
|
||||||
navMeshQuery.init(&navMesh, settings.mMaxNavMeshQueryNodes);
|
navMeshQuery.init(&navMesh, settings.mDetour.mMaxNavMeshQueryNodes);
|
||||||
drawMeshTile(&debugDraw, navMesh, &navMeshQuery, &meshTile, DU_DRAWNAVMESH_OFFMESHCONS | DU_DRAWNAVMESH_CLOSEDLIST);
|
drawMeshTile(&debugDraw, navMesh, &navMeshQuery, &meshTile, DU_DRAWNAVMESH_OFFMESHCONS | DU_DRAWNAVMESH_CLOSEDLIST);
|
||||||
|
|
||||||
return group;
|
return group;
|
||||||
|
|
|
@ -42,7 +42,7 @@ namespace
|
||||||
namespace SceneUtil
|
namespace SceneUtil
|
||||||
{
|
{
|
||||||
osg::ref_ptr<osg::Group> createRecastMeshGroup(const DetourNavigator::RecastMesh& recastMesh,
|
osg::ref_ptr<osg::Group> createRecastMeshGroup(const DetourNavigator::RecastMesh& recastMesh,
|
||||||
const DetourNavigator::Settings& settings)
|
const DetourNavigator::RecastSettings& settings)
|
||||||
{
|
{
|
||||||
using namespace DetourNavigator;
|
using namespace DetourNavigator;
|
||||||
|
|
||||||
|
|
|
@ -11,13 +11,13 @@ namespace osg
|
||||||
namespace DetourNavigator
|
namespace DetourNavigator
|
||||||
{
|
{
|
||||||
class RecastMesh;
|
class RecastMesh;
|
||||||
struct Settings;
|
struct RecastSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace SceneUtil
|
namespace SceneUtil
|
||||||
{
|
{
|
||||||
osg::ref_ptr<osg::Group> createRecastMeshGroup(const DetourNavigator::RecastMesh& recastMesh,
|
osg::ref_ptr<osg::Group> createRecastMeshGroup(const DetourNavigator::RecastMesh& recastMesh,
|
||||||
const DetourNavigator::Settings& settings);
|
const DetourNavigator::RecastSettings& settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -79,6 +79,15 @@ int Manager::getInt (const std::string& setting, const std::string& category)
|
||||||
return number;
|
return number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::int64_t Manager::getInt64 (const std::string& setting, const std::string& category)
|
||||||
|
{
|
||||||
|
const std::string& value = getString(setting, category);
|
||||||
|
std::stringstream stream(value);
|
||||||
|
std::size_t number = 0;
|
||||||
|
stream >> number;
|
||||||
|
return number;
|
||||||
|
}
|
||||||
|
|
||||||
bool Manager::getBool (const std::string& setting, const std::string& category)
|
bool Manager::getBool (const std::string& setting, const std::string& category)
|
||||||
{
|
{
|
||||||
const std::string& string = getString(setting, category);
|
const std::string& string = getString(setting, category);
|
||||||
|
|
|
@ -51,6 +51,7 @@ namespace Settings
|
||||||
///< returns the list of changed settings intersecting with the filter
|
///< returns the list of changed settings intersecting with the filter
|
||||||
|
|
||||||
static int getInt (const std::string& setting, const std::string& category);
|
static int getInt (const std::string& setting, const std::string& category);
|
||||||
|
static std::int64_t getInt64 (const std::string& setting, const std::string& category);
|
||||||
static float getFloat (const std::string& setting, const std::string& category);
|
static float getFloat (const std::string& setting, const std::string& category);
|
||||||
static double getDouble (const std::string& setting, const std::string& category);
|
static double getDouble (const std::string& setting, const std::string& category);
|
||||||
static std::string getString (const std::string& setting, const std::string& category);
|
static std::string getString (const std::string& setting, const std::string& category);
|
||||||
|
|
|
@ -365,20 +365,20 @@ max verts per poly
|
||||||
|
|
||||||
The maximum number of vertices allowed for polygons generated during the contour to polygon conversion process.
|
The maximum number of vertices allowed for polygons generated during the contour to polygon conversion process.
|
||||||
|
|
||||||
region merge size
|
region merge area
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
:Type: integer
|
:Type: integer
|
||||||
:Range: >= 0
|
:Range: >= 0
|
||||||
:Default: 20
|
:Default: 400
|
||||||
|
|
||||||
Any regions with a span count smaller than this value will, if possible, be merged with larger regions.
|
Any regions with a span count smaller than this value will, if possible, be merged with larger regions.
|
||||||
|
|
||||||
region min size
|
region min area
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
:Type: integer
|
:Type: integer
|
||||||
:Range: >= 0
|
:Range: >= 0
|
||||||
:Default: 8
|
:Default: 64
|
||||||
|
|
||||||
The minimum number of cells allowed to form isolated island areas.
|
The minimum number of cells allowed to form isolated island areas.
|
||||||
|
|
|
@ -876,10 +876,10 @@ max polygons per tile = 4096
|
||||||
max verts per poly = 6
|
max verts per poly = 6
|
||||||
|
|
||||||
# Any regions with a span count smaller than this value will, if possible, be merged with larger regions. (value >= 0)
|
# Any regions with a span count smaller than this value will, if possible, be merged with larger regions. (value >= 0)
|
||||||
region merge size = 20
|
region merge area = 400
|
||||||
|
|
||||||
# The minimum number of cells allowed to form isolated island areas. (value >= 0)
|
# The minimum number of cells allowed to form isolated island areas. (value >= 0)
|
||||||
region min size = 8
|
region min area = 64
|
||||||
|
|
||||||
# Number of background threads to update nav mesh (value >= 1)
|
# Number of background threads to update nav mesh (value >= 1)
|
||||||
async nav mesh updater threads = 1
|
async nav mesh updater threads = 1
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue