mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-30 01:45:33 +00:00
Use status codes to handle navigator errors instead of exceptions
For find path use case.
This commit is contained in:
parent
d5cee5aea9
commit
349040ffb2
7 changed files with 163 additions and 87 deletions
|
@ -341,21 +341,23 @@ namespace MWMechanics
|
|||
const osg::Vec3f& endPoint, const osg::Vec3f& halfExtents, const DetourNavigator::Flags flags,
|
||||
std::back_insert_iterator<std::deque<osg::Vec3f>> out)
|
||||
{
|
||||
try
|
||||
const auto world = MWBase::Environment::get().getWorld();
|
||||
const auto stepSize = getPathStepSize(actor);
|
||||
const auto navigator = world->getNavigator();
|
||||
const auto status = navigator->findPath(halfExtents, stepSize, startPoint, endPoint, flags, out);
|
||||
|
||||
if (status == DetourNavigator::Status::NavMeshNotFound)
|
||||
return false;
|
||||
|
||||
if (status != DetourNavigator::Status::Success)
|
||||
{
|
||||
const auto world = MWBase::Environment::get().getWorld();
|
||||
const auto stepSize = getPathStepSize(actor);
|
||||
const auto navigator = world->getNavigator();
|
||||
return navigator->findPath(halfExtents, stepSize, startPoint, endPoint, flags, out).is_initialized();
|
||||
}
|
||||
catch (const DetourNavigator::NavigatorException& exception)
|
||||
{
|
||||
Log(Debug::Debug) << "Build path by navigator exception: \"" << exception.what()
|
||||
Log(Debug::Debug) << "Build path by navigator error: \"" << DetourNavigator::getMessage(status)
|
||||
<< "\" for \"" << actor.getClass().getName(actor) << "\" (" << actor.getBase()
|
||||
<< ") from " << startPoint << " to " << endPoint << " with flags ("
|
||||
<< DetourNavigator::WriteFlags {flags} << ")";
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PathFinder::buildPathByNavMeshToNextPoint(const MWWorld::ConstPtr& actor, const osg::Vec3f& halfExtents,
|
||||
|
@ -370,26 +372,30 @@ namespace MWMechanics
|
|||
if (sqrDistanceIgnoreZ(mPath.front(), startPoint) <= 4 * stepSize * stepSize)
|
||||
return;
|
||||
|
||||
try
|
||||
const auto navigator = MWBase::Environment::get().getWorld()->getNavigator();
|
||||
std::deque<osg::Vec3f> prePath;
|
||||
auto prePathInserter = std::back_inserter(prePath);
|
||||
const auto status = navigator->findPath(halfExtents, stepSize, startPoint, mPath.front(), flags,
|
||||
prePathInserter);
|
||||
|
||||
if (status == DetourNavigator::Status::NavMeshNotFound)
|
||||
return;
|
||||
|
||||
if (status != DetourNavigator::Status::Success)
|
||||
{
|
||||
const auto navigator = MWBase::Environment::get().getWorld()->getNavigator();
|
||||
std::deque<osg::Vec3f> prePath;
|
||||
navigator->findPath(halfExtents, stepSize, startPoint, mPath.front(), flags, std::back_inserter(prePath));
|
||||
|
||||
while (!prePath.empty() && sqrDistanceIgnoreZ(prePath.front(), startPoint) < stepSize * stepSize)
|
||||
prePath.pop_front();
|
||||
|
||||
while (!prePath.empty() && sqrDistanceIgnoreZ(prePath.back(), mPath.front()) < stepSize * stepSize)
|
||||
prePath.pop_back();
|
||||
|
||||
std::copy(prePath.rbegin(), prePath.rend(), std::front_inserter(mPath));
|
||||
}
|
||||
catch (const DetourNavigator::NavigatorException& exception)
|
||||
{
|
||||
Log(Debug::Debug) << "Build path by navigator exception: \"" << exception.what()
|
||||
Log(Debug::Debug) << "Build path by navigator error: \"" << DetourNavigator::getMessage(status)
|
||||
<< "\" for \"" << actor.getClass().getName(actor) << "\" (" << actor.getBase()
|
||||
<< ") from " << startPoint << " to " << mPath.front() << " with flags ("
|
||||
<< DetourNavigator::WriteFlags {flags} << ")";
|
||||
return;
|
||||
}
|
||||
|
||||
while (!prePath.empty() && sqrDistanceIgnoreZ(prePath.front(), startPoint) < stepSize * stepSize)
|
||||
prePath.pop_front();
|
||||
|
||||
while (!prePath.empty() && sqrDistanceIgnoreZ(prePath.back(), mPath.front()) < stepSize * stepSize)
|
||||
prePath.pop_back();
|
||||
|
||||
std::copy(prePath.rbegin(), prePath.rend(), std::front_inserter(mPath));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -73,14 +73,16 @@ namespace
|
|||
|
||||
TEST_F(DetourNavigatorNavigatorTest, find_path_for_empty_should_return_empty)
|
||||
{
|
||||
mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mOut);
|
||||
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mOut),
|
||||
Status::NavMeshNotFound);
|
||||
EXPECT_EQ(mPath, std::deque<osg::Vec3f>());
|
||||
}
|
||||
|
||||
TEST_F(DetourNavigatorNavigatorTest, find_path_for_existing_agent_with_no_navmesh_should_throw_exception)
|
||||
{
|
||||
mNavigator->addAgent(mAgentHalfExtents);
|
||||
EXPECT_THROW(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mOut), NavigatorException);
|
||||
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mOut),
|
||||
Status::StartPolygonNotFound);
|
||||
}
|
||||
|
||||
TEST_F(DetourNavigatorNavigatorTest, add_agent_should_count_each_agent)
|
||||
|
@ -88,7 +90,8 @@ namespace
|
|||
mNavigator->addAgent(mAgentHalfExtents);
|
||||
mNavigator->addAgent(mAgentHalfExtents);
|
||||
mNavigator->removeAgent(mAgentHalfExtents);
|
||||
EXPECT_THROW(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mOut), NavigatorException);
|
||||
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mOut),
|
||||
Status::StartPolygonNotFound);
|
||||
}
|
||||
|
||||
TEST_F(DetourNavigatorNavigatorTest, update_then_find_path_should_return_path)
|
||||
|
@ -108,7 +111,7 @@ namespace
|
|||
mNavigator->update(mPlayerPosition);
|
||||
mNavigator->wait();
|
||||
|
||||
mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mOut);
|
||||
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mOut), Status::Success);
|
||||
|
||||
EXPECT_EQ(mPath, std::deque<osg::Vec3f>({
|
||||
osg::Vec3f(-215, 215, 1.85963428020477294921875),
|
||||
|
@ -158,7 +161,7 @@ namespace
|
|||
mNavigator->update(mPlayerPosition);
|
||||
mNavigator->wait();
|
||||
|
||||
mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, std::back_inserter(mPath));
|
||||
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mOut), Status::Success);
|
||||
|
||||
EXPECT_EQ(mPath, std::deque<osg::Vec3f>({
|
||||
osg::Vec3f(-215, 215, 1.85963428020477294921875),
|
||||
|
@ -191,7 +194,8 @@ namespace
|
|||
mNavigator->wait();
|
||||
|
||||
mPath.clear();
|
||||
mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, std::back_inserter(mPath));
|
||||
mOut = std::back_inserter(mPath);
|
||||
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mOut), Status::Success);
|
||||
|
||||
EXPECT_EQ(mPath, std::deque<osg::Vec3f>({
|
||||
osg::Vec3f(-215, 215, 1.87826788425445556640625),
|
||||
|
@ -242,7 +246,7 @@ namespace
|
|||
mNavigator->update(mPlayerPosition);
|
||||
mNavigator->wait();
|
||||
|
||||
mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, std::back_inserter(mPath));
|
||||
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mOut), Status::Success);
|
||||
|
||||
EXPECT_EQ(mPath, std::deque<osg::Vec3f>({
|
||||
osg::Vec3f(-215, 215, 1.87826788425445556640625),
|
||||
|
@ -277,7 +281,8 @@ namespace
|
|||
mNavigator->wait();
|
||||
|
||||
mPath.clear();
|
||||
mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mOut);
|
||||
mOut = std::back_inserter(mPath);
|
||||
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mOut), Status::Success);
|
||||
|
||||
EXPECT_EQ(mPath, std::deque<osg::Vec3f>({
|
||||
osg::Vec3f(-215, 215, 1.85963428020477294921875),
|
||||
|
@ -334,7 +339,7 @@ namespace
|
|||
mNavigator->update(mPlayerPosition);
|
||||
mNavigator->wait();
|
||||
|
||||
mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mOut);
|
||||
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mOut), Status::Success);
|
||||
|
||||
EXPECT_EQ(mPath, std::deque<osg::Vec3f>({
|
||||
osg::Vec3f(-215, 215, 1.96328866481781005859375),
|
||||
|
@ -390,7 +395,7 @@ namespace
|
|||
mNavigator->update(mPlayerPosition);
|
||||
mNavigator->wait();
|
||||
|
||||
mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mOut);
|
||||
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mOut), Status::Success);
|
||||
|
||||
EXPECT_EQ(mPath, std::deque<osg::Vec3f>({
|
||||
osg::Vec3f(-215, 215, 1.9393787384033203125),
|
||||
|
@ -443,7 +448,7 @@ namespace
|
|||
mEnd.x() = 0;
|
||||
mEnd.z() = 300;
|
||||
|
||||
mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_swim, mOut);
|
||||
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_swim, mOut), Status::Success);
|
||||
|
||||
EXPECT_EQ(mPath, std::deque<osg::Vec3f>({
|
||||
osg::Vec3f(0, 215, 185.33331298828125),
|
||||
|
@ -489,7 +494,8 @@ namespace
|
|||
mStart.x() = 0;
|
||||
mEnd.x() = 0;
|
||||
|
||||
mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_swim | Flag_walk, mOut);
|
||||
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_swim | Flag_walk, mOut),
|
||||
Status::Success);
|
||||
|
||||
EXPECT_EQ(mPath, std::deque<osg::Vec3f>({
|
||||
osg::Vec3f(0, 215, -94.75363922119140625),
|
||||
|
@ -535,7 +541,8 @@ namespace
|
|||
mStart.x() = 0;
|
||||
mEnd.x() = 0;
|
||||
|
||||
mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_swim | Flag_walk, mOut);
|
||||
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_swim | Flag_walk, mOut),
|
||||
Status::Success);
|
||||
|
||||
EXPECT_EQ(mPath, std::deque<osg::Vec3f>({
|
||||
osg::Vec3f(0, 215, -94.75363922119140625),
|
||||
|
@ -581,7 +588,7 @@ namespace
|
|||
mStart.x() = 0;
|
||||
mEnd.x() = 0;
|
||||
|
||||
mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mOut);
|
||||
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mOut), Status::Success);
|
||||
|
||||
EXPECT_EQ(mPath, std::deque<osg::Vec3f>({
|
||||
osg::Vec3f(0, 215, -94.75363922119140625),
|
||||
|
@ -630,7 +637,7 @@ namespace
|
|||
mNavigator->update(mPlayerPosition);
|
||||
mNavigator->wait();
|
||||
|
||||
mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mOut);
|
||||
EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mOut), Status::Success);
|
||||
|
||||
EXPECT_EQ(mPath, std::deque<osg::Vec3f>({
|
||||
osg::Vec3f(-215, 215, 1.85963428020477294921875),
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define OPENMW_COMPONENTS_DETOURNAVIGATOR_DEBUG_H
|
||||
|
||||
#include "tilebounds.hpp"
|
||||
#include "status.hpp"
|
||||
|
||||
#include <osg/io_utils>
|
||||
|
||||
|
@ -26,6 +27,25 @@ namespace DetourNavigator
|
|||
return stream << "TileBounds {" << value.mMin << ", " << value.mMax << "}";
|
||||
}
|
||||
|
||||
inline std::ostream& operator <<(std::ostream& stream, Status value)
|
||||
{
|
||||
#define OPENMW_COMPONENTS_DETOURNAVIGATOR_DEBUG_STATUS_MESSAGE(name) \
|
||||
case Status::name: return stream << "DetourNavigator::Status::"#name;
|
||||
switch (value)
|
||||
{
|
||||
OPENMW_COMPONENTS_DETOURNAVIGATOR_DEBUG_STATUS_MESSAGE(Success)
|
||||
OPENMW_COMPONENTS_DETOURNAVIGATOR_DEBUG_STATUS_MESSAGE(NavMeshNotFound)
|
||||
OPENMW_COMPONENTS_DETOURNAVIGATOR_DEBUG_STATUS_MESSAGE(StartPolygonNotFound)
|
||||
OPENMW_COMPONENTS_DETOURNAVIGATOR_DEBUG_STATUS_MESSAGE(EndPolygonNotFound)
|
||||
OPENMW_COMPONENTS_DETOURNAVIGATOR_DEBUG_STATUS_MESSAGE(MoveAlongSurfaceFailed)
|
||||
OPENMW_COMPONENTS_DETOURNAVIGATOR_DEBUG_STATUS_MESSAGE(FindPathOverPolygonsFailed)
|
||||
OPENMW_COMPONENTS_DETOURNAVIGATOR_DEBUG_STATUS_MESSAGE(GetPolyHeightFailed)
|
||||
OPENMW_COMPONENTS_DETOURNAVIGATOR_DEBUG_STATUS_MESSAGE(InitNavMeshQueryFailed)
|
||||
}
|
||||
#undef OPENMW_COMPONENTS_DETOURNAVIGATOR_DEBUG_STATUS_MESSAGE
|
||||
return stream << "DetourNavigator::Error::" << static_cast<int>(value);
|
||||
}
|
||||
|
||||
class RecastMesh;
|
||||
|
||||
void writeToFile(const RecastMesh& recastMesh, const std::string& pathPrefix, const std::string& revision);
|
||||
|
|
|
@ -14,7 +14,8 @@ namespace DetourNavigator
|
|||
const osg::Vec3f& start, const float maxRadius, const Flags includeFlags, const Settings& settings)
|
||||
{
|
||||
dtNavMeshQuery navMeshQuery;
|
||||
initNavMeshQuery(navMeshQuery, navMesh, settings.mMaxNavMeshQueryNodes);
|
||||
if (!initNavMeshQuery(navMeshQuery, navMesh, settings.mMaxNavMeshQueryNodes))
|
||||
return boost::optional<osg::Vec3f>();
|
||||
|
||||
dtQueryFilter queryFilter;
|
||||
queryFilter.setIncludeFlags(includeFlags);
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "settings.hpp"
|
||||
#include "settingsutils.hpp"
|
||||
#include "debug.hpp"
|
||||
#include "status.hpp"
|
||||
|
||||
#include <DetourCommon.h>
|
||||
#include <DetourNavMesh.h>
|
||||
|
@ -97,11 +98,10 @@ namespace DetourNavigator
|
|||
std::reference_wrapper<const Settings> mSettings;
|
||||
};
|
||||
|
||||
inline void initNavMeshQuery(dtNavMeshQuery& value, const dtNavMesh& navMesh, const int maxNodes)
|
||||
inline bool initNavMeshQuery(dtNavMeshQuery& value, const dtNavMesh& navMesh, const int maxNodes)
|
||||
{
|
||||
const auto status = value.init(&navMesh, maxNodes);
|
||||
if (!dtStatusSucceed(status))
|
||||
throw NavigatorException("Failed to init navmesh query");
|
||||
return dtStatusSucceed(status);
|
||||
}
|
||||
|
||||
struct MoveAlongSurfaceResult
|
||||
|
@ -110,8 +110,8 @@ namespace DetourNavigator
|
|||
std::vector<dtPolyRef> mVisited;
|
||||
};
|
||||
|
||||
inline MoveAlongSurfaceResult moveAlongSurface(const dtNavMeshQuery& navMeshQuery, const dtPolyRef startRef,
|
||||
const osg::Vec3f& startPos, const osg::Vec3f& endPos, const dtQueryFilter& filter,
|
||||
inline boost::optional<MoveAlongSurfaceResult> moveAlongSurface(const dtNavMeshQuery& navMeshQuery,
|
||||
const dtPolyRef startRef, const osg::Vec3f& startPos, const osg::Vec3f& endPos, const dtQueryFilter& filter,
|
||||
const std::size_t maxVisitedSize)
|
||||
{
|
||||
MoveAlongSurfaceResult result;
|
||||
|
@ -120,18 +120,14 @@ namespace DetourNavigator
|
|||
const auto status = navMeshQuery.moveAlongSurface(startRef, startPos.ptr(), endPos.ptr(),
|
||||
&filter, result.mResultPos.ptr(), result.mVisited.data(), &visitedNumber, static_cast<int>(maxVisitedSize));
|
||||
if (!dtStatusSucceed(status))
|
||||
{
|
||||
std::ostringstream message;
|
||||
message << "Failed to move along surface from " << startPos << " to " << endPos;
|
||||
throw NavigatorException(message.str());
|
||||
}
|
||||
return {};
|
||||
assert(visitedNumber >= 0);
|
||||
assert(visitedNumber <= static_cast<int>(maxVisitedSize));
|
||||
result.mVisited.resize(static_cast<std::size_t>(visitedNumber));
|
||||
return result;
|
||||
return {std::move(result)};
|
||||
}
|
||||
|
||||
inline std::vector<dtPolyRef> findPath(const dtNavMeshQuery& navMeshQuery, const dtPolyRef startRef,
|
||||
inline boost::optional<std::vector<dtPolyRef>> findPath(const dtNavMeshQuery& navMeshQuery, const dtPolyRef startRef,
|
||||
const dtPolyRef endRef, const osg::Vec3f& startPos, const osg::Vec3f& endPos, const dtQueryFilter& queryFilter,
|
||||
const std::size_t maxSize)
|
||||
{
|
||||
|
@ -140,34 +136,26 @@ namespace DetourNavigator
|
|||
const auto status = navMeshQuery.findPath(startRef, endRef, startPos.ptr(), endPos.ptr(), &queryFilter,
|
||||
result.data(), &pathLen, static_cast<int>(maxSize));
|
||||
if (!dtStatusSucceed(status))
|
||||
{
|
||||
std::ostringstream message;
|
||||
message << "Failed to find path over polygons from " << startRef << " to " << endRef;
|
||||
throw NavigatorException(message.str());
|
||||
}
|
||||
return {};
|
||||
assert(pathLen >= 0);
|
||||
assert(static_cast<std::size_t>(pathLen) <= maxSize);
|
||||
result.resize(static_cast<std::size_t>(pathLen));
|
||||
return result;
|
||||
return {std::move(result)};
|
||||
}
|
||||
|
||||
inline float getPolyHeight(const dtNavMeshQuery& navMeshQuery, const dtPolyRef ref, const osg::Vec3f& pos)
|
||||
inline boost::optional<float> getPolyHeight(const dtNavMeshQuery& navMeshQuery, const dtPolyRef ref, const osg::Vec3f& pos)
|
||||
{
|
||||
float result = 0.0f;
|
||||
const auto status = navMeshQuery.getPolyHeight(ref, pos.ptr(), &result);
|
||||
if (!dtStatusSucceed(status))
|
||||
{
|
||||
std::ostringstream message;
|
||||
message << "Failed to get polygon height ref=" << ref << " pos=" << pos;
|
||||
throw NavigatorException(message.str());
|
||||
}
|
||||
return {};
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class OutputIterator>
|
||||
OutputIterator makeSmoothPath(const dtNavMesh& navMesh, const dtNavMeshQuery& navMeshQuery,
|
||||
Status makeSmoothPath(const dtNavMesh& navMesh, const dtNavMeshQuery& navMeshQuery,
|
||||
const dtQueryFilter& filter, const osg::Vec3f& start, const osg::Vec3f& end, const float stepSize,
|
||||
std::vector<dtPolyRef> polygonPath, std::size_t maxSmoothPathSize, OutputIterator out)
|
||||
std::vector<dtPolyRef> polygonPath, std::size_t maxSmoothPathSize, OutputIterator& out)
|
||||
{
|
||||
// Iterate over the path to find smooth path on the detail mesh surface.
|
||||
osg::Vec3f iterPos;
|
||||
|
@ -207,12 +195,15 @@ namespace DetourNavigator
|
|||
const osg::Vec3f moveTgt = iterPos + delta * len;
|
||||
const auto result = moveAlongSurface(navMeshQuery, polygonPath.front(), iterPos, moveTgt, filter, 16);
|
||||
|
||||
polygonPath = fixupCorridor(polygonPath, result.mVisited);
|
||||
if (!result)
|
||||
return Status::MoveAlongSurfaceFailed;
|
||||
|
||||
polygonPath = fixupCorridor(polygonPath, result->mVisited);
|
||||
polygonPath = fixupShortcuts(polygonPath, navMeshQuery);
|
||||
|
||||
float h = 0;
|
||||
navMeshQuery.getPolyHeight(polygonPath.front(), result.mResultPos.ptr(), &h);
|
||||
iterPos = result.mResultPos;
|
||||
navMeshQuery.getPolyHeight(polygonPath.front(), result->mResultPos.ptr(), &h);
|
||||
iterPos = result->mResultPos;
|
||||
iterPos.y() = h;
|
||||
|
||||
// Handle end of path and off-mesh links when close enough.
|
||||
|
@ -259,7 +250,12 @@ namespace DetourNavigator
|
|||
|
||||
// Move position at the other side of the off-mesh link.
|
||||
iterPos = endPos;
|
||||
iterPos.y() = getPolyHeight(navMeshQuery, polygonPath.front(), iterPos);
|
||||
const auto height = getPolyHeight(navMeshQuery, polygonPath.front(), iterPos);
|
||||
|
||||
if (!height)
|
||||
return Status::GetPolyHeightFailed;
|
||||
|
||||
iterPos.y() = *height;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -268,16 +264,17 @@ namespace DetourNavigator
|
|||
++smoothPathSize;
|
||||
}
|
||||
|
||||
return out;
|
||||
return Status::Success;
|
||||
}
|
||||
|
||||
template <class OutputIterator>
|
||||
OutputIterator findSmoothPath(const dtNavMesh& navMesh, const osg::Vec3f& halfExtents, const float stepSize,
|
||||
Status findSmoothPath(const dtNavMesh& navMesh, const osg::Vec3f& halfExtents, const float stepSize,
|
||||
const osg::Vec3f& start, const osg::Vec3f& end, const Flags includeFlags,
|
||||
const Settings& settings, OutputIterator out)
|
||||
const Settings& settings, OutputIterator& out)
|
||||
{
|
||||
dtNavMeshQuery navMeshQuery;
|
||||
initNavMeshQuery(navMeshQuery, navMesh, settings.mMaxNavMeshQueryNodes);
|
||||
if (!initNavMeshQuery(navMeshQuery, navMesh, settings.mMaxNavMeshQueryNodes))
|
||||
return Status::InitNavMeshQueryFailed;
|
||||
|
||||
dtQueryFilter queryFilter;
|
||||
queryFilter.setIncludeFlags(includeFlags);
|
||||
|
@ -293,7 +290,7 @@ namespace DetourNavigator
|
|||
}
|
||||
|
||||
if (startRef == 0)
|
||||
throw NavigatorException("Navmesh polygon for start point is not found");
|
||||
return Status::StartPolygonNotFound;
|
||||
|
||||
dtPolyRef endRef = 0;
|
||||
osg::Vec3f endPolygonPosition;
|
||||
|
@ -306,18 +303,20 @@ namespace DetourNavigator
|
|||
}
|
||||
|
||||
if (endRef == 0)
|
||||
throw NavigatorException("Navmesh polygon for end polygon is not found");
|
||||
return Status::EndPolygonNotFound;
|
||||
|
||||
const auto polygonPath = findPath(navMeshQuery, startRef, endRef, start, end, queryFilter,
|
||||
settings.mMaxPolygonPathSize);
|
||||
|
||||
if (polygonPath.empty() || polygonPath.back() != endRef)
|
||||
return out;
|
||||
if (!polygonPath)
|
||||
return Status::FindPathOverPolygonsFailed;
|
||||
|
||||
makeSmoothPath(navMesh, navMeshQuery, queryFilter, start, end, stepSize, std::move(polygonPath),
|
||||
settings.mMaxSmoothPathSize, OutputTransformIterator<OutputIterator>(out, settings));
|
||||
if (polygonPath->empty() || polygonPath->back() != endRef)
|
||||
return Status::Success;
|
||||
|
||||
return out;
|
||||
auto outTransform = OutputTransformIterator<OutputIterator>(out, settings);
|
||||
return makeSmoothPath(navMesh, navMeshQuery, queryFilter, start, end, stepSize, std::move(*polygonPath),
|
||||
settings.mMaxSmoothPathSize, outTransform);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#ifndef OPENMW_COMPONENTS_DETOURNAVIGATOR_NAVIGATOR_H
|
||||
#ifndef OPENMW_COMPONENTS_DETOURNAVIGATOR_NAVIGATOR_H
|
||||
#define OPENMW_COMPONENTS_DETOURNAVIGATOR_NAVIGATOR_H
|
||||
|
||||
#include "findsmoothpath.hpp"
|
||||
|
@ -159,8 +159,8 @@ namespace DetourNavigator
|
|||
* Equal to out if no path is found.
|
||||
*/
|
||||
template <class OutputIterator>
|
||||
boost::optional<OutputIterator> findPath(const osg::Vec3f& agentHalfExtents, const float stepSize, const osg::Vec3f& start,
|
||||
const osg::Vec3f& end, const Flags includeFlags, OutputIterator out) const
|
||||
Status findPath(const osg::Vec3f& agentHalfExtents, const float stepSize, const osg::Vec3f& start,
|
||||
const osg::Vec3f& end, const Flags includeFlags, OutputIterator& out) const
|
||||
{
|
||||
static_assert(
|
||||
std::is_same<
|
||||
|
@ -171,7 +171,7 @@ namespace DetourNavigator
|
|||
);
|
||||
const auto navMesh = getNavMesh(agentHalfExtents);
|
||||
if (!navMesh)
|
||||
return {};
|
||||
return Status::NavMeshNotFound;
|
||||
const auto settings = getSettings();
|
||||
return findSmoothPath(navMesh->lockConst()->getImpl(), toNavMeshCoordinates(settings, agentHalfExtents),
|
||||
toNavMeshCoordinates(settings, stepSize), toNavMeshCoordinates(settings, start),
|
||||
|
|
43
components/detournavigator/status.hpp
Normal file
43
components/detournavigator/status.hpp
Normal file
|
@ -0,0 +1,43 @@
|
|||
#ifndef OPENMW_COMPONENTS_DETOURNAVIGATOR_STATUS_H
|
||||
#define OPENMW_COMPONENTS_DETOURNAVIGATOR_STATUS_H
|
||||
|
||||
namespace DetourNavigator
|
||||
{
|
||||
enum class Status
|
||||
{
|
||||
Success,
|
||||
NavMeshNotFound,
|
||||
StartPolygonNotFound,
|
||||
EndPolygonNotFound,
|
||||
MoveAlongSurfaceFailed,
|
||||
FindPathOverPolygonsFailed,
|
||||
GetPolyHeightFailed,
|
||||
InitNavMeshQueryFailed,
|
||||
};
|
||||
|
||||
constexpr const char* getMessage(Status value)
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case Status::Success:
|
||||
return "success";
|
||||
case Status::NavMeshNotFound:
|
||||
return "navmesh is not found";
|
||||
case Status::StartPolygonNotFound:
|
||||
return "polygon for start position is not found on navmesh";
|
||||
case Status::EndPolygonNotFound:
|
||||
return "polygon for end position is not found on navmesh";
|
||||
case Status::MoveAlongSurfaceFailed:
|
||||
return "move along surface on navmesh is failed";
|
||||
case Status::FindPathOverPolygonsFailed:
|
||||
return "path over navmesh polygons is not found";
|
||||
case Status::GetPolyHeightFailed:
|
||||
return "failed to get polygon height";
|
||||
case Status::InitNavMeshQueryFailed:
|
||||
return "failed to init navmesh query";
|
||||
}
|
||||
return "unknown error";
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue