UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
AnimationCoreUtil.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3/*=============================================================================
4 AnimationCoreUtil.h: Render core module definitions.
5=============================================================================*/
6
7#pragma once
8
9#include "CoreMinimal.h"
10
12{
13 void Reset()
14 {
15 Transforms.Reset();
16 Translations.Reset();
17 Rotations.Reset();
18 Scales.Reset();
19 TranslationWeights.Reset();
20 RotationWeights.Reset();
21 ScaleWeights.Reset();
22 }
23
25 {
26 Transforms.Add(InTransform);
27 ParentWeights.Add(Weight);
28 ensureAlways(Transforms.Num() == ParentWeights.Num());
29 }
30
32 {
33 Translations.Add(Translation);
34 TranslationWeights.Add(Weight);
35 ensureAlways(Translations.Num() == TranslationWeights.Num());
36 }
37
38 void AddRotation(const FQuat& Rotation, float Weight)
39 {
40 Rotations.Add(Rotation);
41 RotationWeights.Add(Weight);
42 ensureAlways(Rotations.Num() == RotationWeights.Num());
43 }
44
45 void AddScale(const FVector& Scale, float Weight)
46 {
47 Scales.Add(Scale);
48 ScaleWeights.Add(Weight);
49 ensureAlways(Scales.Num() == ScaleWeights.Num());
50 }
51
52 bool GetBlendedParent(FTransform& OutTransform)
53 {
54 // there is no correct value to return if no translation
55 // so if false, do not use this value
56 if (Transforms.Num() > 0)
57 {
58 float TotalWeight = GetTotalWeight(ParentWeights);
59
60 if (TotalWeight > ZERO_ANIMWEIGHT_THRESH)
61 {
62 float MultiplyWeight = (TotalWeight > 1.f) ? 1.f / TotalWeight : 1.f;
63
64 int32 NumBlends = Transforms.Num();
65
66 float ParentWeight = ParentWeights[0] * MultiplyWeight;
67 FVector OutTranslation = Transforms[0].GetTranslation() * ParentWeight;
68 FQuat OutRotation = Transforms[0].GetRotation() * ParentWeight;
69 FVector OutScale = Transforms[0].GetScale3D() * ParentWeight;
70
71 // otherwise we just purely blend by number, and then later we normalize
72 for (int32 Index = 1; Index < NumBlends; ++Index)
73 {
74 // Simple linear interpolation for translation and scale.
75 ParentWeight = ParentWeights[Index] * MultiplyWeight;
76 OutTranslation = FMath::Lerp(OutTranslation, Transforms[Index].GetTranslation(), ParentWeight);
77 OutScale = OutScale + Transforms[Index].GetScale3D()*ParentWeight;
78 OutRotation = FQuat::FastLerp(OutRotation, Transforms[Index].GetRotation(), ParentWeight);
79 }
80
81 OutRotation.Normalize();
83
84 return true;
85 }
86 }
87
88 return false;
89 }
90
92 {
93 // there is no correct value to return if no translation
94 // so if false, do not use this value
95 if (Translations.Num() > 0)
96 {
97 float TotalWeight = GetTotalWeight(TranslationWeights);
98
99 if (TotalWeight > ZERO_ANIMWEIGHT_THRESH)
100 {
101 float MultiplyWeight = (TotalWeight > 1.f) ? 1.f / TotalWeight : 1.f;
102
103 Output = Translations[0] * (TranslationWeights[0] * MultiplyWeight);
104
105 for (int32 Index = 1; Index < Translations.Num(); ++Index)
106 {
107 Output += Translations[Index] * (TranslationWeights[Index] * MultiplyWeight);
108 }
109
110 return true;
111 }
112 }
113
114 return false;
115 }
116
118 {
119 // there is no correct value to return if no translation
120 // so if false, do not use this value
121 if (Rotations.Num() > 0)
122 {
123 float TotalWeight = GetTotalWeight(RotationWeights);
124
125 if (TotalWeight > ZERO_ANIMWEIGHT_THRESH)
126 {
127 float MultiplyWeight = (TotalWeight > 1.f) ? 1.f / TotalWeight : 1.f;
128
129 Output = Rotations[0] * (RotationWeights[0] * MultiplyWeight);
130
131 for (int32 Index = 1; Index < Rotations.Num(); ++Index)
132 {
133 FQuat BlendRotation = Rotations[Index] * (RotationWeights[Index] * MultiplyWeight);
134 if ((Output | BlendRotation) < 0)
135 {
136 Output.X -= BlendRotation.X;
137 Output.Y -= BlendRotation.Y;
138 Output.Z -= BlendRotation.Z;
139 Output.W -= BlendRotation.W;
140 }
141 else
142 {
143 Output.X += BlendRotation.X;
144 Output.Y += BlendRotation.Y;
145 Output.Z += BlendRotation.Z;
146 Output.W += BlendRotation.W;
147 }
148 }
149
150 Output.Normalize();
151 return true;
152 }
153 }
154
155 return false;
156 }
158 {
159 // there is no correct value to return if no translation
160 // so if false, do not use this value
161 if (Scales.Num() > 0)
162 {
163 float TotalWeight = GetTotalWeight(ScaleWeights);
164
165 if (TotalWeight > ZERO_ANIMWEIGHT_THRESH)
166 {
167 float MultiplyWeight = (TotalWeight > 1.f) ? 1.f / TotalWeight : 1.f;
168
170
171 for (int32 Index = 0; Index < Scales.Num(); ++Index)
172 {
173 Output += Scales[Index] * (ScaleWeights[Index] * MultiplyWeight);
174 }
175
176 return true;
177 }
178 }
179
180 return false;
181 }
182
183private:
184 // data member to accumulate blending intermediate result per component
185 TArray<FTransform> Transforms;
186 TArray<FVector> Translations;
187 TArray<FQuat> Rotations;
188 TArray<FVector> Scales;
189 TArray<float> ParentWeights;
190 TArray<float> TranslationWeights;
191 TArray<float> RotationWeights;
192 TArray<float> ScaleWeights;
193
194 float GetTotalWeight(const TArray<float>& Weights)
195 {
196 float TotalWeight = 0.f;
197 for (float Weight : Weights)
198 {
199 TotalWeight += Weight;
200 }
201
202 return TotalWeight;
203 }
204};
205
207{
208 void Reset()
209 {
210 Transforms.Reset();
211 Translations.Reset();
212 Rotations.Reset();
213 Scales.Reset();
214 TranslationWeights.Reset();
215 RotationWeights.Reset();
216 ScaleWeights.Reset();
217 }
218
220 {
221 Transforms.Add(InTransform);
222 ParentWeights.Add(Weight);
223 ensureAlways(Transforms.Num() == ParentWeights.Num());
224 }
225
227 {
228 Translations.Add(Translation);
229 TranslationWeights.Add(Weight);
230 ensureAlways(Translations.Num() == TranslationWeights.Num());
231 }
232
233 void AddRotation(const FQuat& Rotation, float Weight)
234 {
235 Rotations.Add(Rotation);
236 RotationWeights.Add(Weight);
237 ensureAlways(Rotations.Num() == RotationWeights.Num());
238 }
239
240 void AddScale(const FVector& Scale, float Weight)
241 {
242 Scales.Add(Scale);
243 ScaleWeights.Add(Weight);
244 ensureAlways(Scales.Num() == ScaleWeights.Num());
245 }
246
247 bool GetBlendedParent(FTransform& OutTransform)
248 {
249 // there is no correct value to return if no translation
250 // so if false, do not use this value
251 if (Transforms.Num() > 0)
252 {
253 float TotalWeight = GetTotalWeight(ParentWeights);
254
255 if (TotalWeight > ZERO_ANIMWEIGHT_THRESH)
256 {
257 float MultiplyWeight = (TotalWeight > 1.f) ? 1.f / TotalWeight : 1.f;
258
259 int32 NumBlends = Transforms.Num();
260
261 OutTransform = Transforms[0] * ScalarRegister(ParentWeights[0] * MultiplyWeight);
262
263 // otherwise we just purely blend by number, and then later we normalize
264 for (int32 Index = 1; Index < NumBlends; ++Index)
265 {
266 // Simple linear interpolation for translation and scale.
267 OutTransform.AccumulateWithShortestRotation(Transforms[Index], ScalarRegister(ParentWeights[Index] * MultiplyWeight));
268 }
269
270 OutTransform.NormalizeRotation();
271
272 return true;
273 }
274 }
275
276 return false;
277 }
278
280 {
281 // there is no correct value to return if no translation
282 // so if false, do not use this value
283 if (Translations.Num() > 0)
284 {
285 float TotalWeight = GetTotalWeight(TranslationWeights);
286
287 if (TotalWeight > ZERO_ANIMWEIGHT_THRESH)
288 {
289 float MultiplyWeight = (TotalWeight > 1.f) ? 1.f / TotalWeight : 1.f;
290
291 Output = Translations[0] * (TranslationWeights[0] * MultiplyWeight);
292
293 for (int32 Index = 1; Index < Translations.Num(); ++Index)
294 {
295 Output += Translations[Index] * (TranslationWeights[Index] * MultiplyWeight);
296 }
297
298 return true;
299 }
300 }
301
302 return false;
303 }
304
306 {
307 // there is no correct value to return if no translation
308 // so if false, do not use this value
309 if (Rotations.Num() > 0)
310 {
311 float TotalWeight = GetTotalWeight(RotationWeights);
312
313 if (TotalWeight > ZERO_ANIMWEIGHT_THRESH)
314 {
315 float MultiplyWeight = (TotalWeight > 1.f) ? 1.f / TotalWeight : 1.f;
316
317 Output = Rotations[0] * (RotationWeights[0] * MultiplyWeight);
318
319 for (int32 Index = 1; Index < Rotations.Num(); ++Index)
320 {
321 FQuat BlendRotation = Rotations[Index] * (RotationWeights[Index] * MultiplyWeight);
322 if ((Output | BlendRotation) < 0)
323 {
324 Output.X -= BlendRotation.X;
325 Output.Y -= BlendRotation.Y;
326 Output.Z -= BlendRotation.Z;
327 Output.W -= BlendRotation.W;
328 }
329 else
330 {
331 Output.X += BlendRotation.X;
332 Output.Y += BlendRotation.Y;
333 Output.Z += BlendRotation.Z;
334 Output.W += BlendRotation.W;
335 }
336 }
337
338 Output.Normalize();
339 return true;
340 }
341 }
342
343 return false;
344 }
346 {
347 // there is no correct value to return if no translation
348 // so if false, do not use this value
349 if (Scales.Num() > 0)
350 {
351 float TotalWeight = GetTotalWeight(ScaleWeights);
352
353 if (TotalWeight > ZERO_ANIMWEIGHT_THRESH)
354 {
355 float MultiplyWeight = (TotalWeight > 1.f) ? 1.f / TotalWeight : 1.f;
356
358
359 for (int32 Index = 0; Index < Scales.Num(); ++Index)
360 {
361 Output += Scales[Index] * (ScaleWeights[Index] * MultiplyWeight);
362 }
363
364 return true;
365 }
366 }
367
368 return false;
369 }
370
371private:
372 // data member to accumulate blending intermediate result per component
373 TArray<FTransform> Transforms;
374 TArray<FVector> Translations;
375 TArray<FQuat> Rotations;
376 TArray<FVector> Scales;
377 TArray<float> ParentWeights;
378 TArray<float> TranslationWeights;
379 TArray<float> RotationWeights;
380 TArray<float> ScaleWeights;
381
382 float GetTotalWeight(const TArray<float>& Weights)
383 {
384 float TotalWeight = 0.f;
385 for (float Weight : Weights)
386 {
387 TotalWeight += Weight;
388 }
389
390 return TotalWeight;
391 }
392};
#define ensureAlways( InExpression)
Definition AssertionMacros.h:466
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::Math::TTransform< double > FTransform
Definition MathFwd.h:53
#define ScalarRegister
Definition ScalarRegister.h:239
#define ZERO_ANIMWEIGHT_THRESH
Definition VectorRegister.h:133
Definition Array.h:670
UE_REWRITE SizeType Num() const
Definition Array.h:1144
void Reset(SizeType NewSize=0)
Definition Array.h:2246
UE_NODEBUG UE_FORCEINLINE_HINT SizeType Add(ElementType &&Item)
Definition Array.h:2696
U16 Index
Definition radfft.cpp:71
Definition AnimationCoreUtil.h:12
bool GetBlendedParent(FTransform &OutTransform)
Definition AnimationCoreUtil.h:52
void AddScale(const FVector &Scale, float Weight)
Definition AnimationCoreUtil.h:45
void AddRotation(const FQuat &Rotation, float Weight)
Definition AnimationCoreUtil.h:38
void AddTranslation(const FVector &Translation, float Weight)
Definition AnimationCoreUtil.h:31
bool GetBlendedScale(FVector &Output)
Definition AnimationCoreUtil.h:157
void AddParent(const FTransform &InTransform, float Weight)
Definition AnimationCoreUtil.h:24
bool GetBlendedTranslation(FVector &Output)
Definition AnimationCoreUtil.h:91
bool GetBlendedRotation(FQuat &Output)
Definition AnimationCoreUtil.h:117
void Reset()
Definition AnimationCoreUtil.h:13
static constexpr UE_FORCEINLINE_HINT T Lerp(const T &A, const T &B, const U &Alpha)
Definition UnrealMathUtility.h:1116
Definition AnimationCoreUtil.h:207
void AddParent(const FTransform &InTransform, float Weight)
Definition AnimationCoreUtil.h:219
void Reset()
Definition AnimationCoreUtil.h:208
bool GetBlendedTranslation(FVector &Output)
Definition AnimationCoreUtil.h:279
bool GetBlendedParent(FTransform &OutTransform)
Definition AnimationCoreUtil.h:247
void AddRotation(const FQuat &Rotation, float Weight)
Definition AnimationCoreUtil.h:233
bool GetBlendedScale(FVector &Output)
Definition AnimationCoreUtil.h:345
bool GetBlendedRotation(FQuat &Output)
Definition AnimationCoreUtil.h:305
void AddScale(const FVector &Scale, float Weight)
Definition AnimationCoreUtil.h:240
void AddTranslation(const FVector &Translation, float Weight)
Definition AnimationCoreUtil.h:226
static TQuat< double > FastLerp(const TQuat< double > &A, const TQuat< double > &B, const double Alpha)
Definition Quat.h:1373
void AccumulateWithShortestRotation(const TTransform< T > &DeltaAtom, FReal BlendWeight)
Definition TransformNonVectorized.h:979
void NormalizeRotation()
Definition TransformNonVectorized.h:1057
static CORE_API const TVector< double > ZeroVector
Definition Vector.h:79