UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
ContactTriangles.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc.All Rights Reserved.
2#pragma once
3
4#include "CoreMinimal.h"
6
7#include "Chaos/Core.h"
8#include "Chaos/Triangle.h"
9
10namespace Chaos
11{
12 // Given a point and a triangle, check if the point is on an edge or vertex and return vertex indices if so.
13 // If Position is at one of the vertices, OutEdgeVertexIndexA will an index into Vertices
14 // If Position is one one of the edges, both OutEdgeVertexIndexA and OutEdgeVertexIndexB will be an index into Vertices
15 // If both OutEdgeVertexIndexA and OutEdgeVertexIndexB are INDEX_NONE, Position is not on the triangle edges
17 const FVec3& Position,
18 const FVec3 VertexA, const FVec3 VertexB, const FVec3 VertexC,
21 {
24
26
27 // Is it a vertex contact?
29 {
31 return true;
32 }
34 {
36 return true;
37 }
39 {
41 return true;
42 }
43
44 // Is it an edge contact?
46 {
49 return true;
50 }
52 {
55 return true;
56 }
58 {
61 return true;
62 }
63
64 return false;
65 }
66
79
80
85 {
86 public:
87 // Triangle data
90
91 // Indices into the mesh (trimesh or heightfield) that generated the triangle
94
95 // Does this triangle contains the specified vertex? (VertexIndex is an index into the owning mesh's vertices)
96 inline bool HasVertexIndex(const int32 VertexIndex) const
97 {
98 return (VertexIndices[0] == VertexIndex) || (VertexIndices[1] == VertexIndex) || (VertexIndices[2] == VertexIndex);
99 }
100
101 // Get the centroid of the triangle
102 inline FVec3 GetCentroid() const
103 {
104 return (Vertices[0] + Vertices[1] + Vertices[2]) / FReal(3);
105 }
106
107 // Get the positions of the other two vertices in the triangle. (VertexIndex is an index into the owning mesh's vertices)
108 inline bool GetOtherVertexPositions(const int32 VertexIndex, FVec3& OutVertex0, FVec3& OutVertex1) const
109 {
110 if (VertexIndex == VertexIndices[0])
111 {
112 OutVertex0 = Vertices[1];
113 OutVertex1 = Vertices[2];
114 return true;
115 }
116 else if (VertexIndex == VertexIndices[1])
117 {
118 OutVertex0 = Vertices[2];
119 OutVertex1 = Vertices[0];
120 return true;
121 }
122 else if (VertexIndex == VertexIndices[2])
123 {
124 OutVertex0 = Vertices[0];
125 OutVertex1 = Vertices[1];
126 return true;
127 }
128 return false;
129 }
130
131 // Given a contact point on a triangle, check if it is an edge contact or vertex contact and return vertex indices if so
132 // @todo(chaos): this function not should be unnecessary. Collision detection should return the vertex indices for the vertex/edge/face that we collide with
156 };
157
158 // ID for a vertex in a trangle mesh, used by FTriangleContactPointData
160
161 // ID for an edge in a trangle mesh, used by FTriangleContactPointData
163 {
168
170 {
171 // EdgeID is the same if we swap the vertex indices
172 // The check for INDEX_NONE allows us to use an EdgeID as a VertexID without swapping order
174 {
177 }
178 else
179 {
182 }
183 }
184
185 FORCEINLINE bool IsValid() const
186 {
187 return (VertexIDs[0] != INDEX_NONE) && (VertexIDs[1] != INDEX_NONE);
188 }
189
191 {
192 return L.EdgeID == R.EdgeID;
193 }
194
196 {
197 return L.EdgeID != R.EdgeID;
198 }
199
201 {
202 return L.EdgeID < R.EdgeID;
203 }
204
206 {
207 return ::GetTypeHash(V.EdgeID);
208 }
209
210 union
211 {
214 };
215 };
216
217
218 //class UE_DEPRECATED(5.4, "No longer used") FTriangleContactPoint : public FContactPoint
219 //{
220 //public:
221 // FTriangleContactPoint()
222 // : FContactPoint()
223 // , EdgeID(INDEX_NONE, INDEX_NONE)
224 // , VertexID(INDEX_NONE)
225 // , ContactTriangleIndex(INDEX_NONE)
226 // {
227 // }
228
229 // FTriangleContactPoint(const FContactPoint& InContactPoint)
230 // : FContactPoint(InContactPoint)
231 // , EdgeID(INDEX_NONE, INDEX_NONE)
232 // , VertexID(INDEX_NONE)
233 // , ContactTriangleIndex(INDEX_NONE)
234 // {
235 // }
236
237 // FContactEdgeID EdgeID;
238 // FContactVertexID VertexID;
239
240 // int32 ContactTriangleIndex;
241 //};
242
247 {
248 public:
250 : EdgeID()
251 {
252 }
253
255 {
256 EdgeID.VertexIDs[0] = VertexIndex;
257 EdgeID.VertexIDs[1] = INDEX_NONE;
258 }
259
264
265 FORCEINLINE bool IsValid() const
266 {
267 return (EdgeID.VertexIDs[0] != INDEX_NONE);
268 }
269
271 {
272 return (EdgeID.VertexIDs[0] != INDEX_NONE) && (EdgeID.VertexIDs[1] == INDEX_NONE);
273 }
274
275 FORCEINLINE bool IsEdge() const
276 {
277 return (EdgeID.VertexIDs[0] != INDEX_NONE) && (EdgeID.VertexIDs[1] != INDEX_NONE);
278 }
279
281 {
282 return EdgeID.VertexIDs[0];
283 }
284
286 {
287 return EdgeID;
288 }
289
291 {
292 return L.EdgeID == R.EdgeID;
293 }
294
296 {
297 return L.EdgeID != R.EdgeID;
298 }
299
301 {
302 return L.EdgeID < R.EdgeID;
303 }
304
306 {
307 return (V.IsVertex()) ? V.GetVertexID() : GetTypeHash(V.GetEdgeID());
308 }
309
310 private:
311 // We treat the EdgeID as a VertexID when only one vertex ID is set
312 FContactEdgeID EdgeID;
313 };
314
321 {
322 public:
324 : EdgeOrVertexID()
325 , ContactTriangleIndex(INDEX_NONE)
326 , ContactNormalDotTriangleNormal(0)
327 , bIsEnabled(false)
328 {
329 }
330
335
340
345
347 {
348 ContactTriangleIndex = InTriangleIndex;
349 }
350
355
357 {
358 bIsEnabled = true;
359 }
360
362 {
363 bIsEnabled = false;
364 }
365
367 {
368 return bIsEnabled;
369 }
370
372 {
373 return ContactTriangleIndex;
374 }
375
377 {
378 return EdgeOrVertexID.IsVertex();
379 }
380
381 FORCEINLINE bool IsEdge() const
382 {
383 return EdgeOrVertexID.IsEdge();
384 }
385
387 {
388 return EdgeOrVertexID.GetVertexID();
389 }
390
392 {
393 return EdgeOrVertexID.GetEdgeID();
394 }
395
397 {
398 return ContactNormalDotTriangleNormal;
399 }
400
401 private:
402 FContactEdgeOrVertexID EdgeOrVertexID;
403 int32 ContactTriangleIndex;
404 FRealSingle ContactNormalDotTriangleNormal;
405 bool bIsEnabled;
406 };
407
413 {
414 public:
415 UE_DEPRECATED(5.3, "Use the constructor below which take PhiTolerance etc")
417 : PhiTolerance(0.1)
418 , DistanceTolerance(0.1)
419 , NumDisabledTriangleContactPoints(0)
420 , bOneSidedCollision(bInOneSided)
421 , ConvexTransform(InConvexTransform)
422 {
423 }
424
426 const bool bInOneSided,
427 const FReal InPhiTolerance,
430 : PhiTolerance(InPhiTolerance)
431 , DistanceTolerance(InDistanceTolerance)
432 , NumDisabledTriangleContactPoints(0)
433 , bOneSidedCollision(bInOneSided)
434 , ConvexTransform(InConvexTransform)
435 {
436 }
437
439 {
440 return MakeArrayView(TriangleContactPoints);
441 }
442
443 // Add contacts between the convex and a single triangle for later processing
444 inline void AddTriangleContacts(const TArrayView<const FContactPoint>& InContactPoints, const FTriangle& Triangle, const int32 TriangleIndex, const int32 VertexIndex0, const int32 VertexIndex1, const int32 VertexIndex2, const FReal CullDistance)
445 {
446 if (InContactPoints.Num() > 0)
447 {
448 const int32 ContactTriangleIndex = AddTriangle(Triangle, TriangleIndex, VertexIndex0, VertexIndex1, VertexIndex2);
449
450 const int32 NewNumContactPoints = TriangleContactPoints.Num() + InContactPoints.Num();
451 TriangleContactPoints.Reserve(NewNumContactPoints);
452 TriangleContactPointDatas.Reserve(NewNumContactPoints);
453
454 for (const FContactPoint& ContactPoint : InContactPoints)
455 {
456 if (ContactPoint.Phi < CullDistance)
457 {
458 const FReal ContactNormalDotTriangleNormal = FVec3::DotProduct(ContactPoint.ShapeContactNormal, ContactTriangles[ContactTriangleIndex].FaceNormal);
459
460 const int32 ContactIndex = TriangleContactPoints.Add(ContactPoint);
461 TriangleContactPointDatas.AddDefaulted();
462
463 TriangleContactPoints[ContactIndex].FaceIndex = TriangleIndex;
464 TriangleContactPointDatas[ContactIndex].SetTriangleIndex(ContactTriangleIndex);
465 TriangleContactPointDatas[ContactIndex].SetContactNormalDotTriangleNormal(FRealSingle(ContactNormalDotTriangleNormal));
466 TriangleContactPointDatas[ContactIndex].SetEnabled();
467 }
468 }
469 }
470 }
471
472 // To be called when all contacts have been added. Reduces the set of contacts to a minimum and transforms data into shape space
474
475 private:
476 void SetNumContacts(const int32 Num);
477 void DisableContact(const int32 ContactIndex);
478 void RemoveDisabledContacts();
479
480 void BuildContactFeatureSets();
481 void SortContactPointsForPruning();
482 void SortContactPointsForSolving();
483 void PruneEdgeAndVertexContactPoints(const bool bPruneEdges, const bool bPruneVertices);
484 void FixInvalidNormalContactPoints();
485 void PruneInfacingContactPoints();
486 void PruneUnnecessaryContactPoints();
487 void ReduceManifoldContactPointsTriangeMesh();
488 void FinalizeContacts(const FRigidTransform3& MeshToConvexTransform);
489
490 int32 AddTriangle(const FTriangle& Triangle, const int32 TriangleIndex, const int32 VertexIndex0, const int32 VertexIndex1, const int32 VertexIndex2);
491 int32 GetOtherTriangleIndexSharingEdge(const int32 KnownTriangleIndex, const int32 EdgeVertexIndexA, const int32 EdgeVertexIndexB) const;
492 int32 GetNextTriangleIndexSharingVertex(const int32 LastContactTriangleIndex, const int32 VertexIndex) const;
493
494 void DebugDrawContactPoints(const FColor& Color, const FReal LineThickness);
495
496 // The collected set of contacts with additional triangle information
497 TArray<FContactPoint> TriangleContactPoints;
498 TArray<FTriangleContactPointData> TriangleContactPointDatas;
499
500 // All the triangles referenced by the TriangleContactPoints
501 TArray<FContactTriangle> ContactTriangles;
502
503 // A list of all the edges of contacts with faces. Used to prune edge contacts
504 TSet<FContactEdgeID> ContactEdges;
505
506 // A list of all the vertices of contacts with faces and edges. Used to prune vertex contacts
507 TSet<FContactVertexID> ContactVertices;
508
509 // We remove contacts that are shallower by this much compared to the deepest contact
510 FReal PhiTolerance;
511
512 // We remove contacts that are closer than this to any other contact (negative to disable this functionality)
513 FReal DistanceTolerance;
514
515 // How many disabled contacts are in the TriangleContactPoints and TriangleContactPointDatas arrays (until the next Pack operation)
516 int32 NumDisabledTriangleContactPoints;
517
518 // Whether we want single-sided collision and therefore reject all normal opposing the triangle faces
519 bool bOneSidedCollision;
520
521 // Local space for the triangles
522 // @todo(chaos): rename this
523 FRigidTransform3 ConvexTransform;
524 };
525
526}
#define FORCEINLINE
Definition AndroidPlatform.h:140
constexpr auto MakeArrayView(OtherRangeType &&Other)
Definition ArrayView.h:873
@ INDEX_NONE
Definition CoreMiscDefines.h:150
#define UE_DEPRECATED(Version, Message)
Definition CoreMiscDefines.h:302
FPlatformTypes::int32 int32
A 32-bit signed integer.
Definition Platform.h:1125
FPlatformTypes::uint64 uint64
A 64-bit unsigned integer.
Definition Platform.h:1117
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
@ Num
Definition MetalRHIPrivate.h:234
#define UE_KINDA_SMALL_NUMBER
Definition UnrealMathUtility.h:131
uint32_t uint32
Definition binka_ue_file_header.h:6
Definition ContactTriangles.h:413
TArrayView< const FContactPoint > GetContactPoints() const
Definition ContactTriangles.h:438
FContactTriangleCollector(const bool bInOneSided, const FReal InPhiTolerance, const FReal InDistanceTolerance, const FRigidTransform3 &InConvexTransform)
Definition ContactTriangles.h:425
void AddTriangleContacts(const TArrayView< const FContactPoint > &InContactPoints, const FTriangle &Triangle, const int32 TriangleIndex, const int32 VertexIndex0, const int32 VertexIndex1, const int32 VertexIndex2, const FReal CullDistance)
Definition ContactTriangles.h:444
void ProcessContacts(const FRigidTransform3 &MeshToConvexTransform)
Definition ContactTriangles.cpp:199
Data held alongside contact points when generating contacts against a (likely non-convex) mesh of tri...
Definition ContactTriangles.h:85
int32 TriangleIndex
Definition ContactTriangles.h:93
bool HasVertexIndex(const int32 VertexIndex) const
Definition ContactTriangles.h:96
FVec3 Vertices[3]
Definition ContactTriangles.h:88
FVec3 GetCentroid() const
Definition ContactTriangles.h:102
FVec3 FaceNormal
Definition ContactTriangles.h:89
int32 VertexIndices[3]
Definition ContactTriangles.h:92
bool GetEdgeVerticesAtPosition(const FVec3 &ContactPosition, FVec3 &OutEdgeVertexA, FVec3 &OutEdgeVertexB, int32 &OutEdgeVertexIndexA, int32 &OutEdgeVertexIndexB, const FReal BaryCentricTolerance=UE_KINDA_SMALL_NUMBER) const
Definition ContactTriangles.h:133
bool GetOtherVertexPositions(const int32 VertexIndex, FVec3 &OutVertex0, FVec3 &OutVertex1) const
Definition ContactTriangles.h:108
Extended data used when processing contactpoints on a triangle mesh. Adds information about which tri...
Definition ContactTriangles.h:321
FORCEINLINE bool IsEnabled() const
Definition ContactTriangles.h:366
FORCEINLINE void SetEdgeOrVertexID(const FContactEdgeOrVertexID InEdgeOrVertexID)
Definition ContactTriangles.h:341
FORCEINLINE void SetDisabled()
Definition ContactTriangles.h:361
FORCEINLINE FContactVertexID GetVertexID() const
Definition ContactTriangles.h:386
FORCEINLINE int32 GetTriangleIndex() const
Definition ContactTriangles.h:371
FORCEINLINE FRealSingle GetContactNormalDotTriangleNormal() const
Definition ContactTriangles.h:396
FORCEINLINE void SetTriangleIndex(const int32 InTriangleIndex)
Definition ContactTriangles.h:346
FORCEINLINE void SetEdgeID(const FContactVertexID InVertexIDA, const FContactVertexID InVertexIDB)
Definition ContactTriangles.h:336
FORCEINLINE void SetContactNormalDotTriangleNormal(const FRealSingle InContactNormalDotTriangleNormal)
Definition ContactTriangles.h:351
FORCEINLINE FContactEdgeID GetEdgeID() const
Definition ContactTriangles.h:391
FORCEINLINE FTriangleContactPointData()
Definition ContactTriangles.h:323
FORCEINLINE void SetEnabled()
Definition ContactTriangles.h:356
FORCEINLINE bool IsVertex() const
Definition ContactTriangles.h:376
FORCEINLINE bool IsEdge() const
Definition ContactTriangles.h:381
FORCEINLINE void SetVertexID(const FContactVertexID InVertexID)
Definition ContactTriangles.h:331
Definition ContactPoint.h:42
Definition ArrayView.h:139
Definition Array.h:670
Definition SkeletalMeshComponent.h:307
FRealDouble FReal
Definition Real.h:22
TVec3< RealType > ToBarycentric(const TVec3< RealType > &Point, const TVec3< RealType > &V0, const TVec3< RealType > &V1, const TVec3< RealType > &V2)
Convert the cartesian coordinate into a barycentric corrdinate. Compute barycentric coordinates/weigh...
Definition Triangle.h:25
float FRealSingle
Definition Real.h:14
int32 FContactVertexID
Definition ContactTriangles.h:159
bool GetTriangleEdgeVerticesAtPosition(const FVec3 &Position, const FVec3 VertexA, const FVec3 VertexB, const FVec3 VertexC, int32 &OutEdgeVertexIndexA, int32 &OutEdgeVertexIndexB, const FReal BaryCentricTolerance=UE_KINDA_SMALL_NUMBER)
Definition ContactTriangles.h:16
@ false
Definition radaudio_common.h:23
Definition ContactTriangles.h:163
FContactVertexID VertexIDs[2]
Definition ContactTriangles.h:212
FORCEINLINE FContactEdgeID()
Definition ContactTriangles.h:164
uint64 EdgeID
Definition ContactTriangles.h:213
FORCEINLINE bool IsValid() const
Definition ContactTriangles.h:185
FORCEINLINE friend bool operator<(const FContactEdgeID &L, const FContactEdgeID &R)
Definition ContactTriangles.h:200
FORCEINLINE FContactEdgeID(const FContactVertexID VertexIndexA, const FContactVertexID VertexIndexB)
Definition ContactTriangles.h:169
FORCEINLINE friend bool operator==(const FContactEdgeID &L, const FContactEdgeID &R)
Definition ContactTriangles.h:190
FORCEINLINE friend bool operator!=(const FContactEdgeID &L, const FContactEdgeID &R)
Definition ContactTriangles.h:195
FORCEINLINE friend uint32 GetTypeHash(const FContactEdgeID &V)
Definition ContactTriangles.h:205
Definition ContactTriangles.h:247
FORCEINLINE bool IsValid() const
Definition ContactTriangles.h:265
FORCEINLINE const FContactVertexID & GetVertexID() const
Definition ContactTriangles.h:280
FORCEINLINE FContactEdgeOrVertexID(const FContactVertexID VertexIndex)
Definition ContactTriangles.h:254
FORCEINLINE friend uint32 GetTypeHash(const FContactEdgeOrVertexID &V)
Definition ContactTriangles.h:305
FORCEINLINE FContactEdgeOrVertexID(const FContactVertexID VertexIndexA, const FContactVertexID VertexIndexB)
Definition ContactTriangles.h:260
FORCEINLINE friend bool operator==(const FContactEdgeOrVertexID &L, const FContactEdgeOrVertexID &R)
Definition ContactTriangles.h:290
FORCEINLINE bool IsEdge() const
Definition ContactTriangles.h:275
FORCEINLINE FContactEdgeOrVertexID()
Definition ContactTriangles.h:249
FORCEINLINE const FContactEdgeID & GetEdgeID() const
Definition ContactTriangles.h:285
FORCEINLINE friend bool operator!=(const FContactEdgeOrVertexID &L, const FContactEdgeOrVertexID &R)
Definition ContactTriangles.h:295
FORCEINLINE friend bool operator<(const FContactEdgeOrVertexID &L, const FContactEdgeOrVertexID &R)
Definition ContactTriangles.h:300
FORCEINLINE bool IsVertex() const
Definition ContactTriangles.h:270
Definition Color.h:486
static UE_FORCEINLINE_HINT bool IsNearlyEqual(float A, float B, float ErrorTolerance=UE_SMALL_NUMBER)
Definition UnrealMathUtility.h:388