// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics) // SPDX-FileCopyrightText: 2021 Jorrit Rouwe // SPDX-License-Identifier: MIT #pragma once #include //#define JPH_CONVEX_BUILDER_2D_DEBUG JPH_NAMESPACE_BEGIN /// A convex hull builder that tries to create 2D hulls as accurately as possible. Used for offline processing. class JPH_EXPORT ConvexHullBuilder2D : public NonCopyable { public: using Positions = Array; using Edges = Array; /// Constructor /// @param inPositions Positions used to make the hull. Uses X and Y component of Vec3 only! explicit ConvexHullBuilder2D(const Positions &inPositions); /// Destructor ~ConvexHullBuilder2D(); /// Result enum that indicates how the hull got created enum class EResult { Success, ///< Hull building finished successfully MaxVerticesReached, ///< Hull building finished successfully, but the desired accuracy was not reached because the max vertices limit was reached }; /// Takes all positions as provided by the constructor and use them to build a hull /// Any points that are closer to the hull than inTolerance will be discarded /// @param inIdx1 , inIdx2 , inIdx3 The indices to use as initial hull (in any order) /// @param inMaxVertices Max vertices to allow in the hull. Specify INT_MAX if there is no limit. /// @param inTolerance Max distance that a point is allowed to be outside of the hull /// @param outEdges On success this will contain the list of indices that form the hull (counter clockwise) /// @return Status code that reports if the hull was created or not EResult Initialize(int inIdx1, int inIdx2, int inIdx3, int inMaxVertices, float inTolerance, Edges &outEdges); private: #ifdef JPH_CONVEX_BUILDER_2D_DEBUG /// Factor to scale convex hull when debug drawing the construction process static constexpr Real cDrawScale = 10; #endif class Edge; /// Frees all edges void FreeEdges(); /// Assigns a position to one of the supplied edges based on which edge is closest. /// @param inPositionIdx Index of the position to add /// @param inEdges List of edges to consider void AssignPointToEdge(int inPositionIdx, const Array &inEdges) const; #ifdef JPH_CONVEX_BUILDER_2D_DEBUG /// Draw state of algorithm void DrawState(); #endif #ifdef JPH_ENABLE_ASSERTS /// Validate that the edge structure is intact void ValidateEdges() const; #endif using ConflictList = Array; /// Linked list of edges class Edge { public: JPH_OVERRIDE_NEW_DELETE /// Constructor explicit Edge(int inStartIdx) : mStartIdx(inStartIdx) { } /// Calculate the center of the edge and the edge normal void CalculateNormalAndCenter(const Vec3 *inPositions); /// Check if this edge is facing inPosition inline bool IsFacing(Vec3Arg inPosition) const { return mNormal.Dot(inPosition - mCenter) > 0.0f; } Vec3 mNormal; ///< Normal of the edge (not normalized) Vec3 mCenter; ///< Center of the edge ConflictList mConflictList; ///< Positions associated with this edge (that are closest to this edge). Last entry is the one furthest away from the edge, remainder is unsorted. Edge * mPrevEdge = nullptr; ///< Previous edge in circular list Edge * mNextEdge = nullptr; ///< Next edge in circular list int mStartIdx; ///< Position index of start of this edge float mFurthestPointDistanceSq = 0.0f; ///< Squared distance of furthest point from the conflict list to the edge }; const Positions & mPositions; ///< List of positions (some of them are part of the hull) Edge * mFirstEdge = nullptr; ///< First edge of the hull int mNumEdges = 0; ///< Number of edges in hull #ifdef JPH_CONVEX_BUILDER_2D_DEBUG RVec3 mOffset; ///< Offset to use for state drawing Vec3 mDelta; ///< Delta offset between next states #endif }; JPH_NAMESPACE_END