From 9f808fbe3a1195ee6fa129a29cf9c394578f3f62 Mon Sep 17 00:00:00 2001 From: elsid Date: Sat, 6 Nov 2021 00:34:06 +0100 Subject: [PATCH] Move findPath-like navigator functions into a separate header --- apps/openmw/mwmechanics/aicombat.cpp | 4 +- apps/openmw/mwmechanics/aiwander.cpp | 5 +- apps/openmw/mwmechanics/pathfinding.cpp | 13 ++-- apps/openmw/mwworld/worldimp.cpp | 1 + .../detournavigator/navigator.cpp | 45 ++++++------ components/CMakeLists.txt | 1 + components/detournavigator/navigator.cpp | 32 --------- components/detournavigator/navigator.hpp | 61 +---------------- components/detournavigator/navigatorutils.cpp | 37 ++++++++++ components/detournavigator/navigatorutils.hpp | 68 +++++++++++++++++++ components/detournavigator/settings.hpp | 1 - 11 files changed, 143 insertions(+), 125 deletions(-) create mode 100644 components/detournavigator/navigatorutils.cpp create mode 100644 components/detournavigator/navigatorutils.hpp diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index eb139c918d..91a9b15b6f 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -8,7 +8,7 @@ #include #include -#include +#include #include "../mwphysics/collisiontype.hpp" @@ -277,7 +277,7 @@ namespace MWMechanics // If there is no path, try to find a point on a line from the actor position to target projected // on navmesh to attack the target from there. const auto navigator = world->getNavigator(); - const auto hit = navigator->raycast(halfExtents, vActorPos, vTargetPos, navigatorFlags); + const auto hit = DetourNavigator::raycast(*navigator, halfExtents, vActorPos, vTargetPos, navigatorFlags); if (hit.has_value() && (*hit - vTargetPos).length() <= rangeAttack) { diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index 9c84555404..53f050c0dd 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -5,7 +5,7 @@ #include #include #include -#include +#include #include #include "../mwbase/world.hpp" @@ -337,7 +337,8 @@ namespace MWMechanics if (!isWaterCreature && !isFlyingCreature) { // findRandomPointAroundCircle uses wanderDistance as limit for random and not as exact distance - if (const auto destination = navigator->findRandomPointAroundCircle(halfExtents, mInitialActorPosition, wanderDistance, navigatorFlags)) + if (const auto destination = DetourNavigator::findRandomPointAroundCircle(*navigator, halfExtents, + mInitialActorPosition, wanderDistance, navigatorFlags)) mDestination = *destination; else mDestination = getRandomPointAround(mInitialActorPosition, wanderRadius); diff --git a/apps/openmw/mwmechanics/pathfinding.cpp b/apps/openmw/mwmechanics/pathfinding.cpp index 4b06993a49..e727d8585d 100644 --- a/apps/openmw/mwmechanics/pathfinding.cpp +++ b/apps/openmw/mwmechanics/pathfinding.cpp @@ -3,8 +3,7 @@ #include #include -#include -#include +#include #include #include @@ -114,7 +113,7 @@ namespace bool operator()(const osg::Vec3f& start, const osg::Vec3f& end) const { - const auto position = mNavigator->raycast(mHalfExtents, start, end, mFlags); + const auto position = DetourNavigator::raycast(*mNavigator, mHalfExtents, start, end, mFlags); return position.has_value() && std::abs((position.value() - start).length2() - (end - start).length2()) <= 1; } }; @@ -422,8 +421,8 @@ namespace MWMechanics 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, areaCosts, - endTolerance, out); + const auto status = DetourNavigator::findPath(*navigator, halfExtents, stepSize, + startPoint, endPoint, flags, areaCosts, endTolerance, out); if (pathType == PathType::Partial && status == DetourNavigator::Status::PartialPath) return DetourNavigator::Status::Success; @@ -455,8 +454,8 @@ namespace MWMechanics std::deque prePath; auto prePathInserter = std::back_inserter(prePath); const float endTolerance = 0; - const auto status = navigator->findPath(halfExtents, stepSize, startPoint, mPath.front(), flags, areaCosts, - endTolerance, prePathInserter); + const auto status = DetourNavigator::findPath(*navigator, halfExtents, stepSize, + startPoint, mPath.front(), flags, areaCosts, endTolerance, prePathInserter); if (status == DetourNavigator::Status::NavMeshNotFound) return; diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 5bb3fa4b58..e1c20d652d 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -28,6 +28,7 @@ #include #include +#include #include "../mwbase/environment.hpp" #include "../mwbase/soundmanager.hpp" diff --git a/apps/openmw_test_suite/detournavigator/navigator.cpp b/apps/openmw_test_suite/detournavigator/navigator.cpp index d4bdcb13b8..d7422cda8b 100644 --- a/apps/openmw_test_suite/detournavigator/navigator.cpp +++ b/apps/openmw_test_suite/detournavigator/navigator.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -136,7 +137,7 @@ namespace TEST_F(DetourNavigatorNavigatorTest, find_path_for_empty_should_return_empty) { - EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mEndTolerance, mOut), + EXPECT_EQ(findPath(*mNavigator, mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mEndTolerance, mOut), Status::NavMeshNotFound); EXPECT_EQ(mPath, std::deque()); } @@ -144,7 +145,7 @@ namespace TEST_F(DetourNavigatorNavigatorTest, find_path_for_existing_agent_with_no_navmesh_should_throw_exception) { mNavigator->addAgent(mAgentHalfExtents); - EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mEndTolerance, mOut), + EXPECT_EQ(findPath(*mNavigator, mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mEndTolerance, mOut), Status::StartPolygonNotFound); } @@ -153,7 +154,7 @@ namespace mNavigator->addAgent(mAgentHalfExtents); mNavigator->addAgent(mAgentHalfExtents); mNavigator->removeAgent(mAgentHalfExtents); - EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mEndTolerance, mOut), + EXPECT_EQ(findPath(*mNavigator, mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mEndTolerance, mOut), Status::StartPolygonNotFound); } @@ -173,7 +174,7 @@ namespace mNavigator->update(mPlayerPosition); mNavigator->wait(mListener, WaitConditionType::requiredTilesPresent); - EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mEndTolerance, mOut), + EXPECT_EQ(findPath(*mNavigator, mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mEndTolerance, mOut), Status::Success); EXPECT_THAT(mPath, ElementsAre( @@ -221,7 +222,7 @@ namespace mNavigator->update(mPlayerPosition); mNavigator->wait(mListener, WaitConditionType::allJobsDone); - EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mEndTolerance, mOut), + EXPECT_EQ(findPath(*mNavigator, mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mEndTolerance, mOut), Status::Success); EXPECT_THAT(mPath, ElementsAre( @@ -255,7 +256,7 @@ namespace mPath.clear(); mOut = std::back_inserter(mPath); - EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mEndTolerance, mOut), + EXPECT_EQ(findPath(*mNavigator, mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mEndTolerance, mOut), Status::Success); EXPECT_THAT(mPath, ElementsAre( @@ -305,7 +306,7 @@ namespace mNavigator->update(mPlayerPosition); mNavigator->wait(mListener, WaitConditionType::allJobsDone); - EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mEndTolerance, mOut), + EXPECT_EQ(findPath(*mNavigator, mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mEndTolerance, mOut), Status::Success); EXPECT_THAT(mPath, ElementsAre( @@ -342,7 +343,7 @@ namespace mPath.clear(); mOut = std::back_inserter(mPath); - EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mEndTolerance, mOut), + EXPECT_EQ(findPath(*mNavigator, mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mEndTolerance, mOut), Status::Success); EXPECT_THAT(mPath, ElementsAre( @@ -399,7 +400,7 @@ namespace mNavigator->update(mPlayerPosition); mNavigator->wait(mListener, WaitConditionType::allJobsDone); - EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mEndTolerance, mOut), + EXPECT_EQ(findPath(*mNavigator, mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mEndTolerance, mOut), Status::Success); EXPECT_THAT(mPath, ElementsAre( @@ -486,7 +487,7 @@ namespace mNavigator->update(mPlayerPosition); mNavigator->wait(mListener, WaitConditionType::allJobsDone); - EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mEndTolerance, mOut), + EXPECT_EQ(findPath(*mNavigator, mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mEndTolerance, mOut), Status::Success); EXPECT_THAT(mPath, ElementsAre( @@ -538,7 +539,7 @@ namespace mEnd.x() = 0; mEnd.z() = 300; - EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_swim, mAreaCosts, mEndTolerance, mOut), + EXPECT_EQ(findPath(*mNavigator, mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_swim, mAreaCosts, mEndTolerance, mOut), Status::Success); EXPECT_THAT(mPath, ElementsAre( @@ -583,7 +584,7 @@ namespace mStart.x() = 0; mEnd.x() = 0; - EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_swim | Flag_walk, mAreaCosts, mEndTolerance, mOut), + EXPECT_EQ(findPath(*mNavigator, mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_swim | Flag_walk, mAreaCosts, mEndTolerance, mOut), Status::Success); EXPECT_THAT(mPath, ElementsAre( @@ -628,7 +629,7 @@ namespace mStart.x() = 0; mEnd.x() = 0; - EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_swim | Flag_walk, mAreaCosts, mEndTolerance, mOut), + EXPECT_EQ(findPath(*mNavigator, mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_swim | Flag_walk, mAreaCosts, mEndTolerance, mOut), Status::Success); EXPECT_THAT(mPath, ElementsAre( @@ -673,7 +674,7 @@ namespace mStart.x() = 0; mEnd.x() = 0; - EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mEndTolerance, mOut), + EXPECT_EQ(findPath(*mNavigator, mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mEndTolerance, mOut), Status::Success); EXPECT_THAT(mPath, ElementsAre( @@ -722,7 +723,7 @@ namespace mNavigator->update(mPlayerPosition); mNavigator->wait(mListener, WaitConditionType::allJobsDone); - EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mEndTolerance, mOut), + EXPECT_EQ(findPath(*mNavigator, mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mEndTolerance, mOut), Status::Success); EXPECT_THAT(mPath, ElementsAre( @@ -775,7 +776,7 @@ namespace mNavigator->update(mPlayerPosition); mNavigator->wait(mListener, WaitConditionType::allJobsDone); - EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mEndTolerance, mOut), + EXPECT_EQ(findPath(*mNavigator, mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mEndTolerance, mOut), Status::Success); EXPECT_THAT(mPath, ElementsAre( @@ -822,7 +823,7 @@ namespace Misc::Rng::init(42); - const auto result = mNavigator->findRandomPointAroundCircle(mAgentHalfExtents, mStart, 100.0, Flag_walk); + const auto result = findRandomPointAroundCircle(*mNavigator, mAgentHalfExtents, mStart, 100.0, Flag_walk); ASSERT_THAT(result, Optional(Vec3fEq(-198.909332275390625, 123.06096649169921875, 1.99998414516448974609375))) << (result ? *result : osg::Vec3f()); @@ -870,7 +871,7 @@ namespace mNavigator->update(mPlayerPosition); mNavigator->wait(mListener, WaitConditionType::allJobsDone); - EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mEndTolerance, mOut), + EXPECT_EQ(findPath(*mNavigator, mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mEndTolerance, mOut), Status::Success); EXPECT_THAT(mPath, ElementsAre( @@ -954,7 +955,7 @@ namespace mNavigator->update(mPlayerPosition); mNavigator->wait(mListener, WaitConditionType::allJobsDone); - const auto result = mNavigator->raycast(mAgentHalfExtents, mStart, mEnd, Flag_walk); + const auto result = raycast(*mNavigator, mAgentHalfExtents, mStart, mEnd, Flag_walk); ASSERT_THAT(result, Optional(Vec3fEq(mEnd.x(), mEnd.y(), 1.99998295307159423828125))) << (result ? *result : osg::Vec3f()); @@ -1019,7 +1020,7 @@ namespace mNavigator->update(mPlayerPosition); mNavigator->wait(mListener, WaitConditionType::requiredTilesPresent); - EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mEndTolerance, mOut), + EXPECT_EQ(findPath(*mNavigator, mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mEndTolerance, mOut), Status::Success); EXPECT_THAT(mPath, ElementsAre( @@ -1069,7 +1070,7 @@ namespace mNavigator->update(mPlayerPosition); mNavigator->wait(mListener, WaitConditionType::allJobsDone); - EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mEndTolerance, mOut), + EXPECT_EQ(findPath(*mNavigator, mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mEndTolerance, mOut), Status::PartialPath); EXPECT_THAT(mPath, ElementsAre( @@ -1116,7 +1117,7 @@ namespace const float endTolerance = 1000.0f; - EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, endTolerance, mOut), + EXPECT_EQ(findPath(*mNavigator, mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, endTolerance, mOut), Status::Success); EXPECT_THAT(mPath, ElementsAre( diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index a3f77d86bf..0b3c95ff45 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -196,6 +196,7 @@ add_component_dir(detournavigator offmeshconnectionsmanager preparednavmeshdata navmeshcacheitem + navigatorutils ) add_component_dir(loadinglistener diff --git a/components/detournavigator/navigator.cpp b/components/detournavigator/navigator.cpp index fc7b0ffb6d..1877c3dd93 100644 --- a/components/detournavigator/navigator.cpp +++ b/components/detournavigator/navigator.cpp @@ -1,42 +1,10 @@ -#include "findrandompointaroundcircle.hpp" #include "navigator.hpp" -#include "raycast.hpp" #include "navigatorimpl.hpp" #include "navigatorstub.hpp" #include "recastglobalallocator.hpp" namespace DetourNavigator { - std::optional Navigator::findRandomPointAroundCircle(const osg::Vec3f& agentHalfExtents, - const osg::Vec3f& start, const float maxRadius, const Flags includeFlags) const - { - const auto navMesh = getNavMesh(agentHalfExtents); - if (!navMesh) - return std::optional(); - const auto settings = getSettings(); - const auto result = DetourNavigator::findRandomPointAroundCircle(navMesh->lockConst()->getImpl(), - toNavMeshCoordinates(settings, agentHalfExtents), toNavMeshCoordinates(settings, start), - toNavMeshCoordinates(settings, maxRadius), includeFlags, settings); - if (!result) - return std::optional(); - return std::optional(fromNavMeshCoordinates(settings, *result)); - } - - std::optional Navigator::raycast(const osg::Vec3f& agentHalfExtents, const osg::Vec3f& start, - const osg::Vec3f& end, const Flags includeFlags) const - { - const auto navMesh = getNavMesh(agentHalfExtents); - if (navMesh == nullptr) - return {}; - const auto settings = getSettings(); - const auto result = DetourNavigator::raycast(navMesh->lockConst()->getImpl(), - toNavMeshCoordinates(settings, agentHalfExtents), toNavMeshCoordinates(settings, start), - toNavMeshCoordinates(settings, end), includeFlags, settings); - if (!result) - return {}; - return fromNavMeshCoordinates(settings, *result); - } - std::unique_ptr makeNavigator(const Settings& settings) { DetourNavigator::RecastGlobalAllocator::init(); diff --git a/components/detournavigator/navigator.hpp b/components/detournavigator/navigator.hpp index 0ab351981a..5edc12ed84 100644 --- a/components/detournavigator/navigator.hpp +++ b/components/detournavigator/navigator.hpp @@ -1,9 +1,6 @@ #ifndef OPENMW_COMPONENTS_DETOURNAVIGATOR_NAVIGATOR_H #define OPENMW_COMPONENTS_DETOURNAVIGATOR_NAVIGATOR_H -#include "findsmoothpath.hpp" -#include "flags.hpp" -#include "settings.hpp" #include "objectid.hpp" #include "navmeshcacheitem.hpp" #include "recastmeshtiles.hpp" @@ -12,8 +9,6 @@ #include -#include - namespace ESM { struct Cell; @@ -27,6 +22,8 @@ namespace Loading namespace DetourNavigator { + struct Settings; + struct ObjectShapes { osg::ref_ptr mShapeInstance; @@ -166,38 +163,6 @@ namespace DetourNavigator */ virtual void wait(Loading::Listener& listener, WaitConditionType waitConditionType) = 0; - /** - * @brief findPath fills output iterator with points of scene surfaces to be used for actor to walk through. - * @param agentHalfExtents allows to find navmesh for given actor. - * @param start path from given point. - * @param end path at given point. - * @param includeFlags setup allowed surfaces for actor to walk. - * @param out the beginning of the destination range. - * @param endTolerance defines maximum allowed distance to end path point in addition to agentHalfExtents - * @return Output iterator to the element in the destination range, one past the last element of found path. - * Equal to out if no path is found. - */ - template - Status findPath(const osg::Vec3f& agentHalfExtents, const float stepSize, const osg::Vec3f& start, - const osg::Vec3f& end, const Flags includeFlags, const DetourNavigator::AreaCosts& areaCosts, - float endTolerance, OutputIterator& out) const - { - static_assert( - std::is_same< - typename std::iterator_traits::iterator_category, - std::output_iterator_tag - >::value, - "out is not an OutputIterator" - ); - const auto navMesh = getNavMesh(agentHalfExtents); - if (!navMesh) - return Status::NavMeshNotFound; - const auto settings = getSettings(); - return findSmoothPath(navMesh->lockConst()->getImpl(), toNavMeshCoordinates(settings, agentHalfExtents), - toNavMeshCoordinates(settings, stepSize), toNavMeshCoordinates(settings, start), - toNavMeshCoordinates(settings, end), includeFlags, areaCosts, settings, endTolerance, out); - } - /** * @brief getNavMesh returns navmesh for specific agent half extents * @return navmesh @@ -214,28 +179,6 @@ namespace DetourNavigator virtual void reportStats(unsigned int frameNumber, osg::Stats& stats) const = 0; - /** - * @brief findRandomPointAroundCircle returns random location on navmesh within the reach of specified location. - * @param agentHalfExtents allows to find navmesh for given actor. - * @param start path from given point. - * @param maxRadius limit maximum distance from start. - * @param includeFlags setup allowed surfaces for actor to walk. - * @return not empty optional with position if point is found and empty optional if point is not found. - */ - std::optional findRandomPointAroundCircle(const osg::Vec3f& agentHalfExtents, - const osg::Vec3f& start, const float maxRadius, const Flags includeFlags) const; - - /** - * @brief raycast finds farest navmesh point from start on a line from start to end that has path from start. - * @param agentHalfExtents allows to find navmesh for given actor. - * @param start of the line - * @param end of the line - * @param includeFlags setup allowed surfaces for actor to walk. - * @return not empty optional with position if point is found and empty optional if point is not found. - */ - std::optional raycast(const osg::Vec3f& agentHalfExtents, const osg::Vec3f& start, - const osg::Vec3f& end, const Flags includeFlags) const; - virtual RecastMeshTiles getRecastMeshTiles() const = 0; virtual float getMaxNavmeshAreaRealRadius() const = 0; diff --git a/components/detournavigator/navigatorutils.cpp b/components/detournavigator/navigatorutils.cpp new file mode 100644 index 0000000000..82a108db6f --- /dev/null +++ b/components/detournavigator/navigatorutils.cpp @@ -0,0 +1,37 @@ +#include "navigatorutils.hpp" +#include "findrandompointaroundcircle.hpp" +#include "navigator.hpp" +#include "raycast.hpp" + +namespace DetourNavigator +{ + std::optional findRandomPointAroundCircle(const Navigator& navigator, const osg::Vec3f& agentHalfExtents, + const osg::Vec3f& start, const float maxRadius, const Flags includeFlags) + { + const auto navMesh = navigator.getNavMesh(agentHalfExtents); + if (!navMesh) + return std::nullopt; + const auto settings = navigator.getSettings(); + const auto result = DetourNavigator::findRandomPointAroundCircle(navMesh->lockConst()->getImpl(), + toNavMeshCoordinates(settings, agentHalfExtents), toNavMeshCoordinates(settings, start), + toNavMeshCoordinates(settings, maxRadius), includeFlags, settings); + if (!result) + return std::nullopt; + return std::optional(fromNavMeshCoordinates(settings, *result)); + } + + std::optional raycast(const Navigator& navigator, const osg::Vec3f& agentHalfExtents, const osg::Vec3f& start, + const osg::Vec3f& end, const Flags includeFlags) + { + const auto navMesh = navigator.getNavMesh(agentHalfExtents); + if (navMesh == nullptr) + return std::nullopt; + const auto settings = navigator.getSettings(); + const auto result = DetourNavigator::raycast(navMesh->lockConst()->getImpl(), + toNavMeshCoordinates(settings, agentHalfExtents), toNavMeshCoordinates(settings, start), + toNavMeshCoordinates(settings, end), includeFlags, settings); + if (!result) + return std::nullopt; + return fromNavMeshCoordinates(settings, *result); + } +} diff --git a/components/detournavigator/navigatorutils.hpp b/components/detournavigator/navigatorutils.hpp new file mode 100644 index 0000000000..4ccc238f97 --- /dev/null +++ b/components/detournavigator/navigatorutils.hpp @@ -0,0 +1,68 @@ +#ifndef OPENMW_COMPONENTS_DETOURNAVIGATOR_NAVIGATORUTILS_H +#define OPENMW_COMPONENTS_DETOURNAVIGATOR_NAVIGATORUTILS_H + +#include "findsmoothpath.hpp" +#include "flags.hpp" +#include "settings.hpp" +#include "navigator.hpp" + +#include + +namespace DetourNavigator +{ + /** + * @brief findPath fills output iterator with points of scene surfaces to be used for actor to walk through. + * @param agentHalfExtents allows to find navmesh for given actor. + * @param start path from given point. + * @param end path at given point. + * @param includeFlags setup allowed surfaces for actor to walk. + * @param out the beginning of the destination range. + * @param endTolerance defines maximum allowed distance to end path point in addition to agentHalfExtents + * @return Output iterator to the element in the destination range, one past the last element of found path. + * Equal to out if no path is found. + */ + template + inline Status findPath(const Navigator& navigator, const osg::Vec3f& agentHalfExtents, const float stepSize, const osg::Vec3f& start, + const osg::Vec3f& end, const Flags includeFlags, const DetourNavigator::AreaCosts& areaCosts, + float endTolerance, OutputIterator& out) + { + static_assert( + std::is_same< + typename std::iterator_traits::iterator_category, + std::output_iterator_tag + >::value, + "out is not an OutputIterator" + ); + const auto navMesh = navigator.getNavMesh(agentHalfExtents); + if (navMesh == nullptr) + return Status::NavMeshNotFound; + const auto settings = navigator.getSettings(); + return findSmoothPath(navMesh->lockConst()->getImpl(), toNavMeshCoordinates(settings, agentHalfExtents), + toNavMeshCoordinates(settings, stepSize), toNavMeshCoordinates(settings, start), + toNavMeshCoordinates(settings, end), includeFlags, areaCosts, settings, endTolerance, out); + } + + /** + * @brief findRandomPointAroundCircle returns random location on navmesh within the reach of specified location. + * @param agentHalfExtents allows to find navmesh for given actor. + * @param start path from given point. + * @param maxRadius limit maximum distance from start. + * @param includeFlags setup allowed surfaces for actor to walk. + * @return not empty optional with position if point is found and empty optional if point is not found. + */ + std::optional findRandomPointAroundCircle(const Navigator& navigator, const osg::Vec3f& agentHalfExtents, + const osg::Vec3f& start, const float maxRadius, const Flags includeFlags); + + /** + * @brief raycast finds farest navmesh point from start on a line from start to end that has path from start. + * @param agentHalfExtents allows to find navmesh for given actor. + * @param start of the line + * @param end of the line + * @param includeFlags setup allowed surfaces for actor to walk. + * @return not empty optional with position if point is found and empty optional if point is not found. + */ + std::optional raycast(const Navigator& navigator, const osg::Vec3f& agentHalfExtents, const osg::Vec3f& start, + const osg::Vec3f& end, const Flags includeFlags); +} + +#endif diff --git a/components/detournavigator/settings.hpp b/components/detournavigator/settings.hpp index 800ad6b2bb..0ea35d9b49 100644 --- a/components/detournavigator/settings.hpp +++ b/components/detournavigator/settings.hpp @@ -2,7 +2,6 @@ #define OPENMW_COMPONENTS_DETOURNAVIGATOR_SETTINGS_H #include -#include #include namespace DetourNavigator