UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
Tetrahedron.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5#include "Chaos/AABB.h"
6#include "Chaos/Core.h"
7#include "Chaos/Triangle.h"
8#include "Chaos/Plane.h"
9#include "Chaos/Math/Poisson.h" // 3x3 row major matrix functions
11#include <limits>
12
13
14namespace Chaos {
15
16 template <typename T>
18 {
19 public:
21 {
22 }
23
24 TTetrahedron(const TVec3<T>& In1, const TVec3<T>& In2, const TVec3<T>& In3, const TVec3<T>& In4)
25 : X{ In1, In2, In3, In4 }
26 {
27 }
28
34
36 {
37 checkSlow(InIndex < 4);
38 return X[InIndex];
39 }
40
41 void Invert()
42 {
43 Swap(X[0], X[1]);
44 }
45
47 {
48 return static_cast<T>(.25) * (X[0] + X[1] + X[2] + X[3]);
49 }
50
51 bool HasBoundingBox() const { return true; }
54 {
56 for (int32 i = 0; i < 4; i++)
57 {
58 Box.GrowToInclude(X[i]);
59 }
60 return Box;
61 }
62
64 {
65 return FMath::Min(
66 FMath::Min3((X[0] - X[1]).SizeSquared(), (X[1] - X[2]).SizeSquared(), (X[2] - X[0]).SizeSquared()),
67 FMath::Min3((X[0] - X[3]).SizeSquared(), (X[1] - X[3]).SizeSquared(), (X[2] - X[3]).SizeSquared()));
68 }
69
71 {
72 return FMath::Sqrt(GetMinEdgeLengthSquared());
73 }
74
76 {
77 return FMath::Max(
78 FMath::Max3((X[0] - X[1]).SizeSquared(), (X[1] - X[2]).SizeSquared(), (X[2] - X[0]).SizeSquared()),
79 FMath::Max3((X[0] - X[3]).SizeSquared(), (X[1] - X[3]).SizeSquared(), (X[2] - X[3]).SizeSquared()));
80 }
81
83 {
84 return FMath::Sqrt(GetMaxEdgeLengthSquared());
85 }
86
87 T GetVolume() const
88 {
89 return fabs(GetSignedVolume());
90 }
91
93 {
94 TVec3<T> U = X[1] - X[0];
95 TVec3<T> V = X[2] - X[0];
96 TVec3<T> W = X[3] - X[0];
97 return TripleProduct(U, V, W) / 6;
98 }
99
101 {
103 TVec4<T> Distance(0, 0, 0, 0);
104 for (int32 i = 0; i < 4; i++)
105 {
106 const TTriangle<T>& Tri = Tris[i];
108 Distance[i] = -Tri.PhiWithNormal(X[3 - i], Norm);
109 }
111 {
112 (*MinAltitudeVertex) = 0;
113 }
114 T MinAltitude = Distance[0];
115 for (int32 i = 0; i < 4; i++)
116 {
117 if (Distance[i] < MinAltitude)
118 {
121 {
122 (*MinAltitudeVertex) = i;
123 }
124 }
125 }
127 {
128 (*MinAltitudeVertex) = 4 - (*MinAltitudeVertex);
129 }
130 return MinAltitude;
131 }
132
134 {
136 }
137
139 {
140 TVec3<T> L1 = X[0] - X[3];
141 TVec3<T> L2 = X[1] - X[3];
142 TVec3<T> L3 = X[2] - X[3];
143 TVec3<T> RHS = Location - X[3];
144 T Matrix[9] =
145 {
146 L1[0], L2[0], L3[0],
147 L1[1], L2[1], L3[1],
148 L1[2], L2[2], L3[2]
149 };
151 }
152
154 {
156 return TVec4<T>(W[0], W[1], W[2], static_cast<T>(1.0) - W[0] - W[1] - W[2]);
157 }
158
160 {
161 return Weights[0] * X[0] + Weights[1] * X[1] + Weights[2] * X[2] + Weights[3] * (static_cast<T>(1.0) - Weights[0] - Weights[1] - Weights[2]);
162 }
163
165 {
166 return Weights[0] * X[0] + Weights[1] * X[1] + Weights[2] * X[2] + Weights[3] * X[3];
167 }
168
169 bool BarycentricInside(const TVec3<T>& Location, const T Tolerance=0) const
170 {
172 return Weights[0] >= Tolerance && Weights[1] >= Tolerance && Weights[2] >= Tolerance && Weights[0]+Weights[1]+Weights[2] <= 1+Tolerance;
173 }
174
175 FString ToString() const
176 {
177 return FString::Printf(TEXT("Tetrahedron: A: [%f, %f, %f], B: [%f, %f, %f], C: [%f, %f, %f], D: [%f, %f, %f]"),
178 X[0][0], X[0][1], X[0][2],
179 X[1][0], X[1][1], X[1][2],
180 X[2][0], X[2][1], X[2][2]);
181 }
182
185 {
186 TArray<TTriangle<T>> Triangles;
187 Triangles.SetNumUninitialized(4);
188 if (GetSignedVolume() <= 0)
189 {
190 Triangles[0] = TTriangle<T>(X[0], X[1], X[2]);
191 Triangles[1] = TTriangle<T>(X[0], X[3], X[1]);
192 Triangles[2] = TTriangle<T>(X[0], X[2], X[3]);
193 Triangles[3] = TTriangle<T>(X[1], X[3], X[2]);
194 }
195 else
196 {
197 Triangles[0] = TTriangle<T>(X[0], X[2], X[1]);
198 Triangles[1] = TTriangle<T>(X[0], X[1], X[3]);
199 Triangles[2] = TTriangle<T>(X[0], X[3], X[2]);
200 Triangles[3] = TTriangle<T>(X[1], X[2], X[3]);
201 }
202 return Triangles;
203 }
204
205 bool Inside(const TVec3<T>& Location, const T HalfThickness=0) const
206 {
209 }
210
211 static bool Inside(const TArray<TTriangle<T>>& Tris, const TVec3<T>& Location, const T HalfThickness=0)
212 {
213 checkSlow(Tris.Num() == 4);
214
215 for(int32 i=0; i < Tris.Num(); i++)
216 if (!Inside(Tris[i].GetPlane(), Location, -HalfThickness))
217 {
218 return false;
219 }
220 return true;
221 }
222
223 bool Outside(const TVec3<T>& Location, const T HalfThickness = 0) const
224 {
227 }
228
229 static bool Outside(const TArray<TTriangle<T>>& Tris, const TVec3<T>& Location, const T HalfThickness = 0)
230 {
231 checkSlow(Tris.Num() == 4);
232 for (int32 i = 0; i < Tris.Num(); i++)
233 if (Outside(Tris[i].GetPlane(), Location, HalfThickness))
234 {
235 return true;
236 }
237 return false;
238 }
239
241 bool RobustInside(const TVec3<T>& Location, const T Tolerance=0) const
242 {
243 T V1 = TripleProduct(Location - X[0], X[1] - X[0], X[2] - X[0]);
244 T V2 = TripleProduct(X[3] - X[0], X[1] - X[0], Location - X[0]);
245 T V3 = TripleProduct(X[3] - X[0], Location - X[0], X[2] - X[0]);
246 T V4 = TripleProduct(X[3] - Location, X[1] - Location, X[2] - Location);
247 return !(fabs(V1) <= Tolerance || fabs(V2) <= Tolerance || fabs(V3) <= Tolerance || fabs(V4) <= Tolerance ||
248 (Sign(V1) != Sign(V2) || Sign(V2) != Sign(V3) || Sign(V3) != Sign(V4)));
249 }
250
251 // Note: this method will fail to project to the actual surface if Location is outside and the closest point is
252 // on an edge with an acute angle such that Location is outside both connected faces. FindClosestPointAndBary will work in this case.
254 {
255 if (Inside(Tris, Location))
256 {
257 int32 Idx = 0;
258 T Dist = TVec3<T>::DotProduct(Tris[0][0] - Location, Tris[0].GetNormal());
259 T DistTemp = TVec3<T>::DotProduct(Tris[1][0] - Location, Tris[1].GetNormal());
260 if (DistTemp < Dist)
261 {
262 Idx = 1;
263 Dist = DistTemp;
264 }
265 DistTemp = TVec3<T>::DotProduct(Tris[2][0] - Location, Tris[2].GetNormal());
266 if (DistTemp < Dist)
267 {
268 Idx = 2;
269 Dist = DistTemp;
270 }
271 DistTemp = TVec3<T>::DotProduct(Tris[3][0] - Location, Tris[3].GetNormal());
272 if (DistTemp < Dist)
273 {
274 Idx = 3;
275 Dist = DistTemp;
276 }
277 return Location + Dist * Tris[Idx].GetNormal();
278 }
279 else
280 {
282 for (int32 i = 0; i < 4; i++)
283 {
284 if (Tris[i].GetPlane().SignedDistance(SurfacePoint) > static_cast<T>(0.0))
285 {
286 const TVec3<T> Norm = Tris[i].GetNormal();
288 }
289 }
290 return SurfacePoint;
291 }
292 }
293
294 // Tolerance should be small negative number or zero. It is used to compare barycentric coordinate values
295 TVec3<T> FindClosestPointAndBary(const TVec3<T>& Location, TVec4<T>& OutBary, const T Tolerance = 0) const
296 {
298 if (TetWeights[0] >= Tolerance && TetWeights[1] >= Tolerance && TetWeights[2] >= Tolerance && TetWeights[0] + TetWeights[1] + TetWeights[2] <= 1 + Tolerance)
299 {
300 // Inside tetrahedron
301 OutBary = TVec4<T>(TetWeights[0], TetWeights[1], TetWeights[2], static_cast<T>(1.0) - TetWeights[0] - TetWeights[1] - TetWeights[2]);
303 return Location;
304 }
305
306 // Test closest point is inside a face
307 const bool IsInverted = GetSignedVolume() <= 0;
308 static const TVec3<int32> InvertedTriangleIndices[4] =
309 {
310 TVec3<int32>(0,1,2),
311 TVec3<int32>(0,3,1),
312 TVec3<int32>(0,2,3),
313 TVec3<int32>(1,3,2)
314 };
316 {
317 TVec3<int32>(0,2,1),
318 TVec3<int32>(0,1,3),
319 TVec3<int32>(0,3,2),
320 TVec3<int32>(1,2,3)
321 };
323 for (int32 FaceId = 0; FaceId < 4; ++FaceId)
324 {
325 const TVec3<int32>& TriIndices = FaceIndices[FaceId];
326 const TTriangle<T> Tri(X[TriIndices[0]], X[TriIndices[1]], X[TriIndices[2]]);
327 const TPlaneConcrete<T, 3> Plane = Tri.GetPlane(0);
328 const T Dist = TVec3<T>::DotProduct(Location - Plane.X(), Plane.Normal());
329 if (Dist >= 0)
330 {
331 // Point is on front-face side of tri.
332 const TVec3<T> ClosestPointOnPlane = Location - Dist * Plane.Normal();
333 const TVec2<T> TriBary = ComputeBarycentricInPlane(Tri[0], Tri[1], Tri[2], ClosestPointOnPlane);
334 if (TriBary[0] >= Tolerance && TriBary[1] >= Tolerance && TriBary[0] + TriBary[1] <= 1 + Tolerance)
335 {
336 OutBary = TVec4<T>(static_cast<T>(0.));
337 OutBary[TriIndices[1]] = TriBary[0];
338 OutBary[TriIndices[2]] = TriBary[1];
339 OutBary[TriIndices[0]] = static_cast<T>(1.) - TriBary[0] - TriBary[1];
341 return ClosestPointOnPlane;
342 }
343 }
344 }
345
346 // Closest point is on an edge/vertex
347 static const TVec2<int32> EdgeIndices[6] =
348 {
349 TVec2<int32>(0,1),
350 TVec2<int32>(0,2),
351 TVec2<int32>(0,3),
352 TVec2<int32>(1,2),
353 TVec2<int32>(1,3),
354 TVec2<int32>(2,3)
355 };
357 T ClosestEdgeAlpha(0);
359 T ClosestEdgeDistSq = std::numeric_limits<T>::max();
360 for (int32 EdgeIndex = 0; EdgeIndex < 6; ++EdgeIndex)
361 {
362 T Alpha;
363 const TVec3<T> ClosestPoint = FindClosestPointAndAlphaOnLineSegment(X[EdgeIndices[EdgeIndex][0]], X[EdgeIndices[EdgeIndex][1]], Location, Alpha);
364 const T DistSq = TVec3<T>::DistSquared(Location, ClosestPoint);
366 {
368 ClosestEdgePoint = ClosestPoint;
370 ClosestEdgeIndex = EdgeIndex;
371 }
372 }
374
375 OutBary = TVec4<T>(static_cast<T>(0.));
376 OutBary[EdgeIndices[ClosestEdgeIndex][0]] = static_cast<T>(1.) - ClosestEdgeAlpha;
377 OutBary[EdgeIndices[ClosestEdgeIndex][1]] = ClosestEdgeAlpha;
379 return ClosestEdgePoint;
380 }
381
382 private:
383 static T TripleProduct(const TVec3<T>& U, const TVec3<T>& V, const TVec3<T>& W)
384 {
386 }
387
388 static int32 Sign(const T Value)
389 {
390 return Value < static_cast<T>(0) ? -1 : 1;
391 }
392
393 static bool Inside(const TPlane<T, 3>& Plane, const TVec3<T>& Location, const T HalfThickness = 0)
394 {
395 return Plane.SignedDistance(Location) <= -HalfThickness;
396 }
397
398 static bool Outside(const TPlane<T, 3>& Plane, const TVec3<T>& Location, const T HalfThickness = 0)
399 {
401 }
402
404
405 TVec3<T> X[4];
406 };
407
409
410 template <typename T>
412 {
413 Ar << Value.X[0] << Value.X[1] << Value.X[2] << Value.X[3];
414 return Ar;
415 }
416
417} // namespace Chaos
#define FORCEINLINE
Definition AndroidPlatform.h:140
#define checkSlow(expr)
Definition AssertionMacros.h:332
@ INDEX_NONE
Definition CoreMiscDefines.h:150
#define TEXT(x)
Definition Platform.h:1272
FPlatformTypes::int32 int32
A 32-bit signed integer.
Definition Platform.h:1125
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
#define X(Name, Desc)
Definition FormatStringSan.h:47
#define UE_SMALL_NUMBER
Definition UnrealMathUtility.h:130
uint32_t uint32
Definition binka_ue_file_header.h:6
Definition ChaosArchive.h:167
Definition AABB.h:37
static FORCEINLINE TAABB< T, d > EmptyAABB()
Definition AABB.h:623
Definition CorePlane.h:12
Definition Tetrahedron.h:18
T GetVolume() const
Definition Tetrahedron.h:87
bool Inside(const TVec3< T > &Location, const T HalfThickness=0) const
Definition Tetrahedron.h:205
TTetrahedron()
Definition Tetrahedron.h:20
TVec3< T > GetCenter() const
Definition Tetrahedron.h:46
static bool Outside(const TArray< TTriangle< T > > &Tris, const TVec3< T > &Location, const T HalfThickness=0)
Definition Tetrahedron.h:229
bool BarycentricInside(const TVec3< T > &Location, const T Tolerance=0) const
Definition Tetrahedron.h:169
T GetSignedVolume() const
Definition Tetrahedron.h:92
TVec4< T > GetBarycentricCoordinates(const TVec3< T > &Location) const
Definition Tetrahedron.h:153
bool RobustInside(const TVec3< T > &Location, const T Tolerance=0) const
Tolerance should be a small negative number to include boundary.
Definition Tetrahedron.h:241
T GetMaxEdgeLength() const
Definition Tetrahedron.h:82
bool Outside(const TVec3< T > &Location, const T HalfThickness=0) const
Definition Tetrahedron.h:223
TArray< TTriangle< T > > GetTriangles() const
Initialize outward facing triangles, regardless of the orientation of the tetrahedron.
Definition Tetrahedron.h:184
bool HasBoundingBox() const
Definition Tetrahedron.h:51
TAABB< T, 3 > BoundingBox() const
Definition Tetrahedron.h:52
TVec3< T > GetFirstThreeBarycentricCoordinates(const TVec3< T > &Location) const
Definition Tetrahedron.h:138
TVec3< T > GetPointFromBarycentricCoordinates(const TVec4< T > &Weights) const
Definition Tetrahedron.h:164
T GetAspectRatio() const
Definition Tetrahedron.h:133
TVec3< T > GetPointFromBarycentricCoordinates(const TVec3< T > &Weights) const
Definition Tetrahedron.h:159
FORCEINLINE const TVec3< T > & operator[](uint32 InIndex) const
Definition Tetrahedron.h:35
T GetMaxEdgeLengthSquared() const
Definition Tetrahedron.h:75
FORCEINLINE TVec3< T > & operator[](uint32 InIndex)
Definition Tetrahedron.h:29
T GetMinEdgeLengthSquared() const
Definition Tetrahedron.h:63
TTetrahedron(const TVec3< T > &In1, const TVec3< T > &In2, const TVec3< T > &In3, const TVec3< T > &In4)
Definition Tetrahedron.h:24
TVec3< T > ProjectToSurface(const TArray< TTriangle< T > > &Tris, const TVec3< T > &Location) const
Definition Tetrahedron.h:253
TAABB< T, 3 > GetBoundingBox() const
Definition Tetrahedron.h:53
TVec3< T > FindClosestPointAndBary(const TVec3< T > &Location, TVec4< T > &OutBary, const T Tolerance=0) const
Definition Tetrahedron.h:295
T GetMinimumAltitude(int32 *MinAltitudeVertex=nullptr) const
Definition Tetrahedron.h:100
static bool Inside(const TArray< TTriangle< T > > &Tris, const TVec3< T > &Location, const T HalfThickness=0)
Definition Tetrahedron.h:211
T GetMinEdgeLength() const
Definition Tetrahedron.h:70
void Invert()
Definition Tetrahedron.h:41
friend FChaosArchive & operator<<(FChaosArchive &Ar, TTetrahedron)
FString ToString() const
Definition Tetrahedron.h:175
Definition Triangle.h:91
FORCEINLINE TPlane< T, 3 > GetPlane() const
Definition Triangle.h:125
FORCEINLINE T PhiWithNormal(const TVec3< T > &InSamplePoint, TVec3< T > &OutNormal) const
Definition Triangle.h:245
Definition Vector.h:1000
Definition Vector.h:41
Definition Array.h:670
void SetNumUninitialized(SizeType NewNum, EAllowShrinking AllowShrinking=UE::Core::Private::AllowShrinkingByDefault< AllocatorType >())
Definition Array.h:2369
Definition SkeletalMeshComponent.h:307
TV RowMaj3x3RobustSolveLinearSystem(const T *A, const TV &b)
Definition Poisson.h:173
const TVector< T, d > FindClosestPointAndAlphaOnLineSegment(const TVector< T, d > &P0, const TVector< T, d > &P1, const TVector< T, d > &P, T &OutAlpha)
Definition Plane.h:130
FChaosArchive & operator<<(FChaosArchive &Ar, FRigidParticleControlFlags &Flags)
Definition RigidParticleControlFlags.cpp:15
TVector< T, 2 > ComputeBarycentricInPlane(const TVector< T, d > &P0, const TVector< T, d > &P1, const TVector< T, d > &P2, const TVector< T, d > &P)
Definition Plane.h:111
static constexpr UE_FORCEINLINE_HINT T Min3(const T A, const T B, const T C)
Definition UnrealMathUtility.h:558
static constexpr UE_FORCEINLINE_HINT T Max3(const T A, const T B, const T C)
Definition UnrealMathUtility.h:551