|
|
- /*
- * Copyright (C) 2017 Christopher J. Howard
- *
- * This file is part of Antkeeper Source Code.
- *
- * Antkeeper Source Code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Antkeeper Source Code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
- */
-
- #ifndef NAVMESH_HPP
- #define NAVMESH_HPP
-
- #include <iostream>
- #include <string>
- #include <tuple>
- #include <vector>
-
- #include <emergent/emergent.hpp>
- using namespace Emergent;
-
- /**
- * Navigation mesh represented by a half-edge structure.
- *
- * @ingroup geometry
- */
- class Navmesh
- {
- public:
- struct Vertex;
- struct Edge;
- struct Triangle;
- struct Step;
-
- /**
- * Creates an instance of Navmesh.
- */
- Navmesh();
-
- /**
- * Destroys an instance of Navmesh.
- */
- ~Navmesh();
-
- /**
- * Forms a navmesh from a list of vertices and indices.
- *
- * @param vertices Specifies a list of vertices.
- * @param indices Specifies a list of indices.
- * @return `true` if the navmesh was successfully created, `false` otherwise.
- */
- bool create(const std::vector<Vector3>& vertices, const std::vector<std::size_t>& indices);
-
- /**
- * Destroys the navmesh.
- */
- void destroy();
-
- /**
- * 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 `#`.
- *
- * @param filename Path to the Wavefront OBJ file.
- * @return `true` if the navmesh was successfully loaded from the OBJ file, `false` otherwise.
- */
- bool loadOBJ(const std::string& filename);
-
- /**
- * Traverses the navmesh.
- *
- * @param[in] startTriangle Initial triangle
- * @param[in] startPosition Initial barycentric coordinates on the start triangle
- * @param[in] startVelocity Initial cartesian velocity vector
- * @param[out] traversal Traversal information
- */
- static void traverse(Navmesh::Triangle* startTriangle, const Vector3& startPosition, const Vector3& startVelocity, std::vector<Navmesh::Step>* traversal);
-
- /**
- * Creates an octree of navmesh triangles
- */
- Octree<Navmesh::Triangle*>* createOctree(std::size_t maxDepth);
-
- /// Returns a pointer to the navmesh vertices
- const std::vector<Navmesh::Vertex*>* getVertices() const;
-
- /// Returns a pointer to the navmesh edges
- const std::vector<Navmesh::Edge*>* getEdges() const;
-
- /// Returns a pointer to the navmesh triangles
- const std::vector<Navmesh::Triangle*>* getTriangles() const;
-
- /// @copydoc Navmesh::getVertices() const
- std::vector<Navmesh::Vertex*>* getVertices();
-
- /// @copydoc Navmesh::getEdges() const
- std::vector<Navmesh::Edge*>* getEdges();
-
- /// @copydoc Navmesh::getTriangles() const
- std::vector<Navmesh::Triangle*>* getTriangles();
-
- /// Returns an AABB which contains this navmesh
- const AABB& getBounds() const;
-
- /**
- * Half-edge vertex which contains a pointer to its parent edge, a position vector, and an index.
- */
- struct Vertex
- {
- /// Pointer to the edge to which this vertex belongs
- Navmesh::Edge* edge;
-
- /// Vertex position vector
- Vector3 position;
-
- /// Vertex flags
- unsigned char flags;
-
- /// Index of this vertex
- std::size_t index;
- };
-
- /**
- * Half-edge edge which contains pointers to its starting vertex, parent triangle, and related edges.
- */
- struct Edge
- {
- /// Pointer to the vertex at which the edge starts
- Navmesh::Vertex* vertex;
-
- /// Pointer to the triangle to which this edge belongs
- Navmesh::Triangle* triangle;
-
- /// Pointer to the previous edge in the parent triangle
- Navmesh::Edge* previous;
-
- /// Pointer to the next edge in the parent triangle
- Navmesh::Edge* next;
-
- /// Pointer to the symmetric edge
- Navmesh::Edge* symmetric;
-
- /// Edge flags
- unsigned char flags;
-
- /// Index of this edge
- std::size_t index;
- };
-
- /**
- * Half-edge triangle which contains a pointer to its first edge and its normal vector.
- */
- struct Triangle
- {
- /// Pointer to the first edge in this triangle
- Navmesh::Edge* edge;
-
- /// Faceted surface normal
- Vector3 normal;
-
- /// Triangle flags
- unsigned char flags;
-
- /// Index of this triangle
- std::size_t index;
- };
-
- /**
- * Contains informations about a single step in a navmesh traversal operation.
- */
- struct Step
- {
- /// Pointer to the triangle on which the step occured
- Triangle* triangle;
-
- /// Barycentric coordinates of the step's starting position
- Vector3 start;
-
- /// Barycentric coordinates of the step's ending position
- Vector3 end;
-
- /// Pointer to the edge on which the step exited the triangle, or `nullptr` if the step is within the triangle
- Edge* edge;
- };
-
- /**
- * Calculates the faceted surface normals for each triangle.
- */
- void calculateNormals();
-
- /**
- * Calculates an AABB which contains the navmesh.
- */
- void calculateBounds();
-
- private:
- /**
- * Reads Wavefront OBJ data from an input stream
- *
- * @param stream Input stream containing OBJ data
- * @param filename Path to the OBJ file
- * @return `true` if OBJ data was successfully read from the file.
- */
- bool readOBJ(std::istream* stream, const std::string& filename);
-
- /**
- * Calculates barycentric coordinates from cartesian coordinates.
- *
- * @param p Cartesian point
- * @param a First vertex in triangle
- * @param b Second vertex in triangle
- * @param c Third vertex in triangle
- */
- static Vector3 barycentric(const Vector3& p, const Vector3& a, const Vector3& b, const Vector3& c);
-
- /**
- * Calculates cartesian coordinates from barycentric coordinates.
- *
- * @param p Barycentric point
- * @param a First vertex in triangle
- * @param b Second vertex in triangle
- * @param c Third vertex in triangle
- */
- static Vector3 cartesian(const Vector3& p, const Vector3& a, const Vector3& b, const Vector3& c);
-
- /**
- * Finds the closest point on a triangle.
- *
- * @param[in] p Point to project
- * @param[in] triangle Triangle on which to find the closest point
- * @param[out] closest Closest point on triangle
- * @param[out] edge Edge on which the closest point is located, or `nullptr` if the closest point is not on an edge.
- */
- static void closestPointOnTriangle(const Vector3& p, const Navmesh::Triangle* triangle, Vector3* closestPoint, Navmesh::Edge** closestEdge);
-
- std::vector<Navmesh::Vertex*> vertices;
- std::vector<Navmesh::Edge*> edges;
- std::vector<Navmesh::Triangle*> triangles;
- AABB bounds;
- };
-
- inline const std::vector<Navmesh::Vertex*>* Navmesh::getVertices() const
- {
- return &vertices;
- }
-
- inline const std::vector<Navmesh::Edge*>* Navmesh::getEdges() const
- {
- return &edges;
- }
-
- inline const std::vector<Navmesh::Triangle*>* Navmesh::getTriangles() const
- {
- return &triangles;
- }
-
- inline std::vector<Navmesh::Vertex*>* Navmesh::getVertices()
- {
- return &vertices;
- }
-
- inline std::vector<Navmesh::Edge*>* Navmesh::getEdges()
- {
- return &edges;
- }
-
- inline std::vector<Navmesh::Triangle*>* Navmesh::getTriangles()
- {
- return &triangles;
- }
-
- inline const AABB& Navmesh::getBounds() const
- {
- return bounds;
- }
-
- std::tuple<bool, float, float, float> intersects(const Ray& ray, const Navmesh::Triangle* triangle);
- std::tuple<bool, float, float, std::size_t, std::size_t> intersects(const Ray& ray, const std::list<Navmesh::Triangle*>& triangles);
-
- std::tuple<bool, float, float, std::size_t, std::size_t> intersects(const Ray& ray, const Navmesh& mesh);
-
- #endif // NAVMESH_HPP
|