#ifndef NAVMESHDIJKSTRA_H #define NAVMESHDIJKSTRA_H #include "../NavMesh.h" #include "../../nav/dijkstra/Dijkstra.h" #include #include #include namespace NM { /** distance to the target for each of the 3 triangle edge points */ struct NavMeshTriangleDijkstra { float distAtCenter; float distAtP1; float distAtP2; float distAtP3; }; // // mapper // template struct Access { // int getNumNeighbors(const Tria& t) const {return t.getNumNeighbors();} // const Tria* getNeighbor(const Tria& t, const int idx) const {return (Tria*)t.getNeighbor(idx);} // float getWeightBetween(const Tria& t1, const Tria& t2) const {return t1.getCenter().getDistance(t2.getCenter());} // }; /** add distance-to-target infos for the triangles */ class NavMeshDijkstra { struct Node { Point3 pt; std::vector neighbors; Node(const Point3 pt) : pt(pt) {;} bool operator == (const Node& o ) {return o.pt == pt;} bool operator == (const Point3& pos ) {return pt == pos;} operator std::string() const {return asString();} std::string asString() const { return "(" + std::to_string(pt.x) + "," + std::to_string(pt.y) + "," + std::to_string(pt.z) + ")"; } }; struct NodeComp { Point3 pos; //bool operator () (const Node* n) {return n->pt == pos;} bool operator () (const Node* n) {return n->pt.getDistance(pos) < 0.0001;} NodeComp(const Point3 pos) : pos(pos) {;} }; struct NodeAccess { int getNumNeighbors(const Node& n) const {return n.neighbors.size();} const Node* getNeighbor(const Node& n, const int idx) const {return n.neighbors[idx];} float getWeightBetween(const Node& n1, const Node& n2) const {return n1.pt.getDistance(n2.pt);} }; public: template static void stamp(NavMesh& mesh, const Point3 dst) { // ensure Tria extends NavMeshTriangleDijkstra StaticAssert::AinheritsB(); // point3 to mesh location //NavMeshLocation endLoc = mesh.getLocation(dst); std::vector nodes = net(mesh); Node* end = nodes[0]; // TODO; NodeAccess acc; // dijkstra Dijkstra dijkstra; dijkstra.build(end, acc); for (Tria* t : mesh) { auto itCenter = std::find_if(nodes.begin(), nodes.end(), NodeComp(t->getCenter())); auto it1 = std::find_if(nodes.begin(), nodes.end(), NodeComp(t->getP1())); auto it2 = std::find_if(nodes.begin(), nodes.end(), NodeComp(t->getP2())); auto it3 = std::find_if(nodes.begin(), nodes.end(), NodeComp(t->getP3())); auto* dnCenter = dijkstra.getNode(*itCenter); if (dnCenter != nullptr) {t->distAtCenter = dnCenter->cumWeight;} auto* dn1 = dijkstra.getNode(*it1); if (dn1 != nullptr) {t->distAtP1 = dn1->cumWeight;} auto* dn2 = dijkstra.getNode(*it2); if (dn2 != nullptr) {t->distAtP2 = dn2->cumWeight;} auto* dn3 = dijkstra.getNode(*it3); if (dn3 != nullptr) {t->distAtP3 = dn3->cumWeight;} } } template static std::vector net(NavMesh& mesh) { std::vector nodes; // 1) add all triangle nodes (center, p1, p2, p3) for (const Tria* t : mesh) { auto itCenter = std::find_if(nodes.begin(), nodes.end(), NodeComp(t->getCenter())); if (itCenter == nodes.end()) {nodes.push_back(new Node(t->getCenter()));} //Node n1(t->getP1()); auto it1 = std::find_if(nodes.begin(), nodes.end(), NodeComp(t->getP1())); if (it1 == nodes.end()) {nodes.push_back(new Node(t->getP1()));} //Node n2(t->getP2()); auto it2 = std::find_if(nodes.begin(), nodes.end(), NodeComp(t->getP2())); if (it2 == nodes.end()) {nodes.push_back(new Node(t->getP2()));} //Node n3(t->getP1()); auto it3 = std::find_if(nodes.begin(), nodes.end(), NodeComp(t->getP3())); if (it3 == nodes.end()) {nodes.push_back(new Node(t->getP3()));} } // 2) connect all possible nodes for (const Tria* t : mesh) { auto itCenter = std::find_if(nodes.begin(), nodes.end(), NodeComp(t->getCenter())); auto it1 = std::find_if(nodes.begin(), nodes.end(), NodeComp(t->getP1())); auto it2 = std::find_if(nodes.begin(), nodes.end(), NodeComp(t->getP2())); auto it3 = std::find_if(nodes.begin(), nodes.end(), NodeComp(t->getP3())); (*itCenter)->neighbors.push_back(*it1); (*itCenter)->neighbors.push_back(*it2); (*itCenter)->neighbors.push_back(*it3); (*it1)->neighbors.push_back(*itCenter); (*it1)->neighbors.push_back(*it2); (*it1)->neighbors.push_back(*it3); (*it2)->neighbors.push_back(*itCenter); (*it2)->neighbors.push_back(*it1); (*it2)->neighbors.push_back(*it3); (*it3)->neighbors.push_back(*itCenter); (*it3)->neighbors.push_back(*it1); (*it3)->neighbors.push_back(*it2); // neighbors for (const auto* n : *t) { auto itCenter2 = std::find_if(nodes.begin(), nodes.end(), NodeComp(n->getCenter())); (*itCenter)->neighbors.push_back(*itCenter2); } } K::Gnuplot gp; K::GnuplotSplot plot; K::GnuplotSplotElementLines lines; plot.add(&lines); for (const Node* n1 : nodes) { for (const Node* n2 : n1->neighbors) { const K::GnuplotPoint3 gp1(n1->pt.x, n1->pt.y, n1->pt.z); const K::GnuplotPoint3 gp2(n2->pt.x, n2->pt.y, n2->pt.z); lines.addSegment(gp1, gp2); } } gp.draw(plot); gp.flush();; int xxxx = 0; (void) xxxx; return nodes; } }; } #endif // NAVMESHDIJKSTRA_H