143 lines
3.6 KiB
C++
143 lines
3.6 KiB
C++
/*
|
||
* © Copyright 2014 – Urheberrechtshinweis
|
||
* Alle Rechte vorbehalten / All Rights Reserved
|
||
*
|
||
* Programmcode ist urheberrechtlich geschuetzt.
|
||
* Das Urheberrecht liegt, soweit nicht ausdruecklich anders gekennzeichnet, bei Frank Ebner.
|
||
* Keine Verwendung ohne explizite Genehmigung.
|
||
* (vgl. § 106 ff UrhG / § 97 UrhG)
|
||
*/
|
||
|
||
#ifndef NAVMESHRANDOM_H
|
||
#define NAVMESHRANDOM_H
|
||
|
||
#include <random>
|
||
#include <vector>
|
||
#include "../math/DrawList.h"
|
||
#include "../geo/Point3.h"
|
||
#include "../misc/PerfCheck.h"
|
||
#include "../math/stats/Histogram.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::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 += 13;
|
||
}
|
||
|
||
public:
|
||
|
||
/** ctor (const/non-const using T) */
|
||
template <typename T> NavMeshRandom(const std::vector<T*>& srcTriangles) : lst(nextSeed()) {
|
||
|
||
Assert::isFalse(srcTriangles.empty(), "no triangles given. mesh is empty");
|
||
|
||
// 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() {
|
||
|
||
// re-use to provide stable random numbers!
|
||
static std::mt19937 gen;
|
||
|
||
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);
|
||
|
||
#ifdef WITH_DEBUG_PLOT_2
|
||
static Stats::Histogram<float> histU(0, 1, 200);
|
||
static Stats::Histogram<float> histV(0, 1, 200);
|
||
if (histU.count() > 200) {histU.showPlot(); histU.clear();}
|
||
if (histV.count() > 200) {histV.showPlot(); histV.clear();}
|
||
histU.add(u);
|
||
histV.add(v);
|
||
#endif
|
||
|
||
// 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) {
|
||
|
||
// re-use to provide stable random numbers!
|
||
static std::mt19937 gen;
|
||
|
||
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;
|
||
|
||
#ifdef WITH_DEBUG_PLOT_2
|
||
static Stats::Histogram<float> hist(0, 10, 200);
|
||
if (hist.count() > 1000) {hist.showPlot(); hist.clear();}
|
||
hist.add(dist);
|
||
#endif
|
||
|
||
// 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
|