#ifndef NAVMESHWALKEVAL_H #define NAVMESHWALKEVAL_H #include "NavMeshWalkParams.h" #include "../NavMeshLocation.h" #include "../../math/distribution/Normal.h" #include "../../misc/PerfCheck.h" #include "../../Assertions.h" #include "../meta/NavMeshDijkstra.h" namespace NM { template struct NavMeshPotentialWalk { NavMeshWalkParams requested; NavMeshLocation end; NavMeshPotentialWalk(const NavMeshWalkParams& requested) : requested(requested) { ; } NavMeshPotentialWalk(const NavMeshWalkParams& requested, const NavMeshLocation& end) : requested(requested), end(end) { ; } }; /** * evaluate a NavMeshWalk from -> to = probability */ template class NavMeshWalkEval { public: virtual double getProbability(const NavMeshPotentialWalk& walk) const = 0; }; // /** // * evaluate the difference between head(start,end) and the requested heading // */ // template class WalkEvalHeadingStartEndVonMises : public NavMeshWalkEval { // const double sigma_rad; // const double kappa; // Distribution::VonMises _dist; // Distribution::LUT dist; // public: // // kappa = 1/var = 1/sigma^2 // // https://en.wikipedia.org/wiki/Von_Mises_distribution // WalkEvalHeadingStartEndVonMises(const double sigma_rad = 0.04) : // sigma_rad(sigma_rad), kappa(1.0/(sigma_rad*sigma_rad)), _dist(0, kappa), dist(_dist.getLUT()) { // ; // } // virtual double getProbability(const NavMeshPotentialWalk& walk) const override { // PERF_REGION(4, "WalkEvalHeadingStartEnd"); // Assert::notEqual(walk.requested.start.pos, walk.end.pos, "start equals end position"); // const Heading head(walk.requested.start.pos.xy(), walk.end.pos.xy()); // const float diff = head.getDiffHalfRAD(walk.requested.heading); // //const float diff = Heading::getSignedDiff(params.heading, head); // //return Distribution::Normal::getProbability(0, sigma, diff); // return dist.getProbability(diff); // } // }; /** * evaluate the difference between head(start,end) and the requested heading */ template class WalkEvalHeadingStartEndNormal : public NavMeshWalkEval { const double sigma_rad; Distribution::Normal dist; public: WalkEvalHeadingStartEndNormal(const double sigma_rad = 0.04) : sigma_rad(sigma_rad), dist(0, sigma_rad) { ; } virtual double getProbability(const NavMeshPotentialWalk& walk) const override { PERF_REGION(4, "WalkEvalHeadingStartEnd"); Assert::notEqual(walk.requested.start.pos, walk.end.pos, "start equals end position"); const Heading head(walk.requested.start.pos.xy(), walk.end.pos.xy()); const float diff = head.getDiffHalfRAD(walk.requested.heading); //const float diff = Heading::getSignedDiff(params.heading, head); //return Distribution::Normal::getProbability(0, sigma, diff); return dist.getProbability(diff); } }; /** * evaluate the difference between distance(start, end) and the requested distance */ template class WalkEvalDistance : public NavMeshWalkEval { const double sigma; const Distribution::Normal dist; public: WalkEvalDistance( const double sigma = 0.1) : sigma(sigma), dist(0, sigma) {;} virtual double getProbability(const NavMeshPotentialWalk& walk) const override { PERF_REGION(5, "WalkEvalDistance"); const float requestedDistance_m = walk.requested.getToBeWalkedDistance(); const float walkedDistance_m = walk.requested.start.pos.getDistance(walk.end.pos); const float diff = walkedDistance_m - requestedDistance_m; return dist.getProbability(diff); //return Distribution::Normal::getProbability(params.distance_m, sigma, walkedDistance_m); } }; /** * higher probability for potints that approach the target location */ template class WalkEvalApproachesTarget : public NavMeshWalkEval { const double p; public: WalkEvalApproachesTarget(const double pApproaching = 0.65) : p(pApproaching) { ; } virtual double getProbability(const NavMeshPotentialWalk& walk) const override { // sanity check StaticAssert::AinheritsB(); const NavMeshLocation locStart = walk.requested.start; const NavMeshLocation locEnd = walk.end; const float distFromNew = locEnd.tria-> template getDistanceToDestination(locEnd.pos); const float distFromOld = locStart.tria-> template getDistanceToDestination(locStart.pos); const double pRemain = 1.0 / (2+distFromNew); return ((distFromNew <= distFromOld) ? (p) : (1.0 - p)) + std::pow(pRemain, 0.2); } }; } #endif // NAVMESHWALKEVAL_H