Build limited path for far destinations

When distance between start and end point is greater than max radius of area
possibly covered by navmesh there is no way to find path via navmesh. Also if
distance is greater than cell size navmesh might not exists withing mentioned
area because cell is not loaded therefore navmesh is not generated. So minumum
of these values is used to limit max path distance. Assuming that path
actually exists it's possible to build path to the edge of a circle. When
actor reaches initial edge path is built further. However it will not be
optimal.
pull/593/head
elsid 4 years ago
parent 313355cb3d
commit 39c0ce9ddf
No known key found for this signature in database
GPG Key ID: B845CB9FEE18AB40

@ -114,7 +114,7 @@ bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, const osg::Vec3f&
if (wasShortcutting || doesPathNeedRecalc(dest, actor)) // if need to rebuild path
{
const auto pathfindingHalfExtents = world->getPathfindingHalfExtents(actor);
mPathFinder.buildPath(actor, position, dest, actor.getCell(), getPathGridGraph(actor.getCell()),
mPathFinder.buildLimitedPath(actor, position, dest, actor.getCell(), getPathGridGraph(actor.getCell()),
pathfindingHalfExtents, getNavigatorFlags(actor), getAreaCosts(actor));
mRotateOnTheRunChecks = 3;

@ -442,4 +442,21 @@ namespace MWMechanics
std::copy(prePath.rbegin(), prePath.rend(), std::front_inserter(mPath));
}
void PathFinder::buildLimitedPath(const MWWorld::ConstPtr& actor, const osg::Vec3f& startPoint, const osg::Vec3f& endPoint,
const MWWorld::CellStore* cell, const PathgridGraph& pathgridGraph, const osg::Vec3f& halfExtents,
const DetourNavigator::Flags flags, const DetourNavigator::AreaCosts& areaCosts)
{
const auto navigator = MWBase::Environment::get().getWorld()->getNavigator();
const auto maxDistance = std::min(
navigator->getMaxNavmeshAreaRealRadius(),
static_cast<float>(Constants::CellSizeInUnits)
);
const auto startToEnd = endPoint - startPoint;
const auto distance = startToEnd.length();
if (distance <= maxDistance)
return buildPath(actor, startPoint, endPoint, cell, pathgridGraph, halfExtents, flags, areaCosts);
const auto end = startPoint + startToEnd * maxDistance / distance;
buildPath(actor, startPoint, end, cell, pathgridGraph, halfExtents, flags, areaCosts);
}
}

@ -101,6 +101,10 @@ namespace MWMechanics
void buildPathByNavMeshToNextPoint(const MWWorld::ConstPtr& actor, const osg::Vec3f& halfExtents,
const DetourNavigator::Flags flags, const DetourNavigator::AreaCosts& areaCosts);
void buildLimitedPath(const MWWorld::ConstPtr& actor, const osg::Vec3f& startPoint, const osg::Vec3f& endPoint,
const MWWorld::CellStore* cell, const PathgridGraph& pathgridGraph, const osg::Vec3f& halfExtents,
const DetourNavigator::Flags flags, const DetourNavigator::AreaCosts& areaCosts);
/// Remove front point if exist and within tolerance
void update(const osg::Vec3f& position, float pointTolerance, float destinationTolerance,
bool shortenIfAlmostStraight, bool canMoveByZ);

@ -235,6 +235,8 @@ namespace DetourNavigator
const osg::Vec3f& end, const Flags includeFlags) const;
virtual RecastMeshTiles getRecastMeshTiles() = 0;
virtual float getMaxNavmeshAreaRealRadius() const = 0;
};
}

@ -213,4 +213,10 @@ namespace DetourNavigator
++it;
}
}
float NavigatorImpl::getMaxNavmeshAreaRealRadius() const
{
const auto& settings = getSettings();
return getRealTileSize(settings) * getMaxNavmeshAreaRadius(settings);
}
}

@ -60,6 +60,8 @@ namespace DetourNavigator
RecastMeshTiles getRecastMeshTiles() override;
float getMaxNavmeshAreaRealRadius() const override;
private:
Settings mSettings;
NavMeshManager mNavMeshManager;

@ -92,6 +92,11 @@ namespace DetourNavigator
return {};
}
float getMaxNavmeshAreaRealRadius() const override
{
return std::numeric_limits<float>::max();
}
private:
Settings mDefaultSettings {};
SharedNavMeshCacheItem mEmptyNavMeshCacheItem;

@ -1,4 +1,4 @@
#ifndef OPENMW_COMPONENTS_DETOURNAVIGATOR_SETTINGSUTILS_H
#ifndef OPENMW_COMPONENTS_DETOURNAVIGATOR_SETTINGSUTILS_H
#define OPENMW_COMPONENTS_DETOURNAVIGATOR_SETTINGSUTILS_H
#include "settings.hpp"
@ -89,6 +89,16 @@ namespace DetourNavigator
transform.getOrigin() + btVector3(0, 0, getSwimLevel(settings, agentHalfExtentsZ) - agentHalfExtentsZ)
);
}
inline float getRealTileSize(const Settings& settings)
{
return settings.mTileSize * settings.mCellSize / settings.mRecastScaleFactor;
}
inline float getMaxNavmeshAreaRadius(const Settings& settings)
{
return std::floor(std::sqrt(settings.mMaxTilesNumber / osg::PI)) - 1;
}
}
#endif

Loading…
Cancel
Save