UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
MeshLocalParam.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5#include "VectorTypes.h"
6#include "MatrixTypes.h"
7#include "BoxTypes.h"
8#include "FrameTypes.h"
10#include "Util/DynamicVector.h"
12
13namespace UE
14{
15namespace Geometry
16{
17
30
41template<class PointSetType>
43{
44public:
46
49
56
59
60
62 {
64
65 int32 MaxID = PointSet->MaxVertexID();
67
68 MaxGraphDistance = 0.0;
69 MaxUVDistance = 0.0;
70 }
71
75 void Reset()
76 {
77 IDToNodeIndexMap.Reset();
79 Queue.Clear(false);
80 MaxGraphDistance = 0.0;
81 MaxUVDistance = 0.0;
82 }
83
84
85
93 {
95 MaxGraphDistance = 0.0f;
96 MaxUVDistance = 0.0f;
97
98 for (int32 j = 0; j < 3; ++j)
99 {
103 Node->GraphDistance = Node->UV.Length();
104 Node->bFrozen = true;
105 check(Queue.Contains(NbrPointID) == false);
106 Queue.Insert(NbrPointID, float(Node->GraphDistance));
107 }
108
110 }
111
112
135
136
137
142 {
143 for (FGraphNode& Node : AllocatedNodes)
144 {
145 if (Node.bFrozen)
146 {
147 Node.UV = (Node.UV * Scale) + Translate;
148 }
149 }
150 }
151
152
153
157 double GetMaxGraphDistance() const
158 {
159 return MaxGraphDistance;
160 }
161
165 double GetMaxUVDistance() const
166 {
167 return MaxUVDistance;
168 }
169
173 bool HasUV(int32 PointID) const
174 {
175 const FGraphNode* Node = GetNodeForPointSetID(PointID);
176 return (Node != nullptr && Node->bFrozen);
177 }
178
182 void GetPointsWithUV(TArray<int32>& Points) const
183 {
184 Points.Empty(AllocatedNodes.Num());
185 for (const FGraphNode& Node : AllocatedNodes)
186 {
187 if (Node.bFrozen)
188 {
189 Points.Add(Node.PointID);
190 }
191 }
192 }
193
197 FVector2d GetUV(int32 PointID) const
198 {
199 const FGraphNode* Node = GetNodeForPointSetID(PointID);
200 return (Node != nullptr && Node->bFrozen) ? Node->UV : InvalidUV();
201 }
202
215 {
217 for (const FGraphNode& Node : AllocatedNodes)
218 {
219 if (Node.bFrozen && Node.GraphDistance < MaxGraphDist && Node.UV.SquaredLength() < MaxUVMagSqr)
220 {
221 PointIDsOut.Add(Node.PointID);
222 PointUVsOut.Add(Node.UV);
223 }
224 }
225 }
226
227
228
232 void ApplyUVs( TFunctionRef<void(int32 PointID, const FVector2d& UV)> ApplyFunc ) const
233 {
234 for ( const FGraphNode& Node : AllocatedNodes )
235 {
236 if (Node.bFrozen)
237 {
238 ApplyFunc(Node.PointID, Node.UV);
239 }
240 }
241 }
242
243
248 {
250 for (const FGraphNode& Node : AllocatedNodes)
251 {
252 if (Node.bFrozen)
253 {
254 Bounds.Contain(Node.UV);
255 }
256 }
257 return Bounds;
258 }
259
260
261protected:
262
263 // wrap the calls to PointSet Vertex/Normal. Should make these more general.
264
265 FVector3d GetPosition(const int32 PointID) const
266 {
267 return PointSet->GetVertex(PointID);
268 }
269
270 FVector3d GetNormal(const int32 PointID) const
271 {
272 if (PointSet->HasVertexNormals())
273 {
274 return FVector3d(PointSet->GetVertexNormal(PointID));
275 }
276 // Note: Currently only have a standard vertex normal calculation for FDynamicMesh3
277 else if constexpr (std::is_same_v<PointSetType, FDynamicMesh3>)
278 {
280 }
281 else
282 {
283 ensureMsgf(false, TEXT("Local parameterization requires vertex normals!"));
284 return FVector3d::UnitY();
285 }
286 }
287
288protected:
289
290 // information about each active/computed point
301
302
303 FFrame3d GetFrame(const FGraphNode& Node) const
304 {
305 return FFrame3d(GetPosition(Node.PointID), Node.CachedNormal);
306 }
307
308
309 // To avoid constructing FGraphNode for all input points (because we are computing a "local" param),
310 // we only allocate on demand, and then store a sparse mapping in IDToNodeIndexMap
313
314 // queue of nodes to process (for dijkstra front propagation)
316
318
319 // seed frame, unwrap is centered around this position/axes
321
322 // max distances encountered during last compute
325
326
328 {
329 while (Queue.GetCount() > 0)
330 {
331 int32 NextID = Queue.Dequeue();
332 FGraphNode* Node = GetNodeForPointSetID(NextID, false);
333 check(Node != nullptr);
334
337 {
338 return;
339 }
340
341 if (Node->ParentPointID >= 0)
342 {
343 switch (ParamMode)
344 {
346 UpdateUVExpmap(*Node);
347 break;
350 break;
352 UpdateUVPlanar(*Node);
353 break;
354 }
355 }
356
357 double UVDistSqr = Node->UV.SquaredLength();
359 {
361 }
362
363 Node->bFrozen = true;
365 }
366
368 }
369
370
371
373 {
374 Position -= Frame.Origin;
375 FVector2d UV(Position.Dot(Frame.X()), Position.Dot(Frame.Y()));
376 return UV;
377 }
378
379 // calculate the UV value at Position based on the existing NbrUV, using the frame at NbrFrame, and the original SeedFrame
381 {
382 // project Position into local space of NbrFrame
384
386 SeedToLocal.AlignAxis(2, NbrFrame.Z());
387
390
391 double CosTheta = vLocalX.Dot(vAlignedSeedX);
392
393 // compute rotated min-dist vector for this particle
394 double Temp = 1.0 - CosTheta * CosTheta;
395 if (Temp < 0)
396 {
397 Temp = 0; // need to clamp so that sqrt works...
398 }
401 if ( vCross.Dot(NbrFrame.Z()) < 0) // get the right sign...
402 {
404 }
406 return NbrUV + FrameRotateMat * LocalUV;
407 }
408
409
411 {
412 FGraphNode* ParentNode = GetNodeForPointSetID(Node.ParentPointID, false);
413 check(ParentNode != nullptr);
414
415 FFrame3d ParentFrame = GetFrame(*ParentNode);
416
417 Node.UV = PropagateUV(GetPosition(Node.PointID), ParentNode->UV, ParentFrame, SeedFrame);
418 }
419
420
421
423 {
424 FGraphNode* ParentNode = GetNodeForPointSetID(Node.ParentPointID, false);
425 check(ParentNode != nullptr);
426
428
430 double WeightSum = 0;
431 int32 NbrCount = 0;
432 for (int32 NbrPointID : PointSet->VtxVerticesItr(Node.PointID))
433 {
435 if (NbrNode != nullptr && NbrNode->bFrozen)
436 {
441 WeightSum += Weight;
442 NbrCount++;
443 }
444 }
445 check(NbrCount > 0);
446
447 Node.UV = AverageUV / WeightSum;
448 }
449
450
451
453 {
455 }
456
457
458
459
461 {
463 if (AllocatedIndex == nullptr)
464 {
465 if (bCreateIfMissing)
466 {
467 FGraphNode NewNode{ PointSetID, -1, 0, FVector2d::Zero(), false, FVector3d::UnitZ() };
468
470 {
471 NewNode.CachedNormal = ExternalNormalFunc(PointSetID);
472 }
473 else
474 {
475 NewNode.CachedNormal = GetNormal(PointSetID);
476 }
477
478 int32 NewIndex = AllocatedNodes.Num();
479 AllocatedNodes.Add(NewNode);
480 IDToNodeIndexMap.Add(PointSetID, NewIndex);
481 return &AllocatedNodes[NewIndex];
482 }
483 else
484 {
485 return nullptr;
486 }
487 }
488 else
489 {
491 }
492 }
493
494
496 {
498 return (AllocatedIndex != nullptr) ? &AllocatedNodes[*AllocatedIndex] : nullptr;
499 }
500
501
502 // given new Distance/UV at Parent, check if any of its neighbours are in the queue,
503 // and if they are, and the new graph distance is shorter, update their queue position
504 // (this is basically the update step of Disjktras algorithm)
506 {
508 double ParentDist = Parent->GraphDistance;
509
510 for (int32 NbrPointID : PointSet->VtxVerticesItr(Parent->PointID))
511 {
513 if (NbrNode->bFrozen)
514 {
515 continue;
516 }
517
520 {
521 if (NbrDist < NbrNode->GraphDistance)
522 {
523 NbrNode->ParentPointID = Parent->PointID;
524 NbrNode->GraphDistance = NbrDist;
525 Queue.Update(NbrPointID, float(NbrNode->GraphDistance));
526 }
527 }
528 else
529 {
530 NbrNode->ParentPointID = Parent->PointID;
531 NbrNode->GraphDistance = NbrDist;
532 Queue.Insert(NbrPointID, float(NbrNode->GraphDistance));
533 }
534 }
535 }
536
537};
538
539
540} // end namespace UE::Geometry
541} // end namespace UE
#define check(expr)
Definition AssertionMacros.h:314
#define ensureMsgf( InExpression, InFormat,...)
Definition AssertionMacros.h:465
#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
D3D12_DESCRIPTOR_HEAP_TYPE Translate(ERHIDescriptorHeapType InHeapType)
Definition D3D12Descriptors.h:19
UE::Math::TVector2< double > FVector2d
Definition MathFwd.h:61
UE::Math::TVector< double > FVector3d
Definition MathFwd.h:60
uint8_t uint8
Definition binka_ue_file_header.h:8
Definition Array.h:670
UE_NODEBUG UE_FORCEINLINE_HINT SizeType Add(ElementType &&Item)
Definition Array.h:2696
void Empty(SizeType Slack=0)
Definition Array.h:2273
Definition AssetRegistryState.h:50
Definition AndroidPlatformMisc.h:14
Definition UnrealString.h.inl:34
Definition MathUtil.h:150
static RealType Max(const RealType A, const RealType B)
Definition MathUtil.h:246
static RealType Sqrt(const RealType Value)
Definition MathUtil.h:342
Definition IndexPriorityQueue.h:22
bool Contains(int NodeID) const
Definition IndexPriorityQueue.h:106
void Clear(bool bFreeMemory=true)
Definition IndexPriorityQueue.h:79
int GetCount() const
Definition IndexPriorityQueue.h:88
void Insert(int NodeID, float priority)
Definition IndexPriorityQueue.h:121
void Update(int NodeID, float Priority)
Definition IndexPriorityQueue.h:172
void Initialize(int MaxNodeID)
Definition IndexPriorityQueue.h:67
int Dequeue()
Definition IndexPriorityQueue.h:142
static GEOMETRYCORE_API FVector3d ComputeVertexNormal(const FDynamicMesh3 &Mesh, int VertIdx, bool bWeightByArea=true, bool bWeightByAngle=true)
Definition MeshNormals.cpp:532
Definition DynamicVector.h:27
void Add(const Type &Data)
Definition DynamicVector.h:662
size_t Num() const
Definition DynamicVector.h:147
void Clear()
Definition DynamicVector.h:578
Definition MeshLocalParam.h:43
void ApplyUVs(TFunctionRef< void(int32 PointID, const FVector2d &UV)> ApplyFunc) const
Definition MeshLocalParam.h:232
void UpdateNeighboursSparse(FGraphNode *Parent)
Definition MeshLocalParam.h:505
void UpdateUVExpmap(FGraphNode &Node)
Definition MeshLocalParam.h:410
FIndexPriorityQueue Queue
Definition MeshLocalParam.h:315
static FVector2d InvalidUV()
Definition MeshLocalParam.h:317
bool HasUV(int32 PointID) const
Definition MeshLocalParam.h:173
void GetPointsWithUV(TArray< int32 > &Points) const
Definition MeshLocalParam.h:182
FFrame3d GetFrame(const FGraphNode &Node) const
Definition MeshLocalParam.h:303
FVector3d GetPosition(const int32 PointID) const
Definition MeshLocalParam.h:265
double MaxUVDistance
Definition MeshLocalParam.h:324
void UpdateUVPlanar(FGraphNode &Node)
Definition MeshLocalParam.h:452
void ProcessQueueUntilTermination(double MaxDistance)
Definition MeshLocalParam.h:327
FGraphNode * GetNodeForPointSetID(int32 PointSetID, bool bCreateIfMissing)
Definition MeshLocalParam.h:460
FAxisAlignedBox2d GetUVBounds() const
Definition MeshLocalParam.h:247
FVector2d GetUV(int32 PointID) const
Definition MeshLocalParam.h:197
void Reset()
Definition MeshLocalParam.h:75
TMap< int32, int32 > IDToNodeIndexMap
Definition MeshLocalParam.h:311
const PointSetType * PointSet
Definition MeshLocalParam.h:45
FFrame3d SeedFrame
Definition MeshLocalParam.h:320
bool bEnableExternalNormals
Definition MeshLocalParam.h:55
void TransformUV(double Scale, FVector2d Translate)
Definition MeshLocalParam.h:141
const FGraphNode * GetNodeForPointSetID(int32 PointSetID) const
Definition MeshLocalParam.h:495
void GetAllComputedUVs(TArray< int32 > &PointIDsOut, TArray< FVector2d > &PointUVsOut, double MaxUVMagnitude=TNumericLimits< float >::Max(), double MaxGraphDist=TNumericLimits< float >::Max()) const
Definition MeshLocalParam.h:210
FVector2d PropagateUV(const FVector3d &Position, const FVector2d &NbrUV, const FFrame3d &NbrFrame, const FFrame3d &SeedFrameIn) const
Definition MeshLocalParam.h:380
void ComputeToMaxDistance(int32 CenterPointVtxID, const FFrame3d &CenterPointFrame, double ComputeToMaxDistanceIn)
Definition MeshLocalParam.h:119
TMeshLocalParam(const PointSetType *PointSetIn)
Definition MeshLocalParam.h:61
FVector2d ComputeLocalUV(const FFrame3d &Frame, FVector3d Position) const
Definition MeshLocalParam.h:372
ELocalParamTypes ParamMode
Definition MeshLocalParam.h:48
void ComputeToMaxDistance(const FFrame3d &SeedFrameIn, const FIndex3i &SeedNbrs, double ComputeToMaxDistanceIn)
Definition MeshLocalParam.h:92
double MaxGraphDistance
Definition MeshLocalParam.h:323
FVector3d GetNormal(const int32 PointID) const
Definition MeshLocalParam.h:270
TFunction< FVector3d(int32)> ExternalNormalFunc
Definition MeshLocalParam.h:58
void UpdateUVExpmapUpwind(FGraphNode &Node)
Definition MeshLocalParam.h:422
double GetMaxUVDistance() const
Definition MeshLocalParam.h:165
double GetMaxGraphDistance() const
Definition MeshLocalParam.h:157
TDynamicVector< FGraphNode > AllocatedNodes
Definition MeshLocalParam.h:312
ELocalParamTypes
Definition MeshLocalParam.h:22
T DistanceSquared(const UE::Math::TVector2< T > &V1, const UE::Math::TVector2< T > &V2)
Definition VectorTypes.h:82
TFrame3< double > FFrame3d
Definition FrameTypes.h:478
Definition AdvancedWidgetsModule.cpp:13
Definition NumericLimits.h:41
Definition IndexTypes.h:158
Definition BoxTypes.h:637
void Contain(const TVector2< RealType > &V)
Definition BoxTypes.h:738
static TAxisAlignedBox2< RealType > Empty()
Definition BoxTypes.h:706
Definition MeshLocalParam.h:292
double GraphDistance
Definition MeshLocalParam.h:295
FVector2d UV
Definition MeshLocalParam.h:296
FVector3d CachedNormal
Definition MeshLocalParam.h:299
int32 PointID
Definition MeshLocalParam.h:293
bool bFrozen
Definition MeshLocalParam.h:297
int32 ParentPointID
Definition MeshLocalParam.h:294
UE_FORCEINLINE_HINT T Length() const
Definition Vector2D.h:497
UE_FORCEINLINE_HINT T SquaredLength() const
Definition Vector2D.h:516
static TVector2< double > Zero()
Definition Vector2D.h:79
static TVector< double > UnitY()
Definition Vector.h:121
static TVector< double > UnitZ()
Definition Vector.h:124
UE_FORCEINLINE_HINT TVector< T > Cross(const TVector< T > &V2) const
Definition Vector.h:1535
T X
Definition Vector.h:62