UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
ConvexStructureData.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2#pragma once
3
4#include "Chaos/Core.h"
7#include "ChaosArchive.h"
8#include "ChaosCheck.h"
9#include "ChaosLog.h"
12
13namespace Chaos
14{
15
16 // Metadata for a convex shape used by the manifold generation system and anything
17 // else that can benefit from knowing which vertices are associated with the faces.
19 {
20 public:
24
25 // Note: this is serialized (do not change order without adding a new ObjectVersion and legacy load path)
26 enum class EIndexType : int8
27 {
28 None,
29 Small,
30 Medium,
31 Large,
32 };
33
34 // Cats the inner data container to the correct index size
35 // Do not use - only public for unit tests
36 const FConvexStructureDataLarge& DataL() const { checkSlow(IndexType == EIndexType::Large); return *Data.DataL; }
37 const FConvexStructureDataMedium& DataM() const { checkSlow(IndexType == EIndexType::Medium); return *Data.DataM; }
38 const FConvexStructureDataSmall& DataS() const { checkSlow(IndexType == EIndexType::Small); return *Data.DataS; }
39
40 private:
41 FConvexStructureDataLarge& DataL() { checkSlow(IndexType == EIndexType::Large); return *Data.DataL; }
42 FConvexStructureDataMedium& DataM() { checkSlow(IndexType == EIndexType::Medium); return *Data.DataM; }
43 FConvexStructureDataSmall& DataS() { checkSlow(IndexType == EIndexType::Small); return *Data.DataS; }
44
45 // Call a function on the read-only data (cast to Small, Medium or Large indices as appropriate).
46 // It will call "Op" on the down-casted data container if we have a valid container. It will
47 // call EmptyOp if the container has not been set up (IndexType is None).
48 // Note: This expands into a switch statement, calling the lambda with a container of each index size.
49 //
50 // Must be used with an auto lambda to handle the downcasting, e.g.:
51 // int32 Plane0VertexCount = ConstDataOp(
52 // [](const auto& ConcreteData) { return ConcreteData.NumPlaneVertices(0); },
53 // []() { return 0; });
54 //
55 template<typename T_OP, typename T_EMPTYOP>
56 inline auto ConstDataOp(const T_OP& Op, const T_EMPTYOP& EmptyOp) const
57 {
58 switch (IndexType)
59 {
61 return Op(DataS());
63 return Op(DataM());
65 return Op(DataL());
66 }
67 return EmptyOp();
68 }
69
70 #define CHAOS_CONVEXSTRUCTUREDATA_DATAOP(Op, DefaultValue) \
71 switch (IndexType) \
72 { \
73 case EIndexType::Small: \
74 return Op(DataS()); \
75 case EIndexType::Medium: \
76 return Op(DataM()); \
77 case EIndexType::Large: \
78 return Op(DataL()); \
79 } \
80 return DefaultValue;
81
82 // A write-enabled version of ConstDataOp
83 template<typename T_OP, typename T_EMPTYOP>
84 inline auto NonConstDataOp(const T_OP& Op, const T_EMPTYOP& EmptyOp)
85 {
86 switch (IndexType)
87 {
89 return Op(DataS());
91 return Op(DataM());
93 return Op(DataL());
94 }
95 return EmptyOp();
96 }
97
98 public:
99
101 : Data{ nullptr }
102 , IndexType(EIndexType::None)
103 {
104 }
105
107
112
114 {
115 DestroyDataContainer();
116 }
117
119
121 {
122 Data.Ptr = Other.Data.Ptr;
123 IndexType = Other.IndexType;
124
125 Other.Data.Ptr = nullptr;
126 Other.IndexType = EIndexType::None;
127
128 return *this;
129 }
130
132 {
133 DestroyDataContainer();
134
135 check(Data.Ptr == nullptr);
136 check(IndexType == EIndexType::None);
137
138 if (Other.IndexType == EIndexType::Large)
139 {
140 check(Other.Data.DataL);
141 Data.DataL = new FConvexStructureDataLarge(*Other.Data.DataL);
142 }
143 else if (Other.IndexType == EIndexType::Medium)
144 {
145 check(Other.Data.DataM);
146 Data.DataM = new FConvexStructureDataMedium(*Other.Data.DataM);
147 }
148 else if (Other.IndexType == EIndexType::Small)
149 {
150 check(Other.Data.DataS);
151 Data.DataS = new FConvexStructureDataSmall(*Other.Data.DataS);
152 }
153
154 IndexType = Other.IndexType;
155 }
156
157 inline bool IsValid() const
158 {
159 return (Data.Ptr != nullptr);
160 }
161
163 {
164 return IndexType;
165 }
166
167 inline int32 FindVertexPlanes(int32 VertexIndex, int32* VertexPlanes, int32 MaxVertexPlanes) const
168 {
169 return ConstDataOp(
170 [VertexIndex, VertexPlanes, MaxVertexPlanes](const auto& ConcreteData) { return ConcreteData.FindVertexPlanes(VertexIndex, VertexPlanes, MaxVertexPlanes); },
171 []() { return 0; });
172 }
173
175 {
176 switch (IndexType)
177 {
184 }
185 return 0;
186 }
187
188 // The number of vertices that make up the corners of the specified face
189 inline int32 NumPlaneVertices(int32 PlaneIndex) const
190 {
191 return ConstDataOp(
192 [PlaneIndex](const auto& ConcreteData) { return ConcreteData.NumPlaneVertices(PlaneIndex); },
193 []() { return 0; });
194 }
195
196 // Get the vertex index (in the outer convex container) of one of the vertices making up the corners of the specified face
198 {
200 return ConstDataOp(
201 [PlaneIndex, PlaneVertexIndex](const auto& ConcreteData) { return ConcreteData.GetPlaneVertex(PlaneIndex, PlaneVertexIndex); },
202 []() { return (int32)INDEX_NONE; });
203 }
204
205
206 inline int32 NumHalfEdges() const
207 {
208 return ConstDataOp(
209 [](const auto& ConcreteData) { return ConcreteData.NumHalfEdges(); },
210 []() { return 0; });
211 }
212
213 inline int32 NumEdges() const
214 {
215 return ConstDataOp(
216 [](const auto& ConcreteData) { return ConcreteData.NumEdges(); },
217 []() { return 0; });
218 }
219
221 {
222 return ConstDataOp(
223 [EdgeIndex, EdgeVertexIndex](const auto& ConcreteData)
224 {
225 return ConcreteData.GetEdgeVertex(EdgeIndex, EdgeVertexIndex);
226 },
227 []() { return (int32)INDEX_NONE; });
228 }
229
230 inline int32 GetEdgePlane(int32 EdgeIndex, int32 EdgePlaneIndex) const
231 {
232 return ConstDataOp(
233 [EdgeIndex, EdgePlaneIndex](const auto& ConcreteData)
234 {
235 return ConcreteData.GetEdgePlane(EdgeIndex, EdgePlaneIndex);
236 },
237 []() { return (int32)INDEX_NONE; });
238 }
239
241 {
242 return ConstDataOp(
243 [PlaneIndex, FaceVertexIndex](const auto& ConcreteData)
244 {
245 return ConcreteData.GetPlaneHalfEdge(PlaneIndex, FaceVertexIndex);
246 },
247 []() { return (int32)INDEX_NONE; });
248 }
249
250 inline void GetHalfEdges(int32 EdgeIndex, int32 &OutEdgeIndex0, int32 &OutEdgeIndex1) const
251 {
252 return ConstDataOp(
253 [EdgeIndex, &OutEdgeIndex0, &OutEdgeIndex1](const auto& ConcreteData)
254 {
255 OutEdgeIndex0 = ConcreteData.GetHalfEdgeIndex(EdgeIndex);
256 OutEdgeIndex1 = ConcreteData.GetTwinHalfEdge(OutEdgeIndex0);
257 return;
258 },
260 {
263 return;
264 });
265 }
266
267 // Initialize the structure data from the set of vertices for each face of the convex
269 {
270 const EIndexType NewIndexType = GetRequiredIndexType(InPlaneVertices, NumVerts);
271 CreateDataContainer(NewIndexType);
272
273 return NonConstDataOp(
275 return bRegularDatas ? ConcreteData.BuildRegularDatas(InPlaneVertices, NumVerts) : ConcreteData.SetPlaneVertices(InPlaneVertices, NumVerts);
276 },
277 []() { return true; });
278 }
279
281 {
284
286
287 // Load and convert the legacy structure if necessary
289 {
290 LoadLegacyData(Ar);
291 return;
292 }
293
294 if (Ar.IsLoading())
295 {
296 // Create the container with the appropriate index size
298 Ar << NewIndexType;
299 CreateDataContainer(NewIndexType);
300 }
301 else
302 {
303 Ar << IndexType;
304 }
305
306 // Serialize the container with the correct index type
307 NonConstDataOp(
308 [&Ar](auto& ConcreteData) { Ar << ConcreteData; },
309 []() {});
310 }
311
313 {
314 Value.Serialize(Ar);
315 return Ar;
316 }
317
318#if INTEL_ISPC
319 // See PerParticlePBDCollisionConstraint.cpp
320 // ISPC code has matching structs for interpreting FImplicitObjects.
321 // This is used to verify that the structs stay the same.
322 struct FISPCDataVerifier
323 {
324 static constexpr int32 OffsetOfData() { return offsetof(FConvexStructureData, Data); }
325 static constexpr int32 SizeOfData() { return sizeof(FConvexStructureData::Data); }
326 static constexpr int32 OffsetOfIndexType() { return offsetof(FConvexStructureData, IndexType); }
327 static constexpr int32 SizeOfIndexType() { return sizeof(FConvexStructureData::IndexType); }
328 };
329 friend FISPCDataVerifier;
330#endif // #if INTEL_ISPC
331
332 private:
333
334 // Load data from an asset saved before we had a proper half-edge data structure
335 void LoadLegacyData(FArchive& Ar)
336 {
339
341
343 }
344
345 // Determine the minimum index size we need for the specified convex size
346 EIndexType GetRequiredIndexType(const TArray<TArray<int32>>& InPlaneVertices, int32 NumVerts)
347 {
349 {
350 return EIndexType::Small;
351 }
353 {
354 return EIndexType::Medium;
355 }
356 else
357 {
358 return EIndexType::Large;
359 }
360 }
361
362 // Create the container to match the desired index size
363 void CreateDataContainer(EIndexType InIndexType)
364 {
365 DestroyDataContainer();
366
367 check(Data.Ptr == nullptr);
368 check(IndexType == EIndexType::None);
369
371 {
372 Data.DataL = new FConvexStructureDataLarge();
373 }
375 {
376 Data.DataM = new FConvexStructureDataMedium();
377 }
378 else if (InIndexType == EIndexType::Small)
379 {
380 Data.DataS = new FConvexStructureDataSmall();
381 }
382
383 IndexType = InIndexType;
384 }
385
386 // Destroy the container we created in CreateDataContainer
387 void DestroyDataContainer()
388 {
389 if (Data.Ptr != nullptr)
390 {
391 check(IndexType != EIndexType::None);
392
393 NonConstDataOp(
394 [](auto& ConcreteData)
395 {
396 delete &ConcreteData;
397 },
398 []() {});
399
400 IndexType = EIndexType::None;
401 Data.Ptr = nullptr;
402 }
403 }
404
405 union FStructureData
406 {
407 void* Ptr;
411 };
412 FStructureData Data;
413
414 // The index type we require for the structure data
415 EIndexType IndexType;
416 };
417
418}
#define checkSlow(expr)
Definition AssertionMacros.h:332
#define check(expr)
Definition AssertionMacros.h:314
@ INDEX_NONE
Definition CoreMiscDefines.h:150
FPlatformTypes::int8 int8
An 8-bit signed integer.
Definition Platform.h:1121
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
UE_INTRINSIC_CAST UE_REWRITE constexpr std::remove_reference_t< T > && MoveTemp(T &&Obj) noexcept
Definition UnrealTemplate.h:520
Definition ConvexStructureData.h:19
int32 GetEdgeVertex(int32 EdgeIndex, int32 EdgeVertexIndex) const
Definition ConvexStructureData.h:220
void Serialize(FArchive &Ar)
Definition ConvexStructureData.h:280
int32 NumHalfEdges() const
Definition ConvexStructureData.h:206
FConvexHalfEdgeStructureDataS32 FConvexStructureDataLarge
Definition ConvexStructureData.h:21
void GetHalfEdges(int32 EdgeIndex, int32 &OutEdgeIndex0, int32 &OutEdgeIndex1) const
Definition ConvexStructureData.h:250
FConvexStructureData(const FConvexStructureData &Other)=delete
const FConvexStructureDataMedium & DataM() const
Definition ConvexStructureData.h:37
FConvexHalfEdgeStructureDataU8 FConvexStructureDataSmall
Definition ConvexStructureData.h:23
int32 GetVertexPlanes3(int32 VertexIndex, int32 &PlaneIndex0, int32 &PlaneIndex1, int32 &PlaneIndex2) const
Definition ConvexStructureData.h:174
void CopyFrom(const FConvexStructureData &Other)
Definition ConvexStructureData.h:131
FConvexHalfEdgeStructureDataS16 FConvexStructureDataMedium
Definition ConvexStructureData.h:22
int32 GetPlaneVertex(int32 PlaneIndex, int32 PlaneVertexIndex) const
Definition ConvexStructureData.h:197
bool SetPlaneVertices(const TArray< TArray< int32 > > &InPlaneVertices, int32 NumVerts, const bool bRegularDatas=false)
Definition ConvexStructureData.h:268
~FConvexStructureData()
Definition ConvexStructureData.h:113
int32 NumPlaneVertices(int32 PlaneIndex) const
Definition ConvexStructureData.h:189
EIndexType
Definition ConvexStructureData.h:27
friend FArchive & operator<<(FArchive &Ar, FConvexStructureData &Value)
Definition ConvexStructureData.h:312
EIndexType GetIndexType() const
Definition ConvexStructureData.h:162
int32 FindVertexPlanes(int32 VertexIndex, int32 *VertexPlanes, int32 MaxVertexPlanes) const
Definition ConvexStructureData.h:167
FConvexStructureData(FConvexStructureData &&Other)
Definition ConvexStructureData.h:108
FConvexStructureData & operator=(const FConvexStructureData &Other)=delete
int32 GetEdgePlane(int32 EdgeIndex, int32 EdgePlaneIndex) const
Definition ConvexStructureData.h:230
FConvexStructureData()
Definition ConvexStructureData.h:100
bool IsValid() const
Definition ConvexStructureData.h:157
FConvexStructureData & operator=(FConvexStructureData &&Other)
Definition ConvexStructureData.h:120
int32 GetPlaneHalfEdge(int32 PlaneIndex, int32 FaceVertexIndex) const
Definition ConvexStructureData.h:240
int32 NumEdges() const
Definition ConvexStructureData.h:213
const FConvexStructureDataSmall & DataS() const
Definition ConvexStructureData.h:38
const FConvexStructureDataLarge & DataL() const
Definition ConvexStructureData.h:36
static void Load(FArchive &Ar, TArray< TArray< int32 > > &OutPlaneVertices, int32 &OutNumVertices)
Definition ConvexFlattenedArrayStructureData.h:203
Definition ConvexHalfEdgeStructureData.h:38
int32 GetVertexPlanes3(int32 VertexIndex, int32 &PlaneIndex0, int32 &PlaneIndex1, int32 &PlaneIndex2) const
Definition ConvexHalfEdgeStructureData.h:326
static bool CanMake(const TArray< TArray< int32 > > &InPlaneVertices, int32 InNumVertices)
Definition ConvexHalfEdgeStructureData.h:116
Definition Archive.h:1208
virtual void Serialize(void *V, int64 Length)
Definition Archive.h:1689
virtual CORE_API void UsingCustomVersion(const struct FGuid &Guid)
Definition Archive.cpp:590
UE_FORCEINLINE_HINT bool IsLoading() const
Definition Archive.h:236
CORE_API int32 CustomVer(const struct FGuid &Key) const
Definition Archive.cpp:602
Definition Array.h:670
Definition SkeletalMeshComponent.h:307
TConvexHalfEdgeStructureData< int32 > FConvexHalfEdgeStructureDataS32
Definition ConvexHalfEdgeStructureData.h:721
TConvexHalfEdgeStructureData< uint8 > FConvexHalfEdgeStructureDataU8
Definition ConvexHalfEdgeStructureData.h:723
TConvexHalfEdgeStructureData< int16 > FConvexHalfEdgeStructureDataS16
Definition ConvexHalfEdgeStructureData.h:722
CORE_API static const FGuid GUID
Definition FortniteMainBranchObjectVersion.h:21
@ ChaosConvexUsesHalfEdges
Definition PhysicsObjectVersion.h:49
CORE_API static const FGuid GUID
Definition PhysicsObjectVersion.h:78