UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
BlendSpaceHelpers.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5#include "CoreMinimal.h"
7
8struct FTriangle;
9
11// SAnimationBlendSpace
12
13struct FTriangle;
14
19struct FVertex
20{
21 // position of Point
23
24 // Triangles this point belongs to
26
27 // The original animation sample associated with this point
29
31
32 bool operator==(const FVector2D& Other) const
33 {
34 // if same position, it's same point
35 return (Other == Position);
36 }
37
38 bool operator==( const FVertex& Other ) const
39 {
40 // if same position, it's same point
41 return (Other.Position == Position);
42 }
43
48
53
54 double GetDistance(const FVertex& Other)
55 {
56 return (Other.Position-Position).Size();
57 }
58};
59
61{
62 // 3 vertices in CCW order
64
67 {
68 Vertices[0] = A;
69 Vertices[1] = B;
70 }
71
72 bool DoesShare(const FHalfEdge& A) const
73 {
74 return (Vertices[0] == A.Vertices[1] && Vertices[1] == A.Vertices[0]);
75 }
76
77 bool operator==( const FHalfEdge& Other ) const
78 {
79 // if same position, it's same point
80 return FMemory::Memcmp(Other.Vertices, Vertices, sizeof(Vertices)) == 0;
81 }
82};
88{
89 // 3 vertices in CCW order
91 // average points for Vertices
93 // FEdges
95
97 {
98 Center = (Vertices[0]->Position + Vertices[1]->Position + Vertices[2]->Position) / 3.0;
99 }
100
101 bool operator==( const FTriangle& Other ) const
102 {
103 // if same position, it's same point
104 return FMemory::Memcmp(Other.Vertices, Vertices, sizeof(Vertices)) == 0;
105 }
106
108 {
109 FMemory::Memcpy(Vertices, Copy.Vertices);
110 FMemory::Memcpy(Edges, Copy.Edges);
111 UpdateCenter();
112
113 Vertices[0]->AddTriangle(this);
114 Vertices[1]->AddTriangle(this);
115 Vertices[2]->AddTriangle(this);
116 }
117
119 {
120 Vertices[0] = A;
121 Vertices[1] = B;
122 Vertices[2] = C;
123 UpdateCenter();
124
125 Vertices[0]->AddTriangle(this);
126 Vertices[1]->AddTriangle(this);
127 Vertices[2]->AddTriangle(this);
128 // when you make triangle first time, make sure it stays in CCW
129 MakeCCW();
130
131 // now create edges, this should be in the CCW order
132 Edges[0] = FHalfEdge(Vertices[0], Vertices[1]);
133 Edges[1] = FHalfEdge(Vertices[1], Vertices[2]);
134 Edges[2] = FHalfEdge(Vertices[2], Vertices[0]);
135 }
136
138 {
139 Vertices[0] = A;
140 Vertices[1] = A;
141 Vertices[2] = A;
142 UpdateCenter();
143
144 Vertices[0]->AddTriangle(this);
145 Vertices[1]->AddTriangle(this);
146 Vertices[2]->AddTriangle(this);
147
148 // now create edges, this should be in the CCW order
149 Edges[0] = FHalfEdge(Vertices[0], Vertices[1]);
150 Edges[1] = FHalfEdge(Vertices[1], Vertices[2]);
151 Edges[2] = FHalfEdge(Vertices[2], Vertices[0]);
152 }
153
155 {
156 Vertices[0] = A;
157 Vertices[1] = B;
158 Vertices[2] = B;
159 UpdateCenter();
160
161 Vertices[0]->AddTriangle(this);
162 Vertices[1]->AddTriangle(this);
163 Vertices[2]->AddTriangle(this);
164
165 // now create edges, this should be in the CCW order
166 Edges[0] = FHalfEdge(Vertices[0], Vertices[1]);
167 Edges[1] = FHalfEdge(Vertices[1], Vertices[2]);
168 Edges[2] = FHalfEdge(Vertices[2], Vertices[0]);
169 }
170
172 {
173 Vertices[0] = nullptr;
174 Vertices[1] = nullptr;
175 Vertices[2] = nullptr;
176 }
177
179 {
180 for (int32 VertexIndex = 0; VertexIndex < 3; ++VertexIndex)
181 {
182 if (Vertices[VertexIndex])
183 {
184 Vertices[VertexIndex]->RemoveTriangle(this);
185 }
186 }
187 }
188
189 bool Contains (const FVertex& Other) const
190 {
191 return (Other == *Vertices[0] || Other == *Vertices[1] || Other == *Vertices[2]);
192 }
193
194 double GetDistance(const FVertex& Other) const
195 {
196 return (Other.Position-Center).Size();
197 }
198
199 double GetDistance(const FVector2D& Other) const
200 {
201 return (Other-Center).Size();
202 }
203
204 bool HasSameHalfEdge(const FTriangle* Other) const
205 {
206 for (int32 I=0; I<3; ++I)
207 {
208 for (int32 J=0; J<3; ++J)
209 {
210 if (Other->Edges[I] == Edges[J])
211 {
212 return true;
213 }
214 }
215 }
216
217 return false;
218 }
219
221 {
222 for (int32 I=0; I<3; ++I)
223 {
224 for (int32 J=0; J<3; ++J)
225 {
226 if (Other->Edges[I].DoesShare(Edges[J]))
227 {
228 return true;
229 }
230 }
231 }
232
233 return false;
234 }
235
236 // find point that doesn't share with this
237 // this should only get called if it shares same edge
239 {
240 if (!Contains(*Other->Vertices[0]))
241 {
242 return Other->Vertices[0];
243 }
244
245 if (!Contains(*Other->Vertices[1]))
246 {
247 return Other->Vertices[1];
248 }
249
250 if (!Contains(*Other->Vertices[2]))
251 {
252 return Other->Vertices[2];
253 }
254
255 return NULL;
256 }
257
258private:
259 void MakeCCW()
260 {
261 // this eventually has to happen on the plane that contains this 3 points
262 // for now we ignore Z
265
266 double Result = Diff1.X*Diff2.Y - Diff1.Y*Diff2.X;
267
268 check (Result != 0.f);
269
270 // it's in left side, we need this to be right side
271 if (Result < 0.f)
272 {
273 // swap 1&2
274 FVertex * TempPt = Vertices[2];
275 Vertices[2] = Vertices[1];
276 Vertices[1] = TempPt;
277 }
278 }
279};
280
286{
287public:
297 void Reset();
298 void EmptyTriangles();
299 void EmptySamplePoints();
300
304 void Triangulate(EPreferredTriangulationDirection PreferredTriangulationDirection);
305
310
315 void AddSamplePoint(const FVector2D& NewPoint, const int32 SampleIndex);
316
321 void Step(int32 StartIndex);
322
324 {
325 Reset();
326 }
327
331 const TArray<FTriangle*> & GetTriangleList() const { return TriangleList; };
332
336 const TArray<FVertex> & GetSamplePointList() const { return SamplePointList; };
337
338 /* Set the grid box, so we can normalize the sample points */
340
341private:
348 void SortSamples();
349
353 void AdjustEdgeDirections(EPreferredTriangulationDirection PreferredTriangulationDirection);
354
359 int32 FindTriangleIndexWithEdge(int32 SampleIndex0, int32 SampleIndex1, int32* VertexIndex = nullptr) const;
360
366 ECircumCircleState GetCircumcircleState(const FTriangle* T, const FVertex& TestPoint);
367
371 bool IsEligibleForTriangulation(const FVertex* A, const FVertex* B, const FVertex* C)
372 {
373 return (IsCollinear(A, B, C)==false);
374 }
375
380 bool IsCollinear(const FVertex* A, const FVertex* B, const FVertex* C);
381
386 bool AllCoincident(const TArray<FVertex>& InPoints);
387
391 bool FlipTriangles(const int32 TriangleIndexOne, const int32 TriangleIndexTwo);
392
396 void AddTriangle(FTriangle & newTriangle, bool bCheckHalfEdge=true);
397
402 int32 GenerateTriangles(TArray<FVertex> & PointList, const int32 TotalNum);
403
404private:
409 TArray<FVertex> SamplePointList;
410
414 TArray<FTriangle*> TriangleList;
415
420 FVector2D GridMin;
421 FVector2D RecipGridSize;
422};
423
424// @todo fixmelh : this code is mess between fvector2D and fvector
425// ideally FBlendSpaceGrid will be handled in 3D, and SBlendSpaceGridWidget only knows about 2D
426// in the future this should all change to 3D
427
433{
434public:
446
454
459 : GridMin(0, 0)
460 , GridMax(100, 100)
461 , NumGridPointsForAxis(5, 5)
462 {
463 }
464
465 void Reset()
466 {
467 GridPoints.Empty();
468 }
469
471 {
472 NumGridPointsForAxis.X = BlendParamX.GridNum + 1;
473 NumGridPointsForAxis.Y = BlendParamY.GridNum + 1;
474
475 NumGridDivisions.X = BlendParamX.GridNum;
476 NumGridDivisions.Y = BlendParamY.GridNum;
477
478 GridMin.X = BlendParamX.Min;
479 GridMax.X = BlendParamX.Max;
480
481 GridMin.Y = BlendParamY.Min;
482 GridMax.Y = BlendParamY.Max;
483 }
484
485 const FEditorElement& GetElement(const int32 GridX, const int32 GridY) const;
486 const TArray<FEditorElement>& GetElements() const { return GridPoints;}
487
491 const FVector2D GetPosFromIndex(const int32 GridX, const int32 GridY) const;
492
493private:
495 // Grid Dimension
496 FVector2D GridMin;
497 FVector2D GridMax;
498
499 // how many rows/cols for each axis
500 FIntPoint NumGridPointsForAxis;
501 FIntPoint NumGridDivisions;
502
503 // Each point data -output data
504 TArray<FEditorElement> GridPoints; // 2D array saved in 1D array, to search (x, y), x*GridSizeX+y;
505};
#define NULL
Definition oodle2base.h:134
#define check(expr)
Definition AssertionMacros.h:314
EPreferredTriangulationDirection
Definition BlendSpace.h:53
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
Definition BlendSpaceHelpers.h:433
void SetGridInfo(const FBlendParameter &BlendParamX, const FBlendParameter &BlendParamY)
Definition BlendSpaceHelpers.h:470
bool FindTriangleThisPointBelongsTo(const FVector2D &TestPoint, FVector &OutBarycentricCoords, FTriangle *&OutTriangle, const TArray< FTriangle * > &TriangleList) const
Definition BlendSpaceHelpers.cpp:593
const FEditorElement & GetElement(const int32 GridX, const int32 GridY) const
Definition BlendSpaceHelpers.cpp:757
const FVector2D GetPosFromIndex(const int32 GridX, const int32 GridY) const
Definition BlendSpaceHelpers.cpp:743
void GenerateGridElements(const TArray< FVertex > &SamplePoints, const TArray< FTriangle * > &TriangleList)
Definition BlendSpaceHelpers.cpp:657
FBlendSpaceGrid()
Definition BlendSpaceHelpers.h:458
void Reset()
Definition BlendSpaceHelpers.h:465
const TArray< FEditorElement > & GetElements() const
Definition BlendSpaceHelpers.h:486
Definition BlendSpaceHelpers.h:286
const TArray< FVertex > & GetSamplePointList() const
Definition BlendSpaceHelpers.h:336
ECircumCircleState
Definition BlendSpaceHelpers.h:289
@ ECCS_Inside
Definition BlendSpaceHelpers.h:292
@ ECCS_Outside
Definition BlendSpaceHelpers.h:290
@ ECCS_On
Definition BlendSpaceHelpers.h:291
void EmptySamplePoints()
Definition BlendSpaceHelpers.cpp:40
void Triangulate(EPreferredTriangulationDirection PreferredTriangulationDirection)
Definition BlendSpaceHelpers.cpp:57
const TArray< FTriangle * > & GetTriangleList() const
Definition BlendSpaceHelpers.h:331
void Step(int32 StartIndex)
void SetGridBox(const FBlendParameter &BlendParamX, const FBlendParameter &BlendParamY)
Definition BlendSpaceHelpers.cpp:18
void Reset()
Definition BlendSpaceHelpers.cpp:45
~FDelaunayTriangleGenerator()
Definition BlendSpaceHelpers.h:323
void AddSamplePoint(const FVector2D &NewPoint, const int32 SampleIndex)
Definition BlendSpaceHelpers.cpp:51
TArray< struct FBlendSpaceTriangle > CalculateTriangles() const
Definition BlendSpaceHelpers.cpp:311
void EmptyTriangles()
Definition BlendSpaceHelpers.cpp:31
Definition Array.h:670
SizeType Remove(const ElementType &Item)
Definition Array.h:3091
UE_FORCEINLINE_HINT SizeType AddUnique(ElementType &&Item)
Definition Array.h:2993
void Empty(SizeType Slack=0)
Definition Array.h:2273
Definition BlendSpace.h:114
Definition BlendSpace.h:377
Definition BlendSpaceHelpers.h:61
bool DoesShare(const FHalfEdge &A) const
Definition BlendSpaceHelpers.h:72
FHalfEdge()
Definition BlendSpaceHelpers.h:65
FHalfEdge(FVertex *A, FVertex *B)
Definition BlendSpaceHelpers.h:66
FVertex * Vertices[2]
Definition BlendSpaceHelpers.h:63
bool operator==(const FHalfEdge &Other) const
Definition BlendSpaceHelpers.h:77
static UE_FORCEINLINE_HINT int32 Memcmp(const void *Buf1, const void *Buf2, SIZE_T Count)
Definition UnrealMemory.h:114
static UE_FORCEINLINE_HINT void * Memcpy(void *Dest, const void *Src, SIZE_T Count)
Definition UnrealMemory.h:160
Definition BlendSpaceHelpers.h:88
void UpdateCenter()
Definition BlendSpaceHelpers.h:96
FHalfEdge Edges[3]
Definition BlendSpaceHelpers.h:94
FTriangle(FTriangle &Copy)
Definition BlendSpaceHelpers.h:107
FVertex * FindNonSharingPoint(const FTriangle *Other) const
Definition BlendSpaceHelpers.h:238
FVector2D Center
Definition BlendSpaceHelpers.h:92
FTriangle(FVertex *A)
Definition BlendSpaceHelpers.h:137
bool Contains(const FVertex &Other) const
Definition BlendSpaceHelpers.h:189
bool HasSameHalfEdge(const FTriangle *Other) const
Definition BlendSpaceHelpers.h:204
FTriangle()
Definition BlendSpaceHelpers.h:171
bool DoesShareSameEdge(const FTriangle *Other) const
Definition BlendSpaceHelpers.h:220
double GetDistance(const FVector2D &Other) const
Definition BlendSpaceHelpers.h:199
FVertex * Vertices[3]
Definition BlendSpaceHelpers.h:90
FTriangle(FVertex *A, FVertex *B, FVertex *C)
Definition BlendSpaceHelpers.h:118
~FTriangle()
Definition BlendSpaceHelpers.h:178
double GetDistance(const FVertex &Other) const
Definition BlendSpaceHelpers.h:194
FTriangle(FVertex *A, FVertex *B)
Definition BlendSpaceHelpers.h:154
bool operator==(const FTriangle &Other) const
Definition BlendSpaceHelpers.h:101
Definition BlendSpaceHelpers.h:20
TArray< FTriangle * > Triangles
Definition BlendSpaceHelpers.h:25
void AddTriangle(FTriangle *NewTriangle)
Definition BlendSpaceHelpers.h:44
int32 SampleIndex
Definition BlendSpaceHelpers.h:28
double GetDistance(const FVertex &Other)
Definition BlendSpaceHelpers.h:54
bool operator==(const FVector2D &Other) const
Definition BlendSpaceHelpers.h:32
FVertex(FVector2D InPosition, int32 InSampleIndex)
Definition BlendSpaceHelpers.h:30
void RemoveTriangle(FTriangle *TriangleToRemove)
Definition BlendSpaceHelpers.h:49
FVector2D Position
Definition BlendSpaceHelpers.h:22
bool operator==(const FVertex &Other) const
Definition BlendSpaceHelpers.h:38
Definition IntPoint.h:25
IntType Y
Definition IntPoint.h:37
IntType X
Definition IntPoint.h:34
T Y
Definition Vector2D.h:52
T X
Definition Vector2D.h:49