💿🐜 Antkeeper source code https://antkeeper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

289 lines
7.7 KiB

  1. /*
  2. * Copyright (C) 2017 Christopher J. Howard
  3. *
  4. * This file is part of Antkeeper Source Code.
  5. *
  6. * Antkeeper Source Code is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Antkeeper Source Code is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #ifndef NAVMESH_HPP
  20. #define NAVMESH_HPP
  21. #include <iostream>
  22. #include <string>
  23. #include <tuple>
  24. #include <vector>
  25. #include <emergent/emergent.hpp>
  26. using namespace Emergent;
  27. /**
  28. * Navigation mesh represented by a half-edge structure.
  29. *
  30. * @ingroup geometry
  31. */
  32. class Navmesh
  33. {
  34. public:
  35. struct Vertex;
  36. struct Edge;
  37. struct Triangle;
  38. struct Step;
  39. /**
  40. * Creates an instance of Navmesh.
  41. */
  42. Navmesh();
  43. /**
  44. * Destroys an instance of Navmesh.
  45. */
  46. ~Navmesh();
  47. /**
  48. * Forms a navmesh from a list of vertices and indices.
  49. *
  50. * @param vertices Specifies a list of vertices.
  51. * @param indices Specifies a list of indices.
  52. * @return `true` if the navmesh was successfully created, `false` otherwise.
  53. */
  54. bool create(const std::vector<Vector3>& vertices, const std::vector<std::size_t>& indices);
  55. /**
  56. * Destroys the navmesh.
  57. */
  58. void destroy();
  59. /**
  60. * Loads this navmesh from a triangulated Wavefront OBJ file. This method only supported **triangulated** Wavefront OBJ files. The supported commands are `v`, `f` and comment lines beginning with `#`.
  61. *
  62. * @param filename Path to the Wavefront OBJ file.
  63. * @return `true` if the navmesh was successfully loaded from the OBJ file, `false` otherwise.
  64. */
  65. bool loadOBJ(const std::string& filename);
  66. /**
  67. * Traverses the navmesh.
  68. *
  69. * @param[in] startTriangle Initial triangle
  70. * @param[in] startPosition Initial barycentric coordinates on the start triangle
  71. * @param[in] startVelocity Initial cartesian velocity vector
  72. * @param[out] traversal Traversal information
  73. */
  74. static void traverse(Navmesh::Triangle* startTriangle, const Vector3& startPosition, const Vector3& startVelocity, std::vector<Navmesh::Step>* traversal);
  75. /**
  76. * Creates an octree of navmesh triangles
  77. */
  78. Octree<Navmesh::Triangle*>* createOctree(std::size_t maxDepth);
  79. /// Returns a pointer to the navmesh vertices
  80. const std::vector<Navmesh::Vertex*>* getVertices() const;
  81. /// Returns a pointer to the navmesh edges
  82. const std::vector<Navmesh::Edge*>* getEdges() const;
  83. /// Returns a pointer to the navmesh triangles
  84. const std::vector<Navmesh::Triangle*>* getTriangles() const;
  85. /// @copydoc Navmesh::getVertices() const
  86. std::vector<Navmesh::Vertex*>* getVertices();
  87. /// @copydoc Navmesh::getEdges() const
  88. std::vector<Navmesh::Edge*>* getEdges();
  89. /// @copydoc Navmesh::getTriangles() const
  90. std::vector<Navmesh::Triangle*>* getTriangles();
  91. /// Returns an AABB which contains this navmesh
  92. const AABB& getBounds() const;
  93. /**
  94. * Half-edge vertex which contains a pointer to its parent edge, a position vector, and an index.
  95. */
  96. struct Vertex
  97. {
  98. /// Pointer to the edge to which this vertex belongs
  99. Navmesh::Edge* edge;
  100. /// Vertex position vector
  101. Vector3 position;
  102. /// Vertex flags
  103. unsigned char flags;
  104. /// Index of this vertex
  105. std::size_t index;
  106. };
  107. /**
  108. * Half-edge edge which contains pointers to its starting vertex, parent triangle, and related edges.
  109. */
  110. struct Edge
  111. {
  112. /// Pointer to the vertex at which the edge starts
  113. Navmesh::Vertex* vertex;
  114. /// Pointer to the triangle to which this edge belongs
  115. Navmesh::Triangle* triangle;
  116. /// Pointer to the previous edge in the parent triangle
  117. Navmesh::Edge* previous;
  118. /// Pointer to the next edge in the parent triangle
  119. Navmesh::Edge* next;
  120. /// Pointer to the symmetric edge
  121. Navmesh::Edge* symmetric;
  122. /// Edge flags
  123. unsigned char flags;
  124. /// Index of this edge
  125. std::size_t index;
  126. };
  127. /**
  128. * Half-edge triangle which contains a pointer to its first edge and its normal vector.
  129. */
  130. struct Triangle
  131. {
  132. /// Pointer to the first edge in this triangle
  133. Navmesh::Edge* edge;
  134. /// Faceted surface normal
  135. Vector3 normal;
  136. /// Triangle flags
  137. unsigned char flags;
  138. /// Index of this triangle
  139. std::size_t index;
  140. };
  141. /**
  142. * Contains informations about a single step in a navmesh traversal operation.
  143. */
  144. struct Step
  145. {
  146. /// Pointer to the triangle on which the step occured
  147. Triangle* triangle;
  148. /// Barycentric coordinates of the step's starting position
  149. Vector3 start;
  150. /// Barycentric coordinates of the step's ending position
  151. Vector3 end;
  152. /// Pointer to the edge on which the step exited the triangle, or `nullptr` if the step is within the triangle
  153. Edge* edge;
  154. };
  155. /**
  156. * Calculates the faceted surface normals for each triangle.
  157. */
  158. void calculateNormals();
  159. /**
  160. * Calculates an AABB which contains the navmesh.
  161. */
  162. void calculateBounds();
  163. private:
  164. /**
  165. * Reads Wavefront OBJ data from an input stream
  166. *
  167. * @param stream Input stream containing OBJ data
  168. * @param filename Path to the OBJ file
  169. * @return `true` if OBJ data was successfully read from the file.
  170. */
  171. bool readOBJ(std::istream* stream, const std::string& filename);
  172. /**
  173. * Calculates barycentric coordinates from cartesian coordinates.
  174. *
  175. * @param p Cartesian point
  176. * @param a First vertex in triangle
  177. * @param b Second vertex in triangle
  178. * @param c Third vertex in triangle
  179. */
  180. static Vector3 barycentric(const Vector3& p, const Vector3& a, const Vector3& b, const Vector3& c);
  181. /**
  182. * Calculates cartesian coordinates from barycentric coordinates.
  183. *
  184. * @param p Barycentric point
  185. * @param a First vertex in triangle
  186. * @param b Second vertex in triangle
  187. * @param c Third vertex in triangle
  188. */
  189. static Vector3 cartesian(const Vector3& p, const Vector3& a, const Vector3& b, const Vector3& c);
  190. /**
  191. * Finds the closest point on a triangle.
  192. *
  193. * @param[in] p Point to project
  194. * @param[in] triangle Triangle on which to find the closest point
  195. * @param[out] closest Closest point on triangle
  196. * @param[out] edge Edge on which the closest point is located, or `nullptr` if the closest point is not on an edge.
  197. */
  198. static void closestPointOnTriangle(const Vector3& p, const Navmesh::Triangle* triangle, Vector3* closestPoint, Navmesh::Edge** closestEdge);
  199. std::vector<Navmesh::Vertex*> vertices;
  200. std::vector<Navmesh::Edge*> edges;
  201. std::vector<Navmesh::Triangle*> triangles;
  202. AABB bounds;
  203. };
  204. inline const std::vector<Navmesh::Vertex*>* Navmesh::getVertices() const
  205. {
  206. return &vertices;
  207. }
  208. inline const std::vector<Navmesh::Edge*>* Navmesh::getEdges() const
  209. {
  210. return &edges;
  211. }
  212. inline const std::vector<Navmesh::Triangle*>* Navmesh::getTriangles() const
  213. {
  214. return &triangles;
  215. }
  216. inline std::vector<Navmesh::Vertex*>* Navmesh::getVertices()
  217. {
  218. return &vertices;
  219. }
  220. inline std::vector<Navmesh::Edge*>* Navmesh::getEdges()
  221. {
  222. return &edges;
  223. }
  224. inline std::vector<Navmesh::Triangle*>* Navmesh::getTriangles()
  225. {
  226. return &triangles;
  227. }
  228. inline const AABB& Navmesh::getBounds() const
  229. {
  230. return bounds;
  231. }
  232. std::tuple<bool, float, float, float> intersects(const Ray& ray, const Navmesh::Triangle* triangle);
  233. std::tuple<bool, float, float, std::size_t, std::size_t> intersects(const Ray& ray, const std::list<Navmesh::Triangle*>& triangles);
  234. std::tuple<bool, float, float, std::size_t, std::size_t> intersects(const Ray& ray, const Navmesh& mesh);
  235. #endif // NAVMESH_HPP