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/NavMeshRandom.h
frank 55061ef0da minor changes to floorplan
fixed some compile issues
worked on nav-meshes
added some tests
2018-01-16 12:41:05 +01:00

113 lines
2.7 KiB
C++

#ifndef NAVMESHRANDOM_H
#define NAVMESHRANDOM_H
#include <random>
#include <vector>
#include "../math/DrawList.h"
#include "../geo/Point3.h"
#include "../misc/PerfCheck.h"
#include "NavMeshLocation.h"
namespace NM {
/**
* randomly pick points within the area of the nav-mesh.
* points are picked evenly:
* bigger triangles are used more often
*
*/
template <typename Tria> class NavMeshRandom {
DrawList<size_t> lst;
std::minstd_rand gen;
std::uniform_real_distribution<float> dOnTriangle = std::uniform_real_distribution<float>(0.0f, 1.0f);
std::uniform_real_distribution<float> dHeading = std::uniform_real_distribution<float>(0, M_PI*2);
std::vector<const Tria*> triangles;
uint32_t nextSeed() {
static uint32_t seed = 0;
return ++seed;
}
public:
/** ctor (const/non-const using T) */
template <typename T> NavMeshRandom(const std::vector<T*>& srcTriangles) : lst(nextSeed()), gen(nextSeed()) {
// 1st = almost always the same number?!
gen(); gen();
// construct a DrawList (probability = size[area] of the triangle
// bigger triangles must be choosen more often
for (size_t idx = 0; idx < srcTriangles.size(); ++idx) {
this->triangles.push_back(srcTriangles[idx]);
this->lst.add(idx, srcTriangles[idx]->getArea());
}
}
/** draw a random point */
NavMeshLocation<Tria> draw() {
PERF_REGION(3, "NavMeshRandom::draw()");
// pick a random triangle to draw from
const size_t idx = lst.get();
const Tria* tria = triangles[idx];
// get random (u,v) on triangle
float u = dOnTriangle(gen);
float v = dOnTriangle(gen);
// if the (u,v) is outside of the triangle, mirror it so its inside the triangle again
if ((u+v) > 1) {
u = 1.0f - u;
v = 1.0f - v;
}
// done
const Point3 pos = tria->getPoint(u,v); //tria->getA() + (tria.getAB() * u) + (tria.getAC() * v);
return NavMeshLocation<Tria>(pos, tria);
}
/** draw a random location within the given radius */
NavMeshLocation<Tria> drawWithin(const Point3 center, const float radius) {
std::uniform_real_distribution<float> dDistance(0.001, radius);
while(true) {
const float head = dHeading(gen);
const float dist = dDistance(gen);
const float ox = std::cos(head) * dist;
const float oy = std::sin(head) * dist;
// 2D destination (ignore z)
const Point2 dst(center.x + ox, center.y + oy);
for (const Tria* t : triangles) {
// if triangle contains 2D position
if (t->contains(dst)) {
// convert it to a 3D position
const Point3 p3 = t->toPoint3(dst);
const NavMeshLocation<Tria> loc(p3, t);
return loc;
}
}
}
}
};
}
#endif // NAVMESHRANDOM_H