35#include <unordered_set>
41#if defined(JPL_ENABLE_VALIDATION)
55 template<CVec3 Vec3Type>
58 using Vec3 = Vec3Type;
61 using Array = std::pmr::vector<T>;
73 Edge& operator =(
const Edge&) =
delete;
94 Face& operator=(
const Face&) =
delete;
105 template<
class Vec3i>
117#ifdef JPL_CONVEX_BUILDER_DEBUG
171 template<
class Vec3i>
176 static constexpr float cMinTriangleAreaSq = 1.0e-12f;
178#ifdef JPL_CONVEX_BUILDER_DEBUG
187 Edge* mNeighbourEdge;
196 float DetermineCoplanarDistance()
const;
209 float GetDistanceToEdgeSq(
const Vec3&
inPoint,
const Face*
inFace)
const;
222 void GarbageCollectFaces();
231 void FreeFace(Face*
inFace);
239 static void sUnlinkFace(Face*
inFace);
246 void MergeFaces(Edge*
inEdge);
269#ifdef JPL_ENABLE_VALIDATION
280#ifdef JPL_CONVEX_BUILDER_DEBUG
291#ifdef JPL_CONVEX_BUILDER_DUMP_SHAPE
305 CoplanarList mCoplanarList;
307#ifdef JPL_CONVEX_BUILDER_DEBUG
324 template<CVec3 Vec3Type>
325 inline ConvexHullBuilder<Vec3Type>::Edge::Edge(ConvexHullBuilder<Vec3Type>::Face*
inFace,
int inStartIdx)
330 template<CVec3 Vec3Type>
339 template<CVec3 Vec3Type>
343 if (
Edge*
e = mFirstEdge)
350 }
while (
e != mFirstEdge);
355 template<CVec3 Vec3Type>
375 template<CVec3 Vec3Type>
381 template<CVec3 Vec3Type>
387 template<CVec3 Vec3Type>
391 Edge*
e = mFirstEdge;
403 mNormal = Vec3{ 0.0f, 0.0f, 0.0f };
406 for (
e =
e->mNextEdge;
e != mFirstEdge;
e =
e->mNextEdge)
420 mNormal += LengthSquared(
e1) < LengthSquared(
e2) ? CrossProduct(
e0,
e1) : CrossProduct(
e2,
e0);
431 mCentroid /=
float(n);
434 template<CVec3 Vec3Type>
435 template<
class Vec3i>
438 using IndexType = std::remove_cvref_t<decltype(std::declval<Vec3i>()[0])>;
444 poly.push_back(mFirstEdge->mStartIdx);
445 for (
Edge*
e = mFirstEdge->mNextEdge;
e != mFirstEdge;
e =
e->mNextEdge)
446 poly.push_back(
e->mStartIdx);
469 template<CVec3 Vec3Type>
473 return DotProduct(mNormal, (
inPosition - mCentroid)) > 0.0f;
477 template<CVec3 Vec3Type>
483#ifdef JPL_CONVEX_BUILDER_DEBUG
488 if (mPositions.empty())
495 Vec3
maxv = Vec3::sReplicate(-std::numeric_limits<float>::max()),
minv = Vec3::sReplicate(std::numeric_limits<float>::max());
496 for (Vec3
v : mPositions)
509 template<CVec3 Vec3Type>
515 template<CVec3 Vec3Type>
522 if (mPositions.size() < 3)
524 outError =
"Need at least 3 points to make a hull";
525 return EResult::TooFewPoints;
539 for (
int i = 0;
i < (
int)mPositions.
size(); ++
i)
541 float dist_sq = LengthSquared(mPositions[
i]);
553 for (
int i = 0;
i < (
int)mPositions.
size(); ++
i)
557 float dist_sq = LengthSquared(mPositions[
i] - mPositions[
idx1]);
571 for (
int i = 0;
i < (
int)mPositions.
size(); ++
i)
587 outError =
"Could not find a suitable initial triangle because its area was too small";
588 return EResult::Degenerate;
592 if (mPositions.size() == 3)
601 sLinkFace(
t1->mFirstEdge,
t2->mFirstEdge->mNextEdge->mNextEdge);
602 sLinkFace(
t1->mFirstEdge->mNextEdge,
t2->mFirstEdge->mNextEdge);
603 sLinkFace(
t1->mFirstEdge->mNextEdge->mNextEdge,
t2->mFirstEdge);
605#ifdef JPL_CONVEX_BUILDER_DEBUG
610 return EResult::Success;
618 for (
int i = 0;
i < (
int)mPositions.
size(); ++
i)
638 return EResult::Degenerate;
645 for (Vec3
v : mPositions)
690 f1->CalculateNormalAndCentroid(mPositions.data());
691 f2->mNormal = -
f1->mNormal;
692 f2->mCentroid =
f1->mCentroid;
694#ifdef JPL_CONVEX_BUILDER_DEBUG
699 return result == ConvexHullBuilder2D::EResult::MaxVerticesReached ? EResult::MaxVerticesReached : EResult::Success;
714 sLinkFace(
t1->mFirstEdge,
t4->mFirstEdge->mNextEdge->mNextEdge);
715 sLinkFace(
t1->mFirstEdge->mNextEdge,
t2->mFirstEdge->mNextEdge->mNextEdge);
716 sLinkFace(
t1->mFirstEdge->mNextEdge->mNextEdge,
t3->mFirstEdge->mNextEdge);
717 sLinkFace(
t2->mFirstEdge,
t4->mFirstEdge->mNextEdge);
718 sLinkFace(
t2->mFirstEdge->mNextEdge,
t3->mFirstEdge->mNextEdge->mNextEdge);
719 sLinkFace(
t3->mFirstEdge,
t4->mFirstEdge);
727#ifdef JPL_CONVEX_BUILDER_DEBUG
744 for (
Face*
f : mFaces)
760 else if (!mCoplanarList.empty())
774 if (mCoplanarList.empty())
780 typename CoplanarList::size_type
best_idx = 0;
782 for (
typename CoplanarList::size_type
idx = 1;
idx < mCoplanarList.
size(); ++
idx)
784 const Coplanar&
c = mCoplanarList[
idx];
793 std::swap(mCoplanarList[
best_idx], mCoplanarList.back());
797 mCoplanarList.pop_back();
820 return EResult::MaxVerticesReached;
833 for (
int idx :
face->mConflictList)
837 GarbageCollectFaces();
839#ifdef JPL_CONVEX_BUILDER_DEBUG
849 if (mFaces.size() < 2)
852 return EResult::TooFewFaces;
855 return EResult::Success;
858 template<CVec3 Vec3Type>
862 for (
const Face*
f : mFaces)
864 const Edge*
e =
f->mFirstEdge;
869 }
while (
e !=
f->mFirstEdge);
874 template<CVec3 Vec3Type>
877 for (
Face*
f : mFaces)
880 Array<int>::const_iterator index = std::find(
inIndices.begin(),
inIndices.end(),
e->mStartIdx);
888 if (*index !=
e->mStartIdx)
901 }
while (
e !=
f->mFirstEdge);
911 template<CVec3 Vec3Type>
912 template<
class Vec3i>
916 outTris.reserve(mFaces.size());
918 for (
const Face*
f : mFaces)
919 f->Triangulate(mPositions,
outTris);
922 template<CVec3 Vec3Type>
925 auto vec3max = [](
const Vec3& a,
const Vec3& b)
931 return Vec3{ std::abs(
GetX(
v)), std::abs(
GetY(
v)), std::abs(
GetZ(
v)) };
935 Vec3
vmax{ 0.0f, 0.0f, 0.0f };
936 for (Vec3
v : mPositions)
941 template<CVec3 Vec3Type>
952 const float dot = DotProduct(
f->mNormal,
inPoint -
f->mCentroid);
966 template<CVec3 Vec3Type>
967 inline float ConvexHullBuilder<Vec3Type>::GetDistanceToEdgeSq(
const Vec3&
inPoint,
const Face*
inFace)
const
974 Vec3
p1 = mPositions[
edge->GetPreviousEdge()->mStartIdx];
977 Vec3
p2 = mPositions[
edge->mStartIdx];
994 template<CVec3 Vec3Type>
1039 template<CVec3 Vec3Type>
1045#ifdef JPL_CONVEX_BUILDER_DEBUG
1051#ifdef JPL_ENABLE_VALIDATION
1063 for (
const FullEdge&
e :
edges)
1066 Face*
f = CreateTriangle(
e.mStartIdx,
e.mEndIdx,
inIdx);
1085 if (!
face->mRemoved)
1094 if (!
face->mRemoved)
1100#ifdef JPL_ENABLE_VALIDATION
1106 template<CVec3 Vec3Type>
1107 inline void ConvexHullBuilder<Vec3Type>::GarbageCollectFaces()
1109 for (
int i = (
int)mFaces.
size() - 1;
i >= 0; --
i)
1111 Face*
f = mFaces[
i];
1115 mFaces.erase(mFaces.begin() +
i);
1120 template<CVec3 Vec3Type>
1121 inline ConvexHullBuilder<Vec3Type>::Face* ConvexHullBuilder<Vec3Type>::CreateFace()
1126#ifdef JPL_CONVEX_BUILDER_DEBUG
1132 mFaces.push_back(
f);
1136 template<CVec3 Vec3Type>
1137 inline ConvexHullBuilder<Vec3Type>::Face* ConvexHullBuilder<Vec3Type>::CreateTriangle(
int inIdx1,
int inIdx2,
int inIdx3)
1139 Face*
f = CreateFace();
1144 template<CVec3 Vec3Type>
1145 inline void ConvexHullBuilder<Vec3Type>::FreeFace(Face*
inFace)
1149#ifdef JPL_ENABLE_VALIDATION
1151 if (Edge*
e =
inFace->mFirstEdge)
1157 }
while (
e !=
inFace->mFirstEdge);
1165 template<CVec3 Vec3Type>
1166 inline void ConvexHullBuilder<Vec3Type>::FreeFaces()
1168 for (Face*
f : mFaces)
1175 template<CVec3 Vec3Type>
1176 inline void ConvexHullBuilder<Vec3Type>::sLinkFace(Edge*
inEdge1, Edge*
inEdge2)
1192 template<CVec3 Vec3Type>
1193 inline void ConvexHullBuilder<Vec3Type>::sUnlinkFace(Face*
inFace)
1199 if (
e->mNeighbourEdge !=
nullptr)
1205 e->mNeighbourEdge->mNeighbourEdge =
nullptr;
1206 e->mNeighbourEdge =
nullptr;
1209 }
while (
e !=
inFace->mFirstEdge);
1212 template<CVec3 Vec3Type>
1234 static_assert(
alignof(Edge) >= 2,
"Need lowest bit to indicate to tell if we completed the loop");
1253 sUnlinkFace(
e->mFace);
1262 Edge*
ne =
e->mNeighbourEdge;
1265 Face* n =
ne->mFace;
1285 full.mNeighbourEdge =
ne;
1286 full.mStartIdx =
e->mStartIdx;
1287 full.mEndIdx =
ne->mStartIdx;
1296#ifdef JPL_ENABLE_VALIDATION
1301#ifdef JPL_CONVEX_BUILDER_DEBUG
1309 template<CVec3 Vec3Type>
1310 inline void ConvexHullBuilder<Vec3Type>::MergeFaces(Edge*
inEdge)
1326#ifdef JPL_CONVEX_BUILDER_DEBUG
1362 face->CalculateNormalAndCentroid(mPositions);
1365 if (
face->mFurthestPointDistanceSq >
other_face->mFurthestPointDistanceSq)
1374 face->mFurthestPointDistanceSq =
other_face->mFurthestPointDistanceSq;
1378#ifdef JPL_CONVEX_BUILDER_DEBUG
1384 template<CVec3 Vec3Type>
1388 if (LengthSquared(
inFace->mNormal) < cMinTriangleAreaSq)
1394 Vec3
p1 = mPositions[
e->mStartIdx];
1397 Edge*
next =
e->mNextEdge;
1398 Vec3
p2 = mPositions[
next->mStartIdx];
1407 }
while (
e !=
inFace->mFirstEdge);
1417 template<CVec3 Vec3Type>
1453 template<CVec3 Vec3Type>
1460 template<CVec3 Vec3Type>
1488#ifdef JPL_CONVEX_BUILDER_DEBUG
1501#ifdef JPL_CONVEX_BUILDER_DEBUG
1519#ifdef JPL_CONVEX_BUILDER_DEBUG
1541#ifdef JPL_CONVEX_BUILDER_DEBUG
1576 inFace->CalculateNormalAndCentroid(mPositions);
1579 template<CVec3 Vec3Type>
1580 inline bool ConvexHullBuilder<Vec3Type>::RemoveTwoEdgeFace(Face*
inFace, Faces&
ioAffectedFaces)
const
1588#ifdef JPL_CONVEX_BUILDER_DEBUG
1606 edge->mNeighbourEdge =
nullptr;
1618#ifdef JPL_ENABLE_VALIDATION
1619 template<CVec3 Vec3Type>
1620 inline void ConvexHullBuilder<Vec3Type>::DumpFace(
const Face*
inFace)
const
1622 std::cout << std::format(
"f:{}", std::uintptr_t(
inFace)) <<
'\n';
1624 const Edge*
e =
inFace->mFirstEdge;
1627 std::cout << std::format(
"e:{} || i:{} e:{} f:{} ",
1630 std::uintptr_t(
e->mNeighbourEdge),
1631 std::uintptr_t(
e->mNeighbourEdge->mFace)) <<
'\n';
1633 }
while (
e !=
inFace->mFirstEdge);
1636 template<CVec3 Vec3Type>
1637 inline void ConvexHullBuilder<Vec3Type>::DumpFaces()
const
1639 std::cout << std::format(
"Dump Faces:") <<
'\n';
1641 for (
const Face*
f : mFaces)
1646 template<CVec3 Vec3Type>
1647 inline void ConvexHullBuilder<Vec3Type>::ValidateFace(
const Face*
inFace)
const
1651 const Edge*
e =
inFace->mFirstEdge;
1657 }
while (
e !=
inFace->mFirstEdge);
1663 const Edge*
e =
inFace->mFirstEdge;
1670 if (mFaces.size() > 2)
1678 const Edge*
nb_edge =
e->mNeighbourEdge;
1695 }
while (
e !=
inFace->mFirstEdge);
1702 template<CVec3 Vec3Type>
1703 inline void ConvexHullBuilder<Vec3Type>::ValidateFaces()
const
1705 for (
const Face*
f : mFaces)
#define JPL_ASSERT(inExpression,...)
Main assert macro, usage: JPL_ASSERT(condition, message) or JPL_ASSERT(condition)
Definition ErrorReporting.h:76
Class that holds the information of an edge.
Definition ConvexHullBuilder.h:71
Edge(Face *inFace, int inStartIdx)
int mStartIdx
Vertex index in mPositions that indicates the start vertex of this edge.
Definition ConvexHullBuilder.h:84
Face * mFace
Face that this edge belongs to.
Definition ConvexHullBuilder.h:81
Edge * mNextEdge
Next edge of this face.
Definition ConvexHullBuilder.h:82
Edge * GetPreviousEdge()
Get the previous edge.
Definition ConvexHullBuilder.h:331
Edge * mNeighbourEdge
Edge that this edge is connected to.
Definition ConvexHullBuilder.h:83
Class that holds the information of one face.
Definition ConvexHullBuilder.h:92
bool Triangulate(std::span< const Vec3 > inPositions, Array< Vec3i > &outTris) const
Definition ConvexHullBuilder.h:436
~Face()
Definition ConvexHullBuilder.h:340
void Initialize(int inIdx0, int inIdx1, int inIdx2, std::span< const Vec3 > inPositions)
Initialize a face with three indices.
Definition ConvexHullBuilder.h:356
ConflictList mConflictList
Positions associated with this edge (that are closest to this edge). The last position in the list is...
Definition ConvexHullBuilder.h:113
Vec3 mCentroid
Center of the face.
Definition ConvexHullBuilder.h:112
Vec3 mNormal
Normal of this face, length is 2 times area of face.
Definition ConvexHullBuilder.h:111
void CalculateNormalAndCentroid(std::span< const Vec3 > inPositions)
Calculates the centroid and normal for this face.
Definition ConvexHullBuilder.h:388
bool mRemoved
Flag that indicates that face has been removed (face will be freed later)
Definition ConvexHullBuilder.h:116
float mFurthestPointDistanceSq
Squared distance of furthest point from the conflict list to the face.
Definition ConvexHullBuilder.h:115
Edge * mFirstEdge
First edge of this face.
Definition ConvexHullBuilder.h:114
bool IsFacing(const Vec3 &inPosition) const
Check if face inFace is facing inPosition.
Definition ConvexHullBuilder.h:470
Definition ConvexHullBuilder.h:57
~ConvexHullBuilder()
Definition ConvexHullBuilder.h:510
EResult
Result enum that indicates how the hull got created.
Definition ConvexHullBuilder.h:135
@ TooFewFaces
Too few faces in the created hull (signifies precision errors during building)
@ Degenerate
Degenerate hull detected.
@ Success
Hull building finished successfully.
@ TooFewPoints
Too few points to create a hull.
@ MaxVerticesReached
Hull building finished successfully, but the desired accuracy was not reached because the max vertice...
int GetNumVerticesUsed() const
Returns the amount of vertices that are currently used by the hull.
Definition ConvexHullBuilder.h:859
std::span< const Vec3 > Positions
Definition ConvexHullBuilder.h:127
Array< int > ConflictList
Definition ConvexHullBuilder.h:88
bool ContainsFace(const Array< int > &inIndices) const
Returns true if the hull contains a polygon with inIndices (counter clockwise indices in mPositions)
Definition ConvexHullBuilder.h:875
void GetTriangles(Array< Vec3i > &outTris)
Definition ConvexHullBuilder.h:913
Array< Face * > Faces
Definition ConvexHullBuilder.h:128
EResult Initialize(int inMaxVertices, float inTolerance, const char *&outError)
Definition ConvexHullBuilder.h:516
const Faces & GetFaces() const
Access to the created faces. Memory is owned by the convex hull builder.
Definition ConvexHullBuilder.h:167
void TriangulatePoly(std::span< const Vec3 > inPositions, std::span< int > poly, ContainerType< Vec3i, Args... > &outTris)
Definition Triangulation.h:80
Definition AcousticMaterial.h:36
JPL_INLINE auto GetX(const Vec3Type &v) noexcept
Definition Vec3Traits.h:35
JPL_INLINE auto GetZ(const Vec3Type &v) noexcept
Definition Vec3Traits.h:37
JPL_INLINE void DefaultDelete(T *object)
Delete object allcoated from deafult global memory resource. The object must had been allocated by ca...
Definition Memory.h:198
std::uint32_t uint32
Definition Core.h:311
std::pmr::memory_resource * GetDefaultMemoryResource() noexcept
Definition Memory.h:42
Vec3 GetClosestPointOnLine(const Vec3 &inA, const Vec3 &inB, uint32_t &outSet)
Definition ClosestPoint.h:66
JPL_INLINE auto GetY(const Vec3Type &v) noexcept
Definition Vec3Traits.h:36
JPL_INLINE simd min(const simd &a, const simd &b) noexcept
Element-wise min.
Definition SIMD.h:1813
static constexpr std::size_t size() noexcept
Get number of element of the vector.
Definition SIMD.h:97