From bb393cb91c42bb9617e94b77e5dea89e72ad064a Mon Sep 17 00:00:00 2001 From: psi29a Date: Thu, 1 Jul 2021 08:59:13 +0000 Subject: [PATCH] Merge branch 'fix_new_game_guard_3' into 'master' Fix new game guard 3 (#6126) Closes #6126 See merge request OpenMW/openmw!976 (cherry picked from commit 89ca56632c6bc37f07e430e7f5cd23d855610b19) a3942a1e Remove redundant check for y coordinate in inRange function cc08a45c Move include where it is needed 7e1630a7 Remove redundant getPolyHeight wrapper 793c30ab Check dtNavMeshQuery::getPolyHeight status a54c4bc2 Check dtNavMeshQuery::findStraightPath status 94e460ba Use proper check for distance 5624fe19 Consider path not found when there is navmesh query error --- apps/openmw/mwmechanics/pathfinding.cpp | 33 ++++++++++----- apps/openmw/mwmechanics/pathfinding.hpp | 8 ++-- components/detournavigator/findsmoothpath.cpp | 13 ++++-- components/detournavigator/findsmoothpath.hpp | 40 ++++++------------- 4 files changed, 49 insertions(+), 45 deletions(-) diff --git a/apps/openmw/mwmechanics/pathfinding.cpp b/apps/openmw/mwmechanics/pathfinding.cpp index f6283831d..2f8e83043 100644 --- a/apps/openmw/mwmechanics/pathfinding.cpp +++ b/apps/openmw/mwmechanics/pathfinding.cpp @@ -369,7 +369,13 @@ namespace MWMechanics mPath.clear(); // If it's not possible to build path over navmesh due to disabled navmesh generation fallback to straight path - if (!buildPathByNavigatorImpl(actor, startPoint, endPoint, halfExtents, flags, areaCosts, std::back_inserter(mPath))) + DetourNavigator::Status status = buildPathByNavigatorImpl(actor, startPoint, endPoint, halfExtents, flags, + areaCosts, std::back_inserter(mPath)); + + if (status != DetourNavigator::Status::Success) + mPath.clear(); + + if (status == DetourNavigator::Status::NavMeshNotFound) mPath.push_back(endPoint); mConstructed = !mPath.empty(); @@ -382,25 +388,33 @@ namespace MWMechanics mPath.clear(); mCell = cell; - bool hasNavMesh = false; + DetourNavigator::Status status = DetourNavigator::Status::NavMeshNotFound; if (!actor.getClass().isPureWaterCreature(actor) && !actor.getClass().isPureFlyingCreature(actor)) - hasNavMesh = buildPathByNavigatorImpl(actor, startPoint, endPoint, halfExtents, flags, areaCosts, std::back_inserter(mPath)); + { + status = buildPathByNavigatorImpl(actor, startPoint, endPoint, halfExtents, flags, areaCosts, std::back_inserter(mPath)); + if (status != DetourNavigator::Status::Success) + mPath.clear(); + } - if (hasNavMesh && mPath.empty()) - buildPathByNavigatorImpl(actor, startPoint, endPoint, halfExtents, + if (status != DetourNavigator::Status::NavMeshNotFound && mPath.empty()) + { + status = buildPathByNavigatorImpl(actor, startPoint, endPoint, halfExtents, flags | DetourNavigator::Flag_usePathgrid, areaCosts, std::back_inserter(mPath)); + if (status != DetourNavigator::Status::Success) + mPath.clear(); + } if (mPath.empty()) buildPathByPathgridImpl(startPoint, endPoint, pathgridGraph, std::back_inserter(mPath)); - if (!hasNavMesh && mPath.empty()) + if (status == DetourNavigator::Status::NavMeshNotFound && mPath.empty()) mPath.push_back(endPoint); mConstructed = !mPath.empty(); } - bool PathFinder::buildPathByNavigatorImpl(const MWWorld::ConstPtr& actor, const osg::Vec3f& startPoint, + DetourNavigator::Status PathFinder::buildPathByNavigatorImpl(const MWWorld::ConstPtr& actor, const osg::Vec3f& startPoint, const osg::Vec3f& endPoint, const osg::Vec3f& halfExtents, const DetourNavigator::Flags flags, const DetourNavigator::AreaCosts& areaCosts, std::back_insert_iterator> out) { @@ -409,9 +423,6 @@ namespace MWMechanics const auto navigator = world->getNavigator(); const auto status = navigator->findPath(halfExtents, stepSize, startPoint, endPoint, flags, areaCosts, out); - if (status == DetourNavigator::Status::NavMeshNotFound) - return false; - if (status != DetourNavigator::Status::Success) { Log(Debug::Debug) << "Build path by navigator error: \"" << DetourNavigator::getMessage(status) @@ -420,7 +431,7 @@ namespace MWMechanics << DetourNavigator::WriteFlags {flags} << ")"; } - return true; + return status; } void PathFinder::buildPathByNavMeshToNextPoint(const MWWorld::ConstPtr& actor, const osg::Vec3f& halfExtents, diff --git a/apps/openmw/mwmechanics/pathfinding.hpp b/apps/openmw/mwmechanics/pathfinding.hpp index 987f2c660..0d281d1e2 100644 --- a/apps/openmw/mwmechanics/pathfinding.hpp +++ b/apps/openmw/mwmechanics/pathfinding.hpp @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -209,9 +210,10 @@ namespace MWMechanics void buildPathByPathgridImpl(const osg::Vec3f& startPoint, const osg::Vec3f& endPoint, const PathgridGraph& pathgridGraph, std::back_insert_iterator> out); - bool buildPathByNavigatorImpl(const MWWorld::ConstPtr& actor, const osg::Vec3f& startPoint, - const osg::Vec3f& endPoint, const osg::Vec3f& halfExtents, const DetourNavigator::Flags flags, - const DetourNavigator::AreaCosts& areaCosts, std::back_insert_iterator> out); + [[nodiscard]] DetourNavigator::Status buildPathByNavigatorImpl(const MWWorld::ConstPtr& actor, + const osg::Vec3f& startPoint, const osg::Vec3f& endPoint, const osg::Vec3f& halfExtents, + const DetourNavigator::Flags flags, const DetourNavigator::AreaCosts& areaCosts, + std::back_insert_iterator> out); }; } diff --git a/components/detournavigator/findsmoothpath.cpp b/components/detournavigator/findsmoothpath.cpp index 8974be532..659826339 100644 --- a/components/detournavigator/findsmoothpath.cpp +++ b/components/detournavigator/findsmoothpath.cpp @@ -1,5 +1,7 @@ #include "findsmoothpath.hpp" +#include + #include #include @@ -103,7 +105,7 @@ namespace DetourNavigator return result; } - std::optional getSteerTarget(const dtNavMeshQuery& navQuery, const osg::Vec3f& startPos, + std::optional getSteerTarget(const dtNavMeshQuery& navMeshQuery, const osg::Vec3f& startPos, const osg::Vec3f& endPos, const float minTargetDist, const std::vector& path) { // Find steer target. @@ -113,8 +115,11 @@ namespace DetourNavigator std::array steerPathFlags; std::array steerPathPolys; int nsteerPath = 0; - navQuery.findStraightPath(startPos.ptr(), endPos.ptr(), path.data(), int(path.size()), steerPath.data(), - steerPathFlags.data(), steerPathPolys.data(), &nsteerPath, maxSteerPoints); + const dtStatus status = navMeshQuery.findStraightPath(startPos.ptr(), endPos.ptr(), path.data(), + static_cast(path.size()), steerPath.data(), steerPathFlags.data(), steerPathPolys.data(), + &nsteerPath, maxSteerPoints); + if (dtStatusFailed(status)) + return std::nullopt; assert(nsteerPath >= 0); if (!nsteerPath) return std::nullopt; @@ -125,7 +130,7 @@ namespace DetourNavigator { // Stop at Off-Mesh link or when point is further than slop away. if ((steerPathFlags[ns] & DT_STRAIGHTPATH_OFFMESH_CONNECTION) || - !inRange(Misc::Convert::makeOsgVec3f(&steerPath[ns * 3]), startPos, minTargetDist, 1000.0f)) + !inRange(Misc::Convert::makeOsgVec3f(&steerPath[ns * 3]), startPos, minTargetDist)) break; ns++; } diff --git a/components/detournavigator/findsmoothpath.hpp b/components/detournavigator/findsmoothpath.hpp index 0a9b5bed8..db2219b2c 100644 --- a/components/detournavigator/findsmoothpath.hpp +++ b/components/detournavigator/findsmoothpath.hpp @@ -14,9 +14,8 @@ #include #include -#include - #include + #include #include @@ -26,10 +25,9 @@ namespace DetourNavigator { struct Settings; - inline bool inRange(const osg::Vec3f& v1, const osg::Vec3f& v2, const float r, const float h) + inline bool inRange(const osg::Vec3f& v1, const osg::Vec3f& v2, const float r) { - const auto d = v2 - v1; - return (d.x() * d.x() + d.z() * d.z()) < r * r && std::abs(d.y()) < h; + return (osg::Vec2f(v1.x(), v1.z()) - osg::Vec2f(v2.x(), v2.z())).length() < r; } std::vector fixupCorridor(const std::vector& path, const std::vector& visited); @@ -143,15 +141,6 @@ namespace DetourNavigator return {std::move(result)}; } - inline std::optional 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)) - return {}; - return result; - } - template Status makeSmoothPath(const dtNavMesh& navMesh, const dtNavMeshQuery& navMeshQuery, const dtQueryFilter& filter, const osg::Vec3f& start, const osg::Vec3f& end, const float stepSize, @@ -201,13 +190,8 @@ namespace DetourNavigator polygonPath = fixupCorridor(polygonPath, result->mVisited); polygonPath = fixupShortcuts(polygonPath, navMeshQuery); - float h = 0; - 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. - if (endOfPath && inRange(iterPos, steerTarget->steerPos, slop, 1.0f)) + if (endOfPath && inRange(result->mResultPos, steerTarget->steerPos, slop)) { // Reached end of path. iterPos = targetPos; @@ -215,7 +199,7 @@ namespace DetourNavigator ++smoothPathSize; break; } - else if (offMeshConnection && inRange(iterPos, steerTarget->steerPos, slop, 1.0f)) + else if (offMeshConnection && inRange(result->mResultPos, steerTarget->steerPos, slop)) { // Advance the path up to and over the off-mesh connection. dtPolyRef prevRef = 0; @@ -249,16 +233,18 @@ namespace DetourNavigator } // Move position at the other side of the off-mesh link. - iterPos = endPos; - const auto height = getPolyHeight(navMeshQuery, polygonPath.front(), iterPos); - - if (!height) + if (dtStatusFailed(navMeshQuery.getPolyHeight(polygonPath.front(), endPos.ptr(), &iterPos.y()))) return Status::GetPolyHeightFailed; - - iterPos.y() = *height; + iterPos.x() = endPos.x(); + iterPos.z() = endPos.z(); } } + if (dtStatusFailed(navMeshQuery.getPolyHeight(polygonPath.front(), result->mResultPos.ptr(), &iterPos.y()))) + return Status::GetPolyHeightFailed; + iterPos.x() = result->mResultPos.x(); + iterPos.z() = result->mResultPos.z(); + // Store results. *out++ = iterPos; ++smoothPathSize;