#ifndef NAVMESHWALKSIMPLE_H #define NAVMESHWALKSIMPLE_H #include "../NavMesh.h" #include "../NavMeshLocation.h" #include "../../geo/Heading.h" #include "NavMeshSub.h" #include "NavMeshWalkParams.h" #include "NavMeshWalkEval.h" namespace NM { template class NavMeshWalkSimple { private: const NavMesh& mesh; std::vector*> evals; int hits = 0; int misses = 0; public: struct Result { NavMeshLocation location; Heading heading; double probability; Result() : heading(0) {;} }; public: /** ctor */ NavMeshWalkSimple(const NavMesh& mesh) : mesh(mesh) { } /** add a new evaluator to the walker */ void addEvaluator(NavMeshWalkEval* eval) { this->evals.push_back(eval); } Result getDestination(const NavMeshWalkParams& params) { Result res; res.heading = params.heading; // to-be-walked distance; const float toBeWalkedDist = params.getToBeWalkedDistance(); const float toBeWalkedDistSafe = 0.75 + toBeWalkedDist * 1.1; // construct reachable region NavMeshSub reachable(params.start, toBeWalkedDistSafe); // get the to-be-reached destination's position (using start+distance+heading) const Point2 dir = res.heading.asVector(); const Point2 dst = params.start.pos.xy() + (dir * toBeWalkedDist); const Tria* dstTria = reachable.getContainingTriangle(dst); // is above destination reachable? if (dstTria) { res.location.pos = dstTria->toPoint3(dst); res.location.tria = dstTria; ++hits; } else { NavMeshRandom rnd = reachable.getRandom(); NavMeshLocation rndLoc = rnd.draw(); res.location = rndLoc; res.heading = Heading(params.start.pos.xy(), rndLoc.pos.xy()); // update the heading ++misses; } const int total = (hits + misses); if (total % 10000 == 0) { std::cout << "hits: " << (hits*100/total) << "%" << std::endl; } const NavMeshPotentialWalk pwalk(params, res.location); res.probability = 1.0; for (const NavMeshWalkEval* eval : evals) { const double p1 = eval->getProbability(pwalk); res.probability *= p1; } return res; } }; } #endif // NAVMESHWALKSIMPLE_H