#ifndef NAVMESHTRIANGLE_H #define NAVMESHTRIANGLE_H #include "../geo/Point3.h" #include "../geo/Point2.h" class NavMeshTriangle { public: Point3 p1; Point3 p2; Point3 p3; uint8_t type; private: template friend class NavMesh; int _neighbors[3]; int _numNeighbors; /** precalculated stuff */ private: Point2 v0; Point2 v1; float dot00; float dot01; float dot11; float invDenom; float area; const Point3 center; const Point3 v12; const Point3 v13; public: /** ctor */ NavMeshTriangle(const Point3 p1, const Point3 p2, const Point3 p3, const uint8_t type) : p1(p1), p2(p2), p3(p3), type(type), _neighbors(), _numNeighbors(0), center((p1+p2+p3)/3), v12(p2-p1), v13(p3-p1) { precompute(); } bool operator == (const NavMeshTriangle& o) const { return (p1 == o.p1) && (p2 == o.p2) && (p3 == o.p3); } Point3 getA() const { return p1; } Point3 getAB() const { return v12; } Point3 getAC() const { return v13; } bool contains(const Point3 p) const { const Point2 v2 = p.xy() - p1.xy(); // Compute dot products float dot02 = dot(v0, v2); float dot12 = dot(v1, v2); // Compute barycentric coordinates float u = (dot11 * dot02 - dot01 * dot12) * invDenom; float v = (dot00 * dot12 - dot01 * dot02) * invDenom; // Check if point is in triangle return (u >= 0) && (v >= 0) && (u + v <= 1); } /** get the triangle's size */ float getArea() const { return area; } /** get the triangle's center-point */ Point3 getCenter() const { return center; } private: /** perform some pre-calculations to speed things up */ void precompute() { // Compute vectors v0 = p3.xy() - p1.xy(); v1 = p2.xy() - p1.xy(); // Compute dot products dot00 = dot(v0, v0); dot01 = dot(v0, v1); dot11 = dot(v1, v1); // Compute barycentric coordinates invDenom = 1.0f / (dot00 * dot11 - dot01 * dot01); const float a = (p2-p1).length(); const float b = (p3-p1).length(); const float c = (p2-p3).length(); const float s = 0.5f * (a+b+c); area = std::sqrt( s * (s-a) * (s-b) * (s-c) ); } }; #endif // NAVMESHTRIANGLE_H