mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-28 19:39:42 +00:00
Merge branch 'optimize_navmesh_related_mechanics' into 'master'
Optimize navmesh related mechanics See merge request OpenMW/openmw!2742
This commit is contained in:
commit
9487312fb8
18 changed files with 108 additions and 112 deletions
|
@ -189,8 +189,17 @@ bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, const osg::Vec3f&
|
|||
= getPointTolerance(actor.getClass().getMaxSpeed(actor), duration, world->getHalfExtents(actor));
|
||||
|
||||
static const bool smoothMovement = Settings::Manager::getBool("smooth movement", "Game");
|
||||
mPathFinder.update(position, pointTolerance, DEFAULT_TOLERANCE,
|
||||
/*shortenIfAlmostStraight=*/smoothMovement, actorCanMoveByZ, agentBounds, getNavigatorFlags(actor));
|
||||
|
||||
PathFinder::UpdateFlags updateFlags{};
|
||||
|
||||
if (actorCanMoveByZ)
|
||||
updateFlags |= PathFinder::UpdateFlag_CanMoveByZ;
|
||||
if (timerStatus == Misc::TimerStatus::Elapsed && smoothMovement)
|
||||
updateFlags |= PathFinder::UpdateFlag_ShortenIfAlmostStraight;
|
||||
if (timerStatus == Misc::TimerStatus::Elapsed)
|
||||
updateFlags |= PathFinder::UpdateFlag_RemoveLoops;
|
||||
|
||||
mPathFinder.update(position, pointTolerance, DEFAULT_TOLERANCE, updateFlags, agentBounds, getNavigatorFlags(actor));
|
||||
|
||||
if (isDestReached || mPathFinder.checkPathCompleted()) // if path is finished
|
||||
{
|
||||
|
|
|
@ -312,6 +312,13 @@ namespace MWMechanics
|
|||
completeManualWalking(actor, storage);
|
||||
}
|
||||
|
||||
if (storage.mState == AiWanderStorage::Wander_Walking && mUsePathgrid)
|
||||
{
|
||||
const auto agentBounds = MWBase::Environment::get().getWorld()->getPathfindingAgentBounds(actor);
|
||||
mPathFinder.buildPathByNavMeshToNextPoint(
|
||||
actor, agentBounds, getNavigatorFlags(actor), getAreaCosts(actor));
|
||||
}
|
||||
|
||||
if (storage.mState == AiWanderStorage::Wander_MoveNow && storage.mCanWanderAlongPathGrid)
|
||||
{
|
||||
// Construct a new path if there isn't one
|
||||
|
@ -560,13 +567,6 @@ namespace MWMechanics
|
|||
|
||||
void AiWander::evadeObstacles(const MWWorld::Ptr& actor, AiWanderStorage& storage)
|
||||
{
|
||||
if (mUsePathgrid)
|
||||
{
|
||||
const auto agentBounds = MWBase::Environment::get().getWorld()->getPathfindingAgentBounds(actor);
|
||||
mPathFinder.buildPathByNavMeshToNextPoint(
|
||||
actor, agentBounds, getNavigatorFlags(actor), getAreaCosts(actor));
|
||||
}
|
||||
|
||||
if (mObstacleCheck.isEvading())
|
||||
{
|
||||
// first check if we're walking into a door
|
||||
|
|
|
@ -313,8 +313,7 @@ namespace MWMechanics
|
|||
}
|
||||
|
||||
void PathFinder::update(const osg::Vec3f& position, float pointTolerance, float destinationTolerance,
|
||||
bool shortenIfAlmostStraight, bool canMoveByZ, const DetourNavigator::AgentBounds& agentBounds,
|
||||
const DetourNavigator::Flags flags)
|
||||
UpdateFlags updateFlags, const DetourNavigator::AgentBounds& agentBounds, DetourNavigator::Flags pathFlags)
|
||||
{
|
||||
if (mPath.empty())
|
||||
return;
|
||||
|
@ -323,9 +322,9 @@ namespace MWMechanics
|
|||
mPath.pop_front();
|
||||
|
||||
const IsValidShortcut isValidShortcut{ MWBase::Environment::get().getWorld()->getNavigator(), agentBounds,
|
||||
flags };
|
||||
pathFlags };
|
||||
|
||||
if (shortenIfAlmostStraight)
|
||||
if ((updateFlags & UpdateFlag_ShortenIfAlmostStraight) != 0)
|
||||
{
|
||||
while (mPath.size() > 2 && isAlmostStraight(mPath[0], mPath[1], mPath[2], pointTolerance)
|
||||
&& isValidShortcut(mPath[0], mPath[2]))
|
||||
|
@ -335,7 +334,7 @@ namespace MWMechanics
|
|||
mPath.pop_front();
|
||||
}
|
||||
|
||||
if (mPath.size() > 1)
|
||||
if ((updateFlags & UpdateFlag_RemoveLoops) != 0 && mPath.size() > 1)
|
||||
{
|
||||
std::size_t begin = 0;
|
||||
for (std::size_t i = 1; i < mPath.size(); ++i)
|
||||
|
@ -351,7 +350,7 @@ namespace MWMechanics
|
|||
if (mPath.size() == 1)
|
||||
{
|
||||
float distSqr;
|
||||
if (canMoveByZ)
|
||||
if ((updateFlags & UpdateFlag_CanMoveByZ) != 0)
|
||||
distSqr = (mPath.front() - position).length2();
|
||||
else
|
||||
distSqr = sqrDistanceIgnoreZ(mPath.front(), position);
|
||||
|
|
|
@ -82,11 +82,16 @@ namespace MWMechanics
|
|||
class PathFinder
|
||||
{
|
||||
public:
|
||||
PathFinder()
|
||||
: mConstructed(false)
|
||||
, mCell(nullptr)
|
||||
using UpdateFlags = unsigned;
|
||||
|
||||
enum UpdateFlag : UpdateFlags
|
||||
{
|
||||
}
|
||||
UpdateFlag_CanMoveByZ = 1 << 0,
|
||||
UpdateFlag_ShortenIfAlmostStraight = 1 << 1,
|
||||
UpdateFlag_RemoveLoops = 1 << 2,
|
||||
};
|
||||
|
||||
PathFinder() = default;
|
||||
|
||||
void clearPath()
|
||||
{
|
||||
|
@ -121,8 +126,7 @@ namespace MWMechanics
|
|||
|
||||
/// Remove front point if exist and within tolerance
|
||||
void update(const osg::Vec3f& position, float pointTolerance, float destinationTolerance,
|
||||
bool shortenIfAlmostStraight, bool canMoveByZ, const DetourNavigator::AgentBounds& agentBounds,
|
||||
const DetourNavigator::Flags flags);
|
||||
UpdateFlags updateFlags, const DetourNavigator::AgentBounds& agentBounds, DetourNavigator::Flags pathFlags);
|
||||
|
||||
bool checkPathCompleted() const { return mConstructed && mPath.empty(); }
|
||||
|
||||
|
@ -201,10 +205,9 @@ namespace MWMechanics
|
|||
}
|
||||
|
||||
private:
|
||||
bool mConstructed;
|
||||
bool mConstructed = false;
|
||||
std::deque<osg::Vec3f> mPath;
|
||||
|
||||
const MWWorld::CellStore* mCell;
|
||||
const MWWorld::CellStore* mCell = nullptr;
|
||||
|
||||
void buildPathByPathgridImpl(const osg::Vec3f& startPoint, const osg::Vec3f& endPoint,
|
||||
const PathgridGraph& pathgridGraph, std::back_insert_iterator<std::deque<osg::Vec3f>> out);
|
||||
|
|
|
@ -74,7 +74,7 @@ namespace
|
|||
mRecastMeshManager.setWorldspace(mWorldspace, nullptr);
|
||||
addHeightFieldPlane(mRecastMeshManager);
|
||||
AsyncNavMeshUpdater updater(mSettings, mRecastMeshManager, mOffMeshConnectionsManager, nullptr);
|
||||
const auto navMeshCacheItem = std::make_shared<GuardedNavMeshCacheItem>(makeEmptyNavMesh(mSettings), 1);
|
||||
const auto navMeshCacheItem = std::make_shared<GuardedNavMeshCacheItem>(1, mSettings);
|
||||
const std::map<TilePosition, ChangeType> changedTiles{ { TilePosition{ 0, 0 }, ChangeType::add } };
|
||||
updater.post(mAgentBounds, navMeshCacheItem, mPlayerTile, mWorldspace, changedTiles);
|
||||
updater.wait(WaitConditionType::allJobsDone, &mListener);
|
||||
|
@ -86,7 +86,7 @@ namespace
|
|||
mRecastMeshManager.setWorldspace(mWorldspace, nullptr);
|
||||
addHeightFieldPlane(mRecastMeshManager);
|
||||
AsyncNavMeshUpdater updater(mSettings, mRecastMeshManager, mOffMeshConnectionsManager, nullptr);
|
||||
const auto navMeshCacheItem = std::make_shared<GuardedNavMeshCacheItem>(makeEmptyNavMesh(mSettings), 1);
|
||||
const auto navMeshCacheItem = std::make_shared<GuardedNavMeshCacheItem>(1, mSettings);
|
||||
const std::map<TilePosition, ChangeType> changedTiles{ { TilePosition{ 0, 0 }, ChangeType::add } };
|
||||
updater.post(mAgentBounds, navMeshCacheItem, mPlayerTile, mWorldspace, changedTiles);
|
||||
updater.wait(WaitConditionType::allJobsDone, &mListener);
|
||||
|
@ -109,7 +109,7 @@ namespace
|
|||
mRecastMeshManager.setWorldspace(mWorldspace, nullptr);
|
||||
addHeightFieldPlane(mRecastMeshManager);
|
||||
AsyncNavMeshUpdater updater(mSettings, mRecastMeshManager, mOffMeshConnectionsManager, nullptr);
|
||||
const auto navMeshCacheItem = std::make_shared<GuardedNavMeshCacheItem>(makeEmptyNavMesh(mSettings), 1);
|
||||
const auto navMeshCacheItem = std::make_shared<GuardedNavMeshCacheItem>(1, mSettings);
|
||||
const std::map<TilePosition, ChangeType> changedTiles{ { TilePosition{ 0, 0 }, ChangeType::update } };
|
||||
updater.post(mAgentBounds, navMeshCacheItem, mPlayerTile, mWorldspace, changedTiles);
|
||||
updater.wait(WaitConditionType::allJobsDone, &mListener);
|
||||
|
@ -135,7 +135,7 @@ namespace
|
|||
auto db = std::make_unique<NavMeshDb>(":memory:", std::numeric_limits<std::uint64_t>::max());
|
||||
NavMeshDb* const dbPtr = db.get();
|
||||
AsyncNavMeshUpdater updater(mSettings, mRecastMeshManager, mOffMeshConnectionsManager, std::move(db));
|
||||
const auto navMeshCacheItem = std::make_shared<GuardedNavMeshCacheItem>(makeEmptyNavMesh(mSettings), 1);
|
||||
const auto navMeshCacheItem = std::make_shared<GuardedNavMeshCacheItem>(1, mSettings);
|
||||
const TilePosition tilePosition{ 0, 0 };
|
||||
const std::map<TilePosition, ChangeType> changedTiles{ { tilePosition, ChangeType::add } };
|
||||
updater.post(mAgentBounds, navMeshCacheItem, mPlayerTile, mWorldspace, changedTiles);
|
||||
|
@ -162,7 +162,7 @@ namespace
|
|||
NavMeshDb* const dbPtr = db.get();
|
||||
mSettings.mWriteToNavMeshDb = false;
|
||||
AsyncNavMeshUpdater updater(mSettings, mRecastMeshManager, mOffMeshConnectionsManager, std::move(db));
|
||||
const auto navMeshCacheItem = std::make_shared<GuardedNavMeshCacheItem>(makeEmptyNavMesh(mSettings), 1);
|
||||
const auto navMeshCacheItem = std::make_shared<GuardedNavMeshCacheItem>(1, mSettings);
|
||||
const TilePosition tilePosition{ 0, 0 };
|
||||
const std::map<TilePosition, ChangeType> changedTiles{ { tilePosition, ChangeType::add } };
|
||||
updater.post(mAgentBounds, navMeshCacheItem, mPlayerTile, mWorldspace, changedTiles);
|
||||
|
@ -187,7 +187,7 @@ namespace
|
|||
NavMeshDb* const dbPtr = db.get();
|
||||
mSettings.mWriteToNavMeshDb = false;
|
||||
AsyncNavMeshUpdater updater(mSettings, mRecastMeshManager, mOffMeshConnectionsManager, std::move(db));
|
||||
const auto navMeshCacheItem = std::make_shared<GuardedNavMeshCacheItem>(makeEmptyNavMesh(mSettings), 1);
|
||||
const auto navMeshCacheItem = std::make_shared<GuardedNavMeshCacheItem>(1, mSettings);
|
||||
const TilePosition tilePosition{ 0, 0 };
|
||||
const std::map<TilePosition, ChangeType> changedTiles{ { tilePosition, ChangeType::add } };
|
||||
updater.post(mAgentBounds, navMeshCacheItem, mPlayerTile, mWorldspace, changedTiles);
|
||||
|
@ -207,7 +207,7 @@ namespace
|
|||
mSettings.mMaxNavMeshTilesCacheSize = 0;
|
||||
AsyncNavMeshUpdater updater(mSettings, mRecastMeshManager, mOffMeshConnectionsManager,
|
||||
std::make_unique<NavMeshDb>(":memory:", std::numeric_limits<std::uint64_t>::max()));
|
||||
const auto navMeshCacheItem = std::make_shared<GuardedNavMeshCacheItem>(makeEmptyNavMesh(mSettings), 1);
|
||||
const auto navMeshCacheItem = std::make_shared<GuardedNavMeshCacheItem>(1, mSettings);
|
||||
const std::map<TilePosition, ChangeType> changedTiles{ { TilePosition{ 0, 0 }, ChangeType::add } };
|
||||
updater.post(mAgentBounds, navMeshCacheItem, mPlayerTile, mWorldspace, changedTiles);
|
||||
updater.wait(WaitConditionType::allJobsDone, &mListener);
|
||||
|
@ -236,7 +236,7 @@ namespace
|
|||
mRecastMeshManager.setWorldspace(mWorldspace, nullptr);
|
||||
addHeightFieldPlane(mRecastMeshManager);
|
||||
AsyncNavMeshUpdater updater(mSettings, mRecastMeshManager, mOffMeshConnectionsManager, nullptr);
|
||||
const auto navMeshCacheItem = std::make_shared<GuardedNavMeshCacheItem>(makeEmptyNavMesh(mSettings), 1);
|
||||
const auto navMeshCacheItem = std::make_shared<GuardedNavMeshCacheItem>(1, mSettings);
|
||||
const std::map<TilePosition, ChangeType> changedTilesAdd{ { TilePosition{ 0, 0 }, ChangeType::add } };
|
||||
updater.post(mAgentBounds, navMeshCacheItem, mPlayerTile, mWorldspace, changedTilesAdd);
|
||||
updater.wait(WaitConditionType::allJobsDone, &mListener);
|
||||
|
@ -258,7 +258,7 @@ namespace
|
|||
auto db = std::make_unique<NavMeshDb>(":memory:", 4097);
|
||||
NavMeshDb* const dbPtr = db.get();
|
||||
AsyncNavMeshUpdater updater(mSettings, mRecastMeshManager, mOffMeshConnectionsManager, std::move(db));
|
||||
const auto navMeshCacheItem = std::make_shared<GuardedNavMeshCacheItem>(makeEmptyNavMesh(mSettings), 1);
|
||||
const auto navMeshCacheItem = std::make_shared<GuardedNavMeshCacheItem>(1, mSettings);
|
||||
std::map<TilePosition, ChangeType> changedTiles;
|
||||
for (int x = -5; x <= 5; ++x)
|
||||
for (int y = -5; y <= 5; ++y)
|
||||
|
|
|
@ -1,20 +1,15 @@
|
|||
#include "findrandompointaroundcircle.hpp"
|
||||
#include "findsmoothpath.hpp"
|
||||
#include "settings.hpp"
|
||||
|
||||
#include <DetourNavMesh.h>
|
||||
#include <DetourNavMeshQuery.h>
|
||||
|
||||
namespace DetourNavigator
|
||||
{
|
||||
std::optional<osg::Vec3f> findRandomPointAroundCircle(const dtNavMesh& navMesh, const osg::Vec3f& halfExtents,
|
||||
const osg::Vec3f& start, const float maxRadius, const Flags includeFlags, const DetourSettings& settings,
|
||||
std::optional<osg::Vec3f> findRandomPointAroundCircle(const dtNavMeshQuery& navMeshQuery,
|
||||
const osg::Vec3f& halfExtents, const osg::Vec3f& start, const float maxRadius, const Flags includeFlags,
|
||||
float (*prng)())
|
||||
{
|
||||
dtNavMeshQuery navMeshQuery;
|
||||
if (!initNavMeshQuery(navMeshQuery, navMesh, settings.mMaxNavMeshQueryNodes))
|
||||
return std::optional<osg::Vec3f>();
|
||||
|
||||
dtQueryFilter queryFilter;
|
||||
queryFilter.setIncludeFlags(includeFlags);
|
||||
|
||||
|
|
|
@ -6,14 +6,14 @@
|
|||
#include <optional>
|
||||
#include <osg/Vec3f>
|
||||
|
||||
class dtNavMesh;
|
||||
class dtNavMeshQuery;
|
||||
|
||||
namespace DetourNavigator
|
||||
{
|
||||
struct DetourSettings;
|
||||
|
||||
std::optional<osg::Vec3f> findRandomPointAroundCircle(const dtNavMesh& navMesh, const osg::Vec3f& halfExtents,
|
||||
const osg::Vec3f& start, const float maxRadius, const Flags includeFlags, const DetourSettings& settings,
|
||||
std::optional<osg::Vec3f> findRandomPointAroundCircle(const dtNavMeshQuery& navMeshQuery,
|
||||
const osg::Vec3f& halfExtents, const osg::Vec3f& start, const float maxRadius, const Flags includeFlags,
|
||||
float (*prng)());
|
||||
}
|
||||
|
||||
|
|
|
@ -252,14 +252,10 @@ namespace DetourNavigator
|
|||
}
|
||||
|
||||
template <class OutputIterator>
|
||||
Status findSmoothPath(const dtNavMesh& navMesh, const osg::Vec3f& halfExtents, const float stepSize,
|
||||
const osg::Vec3f& start, const osg::Vec3f& end, const Flags includeFlags, const AreaCosts& areaCosts,
|
||||
const Settings& settings, float endTolerance, OutputIterator out)
|
||||
Status findSmoothPath(const dtNavMesh& navMesh, const dtNavMeshQuery& navMeshQuery, const osg::Vec3f& halfExtents,
|
||||
const float stepSize, const osg::Vec3f& start, const osg::Vec3f& end, const Flags includeFlags,
|
||||
const AreaCosts& areaCosts, const Settings& settings, float endTolerance, OutputIterator out)
|
||||
{
|
||||
dtNavMeshQuery navMeshQuery;
|
||||
if (!initNavMeshQuery(navMeshQuery, navMesh, settings.mDetour.mMaxNavMeshQueryNodes))
|
||||
return Status::InitNavMeshQueryFailed;
|
||||
|
||||
dtQueryFilter queryFilter;
|
||||
queryFilter.setIncludeFlags(includeFlags);
|
||||
queryFilter.setAreaCost(AreaType_water, areaCosts.mWater);
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
#include "recastparams.hpp"
|
||||
#include "settings.hpp"
|
||||
#include "settingsutils.hpp"
|
||||
#include "sharednavmesh.hpp"
|
||||
|
||||
#include "components/debug/debuglog.hpp"
|
||||
|
||||
|
@ -604,7 +603,7 @@ namespace DetourNavigator
|
|||
return NavMeshData(navMeshData, navMeshDataSize);
|
||||
}
|
||||
|
||||
NavMeshPtr makeEmptyNavMesh(const Settings& settings)
|
||||
void initEmptyNavMesh(const Settings& settings, dtNavMesh& navMesh)
|
||||
{
|
||||
// Max tiles and max polys affect how the tile IDs are caculated.
|
||||
// There are 22 bits available for identifying a tile and a polygon.
|
||||
|
@ -623,17 +622,10 @@ namespace DetourNavigator
|
|||
params.maxTiles = 1 << tilesBits;
|
||||
params.maxPolys = 1 << polysBits;
|
||||
|
||||
NavMeshPtr navMesh(dtAllocNavMesh(), &dtFreeNavMesh);
|
||||
|
||||
if (navMesh == nullptr)
|
||||
throw NavigatorException("Failed to allocate navmesh");
|
||||
|
||||
const auto status = navMesh->init(¶ms);
|
||||
const auto status = navMesh.init(¶ms);
|
||||
|
||||
if (!dtStatusSucceed(status))
|
||||
throw NavigatorException("Failed to init navmesh");
|
||||
|
||||
return navMesh;
|
||||
}
|
||||
|
||||
bool isSupportedAgentBounds(const RecastSettings& settings, const AgentBounds& agentBounds)
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
#define OPENMW_COMPONENTS_DETOURNAVIGATOR_MAKENAVMESH_H
|
||||
|
||||
#include "recastmesh.hpp"
|
||||
#include "sharednavmesh.hpp"
|
||||
#include "tileposition.hpp"
|
||||
|
||||
#include <memory>
|
||||
|
@ -49,7 +48,7 @@ namespace DetourNavigator
|
|||
const std::vector<OffMeshConnection>& offMeshConnections, const AgentBounds& agentBounds,
|
||||
const TilePosition& tile, const RecastSettings& settings);
|
||||
|
||||
NavMeshPtr makeEmptyNavMesh(const Settings& settings);
|
||||
void initEmptyNavMesh(const Settings& settings, dtNavMesh& navMesh);
|
||||
|
||||
bool isSupportedAgentBounds(const RecastSettings& settings, const AgentBounds& agentBounds);
|
||||
}
|
||||
|
|
|
@ -11,11 +11,12 @@ namespace DetourNavigator
|
|||
const auto navMesh = navigator.getNavMesh(agentBounds);
|
||||
if (!navMesh)
|
||||
return std::nullopt;
|
||||
const auto& settings = navigator.getSettings();
|
||||
const auto result = DetourNavigator::findRandomPointAroundCircle(navMesh->lockConst()->getImpl(),
|
||||
const Settings& settings = navigator.getSettings();
|
||||
const auto locked = navMesh->lock();
|
||||
const auto result = DetourNavigator::findRandomPointAroundCircle(locked->getQuery(),
|
||||
toNavMeshCoordinates(settings.mRecast, agentBounds.mHalfExtents),
|
||||
toNavMeshCoordinates(settings.mRecast, start), toNavMeshCoordinates(settings.mRecast, maxRadius),
|
||||
includeFlags, settings.mDetour, prng);
|
||||
includeFlags, prng);
|
||||
if (!result)
|
||||
return std::nullopt;
|
||||
return std::optional<osg::Vec3f>(fromNavMeshCoordinates(settings.mRecast, *result));
|
||||
|
@ -27,11 +28,11 @@ namespace DetourNavigator
|
|||
const auto navMesh = navigator.getNavMesh(agentBounds);
|
||||
if (navMesh == nullptr)
|
||||
return std::nullopt;
|
||||
const auto& settings = navigator.getSettings();
|
||||
const auto result = DetourNavigator::raycast(navMesh->lockConst()->getImpl(),
|
||||
const Settings& settings = navigator.getSettings();
|
||||
const auto locked = navMesh->lock();
|
||||
const auto result = DetourNavigator::raycast(locked->getQuery(),
|
||||
toNavMeshCoordinates(settings.mRecast, agentBounds.mHalfExtents),
|
||||
toNavMeshCoordinates(settings.mRecast, start), toNavMeshCoordinates(settings.mRecast, end), includeFlags,
|
||||
settings.mDetour);
|
||||
toNavMeshCoordinates(settings.mRecast, start), toNavMeshCoordinates(settings.mRecast, end), includeFlags);
|
||||
if (!result)
|
||||
return std::nullopt;
|
||||
return fromNavMeshCoordinates(settings.mRecast, *result);
|
||||
|
|
|
@ -35,8 +35,9 @@ namespace DetourNavigator
|
|||
const auto navMesh = navigator.getNavMesh(agentBounds);
|
||||
if (navMesh == nullptr)
|
||||
return Status::NavMeshNotFound;
|
||||
const auto settings = navigator.getSettings();
|
||||
return findSmoothPath(navMesh->lockConst()->getImpl(),
|
||||
const Settings& settings = navigator.getSettings();
|
||||
const auto locked = navMesh->lock();
|
||||
return findSmoothPath(locked->getImpl(), locked->getQuery(),
|
||||
toNavMeshCoordinates(settings.mRecast, agentBounds.mHalfExtents),
|
||||
toNavMeshCoordinates(settings.mRecast, stepSize), toNavMeshCoordinates(settings.mRecast, start),
|
||||
toNavMeshCoordinates(settings.mRecast, end), includeFlags, areaCosts, settings, endTolerance, out);
|
||||
|
|
|
@ -1,12 +1,16 @@
|
|||
#include "navmeshcacheitem.hpp"
|
||||
#include "debug.hpp"
|
||||
#include "makenavmesh.hpp"
|
||||
#include "navmeshdata.hpp"
|
||||
#include "navmeshtilescache.hpp"
|
||||
#include "navmeshtileview.hpp"
|
||||
#include "settings.hpp"
|
||||
#include "tileposition.hpp"
|
||||
|
||||
#include <DetourNavMesh.h>
|
||||
|
||||
#include <ostream>
|
||||
#include <sstream>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
@ -66,18 +70,32 @@ namespace DetourNavigator
|
|||
return navMesh.getTileAt(position.x(), position.y(), layer);
|
||||
}
|
||||
|
||||
NavMeshCacheItem::NavMeshCacheItem(std::size_t generation, const Settings& settings)
|
||||
: mVersion{ generation, 0 }
|
||||
{
|
||||
initEmptyNavMesh(settings, mImpl);
|
||||
|
||||
if (const dtStatus status = mQuery.init(&mImpl, settings.mDetour.mMaxNavMeshQueryNodes);
|
||||
!dtStatusSucceed(status))
|
||||
{
|
||||
std::ostringstream error;
|
||||
error << "Failed to init navmesh query: " << WriteDtStatus{ status };
|
||||
throw std::runtime_error(error.str());
|
||||
}
|
||||
}
|
||||
|
||||
UpdateNavMeshStatus NavMeshCacheItem::updateTile(
|
||||
const TilePosition& position, NavMeshTilesCache::Value&& cached, NavMeshData&& navMeshData)
|
||||
{
|
||||
const dtMeshTile* currentTile = getTile(*mImpl, position);
|
||||
const dtMeshTile* currentTile = getTile(mImpl, position);
|
||||
if (currentTile != nullptr
|
||||
&& asNavMeshTileConstView(*currentTile) == asNavMeshTileConstView(navMeshData.mValue.get()))
|
||||
{
|
||||
return UpdateNavMeshStatus::ignored;
|
||||
}
|
||||
bool removed = ::removeTile(*mImpl, position);
|
||||
bool removed = ::removeTile(mImpl, position);
|
||||
removed = mEmptyTiles.erase(position) > 0 || removed;
|
||||
const auto addStatus = addTile(*mImpl, navMeshData.mValue.get(), navMeshData.mSize);
|
||||
const auto addStatus = addTile(mImpl, navMeshData.mValue.get(), navMeshData.mSize);
|
||||
if (dtStatusSucceed(addStatus))
|
||||
{
|
||||
auto tile = mUsedTiles.find(position);
|
||||
|
@ -111,7 +129,7 @@ namespace DetourNavigator
|
|||
|
||||
UpdateNavMeshStatus NavMeshCacheItem::removeTile(const TilePosition& position)
|
||||
{
|
||||
bool removed = ::removeTile(*mImpl, position);
|
||||
bool removed = ::removeTile(mImpl, position);
|
||||
removed = mEmptyTiles.erase(position) > 0 || removed;
|
||||
if (removed)
|
||||
{
|
||||
|
@ -123,7 +141,7 @@ namespace DetourNavigator
|
|||
|
||||
UpdateNavMeshStatus NavMeshCacheItem::markAsEmpty(const TilePosition& position)
|
||||
{
|
||||
bool removed = ::removeTile(*mImpl, position);
|
||||
bool removed = ::removeTile(mImpl, position);
|
||||
removed = mEmptyTiles.insert(position).second || removed;
|
||||
if (removed)
|
||||
{
|
||||
|
|
|
@ -3,10 +3,12 @@
|
|||
|
||||
#include "navmeshdata.hpp"
|
||||
#include "navmeshtilescache.hpp"
|
||||
#include "sharednavmesh.hpp"
|
||||
#include "tileposition.hpp"
|
||||
#include "version.hpp"
|
||||
|
||||
#include <DetourNavMesh.h>
|
||||
#include <DetourNavMeshQuery.h>
|
||||
|
||||
#include <iosfwd>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
@ -15,6 +17,8 @@ struct dtMeshTile;
|
|||
|
||||
namespace DetourNavigator
|
||||
{
|
||||
struct Settings;
|
||||
|
||||
enum class UpdateNavMeshStatus : unsigned
|
||||
{
|
||||
ignored = 0,
|
||||
|
@ -102,13 +106,11 @@ namespace DetourNavigator
|
|||
class NavMeshCacheItem
|
||||
{
|
||||
public:
|
||||
NavMeshCacheItem(const NavMeshPtr& impl, std::size_t generation)
|
||||
: mImpl(impl)
|
||||
, mVersion{ generation, 0 }
|
||||
{
|
||||
}
|
||||
explicit NavMeshCacheItem(std::size_t generation, const Settings& settings);
|
||||
|
||||
const dtNavMesh& getImpl() const { return *mImpl; }
|
||||
const dtNavMesh& getImpl() const { return mImpl; }
|
||||
|
||||
dtNavMeshQuery& getQuery() { return mQuery; }
|
||||
|
||||
const Version& getVersion() const { return mVersion; }
|
||||
|
||||
|
@ -125,7 +127,7 @@ namespace DetourNavigator
|
|||
void forEachUsedTile(Function&& function) const
|
||||
{
|
||||
for (const auto& [position, tile] : mUsedTiles)
|
||||
if (const dtMeshTile* meshTile = getTile(*mImpl, position))
|
||||
if (const dtMeshTile* meshTile = getTile(mImpl, position))
|
||||
function(position, tile.mVersion, *meshTile);
|
||||
}
|
||||
|
||||
|
@ -137,8 +139,9 @@ namespace DetourNavigator
|
|||
NavMeshData mData;
|
||||
};
|
||||
|
||||
NavMeshPtr mImpl;
|
||||
Version mVersion;
|
||||
dtNavMesh mImpl;
|
||||
dtNavMeshQuery mQuery;
|
||||
std::map<TilePosition, Tile> mUsedTiles;
|
||||
std::set<TilePosition> mEmptyTiles;
|
||||
};
|
||||
|
|
|
@ -69,7 +69,7 @@ namespace DetourNavigator
|
|||
return;
|
||||
mRecastMeshManager.setWorldspace(worldspace, getImpl(guard));
|
||||
for (auto& [agent, cache] : mCache)
|
||||
cache = std::make_shared<GuardedNavMeshCacheItem>(makeEmptyNavMesh(mSettings), ++mGenerationCounter);
|
||||
cache = std::make_shared<GuardedNavMeshCacheItem>(++mGenerationCounter, mSettings);
|
||||
mWorldspace = worldspace;
|
||||
}
|
||||
|
||||
|
@ -123,8 +123,7 @@ namespace DetourNavigator
|
|||
auto cached = mCache.find(agentBounds);
|
||||
if (cached != mCache.end())
|
||||
return;
|
||||
mCache.insert(std::make_pair(
|
||||
agentBounds, std::make_shared<GuardedNavMeshCacheItem>(makeEmptyNavMesh(mSettings), ++mGenerationCounter)));
|
||||
mCache.emplace(agentBounds, std::make_shared<GuardedNavMeshCacheItem>(++mGenerationCounter, mSettings));
|
||||
mPlayerTile.reset();
|
||||
Log(Debug::Debug) << "cache add for agent=" << agentBounds;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
#include "raycast.hpp"
|
||||
#include "findsmoothpath.hpp"
|
||||
#include "settings.hpp"
|
||||
|
||||
#include <DetourNavMesh.h>
|
||||
#include <DetourNavMeshQuery.h>
|
||||
|
@ -9,13 +7,9 @@
|
|||
|
||||
namespace DetourNavigator
|
||||
{
|
||||
std::optional<osg::Vec3f> raycast(const dtNavMesh& navMesh, const osg::Vec3f& halfExtents, const osg::Vec3f& start,
|
||||
const osg::Vec3f& end, const Flags includeFlags, const DetourSettings& settings)
|
||||
std::optional<osg::Vec3f> raycast(const dtNavMeshQuery& navMeshQuery, const osg::Vec3f& halfExtents,
|
||||
const osg::Vec3f& start, const osg::Vec3f& end, const Flags includeFlags)
|
||||
{
|
||||
dtNavMeshQuery navMeshQuery;
|
||||
if (!initNavMeshQuery(navMeshQuery, navMesh, settings.mMaxNavMeshQueryNodes))
|
||||
return {};
|
||||
|
||||
dtQueryFilter queryFilter;
|
||||
queryFilter.setIncludeFlags(includeFlags);
|
||||
|
||||
|
|
|
@ -6,14 +6,14 @@
|
|||
#include <optional>
|
||||
#include <osg/Vec3f>
|
||||
|
||||
class dtNavMesh;
|
||||
class dtNavMeshQuery;
|
||||
|
||||
namespace DetourNavigator
|
||||
{
|
||||
struct DetourSettings;
|
||||
|
||||
std::optional<osg::Vec3f> raycast(const dtNavMesh& navMesh, const osg::Vec3f& halfExtents, const osg::Vec3f& start,
|
||||
const osg::Vec3f& end, const Flags includeFlags, const DetourSettings& settings);
|
||||
std::optional<osg::Vec3f> raycast(const dtNavMeshQuery& navMeshQuery, const osg::Vec3f& halfExtents,
|
||||
const osg::Vec3f& start, const osg::Vec3f& end, const Flags includeFlags);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
#ifndef OPENMW_COMPONENTS_DETOURNAVIGATOR_SHAREDNAVMESH_H
|
||||
#define OPENMW_COMPONENTS_DETOURNAVIGATOR_SHAREDNAVMESH_H
|
||||
|
||||
#include <memory>
|
||||
|
||||
class dtNavMesh;
|
||||
|
||||
namespace DetourNavigator
|
||||
{
|
||||
using NavMeshPtr = std::shared_ptr<dtNavMesh>;
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue