UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
DynamicVertexAttribute.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
7
8namespace UE
9{
10namespace Geometry
11{
12
13template<typename AttribValueType, int AttribDimension, typename ParentType>
14class TDynamicVertexAttribute;
15
16
17template<typename AttribValueType, int AttribDimension, typename ParentType>
19{
20private:
21 struct FChangeVertexAttribute
22 {
24 int VertexID;
25 };
26
27 TArray<FChangeVertexAttribute> OldVertexAttributes, NewVertexAttributes;
28
29public:
32
35
36 inline virtual void SaveInitialVertex(const TDynamicAttributeBase<ParentType>* Attribute, int VertexID) override;
37
38 inline virtual void StoreAllFinalVertices(const TDynamicAttributeBase<ParentType>* Attribute, const TSet<int>& VertexIDs) override;
39
40 inline virtual bool Apply(TDynamicAttributeBase<ParentType>* Attribute, bool bRevert) const override;
41};
42
43
47template<typename AttribValueType, int AttribDimension, typename ParentType>
49{
50
51protected:
53 ParentType* Parent;
54
57
59
61
62public:
65 {
66 }
67
70 {
71 if (bAutoInit)
72 {
73 Initialize();
74 }
75 }
76
78 {
79 }
80
82 const ParentType* GetParent() const { return Parent; }
84 ParentType* GetParent() { return Parent; }
85private:
86 void Reparent(ParentType* NewParent) override { Parent = NewParent; }
87public:
100
107
115
117 {
118 for (int VID = 0, NumVID = CompactMaps.NumVertexMappings(); VID < NumVID; VID++)
119 {
120 const int ToVID = CompactMaps.GetVertexMapping(VID);
122 {
123 continue;
124 }
125 if (ensure(ToVID <= VID))
126 {
127 CopyValue(VID, ToVID);
128 }
129 }
130 AttribValues.Resize(Parent->MaxVertexID() * AttribDimension);
131 }
132
134 {
136 check(CompactMaps.NumVertexMappings() <= int(ToCopy.AttribValues.Num() / AttribDimension));
137
139 for (int VID = 0, NumVID = CompactMaps.NumVertexMappings(); VID < NumVID; VID++)
140 {
141 int ToVID = CompactMaps.GetVertexMapping(VID);
143 {
144 continue;
145 }
146 ToCopy.GetValue(VID, Data);
147 SetValue(ToVID, Data);
148 }
149 }
150
153 {
154 check(Parent != nullptr);
155 AttribValues.Resize(Parent->MaxVertexID() * AttribDimension);
156 AttribValues.Fill(InitialValue);
157 }
158
160 {
162 for (int i = 0; i < AttribDimension; ++i)
163 {
164 AttribValues.InsertAt(Data[i], k + i);
165 }
166 }
167
168
169
170 //
171 // Accessors/Queries
172 //
173
174 virtual bool CopyThroughMapping(const TDynamicAttributeBase<ParentType>* Source, const FMeshIndexMappings& Mapping) override
175 {
177 int BufferSize = sizeof(BufferData);
178 for (const TPair<int32, int32>& MapVID : Mapping.GetVertexMap().GetForwardMap())
179 {
180 if (!ensure(Source->CopyOut(MapVID.Key, BufferData, BufferSize)))
181 {
182 return false;
183 }
184 SetValue(MapVID.Value, BufferData);
185 }
186 return true;
187 }
188
190 {
192 int BufferSize = sizeof(BufferData);
193
194 int32 NewMaxID = Info.NumVertex + Info.VertexOffset;
196 {
198 }
199 for (int32 Idx = 0; Idx < Info.NumVertex; ++Idx)
200 {
201 if (!ensure(Source.CopyOut(Idx, BufferData, BufferSize)))
202 {
203 return false;
204 }
205 SetValue(Idx + Info.VertexOffset, BufferData);
206 }
207 return true;
208 }
209
214
215 virtual bool CopyOut(int RawID, void* Buffer, int BufferSize) const override
216 {
217 if (sizeof(AttribValueType)*AttribDimension != BufferSize)
218 {
219 return false;
220 }
222 int k = RawID * AttribDimension;
223 for (int i = 0; i < AttribDimension; ++i)
224 {
225 BufferData[i] = AttribValues[k + i];
226 }
227 return true;
228 }
229 virtual bool CopyIn(int RawID, void* Buffer, int BufferSize) override
230 {
231 if (sizeof(AttribValueType) * AttribDimension != BufferSize)
232 {
233 return false;
234 }
236 int k = RawID * AttribDimension;
237 for (int i = 0; i < AttribDimension; ++i)
238 {
239 AttribValues[k + i] = BufferData[i];
240 }
241 return true;
242 }
243
245 inline void GetValue(int VertexID, AttribValueType* Data) const
246 {
247 int k = VertexID * AttribDimension;
248 for (int i = 0; i < AttribDimension; ++i)
249 {
250 Data[i] = AttribValues[k + i];
251 }
252 }
253
255 template<typename AsType>
256 void GetValue(int VertexID, AsType& Data) const
257 {
258 int k = VertexID * AttribDimension;
259 for (int i = 0; i < AttribDimension; ++i)
260 {
261 Data[i] = AttribValues[k + i];
262 }
263 }
264
265
267 inline void SetValue(int VertexID, const AttribValueType* Data)
268 {
269 int k = VertexID * AttribDimension;
270 for (int i = 0; i < AttribDimension; ++i)
271 {
272 AttribValues[k + i] = Data[i];
273 }
274 }
275
277 template<typename AsType>
278 void SetValue(int VertexID, const AsType& Data)
279 {
280 int k = VertexID * AttribDimension;
281 for (int i = 0; i < AttribDimension; ++i)
282 {
283 AttribValues[k + i] = Data[i];
284 }
285 }
286
288 inline void SetScalarValue(int32 VertexID, const AttribValueType& SingleValue)
289 {
290 int k = VertexID * AttribDimension;
291 for (int i = 0; i < AttribDimension; ++i)
292 {
293 AttribValues[k + i] = SingleValue;
294 }
295 }
296
300 inline void CopyValue(int FromVertexID, int ToVertexID)
301 {
304 for (int i = 0; i < AttribDimension; ++i)
305 {
307 }
308 }
309
310
311public:
312
315 {
317 SetAttributeFromLerp(SplitInfo.NewVertex, SplitInfo.OriginalVertices.A, SplitInfo.OriginalVertices.B, SplitInfo.SplitT);
318 }
319
322 {
323 // vertices unchanged
324 }
325
328 {
329 SetAttributeFromLerp(CollapseInfo.KeptVertex, CollapseInfo.KeptVertex, CollapseInfo.RemovedVertex, CollapseInfo.CollapseT);
330 }
331
333 {
334 return (AttribValueType)0;
335 }
336
337 inline void ResizeAttribStoreIfNeeded(int VertexID)
338 {
339 if (!ensure(VertexID >= 0))
340 {
341 return;
342 }
343 size_t NeededSize = (size_t(VertexID)+1) * AttribDimension;
345 {
347 }
348 }
349
350 virtual void OnNewVertex(int VertexID, bool bInserted) override
351 {
354 }
355
358 {
359 FIndex3i Tri = PokeInfo.TriVertices;
361 SetAttributeFromBary(PokeInfo.NewVertex, Tri.A, Tri.B, Tri.C, PokeInfo.BaryCoords);
362 }
363
366 {
367 // just blend the attributes?
368 if (MergeInfo.RemovedVerts.A != FDynamicMesh3::InvalidID)
369 {
370 SetAttributeFromLerp(MergeInfo.KeptVerts.A, MergeInfo.KeptVerts.A, MergeInfo.RemovedVerts.A, MergeInfo.InterpolationT);
371 }
372 if (MergeInfo.RemovedVerts.B != FDynamicMesh3::InvalidID)
373 {
374 SetAttributeFromLerp(MergeInfo.KeptVerts.B, MergeInfo.KeptVerts.B, MergeInfo.RemovedVerts.B, MergeInfo.InterpolationT);
375 }
376 }
377
379 {
380 SetAttributeFromLerp(MergeInfo.KeptVertex, MergeInfo.KeptVertex, MergeInfo.RemovedVertex, MergeInfo.InterpolationT);
381 }
382
385 {
386 CopyValue(SplitInfo.OriginalVertex, SplitInfo.NewVertex);
387 }
388
393
401 {
402 // just check that the values buffer is big enough
403 if (Parent->MaxVertexID() < 0 || static_cast<size_t>(Parent->MaxVertexID())*AttribDimension > AttribValues.Num())
404 {
405 switch (FailMode)
406 {
408 check(false);
410 ensure(false);
411 default:
412 return false;
413 }
414 }
415
416 return true;
417 }
418
424 {
425 if (!bIgnoreDataLayout)
426 {
427 if (AttribValues.Num() != Other.AttribValues.Num())
428 {
429 return false;
430 }
431
432 for (int Idx = 0, NumValues = AttribValues.Num(); Idx < NumValues; Idx++)
433 {
434 if (AttribValues[Idx] != Other.AttribValues[Idx])
435 {
436 return false;
437 }
438 }
439 }
440 else
441 {
442 // bIgnoreDataLayout
443
444 FRefCountVector::IndexIterator ItVid = Parent->GetVerticesRefCounts().BeginIndices();
445 const FRefCountVector::IndexIterator ItVidEnd = Parent->GetVerticesRefCounts().EndIndices();
446 FRefCountVector::IndexIterator ItVidOther = Other.Parent->GetVerticesRefCounts().BeginIndices();
447 const FRefCountVector::IndexIterator ItVidEndOther = Other.Parent->GetVerticesRefCounts().EndIndices();
448
449 while (ItVid != ItVidEnd && ItVidOther != ItVidEndOther)
450 {
451 for (int32 i = 0; i < AttribDimension; ++i)
452 {
456 {
457 // Vertex attribute value is not the same.
458 return false;
459 }
460 }
461 ++ItVid;
462 ++ItVidOther;
463 }
464
466 {
467 // Number of vertex attribute values is not the same.
468 return false;
469 }
470 }
471
472 return true;
473 }
474
475
484 {
485 Attr.Serialize(Ar, nullptr, false);
486 return Ar;
487 }
488
496 void Serialize(FArchive& Ar, const FCompactMaps* CompactMaps, bool bUseCompression)
497 {
499
501 if (Ar.IsLoading() && Ar.CustomVer(FUE5MainStreamObjectVersion::GUID) < FUE5MainStreamObjectVersion::DynamicMeshCompactedSerialization)
502 {
503 Ar << AttribValues;
504 }
505 else
506 {
507 auto SerializeVector = [](FArchive& Ar, auto& Vector, bool bUseCompression)
508 {
509 if (bUseCompression)
510 {
511 Vector.template Serialize<true, true>(Ar);
512 }
513 else
514 {
515 Vector.template Serialize<true, false>(Ar);
516 }
517 };
518
519 Ar << bUseCompression;
520
521 if (CompactMaps == nullptr || !CompactMaps->VertexMapIsSet())
522 {
523 SerializeVector(Ar, AttribValues, bUseCompression);
524 }
525 else
526 {
529
530 int32 VidCompact = 0;
531 for (int32 Vid = 0, Num = AttribValues.Num() / AttribDimension; Vid < Num; ++Vid)
532 {
533 const int32 VidMapping = CompactMaps->GetVertexMapping(Vid);
535 {
536 for (int32 i = 0; i < AttribDimension; ++i)
537 {
539 }
540 }
541 }
542
543 SerializeVector(Ar, AttribValuesCompact, bUseCompression);
544 }
545 }
546 }
547
548 virtual SIZE_T GetByteCount() const override
549 {
550 return AttribValues.GetByteCount();
551 }
552
553
554protected:
555
556 // interpolation functions; default implementation assumes your attributes can be interpolated as reals
557
559 virtual void SetAttributeFromLerp(int SetAttribute, int AttributeA, int AttributeB, double Alpha)
560 {
561 int IndexSet = AttribDimension * SetAttribute;
562 int IndexA = AttribDimension * AttributeA;
563 int IndexB = AttribDimension * AttributeB;
564 double Beta = (1. - Alpha);
565 for (int i = 0; i < AttribDimension; ++i)
566 {
567 AttribValues[IndexSet+i] = AttribValueType(Beta*AttribValues[IndexA+i] + Alpha*AttribValues[IndexB+i]);
568 }
569 }
570
572 virtual void SetAttributeFromBary(int SetAttribute, int AttributeA, int AttributeB, int AttributeC, const FVector3d& BaryCoords)
573 {
574 int IndexSet = AttribDimension * SetAttribute;
575 int IndexA = AttribDimension * AttributeA;
576 int IndexB = AttribDimension * AttributeB;
578 for (int i = 0; i < AttribDimension; ++i)
579 {
581 BaryCoords.X*AttribValues[IndexA+i] + BaryCoords.Y*AttribValues[IndexB+i] + BaryCoords.Z*AttribValues[IndexC+i]);
582 }
583 }
584
585};
586
587
588template<typename AttribValueType, int AttribDimension>
590
591
592template<typename AttribValueType, int AttribDimension, typename ParentType>
594{
595 FChangeVertexAttribute& Change = OldVertexAttributes.Emplace_GetRef();
596 Change.VertexID = VertexID;
598 AttribCast->GetValue(VertexID, Change.Data);
599}
600
601template<typename AttribValueType, int AttribDimension, typename ParentType>
603{
604 NewVertexAttributes.Reserve(NewVertexAttributes.Num() + VertexIDs.Num());
606 for (int VertexID : VertexIDs)
607 {
608 FChangeVertexAttribute& Change = NewVertexAttributes.Emplace_GetRef();
609 Change.VertexID = VertexID;
610 AttribCast->GetValue(VertexID, Change.Data);
611 }
612}
613
614template<typename AttribValueType, int AttribDimension, typename ParentType>
616{
617 const TArray<FChangeVertexAttribute> *Changes = bRevert ? &OldVertexAttributes : &NewVertexAttributes;
619 for (const FChangeVertexAttribute& Change : *Changes)
620 {
621 bool bIsVertex = AttribCast->GetParent()->IsVertex(Change.VertexID);
623 if (bIsVertex)
624 {
625 AttribCast->SetValue(Change.VertexID, Change.Data);
626 }
627 }
628 return true;
629}
630
631
632} // end namespace UE::Geometry
633} // end namespace UE
#define check(expr)
Definition AssertionMacros.h:314
#define ensure( InExpression)
Definition AssertionMacros.h:464
FPlatformTypes::SIZE_T SIZE_T
An unsigned integer the same size as a pointer, the same as UPTRINT.
Definition Platform.h:1150
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
@ Num
Definition MetalRHIPrivate.h:234
Definition Archive.h:1208
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 ArrayView.h:139
Definition Array.h:670
Definition UniquePtr.h:107
Definition CompactMaps.h:20
static constexpr int32 InvalidID
Definition CompactMaps.h:25
static constexpr int InvalidID
Definition DynamicMesh3.h:158
Definition DynamicMeshAttributeSet.h:84
Definition RefCountVector.h:403
Definition DynamicAttribute.h:67
virtual void CopyParentClassData(const TDynamicAttributeBase< ParentType > &Other)
Definition DynamicAttribute.h:249
void Serialize(FArchive &Ar)
Definition DynamicAttribute.h:231
Definition DynamicAttribute.h:24
Definition DynamicVector.h:27
size_t GetByteCount() const
Definition DynamicVector.h:149
void InsertAt(const Type &Data, unsigned int Index)
Definition DynamicVector.h:747
bool SetMinimumSize(unsigned int Count, const Type &InitValue)
Resize if Num() is less than Count; returns true if resize occurred.
Definition DynamicVector.h:646
size_t Num() const
Definition DynamicVector.h:147
void Resize(unsigned int Count)
Definition DynamicVector.h:603
void Fill(const Type &Value)
Definition DynamicVector.h:590
void SetNum(unsigned int Count)
Definition DynamicVector.h:143
Definition DynamicVertexAttribute.h:19
virtual ~TDynamicVertexAttributeChange()
Definition DynamicVertexAttribute.h:33
virtual bool Apply(TDynamicAttributeBase< ParentType > *Attribute, bool bRevert) const override
Definition DynamicVertexAttribute.h:615
virtual void StoreAllFinalVertices(const TDynamicAttributeBase< ParentType > *Attribute, const TSet< int > &VertexIDs) override
Definition DynamicVertexAttribute.h:602
TDynamicVertexAttributeChange()
Definition DynamicVertexAttribute.h:30
virtual void SaveInitialVertex(const TDynamicAttributeBase< ParentType > *Attribute, int VertexID) override
Definition DynamicVertexAttribute.h:593
Definition DynamicVertexAttribute.h:49
void SetNewValue(int NewVertexID, const AttribValueType *Data)
Definition DynamicVertexAttribute.h:159
void SetValue(int VertexID, const AsType &Data)
Definition DynamicVertexAttribute.h:278
const ParentType * GetParent() const
Definition DynamicVertexAttribute.h:82
void OnCollapseEdge(const FDynamicMesh3::FEdgeCollapseInfo &CollapseInfo) override
Definition DynamicVertexAttribute.h:327
void OnMergeVertices(const FDynamicMesh3::FMergeVerticesInfo &MergeInfo) override
Definition DynamicVertexAttribute.h:378
bool IsSameAs(const TDynamicVertexAttribute< AttribValueType, AttribDimension, ParentType > &Other, bool bIgnoreDataLayout) const
Definition DynamicVertexAttribute.h:423
virtual TDynamicAttributeBase< ParentType > * MakeNew(ParentType *ParentIn) const override
Definition DynamicVertexAttribute.h:88
virtual bool Append(const TDynamicAttributeBase< ParentType > &Source, const UE::Geometry::FDynamicMesh3::FAppendInfo &Info) override
Definition DynamicVertexAttribute.h:189
void Serialize(FArchive &Ar, const FCompactMaps *CompactMaps, bool bUseCompression)
Definition DynamicVertexAttribute.h:496
virtual SIZE_T GetByteCount() const override
Definition DynamicVertexAttribute.h:548
virtual void SetAttributeFromBary(int SetAttribute, int AttributeA, int AttributeB, int AttributeC, const FVector3d &BaryCoords)
Definition DynamicVertexAttribute.h:572
TDynamicVertexAttribute(ParentType *ParentIn, bool bAutoInit=true)
Definition DynamicVertexAttribute.h:69
virtual TDynamicAttributeBase< ParentType > * MakeCopy(ParentType *ParentIn) const override
Definition DynamicVertexAttribute.h:94
void OnFlipEdge(const FDynamicMesh3::FEdgeFlipInfo &FlipInfo) override
Definition DynamicVertexAttribute.h:321
virtual bool CopyOut(int RawID, void *Buffer, int BufferSize) const override
Definition DynamicVertexAttribute.h:215
virtual TUniquePtr< TDynamicAttributeChangeBase< ParentType > > NewBlankChange() const override
Definition DynamicVertexAttribute.h:389
virtual void OnNewVertex(int VertexID, bool bInserted) override
Definition DynamicVertexAttribute.h:350
void CompactInPlace(const FCompactMaps &CompactMaps)
Definition DynamicVertexAttribute.h:116
void GetValue(int VertexID, AsType &Data) const
Definition DynamicVertexAttribute.h:256
virtual void AppendDefaulted(const UE::Geometry::FDynamicMesh3::FAppendInfo &Info) override
Definition DynamicVertexAttribute.h:210
void OnSplitEdge(const FDynamicMesh3::FEdgeSplitInfo &SplitInfo) override
Definition DynamicVertexAttribute.h:314
virtual bool CheckValidity(bool bAllowNonmanifold, EValidityCheckFailMode FailMode) const override
Definition DynamicVertexAttribute.h:400
friend FArchive & operator<<(FArchive &Ar, TDynamicVertexAttribute< AttribValueType, AttribDimension, ParentType > &Attr)
Definition DynamicVertexAttribute.h:483
TDynamicVertexAttribute()
Definition DynamicVertexAttribute.h:64
void OnPokeTriangle(const FDynamicMesh3::FPokeTriangleInfo &PokeInfo) override
Definition DynamicVertexAttribute.h:357
virtual AttribValueType GetDefaultAttributeValue()
Definition DynamicVertexAttribute.h:332
void CompactCopy(const FCompactMaps &CompactMaps, const TDynamicVertexAttribute< AttribValueType, AttribDimension, ParentType > &ToCopy)
Definition DynamicVertexAttribute.h:133
virtual bool CopyThroughMapping(const TDynamicAttributeBase< ParentType > *Source, const FMeshIndexMappings &Mapping) override
Definition DynamicVertexAttribute.h:174
void SetScalarValue(int32 VertexID, const AttribValueType &SingleValue)
Definition DynamicVertexAttribute.h:288
void OnSplitVertex(const FDynamicMesh3::FVertexSplitInfo &SplitInfo, const TArrayView< const int > &TrianglesToUpdate) override
Definition DynamicVertexAttribute.h:384
void CopyValue(int FromVertexID, int ToVertexID)
Definition DynamicVertexAttribute.h:300
void ResizeAttribStoreIfNeeded(int VertexID)
Definition DynamicVertexAttribute.h:337
void SetValue(int VertexID, const AttribValueType *Data)
Definition DynamicVertexAttribute.h:267
virtual TDynamicAttributeBase< ParentType > * MakeCompactCopy(const FCompactMaps &CompactMaps, ParentType *ParentTypeIn) const override
Definition DynamicVertexAttribute.h:108
void Initialize(AttribValueType InitialValue=(AttribValueType) 0)
Definition DynamicVertexAttribute.h:152
TDynamicVector< AttribValueType > AttribValues
Definition DynamicVertexAttribute.h:56
void GetValue(int VertexID, AttribValueType *Data) const
Definition DynamicVertexAttribute.h:245
void OnMergeEdges(const FDynamicMesh3::FMergeEdgesInfo &MergeInfo) override
Definition DynamicVertexAttribute.h:365
ParentType * Parent
Definition DynamicVertexAttribute.h:53
virtual void SetAttributeFromLerp(int SetAttribute, int AttributeA, int AttributeB, double Alpha)
Definition DynamicVertexAttribute.h:559
virtual bool CopyIn(int RawID, void *Buffer, int BufferSize) override
Definition DynamicVertexAttribute.h:229
void Copy(const TDynamicVertexAttribute< AttribValueType, AttribDimension, ParentType > &Copy)
Definition DynamicVertexAttribute.h:102
virtual ~TDynamicVertexAttribute()
Definition DynamicVertexAttribute.h:77
ParentType * GetParent()
Definition DynamicVertexAttribute.h:84
EValidityCheckFailMode
Definition GeometryTypes.h:72
Definition AdvancedWidgetsModule.cpp:13
Definition InfoTypes.h:181
Definition InfoTypes.h:171
Definition InfoTypes.h:155
Definition InfoTypes.h:197
Definition InfoTypes.h:216
Definition InfoTypes.h:229
Definition InfoTypes.h:242
CORE_API static const FGuid GUID
Definition UE5MainStreamObjectVersion.h:22
Definition Tuple.h:652
Definition DynamicMesh3.h:309
Definition IndexTypes.h:158
int B
Definition IndexTypes.h:164
int A
Definition IndexTypes.h:163
int C
Definition IndexTypes.h:165
Definition MeshIndexMappings.h:22
FIndexMapi & GetVertexMap()
Definition MeshIndexMappings.h:60
TMap< IntType, IntType > & GetForwardMap()
Definition GeometryTypes.h:119
T Z
Definition Vector.h:68
T Y
Definition Vector.h:65
T X
Definition Vector.h:62