#pragma once #include #include #include #include namespace J3ML::Geometry { using namespace J3ML::LinearAlgebra; // Represents a three-dimensional closed geometric solid defined by flat polygonal faces. class Polyhedron { public: // Stores a list of indices of a single face of a Polygon struct Face { // Specifies the indices of the corner vertices of the polyhedron. // Indices point to the polyhedron vertex array. // The face vertices should all lie on the same plane. // The positive direction of the plane (the direction the face outwards normal points) // is the one where the vertices are wound in counter-clockwise order. std::vector v; // Reverses the winding order of this face. This has the effect of reversing the direction // the normal of this face points to. void FlipWindingOrder(); }; // Specifies the vertices of this polyhedron. std::vector v; std::vector f; public: /// The default constructor creates a null polyhedron. /** The null polyhedron has 0 vertices and 0 faces. @see IsNull(). */ Polyhedron() = default; [[nodiscard]] int NumVertices() const {return (int)v.size();} [[nodiscard]] int NumFaces() const { return (int)f.size();} [[nodiscard]] AABB MinimalEnclosingAABB() const; [[nodiscard]] Vector3 Vertex(int vertexIndex) const; [[nodiscard]] bool Contains(const Vector3&) const; [[nodiscard]] bool Contains(const LineSegment&) const; [[nodiscard]] bool Contains(const Triangle&) const; [[nodiscard]] bool Contains(const Polygon&) const; [[nodiscard]] bool Contains(const AABB&) const; [[nodiscard]] bool Contains(const OBB&) const; [[nodiscard]] bool Contains(const Frustum&) const; [[nodiscard]] bool Contains(const Polyhedron&) const; [[nodiscard]] bool ContainsConvex(const Vector3&, float epsilon = 1e-4f) const; [[nodiscard]] bool ContainsConvex(const LineSegment&) const; [[nodiscard]] bool ContainsConvex(const Triangle&) const; /// Tests whether this polyhedron and the given object intersect. /** Both objects are treated as "solid", meaning that if one of the objects is fully contained inside another, this function still returns true. (e.g. in case a line segment is contained inside this polyhedron, or this polyhedron is contained inside a sphere, etc.) @return True if an intersection occurs or one of the objects is contained inside the other, false otherwise. @note This function assumes that this polyhedron is closed and the edges are not self-intersecting. @see Contains(), ContainsConvex(), ClosestPoint(), ClosestPointConvex(), Distance(), IntersectsConvex(). @todo Add Intersects(Circle/Disc). */ [[nodiscard]] bool Intersects(const Line&) const; [[nodiscard]] bool Intersects(const LineSegment&) const; [[nodiscard]] bool Intersects(const Ray&) const; [[nodiscard]] bool Intersects(const Plane&) const; [[nodiscard]] bool Intersects(const Polyhedron&) const; [[nodiscard]] bool Intersects(const AABB& aabb) const; [[nodiscard]] bool Intersects(const OBB&) const; [[nodiscard]] bool Intersects(const Triangle&) const; [[nodiscard]] bool Intersects(const Polygon&) const; [[nodiscard]] bool Intersects(const Frustum&) const; [[nodiscard]] bool Intersects(const Sphere&) const; [[nodiscard]] bool Intersects(const Capsule& capsule) const; [[nodiscard]] bool IsClosed() const; [[nodiscard]] Plane FacePlane(int faceIndex) const; [[nodiscard]] std::vector Faces() const; [[nodiscard]] int NumEdges() const; [[nodiscard]] LineSegment Edge(int edgeIndex) const; [[nodiscard]] std::vector> EdgeIndices() const; [[nodiscard]] std::vector Edges() const; [[nodiscard]] Polygon FacePolygon(int faceIndex) const; [[nodiscard]] Vector3 FaceNormal(int faceIndex) const; [[nodiscard]] bool IsConvex() const; /// Returns true if the Euler formula (V + F - E == 2) holds for this Polyhedron. /** The running time is O(E) ~ O(V). @see NumVertices(), NumEdges(), NumFaces(). */ [[nodiscard]] bool EulerFormulaHolds() const; [[nodiscard]] Vector3 ApproximateConvexCentroid() const; [[nodiscard]] int ExtremeVertex(const Vector3 &direction) const; [[nodiscard]] Vector3 ExtremePoint(const Vector3 &direction) const; /// Tests if the given face of this Polyhedron contains the given point. [[nodiscard]] bool FaceContains(int faceIndex, const Vector3 &worldSpacePoint, float polygonThickness = 1e-3f) const; /// A helper for Contains() and FaceContains() tests: Returns a positive value if the given point is contained in the given face, /// and a negative value if the given point is outside the face. The magnitude of the return value reports a pseudo-distance /// from the point to the nearest edge of the face polygon. This is used as a robustness/stability criterion to estimate how /// numerically believable the result is. [[nodiscard]] float FaceContainmentDistance2D(int faceIndex, const Vector3 &worldSpacePoint, float polygonThickness = 1e-5f) const; void ProjectToAxis(const Vector3 &direction, float &outMin, float &outMax) const; Vector3 ClosestPoint(const LineSegment& lineSegment, Vector3 *lineSegmentPt) const; [[nodiscard]] Vector3 ClosestPoint(const Vector3& point) const; /// Returns true if this polyhedron has 0 vertices and 0 faces. bool IsNull() const { return v.empty() && f.empty(); } protected: private: }; }