This repository has been archived on 2020-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
Files
Indoor/navMesh/walk/NavMeshWalkSemiDirected.h
k-a-z-u 3c72bc814c worked on nav-mesh
added dijkstra support for nav mesh
some minor changes to distributions
minor fixes
2018-01-17 16:36:37 +01:00

129 lines
3.0 KiB
C++

#ifndef NAVMESHWALKSEMIDIRECTED_H
#define NAVMESHWALKSEMIDIRECTED_H
#include "../NavMesh.h"
#include "../NavMeshLocation.h"
#include "../../geo/Heading.h"
#include "NavMeshSub.h"
#include "NavMeshWalkParams.h"
#include "NavMeshWalkEval.h"
namespace NM {
template <typename Tria> class NavMeshWalkSemiDirected {
private:
const NavMesh<Tria>& mesh;
std::vector<NavMeshWalkEval<Tria>*> evals;
public:
/** single result */
struct ResultEntry {
NavMeshLocation<Tria> location;
Heading heading;
double probability;
ResultEntry() : heading(0) {;}
};
/** list of results */
using ResultList = std::vector<ResultEntry>;
public:
/** ctor */
NavMeshWalkSemiDirected(const NavMesh<Tria>& mesh) : mesh(mesh) {
}
/** add a new evaluator to the walker */
void addEvaluator(NavMeshWalkEval<Tria>* eval) {
this->evals.push_back(eval);
}
ResultEntry getOne(const NavMeshWalkParams<Tria>& params) {
ResultEntry re;
static Distribution::Uniform<float> dHead(-0.10, +0.10, 1337);
static Distribution::Uniform<float> dDist(-0.10, +0.10, 7331);
float impactHead = 1;
float impactDist = 1;
int runs = 0;
// construct reachable region once
// must be large enough to also contain increased distances!
const float searchRegion = 2.0 + params.getToBeWalkedDistance() * 1.1;
const NavMeshSub<Tria> reachable(params.start, searchRegion);
while(true) {
// not to be found.. plan B
if (++runs > 8) {
NM::NavMeshRandom<Tria> rnd = reachable.getRandom();
re.location = rnd.drawWithin(params.start.pos, params.getToBeWalkedDistance());
re.heading = Heading(params.start.pos.xy(), re.location.pos.xy());
break;
}
// to-be-walked distance;
const float modHead = dHead.draw() * impactHead;
const float modDist = dDist.draw() * impactDist;
impactHead += 3;
impactDist += 1.05;
const float toBeWalkedDist = params.getToBeWalkedDistance() + modDist;
const Heading head = params.heading + modHead;
if (toBeWalkedDist < 0.01) {continue;}
if (toBeWalkedDist > searchRegion) {continue;}
// get the to-be-reached destination's position (using start+distance+heading)
const Point2 dir = head.asVector();
const Point2 dst = params.start.pos.xy() + (dir * toBeWalkedDist);
const Tria* dstTria = reachable.getContainingTriangle(dst);
// is above destination reachable?
if (dstTria) {
re.heading = head; // adjust walked heading
re.location.pos = dstTria->toPoint3(dst); // new destination position
re.location.tria = dstTria; // new destination triangle
break;
}
}
// calculate probability
const NavMeshPotentialWalk<Tria> pwalk(params, re.location);
re.probability = 1.0;
for (const NavMeshWalkEval<Tria>* eval : evals) {
const double p1 = eval->getProbability(pwalk);
re.probability *= p1;
}
// done
return re;
}
ResultList getMany(const NavMeshWalkParams<Tria>& params) {
return {getOne(params)};
}
};
}
#endif // NAVMESHWALKSEMIDIRECTED_H