From 38f5a225eaf9e893bbb581d4e9f7ddcab337302a Mon Sep 17 00:00:00 2001 From: Austin Salgat Date: Sun, 10 Apr 2016 20:44:08 -0500 Subject: [PATCH] Refactor PathFinder functions to be useable by AiWander This avoids having to duplicate the distanceSquared and getClosestPoint functions. --- apps/openmw/mwmechanics/aiwander.cpp | 29 +------------- apps/openmw/mwmechanics/pathfinding.cpp | 51 ++++--------------------- apps/openmw/mwmechanics/pathfinding.hpp | 38 ++++++++++++++++++ 3 files changed, 46 insertions(+), 72 deletions(-) diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index ad4e596c1e..f0295f3316 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -39,33 +39,6 @@ namespace MWMechanics // distance must be long enough that NPC will need to move to get there. static const int MINIMUM_WANDER_DISTANCE = DESTINATION_TOLERANCE * 2; - float distanceSquared(ESM::Pathgrid::Point point, const osg::Vec3f& pos) - { - return (MWMechanics::PathFinder::MakeOsgVec3(point) - pos).length2(); - } - - int getClosestPoint(const ESM::Pathgrid* grid, const osg::Vec3f& pos) - { - assert(grid && !grid->mPoints.empty()); - - float distanceBetween = distanceSquared(grid->mPoints[0], pos); - int closestIndex = 0; - - // TODO: if this full scan causes performance problems mapping pathgrid - // points to a quadtree may help - for(unsigned int counter = 1; counter < grid->mPoints.size(); counter++) - { - float potentialDistBetween = distanceSquared(grid->mPoints[counter], pos); - if(potentialDistBetween < distanceBetween) - { - distanceBetween = potentialDistBetween; - closestIndex = counter; - } - } - - return closestIndex; - } - const std::string AiWander::sIdleSelectToGroupName[GroupIndex_MaxIdle - GroupIndex_MinIdle + 1] = { std::string("idle2"), @@ -779,7 +752,7 @@ namespace MWMechanics CoordinateConverter(cell).toLocal(npcPos); // Find closest pathgrid point - int closestPointIndex = getClosestPoint(pathgrid, npcPos); + int closestPointIndex = PathFinder::GetClosestPoint(pathgrid, npcPos); // mAllowedNodes for this actor with pathgrid point indexes based on mDistance // and if the point is connected to the closest current point diff --git a/apps/openmw/mwmechanics/pathfinding.cpp b/apps/openmw/mwmechanics/pathfinding.cpp index dbe20fdc05..c8ba867032 100644 --- a/apps/openmw/mwmechanics/pathfinding.cpp +++ b/apps/openmw/mwmechanics/pathfinding.cpp @@ -10,43 +10,6 @@ namespace { - // Slightly cheaper version for comparisons. - // Caller needs to be careful for very short distances (i.e. less than 1) - // or when accumuating the results i.e. (a + b)^2 != a^2 + b^2 - // - float distanceSquared(ESM::Pathgrid::Point point, const osg::Vec3f& pos) - { - return (MWMechanics::PathFinder::MakeOsgVec3(point) - pos).length2(); - } - - // Return the closest pathgrid point index from the specified position co - // -ordinates. NOTE: Does not check if there is a sensible way to get there - // (e.g. a cliff in front). - // - // NOTE: pos is expected to be in local co-ordinates, as is grid->mPoints - // - int getClosestPoint(const ESM::Pathgrid* grid, const osg::Vec3f& pos) - { - assert(grid && !grid->mPoints.empty()); - - float distanceBetween = distanceSquared(grid->mPoints[0], pos); - int closestIndex = 0; - - // TODO: if this full scan causes performance problems mapping pathgrid - // points to a quadtree may help - for(unsigned int counter = 1; counter < grid->mPoints.size(); counter++) - { - float potentialDistBetween = distanceSquared(grid->mPoints[counter], pos); - if(potentialDistBetween < distanceBetween) - { - distanceBetween = potentialDistBetween; - closestIndex = counter; - } - } - - return closestIndex; - } - // Chooses a reachable end pathgrid point. start is assumed reachable. std::pair getClosestReachablePoint(const ESM::Pathgrid* grid, const MWWorld::CellStore *cell, @@ -62,7 +25,7 @@ namespace // points to a quadtree may help for(unsigned int counter = 0; counter < grid->mPoints.size(); counter++) { - float potentialDistBetween = distanceSquared(grid->mPoints[counter], pos); + float potentialDistBetween = MWMechanics::PathFinder::DistanceSquared(grid->mPoints[counter], pos); if (potentialDistBetween < closestDistanceReachable) { // found a closer one @@ -146,7 +109,7 @@ namespace MWMechanics * pathgrid point (e.g. wander) then it may be worth while to call * pop_back() to remove the redundant entry. * - * NOTE: co-ordinates must be converted prior to calling getClosestPoint() + * NOTE: co-ordinates must be converted prior to calling GetClosestPoint() * * | * | cell @@ -199,16 +162,16 @@ namespace MWMechanics return; } - // NOTE: getClosestPoint expects local co-ordinates + // NOTE: GetClosestPoint expects local co-ordinates CoordinateConverter converter(mCell->getCell()); - // NOTE: It is possible that getClosestPoint returns a pathgrind point index + // NOTE: It is possible that GetClosestPoint returns a pathgrind point index // that is unreachable in some situations. e.g. actor is standing // outside an area enclosed by walls, but there is a pathgrid // point right behind the wall that is closer than any pathgrid // point outside the wall osg::Vec3f startPointInLocalCoords(converter.toLocalVec3(startPoint)); - int startNode = getClosestPoint(mPathgrid, startPointInLocalCoords); + int startNode = GetClosestPoint(mPathgrid, startPointInLocalCoords); osg::Vec3f endPointInLocalCoords(converter.toLocalVec3(endPoint)); std::pair endNode = getClosestReachablePoint(mPathgrid, cell, @@ -218,8 +181,8 @@ namespace MWMechanics // if it's shorter for actor to travel from start to end, than to travel from either // start or end to nearest pathgrid point, just travel from start to end. float startToEndLength2 = (endPointInLocalCoords - startPointInLocalCoords).length2(); - float endTolastNodeLength2 = distanceSquared(mPathgrid->mPoints[endNode.first], endPointInLocalCoords); - float startTo1stNodeLength2 = distanceSquared(mPathgrid->mPoints[startNode], startPointInLocalCoords); + float endTolastNodeLength2 = DistanceSquared(mPathgrid->mPoints[endNode.first], endPointInLocalCoords); + float startTo1stNodeLength2 = DistanceSquared(mPathgrid->mPoints[startNode], startPointInLocalCoords); if ((startToEndLength2 < startTo1stNodeLength2) || (startToEndLength2 < endTolastNodeLength2)) { mPath.push_back(endPoint); diff --git a/apps/openmw/mwmechanics/pathfinding.hpp b/apps/openmw/mwmechanics/pathfinding.hpp index 1765a5cc56..7262842dc7 100644 --- a/apps/openmw/mwmechanics/pathfinding.hpp +++ b/apps/openmw/mwmechanics/pathfinding.hpp @@ -4,6 +4,7 @@ #include #include #include +#include namespace MWWorld { @@ -89,6 +90,43 @@ namespace MWMechanics { return osg::Vec3f(static_cast(p.mX), static_cast(p.mY), static_cast(p.mZ)); } + + // Slightly cheaper version for comparisons. + // Caller needs to be careful for very short distances (i.e. less than 1) + // or when accumuating the results i.e. (a + b)^2 != a^2 + b^2 + // + static float DistanceSquared(ESM::Pathgrid::Point point, const osg::Vec3f& pos) + { + return (MWMechanics::PathFinder::MakeOsgVec3(point) - pos).length2(); + } + + // Return the closest pathgrid point index from the specified position co + // -ordinates. NOTE: Does not check if there is a sensible way to get there + // (e.g. a cliff in front). + // + // NOTE: pos is expected to be in local co-ordinates, as is grid->mPoints + // + static int GetClosestPoint(const ESM::Pathgrid* grid, const osg::Vec3f& pos) + { + assert(grid && !grid->mPoints.empty()); + + float distanceBetween = DistanceSquared(grid->mPoints[0], pos); + int closestIndex = 0; + + // TODO: if this full scan causes performance problems mapping pathgrid + // points to a quadtree may help + for(unsigned int counter = 1; counter < grid->mPoints.size(); counter++) + { + float potentialDistBetween = DistanceSquared(grid->mPoints[counter], pos); + if(potentialDistBetween < distanceBetween) + { + distanceBetween = potentialDistBetween; + closestIndex = counter; + } + } + + return closestIndex; + } private: void buildPath(const ESM::Pathgrid::Point &startPoint, const ESM::Pathgrid::Point &endPoint,