PolygonPrismMeshUtils.h 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #pragma once
  9. #include <AzCore/std/containers/vector.h>
  10. #include <AzCore/std/containers/queue.h>
  11. #include <AzCore/Math/Vector2.h>
  12. #include <poly2tri.h>
  13. namespace PolygonPrismMeshUtils
  14. {
  15. //! The largest number of edges a polygon prism can have if it is to be represented as a PhysX convex mesh.
  16. //! Convex meshes are limited to 255 edges and (polygonal) faces. An n-sided polygon prism has n + 2 faces and
  17. //! 2n vertices, so the largest number of edges for a polygon prism which can be used with PhysX is 127. Prisms
  18. //! with more edges will need to be decomposed into a collection of simpler prisms.
  19. static const int MaxPolygonPrismEdges = 127;
  20. //! Calculates the three internal angles in a triangle.
  21. AZ::Vector3 CalculateAngles(p2t::Triangle& triangle);
  22. struct HalfEdge;
  23. //! A face in a doubly connected edge list (a data structure for efficiently manipulating meshes).
  24. struct Face
  25. {
  26. HalfEdge* m_edge = nullptr; //!< One arbitrary half-edge in this face.
  27. int m_numEdges = 0; //!< The number of edges this face has.
  28. bool m_removed = false; //!< Marks if the face has been removed due to merging with another face.
  29. };
  30. //! A half-edge in a doubly connected edge list (a data structure for efficiently manipulating meshes).
  31. //! An edge connecting two adjoining faces in the mesh is represented as two oppositely directed half-edges,
  32. //! which each half-edge belonging to one of the faces, and owning a pointer to its twin in the other face.
  33. struct HalfEdge
  34. {
  35. Face* m_face = nullptr; //!< The face this half-edge belongs to.
  36. AZ::Vector2 m_origin = AZ::Vector2::CreateZero(); //!< The point where this half-edge meets the previous half-edge.
  37. HalfEdge* m_prev = nullptr; //!< The previous half-edge.
  38. HalfEdge* m_next = nullptr; //!< The next half-edge.
  39. HalfEdge* m_twin = nullptr; //!< The half-edge which shares this edge, or nullptr if this edge has no adjacent face.
  40. float m_prevAngle = 0.0f; //!< The internal angle between this half-edge and the previous half-edge.
  41. float m_nextAngle = 0.0f; //!< The internal angle between this half-edge and the next half-edge.
  42. bool m_visited = false; //!< Marks if the half edge has been visited during the process of matching up twin edges.
  43. bool m_dirty = false; //!< Marks if an update is required because an adjacent internal edge has been removed.
  44. };
  45. //! An internal edge (twinned pair of half-edges).
  46. //! An internal edge means an edge in the interior of the mesh, so that it has two connected faces, as opposed to
  47. //! an edge on the exterior of the mesh, which would only be connected to one face. The smallest of the four
  48. //! internal angles between this edge and the adjacent edges of the two connected faces is used to prioritize
  49. //! which internal edges to remove when merging faces to produce a convex decomposition.
  50. struct InternalEdge
  51. {
  52. HalfEdge* m_edges[2] = { nullptr, nullptr }; //!< The two half-edges which together make up the internal edge.
  53. float m_minAngle = 0.0f; //!< The smallest of the four angles between this edge and adjacent edges.
  54. };
  55. //! Sorts internal edges so that the edges with small adjacent angles are considered for removal first.
  56. struct InternalEdgeCompare
  57. {
  58. bool operator()(const InternalEdge& left, const InternalEdge& right) const;
  59. };
  60. using InternalEdgePriorityQueue = AZStd::priority_queue<InternalEdge, AZStd::vector<InternalEdge>, InternalEdgeCompare>;
  61. //! A collection of Face and HalfEdge objects used to represent a 2d mesh.
  62. class Mesh2D
  63. {
  64. public:
  65. //! Populates this mesh from a set of triangles obtained from poly2tri.
  66. void CreateFromPoly2Tri(const std::vector<p2t::Triangle*>& triangles);
  67. //! Populates this mesh from a simple convex polygon.
  68. void CreateFromSimpleConvexPolygon(const AZStd::vector<AZ::Vector2>& vertices);
  69. //! Removes an internal edge of the mesh.
  70. //! The first of the two faces connected to the edge is updated in place to hold the merged face.
  71. //! The other face is marked as removed, but not deleted from the collection.
  72. void RemoveInternalEdge(const InternalEdge& internalEdge);
  73. //! Iteratively merges faces in the mesh if it is possible to do so while maintaining convexity.
  74. //! Internal edges of the mesh are considered for removal in an order based on
  75. //! @return The number of faces which have been removed during the merging process.
  76. size_t ConvexMerge();
  77. const AZStd::vector<Face>& GetFaces() const;
  78. const InternalEdgePriorityQueue& GetInternalEdges() const;
  79. const AZStd::vector<AZ::Vector3>& GetDebugDrawPoints(float height, const AZ::Vector3& nonUniformScale) const;
  80. void SetDebugDrawDirty();
  81. void Clear();
  82. private:
  83. //! Together with m_faces, composes the doubly connected edge list representation of the decomposed polygon prism.
  84. AZStd::vector<HalfEdge> m_halfEdges;
  85. //! Together with m_halfEdges, composes the doubly connected edge list representation of the decomposed polygon prism.
  86. AZStd::vector<Face> m_faces;
  87. //! A queue used to remove internal edges in order based on eliminating small angles from the decomposition first.
  88. InternalEdgePriorityQueue m_edgeQueue;
  89. //! Used for caching debug draw vertices.
  90. mutable AZStd::vector<AZ::Vector3> m_debugDrawPoints;
  91. //! Used to track when to recalculate the cached debug draw vertices.
  92. mutable bool m_debugDrawDirty = true;
  93. };
  94. } // namespace PolygonPrismMeshUtils