UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
TransformNonVectorized.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5#include "CoreTypes.h"
10
11#if !ENABLE_VECTORIZED_TRANSFORM
12
28struct Z_Construct_UScriptStruct_FTransform3f_Statics;
29struct Z_Construct_UScriptStruct_FTransform3d_Statics;
30struct Z_Construct_UScriptStruct_FTransform_Statics;
31
32namespace UE
33{
34namespace Math
35{
36
37template<typename T>
38struct alignas(alignof(TQuat<T>)) TTransform
39{
43
44 using FReal = T;
46
47protected:
54public:
59
60#if ENABLE_NAN_DIAGNOSTIC
61 inline void DiagnosticCheckNaN_Scale3D() const
62 {
63 if (Scale3D.ContainsNaN())
64 {
65 logOrEnsureNanError(TEXT("TTransform<T> Scale3D contains NaN: %s"), *Scale3D.ToString());
66 const_cast<TTransform<T>*>(this)->Scale3D = TVector<T>::OneVector;
67 }
68 }
69
70 inline void DiagnosticCheckNaN_Translate() const
71 {
73 {
74 logOrEnsureNanError(TEXT("TTransform<T> Translation contains NaN: %s"), *Translation.ToString());
76 }
77 }
78
79 inline void DiagnosticCheckNaN_Rotate() const
80 {
81 if (Rotation.ContainsNaN())
82 {
83 logOrEnsureNanError(TEXT("TTransform<T> Rotation contains NaN: %s"), *Rotation.ToString());
84 const_cast<TTransform<T>*>(this)->Rotation = TQuat<T>::Identity;
85 }
86 }
87
88 inline void DiagnosticCheckNaN_All() const
89 {
93 }
94
95 inline void DiagnosticCheck_IsValid() const
96 {
98 if (!IsValid())
99 {
100 logOrEnsureNanError(TEXT("TTransform<T> transform is not valid: %s"), *ToHumanReadableString());
101 }
102
103 }
104#else
110#endif
111
114 : Rotation(0.f, 0.f, 0.f, 1.f)
115 , Translation(0.f)
116 , Scale3D(TVector<T>::OneVector)
117 {
118 }
119
125 [[nodiscard]] inline explicit TTransform(const TVector<T>& InTranslation)
126 : Rotation(TQuat<T>::Identity),
128 Scale3D(TVector<T>::OneVector)
129 {
131 }
132
136 [[nodiscard]] inline explicit TTransform(ENoInit)
137 {
138 // Note: This can be used to track down initialization issues with bone transform arrays; but it will
139 // cause issues with transient fields such as RootMotionDelta that get initialized to 0 by default
140#if ENABLE_NAN_DIAGNOSTIC
141 // It is unsafe to call normal constructors here as they do their own NaN checks, so would always hit a false positive
142 T qnan = FMath::Log2(-5.3f);
143 check(FMath::IsNaN(qnan));
145 Rotation.X = Rotation.Y = Rotation.Z = Rotation.W = qnan;
146 Scale3D.X = Scale3D.Y = Scale3D.Z = qnan;
147#endif
148 }
149
155 [[nodiscard]] inline explicit TTransform(const TQuat<T>& InRotation)
157 Translation(TVector<T>::ZeroVector),
158 Scale3D(TVector<T>::OneVector)
159 {
161 }
162
168 [[nodiscard]] inline explicit TTransform(const TRotator<T>& InRotation)
170 Translation(TVector<T>::ZeroVector),
171 Scale3D(TVector<T>::OneVector)
172 {
174 }
175
190
205
209 [[nodiscard]] inline explicit TTransform(const TMatrix<T>& InMatrix)
210 {
213 }
214
221
225 CORE_API void DebugPrint() const;
226
228 [[nodiscard]] bool DebugEqualMatrix(const TMatrix<T>& Matrix) const;
229
231 [[nodiscard]] CORE_API FString ToHumanReadableString() const;
232
233 [[nodiscard]] CORE_API FString ToString() const;
234
236 CORE_API bool InitFromString(const FString& InSourceString);
237
242 {
244
245#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST) && WITH_EDITORONLY_DATA
246 // Make sure Rotation is normalized when we turn it into a matrix.
248#endif
249 OutMatrix.M[3][0] = Translation.X;
250 OutMatrix.M[3][1] = Translation.Y;
251 OutMatrix.M[3][2] = Translation.Z;
252
253 const FReal x2 = Rotation.X + Rotation.X;
254 const FReal y2 = Rotation.Y + Rotation.Y;
255 const FReal z2 = Rotation.Z + Rotation.Z;
256 {
257 const FReal xx2 = Rotation.X * x2;
258 const FReal yy2 = Rotation.Y * y2;
259 const FReal zz2 = Rotation.Z * z2;
260
261 OutMatrix.M[0][0] = (1.0f - (yy2 + zz2)) * Scale3D.X;
262 OutMatrix.M[1][1] = (1.0f - (xx2 + zz2)) * Scale3D.Y;
263 OutMatrix.M[2][2] = (1.0f - (xx2 + yy2)) * Scale3D.Z;
264 }
265 {
266 const FReal yz2 = Rotation.Y * z2;
267 const FReal wx2 = Rotation.W * x2;
268
269 OutMatrix.M[2][1] = (yz2 - wx2) * Scale3D.Z;
270 OutMatrix.M[1][2] = (yz2 + wx2) * Scale3D.Y;
271 }
272 {
273 const FReal xy2 = Rotation.X * y2;
274 const FReal wz2 = Rotation.W * z2;
275
276 OutMatrix.M[1][0] = (xy2 - wz2) * Scale3D.Y;
277 OutMatrix.M[0][1] = (xy2 + wz2) * Scale3D.X;
278 }
279 {
280 const FReal xz2 = Rotation.X * z2;
281 const FReal wy2 = Rotation.W * y2;
282
283 OutMatrix.M[2][0] = (xz2 + wy2) * Scale3D.Z;
284 OutMatrix.M[0][2] = (xz2 - wy2) * Scale3D.X;
285 }
286
287 OutMatrix.M[0][3] = 0.0f;
288 OutMatrix.M[1][3] = 0.0f;
289 OutMatrix.M[2][3] = 0.0f;
290 OutMatrix.M[3][3] = 1.0f;
291
292 return OutMatrix;
293 }
294
299 {
300 // todo: optimize
301 return ToMatrixWithScale().Inverse();
302 }
303
307 [[nodiscard]] inline TTransform<T> Inverse() const
308 {
310 // this used to cause NaN if Scale contained 0
313
315 }
316
321 {
323
324#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST) && WITH_EDITORONLY_DATA
325 // Make sure Rotation is normalized when we turn it into a matrix.
327#endif
328 OutMatrix.M[3][0] = Translation.X;
329 OutMatrix.M[3][1] = Translation.Y;
330 OutMatrix.M[3][2] = Translation.Z;
331
332 const FReal x2 = Rotation.X + Rotation.X;
333 const FReal y2 = Rotation.Y + Rotation.Y;
334 const FReal z2 = Rotation.Z + Rotation.Z;
335 {
336 const FReal xx2 = Rotation.X * x2;
337 const FReal yy2 = Rotation.Y * y2;
338 const FReal zz2 = Rotation.Z * z2;
339
340 OutMatrix.M[0][0] = (1.0f - (yy2 + zz2));
341 OutMatrix.M[1][1] = (1.0f - (xx2 + zz2));
342 OutMatrix.M[2][2] = (1.0f - (xx2 + yy2));
343 }
344 {
345 const FReal yz2 = Rotation.Y * z2;
346 const FReal wx2 = Rotation.W * x2;
347
348 OutMatrix.M[2][1] = (yz2 - wx2);
349 OutMatrix.M[1][2] = (yz2 + wx2);
350 }
351 {
352 const FReal xy2 = Rotation.X * y2;
353 const FReal wz2 = Rotation.W * z2;
354
355 OutMatrix.M[1][0] = (xy2 - wz2);
356 OutMatrix.M[0][1] = (xy2 + wz2);
357 }
358 {
359 const FReal xz2 = Rotation.X * z2;
360 const FReal wy2 = Rotation.W * y2;
361
362 OutMatrix.M[2][0] = (xz2 + wy2);
363 OutMatrix.M[0][2] = (xz2 - wy2);
364 }
365
366 OutMatrix.M[0][3] = 0.0f;
367 OutMatrix.M[1][3] = 0.0f;
368 OutMatrix.M[2][3] = 0.0f;
369 OutMatrix.M[3][3] = 1.0f;
370
371 return OutMatrix;
372 }
373
375 inline void Blend(const TTransform<T>& Atom1, const TTransform<T>& Atom2, float Alpha)
376 {
377#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST) && WITH_EDITORONLY_DATA
378 // Check that all bone atoms coming from animation are normalized
379 check(Atom1.IsRotationNormalized());
380 check(Atom2.IsRotationNormalized());
381#endif
383 {
384 // if blend is all the way for child1, then just copy its bone atoms
385 (*this) = Atom1;
386 }
387 else if (Alpha >= 1.f - ZERO_ANIMWEIGHT_THRESH)
388 {
389 // if blend is all the way for child2, then just copy its bone atoms
390 (*this) = Atom2;
391 }
392 else
393 {
394 // Simple linear interpolation for translation and scale.
395 Translation = FMath::Lerp(Atom1.Translation, Atom2.Translation, Alpha);
396 Scale3D = FMath::Lerp(Atom1.Scale3D, Atom2.Scale3D, Alpha);
397 Rotation = TQuat<T>::FastLerp(Atom1.Rotation, Atom2.Rotation, Alpha);
398
399 // ..and renormalize
400 Rotation.Normalize();
401 }
402 }
403
405 inline void BlendWith(const TTransform<T>& OtherAtom, float Alpha)
406 {
407#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST) && WITH_EDITORONLY_DATA
408 // Check that all bone atoms coming from animation are normalized
410 check(OtherAtom.IsRotationNormalized());
411#endif
413 {
414 if (Alpha >= 1.f - ZERO_ANIMWEIGHT_THRESH)
415 {
416 // if blend is all the way for child2, then just copy its bone atoms
417 (*this) = OtherAtom;
418 }
419 else
420 {
421 // Simple linear interpolation for translation and scale.
425
426 // ..and renormalize
427 Rotation.Normalize();
428 }
429 }
430 }
431
432
439 {
440 return TTransform(Rotation + Atom.Rotation, Translation + Atom.Translation, Scale3D + Atom.Scale3D);
441 }
442
444 {
445 Translation += Atom.Translation;
446
447 Rotation.X += Atom.Rotation.X;
448 Rotation.Y += Atom.Rotation.Y;
449 Rotation.Z += Atom.Rotation.Z;
450 Rotation.W += Atom.Rotation.W;
451
452 Scale3D += Atom.Scale3D;
453
454 return *this;
455 }
456
461
463 {
464 Translation *= Mult;
465 Rotation.X *= Mult;
466 Rotation.Y *= Mult;
467 Rotation.Z *= Mult;
468 Rotation.W *= Mult;
469 Scale3D *= Mult;
470
471 return *this;
472 }
473
482
483
491
500
507 inline void operator*=(const TQuat<T>& Other);
508
511 inline void ScaleTranslation(const FReal& Scale);
512 inline void RemoveScaling(FReal Tolerance = UE_SMALL_NUMBER);
513 [[nodiscard]] inline T GetMaximumAxisScale() const;
514 [[nodiscard]] inline T GetMinimumAxisScale() const;
515
516 // Inverse does not work well with VQS format(in particular non-uniform), so removing it, but made two below functions to be used instead.
517
518 /*******************************************************************************************
519 * The below 2 functions are the ones to get delta transform and return TTransform<T> format that can be concatenated
520 * Inverse itself can't concatenate with VQS format(since VQS always transform from S->Q->T, where inverse happens from T(-1)->Q(-1)->S(-1))
521 * So these 2 provides ways to fix this
522 * GetRelativeTransform returns this*Other(-1) and parameter is Other(not Other(-1))
523 * GetRelativeTransformReverse returns this(-1)*Other, and parameter is Other.
524 *******************************************************************************************/
531 CORE_API void SetToRelativeTransform(const TTransform<T>& ParentTransform);
532
537
543
550
556
562
567 [[nodiscard]] inline void Mirror(EAxis::Type MirrorAxis, EAxis::Type FlipAxis);
569
570 // temp function for easy conversion
575
577 {
578 return Rotation.Rotator();
579 }
580
583 {
584 return (float)(Scale3D.X * Scale3D.Y * Scale3D.Z);
585 }
586
588 inline void SetLocation(const TVector<T>& Origin)
589 {
590 Translation = Origin;
592 }
593
598 [[nodiscard]] bool ContainsNaN() const
599 {
600 return (Translation.ContainsNaN() || Rotation.ContainsNaN() || Scale3D.ContainsNaN());
601 }
602
603 [[nodiscard]] inline bool IsValid() const
604 {
605 if (ContainsNaN())
606 {
607 return false;
608 }
609
610 if (!Rotation.IsNormalized())
611 {
612 return false;
613 }
614
615 return true;
616 }
617
618 // Serializer.
620 {
621 Ar << M.Rotation;
622 Ar << M.Translation;
623 Ar << M.Scale3D;
624 return Ar;
625 }
626
628 {
629 Ar << *this;
630 return true;
631 }
632
634 {
635 // FTransform3f/d are immutable, but FTransform is not and needs a per-property conversion
637 {
638 return false;
639 }
640
641 if constexpr (std::is_same_v<T, float>)
642 {
643 return UE_SERIALIZE_VARIANT_FROM_MISMATCHED_TAG(Ar, Transform, Transform3f, Transform3d);
644 }
645 else
646 {
647 return UE_SERIALIZE_VARIANT_FROM_MISMATCHED_TAG(Ar, Transform, Transform3d, Transform3f);
648 }
649 }
650
651 // Binary comparison operators.
652 /*
653 bool operator==(const TTransform<T>& Other) const
654 {
655 return Rotation==Other.Rotation && Translation==Other.Translation && Scale3D==Other.Scale3D;
656 }
657 bool operator!=(const TTransform<T>& Other) const
658 {
659 return Rotation!=Other.Rotation || Translation!=Other.Translation || Scale3D!=Other.Scale3D;
660 }
661 */
662
663private:
664
665 UE_FORCEINLINE_HINT bool Private_RotationEquals(const TQuat<T>& InRotation, const FReal Tolerance = UE_KINDA_SMALL_NUMBER) const
666 {
667 return Rotation.Equals(InRotation, Tolerance);
668 }
669
670 UE_FORCEINLINE_HINT bool Private_TranslationEquals(const TVector<T>& InTranslation, const FReal Tolerance = UE_KINDA_SMALL_NUMBER) const
671 {
672 return Translation.Equals(InTranslation, Tolerance);
673 }
674
675 UE_FORCEINLINE_HINT bool Private_Scale3DEquals(const TVector<T>& InScale3D, const FReal Tolerance = UE_KINDA_SMALL_NUMBER) const
676 {
677 return Scale3D.Equals(InScale3D, Tolerance);
678 }
679
680public:
681
682 // Test if A's rotation equals B's rotation, within a tolerance. Preferred over "A.GetRotation().Equals(B.GetRotation())" because it is faster on some platforms.
684 {
685 return A.Private_RotationEquals(B.Rotation, Tolerance);
686 }
687
688 // Test if A's translation equals B's translation, within a tolerance. Preferred over "A.GetTranslation().Equals(B.GetTranslation())" because it is faster on some platforms.
690 {
691 return A.Private_TranslationEquals(B.Translation, Tolerance);
692 }
693
694 // Test if A's scale equals B's scale, within a tolerance. Preferred over "A.GetScale3D().Equals(B.GetScale3D())" because it is faster on some platforms.
696 {
697 return A.Private_Scale3DEquals(B.Scale3D, Tolerance);
698 }
699
700
701
702 // Test if this Transform's rotation equals another's rotation, within a tolerance. Preferred over "GetRotation().Equals(Other.GetRotation())" because it is faster on some platforms.
704 {
705 return AreRotationsEqual(*this, Other, Tolerance);
706 }
707
708 // Test if this Transform's translation equals another's translation, within a tolerance. Preferred over "GetTranslation().Equals(Other.GetTranslation())" because it is faster on some platforms.
710 {
711 return AreTranslationsEqual(*this, Other, Tolerance);
712 }
713
714 // Test if this Transform's scale equals another's scale, within a tolerance. Preferred over "GetScale3D().Equals(Other.GetScale3D())" because it is faster on some platforms.
716 {
717 return AreScale3DsEqual(*this, Other, Tolerance);
718 }
719
720 // Test if all components of the transforms are equal, within a tolerance.
722 {
723 return Private_TranslationEquals(Other.Translation, Tolerance) && Private_RotationEquals(Other.Rotation, Tolerance) && Private_Scale3DEquals(Other.Scale3D, Tolerance);
724 }
725
726 // Test if all components of the transform property are equal.
728 {
729 return Equals(*Other, 0.f);
730 }
731
732 // Test if rotation and translation components of the transforms are equal, within a tolerance.
734 {
735 return Private_TranslationEquals(Other.Translation, Tolerance) && Private_RotationEquals(Other.Rotation, Tolerance);
736 }
737
747 UE_FORCEINLINE_HINT static void Multiply(TTransform<T>* OutTransform, const TTransform<T>* A, const TTransform<T>* B);
748
763
770 inline void SetIdentity()
771 {
774 Scale3D = TVector<T>(1, 1, 1);
775 }
776
789
799
804 inline void SetTranslation(const TVector<T>& NewTranslation)
805 {
806 Translation = NewTranslation;
808 }
809
812 {
813 Translation = Other.Translation;
814 }
815
820 inline void ConcatenateRotation(const TQuat<T>& DeltaRotation)
821 {
822 Rotation = Rotation * DeltaRotation;
824 }
825
835
841 {
842 return A.Translation + B.Translation;
843 }
844
850 {
851 return A.Translation - B.Translation;
852 }
853
858 inline void SetRotation(const TQuat<T>& NewRotation)
859 {
860 Rotation = NewRotation;
862 }
863
866 {
867 Rotation = Other.Rotation;
868 }
869
874 inline void SetScale3D(const TVector<T>& NewScale3D)
875 {
878 }
879
882 {
883 Scale3D = Other.Scale3D;
884 }
885
891 inline void SetTranslationAndScale3D(const TVector<T>& NewTranslation, const TVector<T>& NewScale3D)
892 {
893 Translation = NewTranslation;
895
898 }
899
900 // For low-level VectorRegister programming
917
936 {
937 Rotation = SourceAtom.Rotation * Rotation;
938 Translation += SourceAtom.Translation;
939 Scale3D *= SourceAtom.Scale3D;
940
942
944 }
945
958 inline void Accumulate(const TTransform<T>& Atom, FReal BlendWeight/* default param doesn't work since vectorized version takes ref param */)
959 {
960 TTransform<T> SourceAtom(Atom * BlendWeight);
961
962 Rotation = SourceAtom.Rotation * Rotation;
963 Translation += SourceAtom.Translation;
964 Scale3D *= SourceAtom.Scale3D;
965
967 }
968
979 inline void AccumulateWithShortestRotation(const TTransform<T>& DeltaAtom, FReal BlendWeight/* default param doesn't work since vectorized version takes ref param */)
980 {
981 TTransform<T> Atom(DeltaAtom * BlendWeight);
982
983 // To ensure the 'shortest route', we make sure the dot product between the accumulator and the incoming child atom is positive.
984 if ((Atom.Rotation | Rotation) < 0.f)
985 {
986 Rotation.X -= Atom.Rotation.X;
987 Rotation.Y -= Atom.Rotation.Y;
988 Rotation.Z -= Atom.Rotation.Z;
989 Rotation.W -= Atom.Rotation.W;
990 }
991 else
992 {
993 Rotation.X += Atom.Rotation.X;
994 Rotation.Y += Atom.Rotation.Y;
995 Rotation.Z += Atom.Rotation.Z;
996 Rotation.W += Atom.Rotation.W;
997 }
998
999 Translation += Atom.Translation;
1000 Scale3D += Atom.Scale3D;
1001
1003 }
1004
1023 inline void AccumulateWithAdditiveScale(const TTransform<T>& Atom, T BlendWeight/* default param doesn't work since vectorized version takes ref param */)
1024 {
1025 const TVector<T> DefaultScale(TVector<T>::OneVector);
1026
1027 TTransform<T> SourceAtom(Atom * BlendWeight);
1028
1029 Rotation = SourceAtom.Rotation * Rotation;
1030 Translation += SourceAtom.Translation;
1031 Scale3D *= (DefaultScale + SourceAtom.Scale3D);
1032
1034 }
1053
1057 inline void NormalizeRotation()
1058 {
1059 Rotation.Normalize();
1061 }
1062
1069 {
1070 return Rotation.IsNormalized();
1071 }
1072
1086 {
1088 const TVector<T> DefaultScale(TVector<T>::OneVector);
1090
1091 // Scale delta by weight
1092 if (BlendWeight < (1.f - ZERO_ANIMWEIGHT_THRESH))
1093 {
1095 }
1096
1097 FinalAtom.Rotation = DeltaAtom.Rotation * FinalAtom.Rotation;
1098 FinalAtom.Translation += DeltaAtom.Translation;
1099 FinalAtom.Scale3D *= (DefaultScale + DeltaAtom.Scale3D);
1100
1101 checkSlow(FinalAtom.IsRotationNormalized());
1102 }
1103
1109 [[nodiscard]] inline TQuat<T> GetRotation() const
1110 {
1112 return Rotation;
1113 }
1114
1121 {
1123 return Translation;
1124 }
1125
1132 {
1134 return Scale3D;
1135 }
1136
1143 {
1144 Rotation = SrcBA.Rotation;
1145 Scale3D = SrcBA.Scale3D;
1146
1149 }
1150
1157 {
1158 Translation = SrcBA.Translation;
1159 Scale3D = SrcBA.Scale3D;
1160
1163 }
1164
1166 {
1167 TMatrix<T> M = InMatrix;
1168
1169 // Get the 3D scale from the matrix
1170 Scale3D = M.ExtractScaling(0);
1171
1172 // If there is negative scaling going on, we handle that here
1173 if (InMatrix.Determinant() < 0.f)
1174 {
1175 // Assume it is along X and modify transform accordingly.
1176 // It doesn't actually matter which axis we choose, the 'appearance' will be the same
1177 Scale3D.X *= -1.f;
1178 M.SetAxis(0, -M.GetScaledAxis(EAxis::X));
1179 }
1180
1181 Rotation = TQuat<T>(M);
1182 Translation = InMatrix.GetOrigin();
1183
1184 // Normalize rotation
1185 Rotation.Normalize();
1186 }
1187
1188private:
1199 UE_FORCEINLINE_HINT static void MultiplyUsingMatrixWithScale(TTransform<T>* OutTransform, const TTransform<T>* A, const TTransform<T>* B);
1210 UE_FORCEINLINE_HINT static void ConstructTransformFromMatrixWithDesiredScale(const TMatrix<T>& AMatrix, const TMatrix<T>& BMatrix, const TVector<T>& DesiredScale, TTransform<T>& OutTransform);
1219 static void GetRelativeTransformUsingMatrixWithScale(TTransform<T>* OutTransform, const TTransform<T>* Base, const TTransform<T>* Relative);
1220
1221public:
1222 // Conversion to other type.
1223 template<typename FArg UE_REQUIRES(!std::is_same_v<T, FArg>)>
1224 explicit TTransform(const TTransform<FArg>& From)
1225 : TTransform<T>((TQuat<T>)From.GetRotation(), (TVector<T>)From.GetTranslation(), (TVector<T>)From.GetScale3D())
1226 {
1227 }
1228};
1229
1230#if !defined(_MSC_VER) || defined(__clang__) // MSVC can't forward declare explicit specializations
1233#endif
1234template<typename T>
1236{
1237 return (InScale3D.X < 0.f || InScale3D.Y < 0.f || InScale3D.Z < 0.f
1238 || InOtherScale3D.X < 0.f || InOtherScale3D.Y < 0.f || InOtherScale3D.Z < 0.f );
1239}
1240
1242template<typename T>
1244{
1246
1247 DiagnosticCheckNaN_Translate();
1248}
1249
1250
1251template<typename T>
1253{
1254 Translation *= Scale;
1255
1256 DiagnosticCheckNaN_Translate();
1257}
1258
1259
1260// this function is from matrix, and all it does is to normalize rotation portion
1261template<typename T>
1262inline void TTransform<T>::RemoveScaling(T Tolerance/*=SMALL_NUMBER*/)
1263{
1264 Scale3D = TVector<T>(1, 1, 1);
1265 Rotation.Normalize();
1266
1267 DiagnosticCheckNaN_Rotate();
1268 DiagnosticCheckNaN_Scale3D();
1269}
1270
1271template<typename T>
1273{
1274 // the goal of using M is to get the correct orientation
1275 // but for translation, we still need scale
1276 ConstructTransformFromMatrixWithDesiredScale(A->ToMatrixWithScale(), B->ToMatrixWithScale(), A->Scale3D*B->Scale3D, *OutTransform);
1277}
1278
1279template<typename T>
1280inline void TTransform<T>::ConstructTransformFromMatrixWithDesiredScale(const TMatrix<T>& AMatrix, const TMatrix<T>& BMatrix, const TVector<T>& DesiredScale, TTransform<T>& OutTransform)
1281{
1282 // the goal of using M is to get the correct orientation
1283 // but for translation, we still need scale
1284 TMatrix<T> M = AMatrix * BMatrix;
1285 M.RemoveScaling();
1286
1287 // apply negative scale back to axes
1288 TVector<T> SignedScale = DesiredScale.GetSignVector();
1289
1290 M.SetAxis(0, SignedScale.X * M.GetScaledAxis(EAxis::X));
1291 M.SetAxis(1, SignedScale.Y * M.GetScaledAxis(EAxis::Y));
1292 M.SetAxis(2, SignedScale.Z * M.GetScaledAxis(EAxis::Z));
1293
1294 // @note: if you have negative with 0 scale, this will return rotation that is identity
1295 // since matrix loses that axes
1297 Rotation.Normalize();
1298
1299 // set values back to output
1300 OutTransform.Scale3D = DesiredScale;
1301 OutTransform.Rotation = Rotation;
1302
1303 // technically I could calculate this using TTransform<T> but then it does more quat multiplication
1304 // instead of using Scale in matrix multiplication
1305 // it's a question of between RemoveScaling vs using TTransform<T> to move translation
1306 OutTransform.Translation = M.GetOrigin();
1307}
1308
1310template<typename T>
1311inline void TTransform<T>::Multiply(TTransform<T>* OutTransform, const TTransform<T>* A, const TTransform<T>* B)
1312{
1313 A->DiagnosticCheckNaN_All();
1314 B->DiagnosticCheckNaN_All();
1315
1316 checkSlow(A->IsRotationNormalized());
1317 checkSlow(B->IsRotationNormalized());
1318
1319 // When Q = quaternion, S = single scalar scale, and T = translation
1320 // QST(A) = Q(A), S(A), T(A), and QST(B) = Q(B), S(B), T(B)
1321
1322 // QST (AxB)
1323
1324 // QST(A) = Q(A)*S(A)*P*-Q(A) + T(A)
1325 // QST(AxB) = Q(B)*S(B)*QST(A)*-Q(B) + T(B)
1326 // QST(AxB) = Q(B)*S(B)*[Q(A)*S(A)*P*-Q(A) + T(A)]*-Q(B) + T(B)
1327 // QST(AxB) = Q(B)*S(B)*Q(A)*S(A)*P*-Q(A)*-Q(B) + Q(B)*S(B)*T(A)*-Q(B) + T(B)
1328 // QST(AxB) = [Q(B)*Q(A)]*[S(B)*S(A)]*P*-[Q(B)*Q(A)] + Q(B)*S(B)*T(A)*-Q(B) + T(B)
1329
1330 // Q(AxB) = Q(B)*Q(A)
1331 // S(AxB) = S(A)*S(B)
1332 // T(AxB) = Q(B)*S(B)*T(A)*-Q(B) + T(B)
1333
1334 if (AnyHasNegativeScale(A->Scale3D, B->Scale3D))
1335 {
1336 // @note, if you have 0 scale with negative, you're going to lose rotation as it can't convert back to quat
1337 MultiplyUsingMatrixWithScale(OutTransform, A, B);
1338 }
1339 else
1340 {
1341 OutTransform->Rotation = B->Rotation*A->Rotation;
1342 OutTransform->Scale3D = A->Scale3D*B->Scale3D;
1343 OutTransform->Translation = B->Rotation*(B->Scale3D*A->Translation) + B->Translation;
1344 }
1345
1346 // we do not support matrix transform when non-uniform
1347 // that was removed at rev 21 with UE4
1348}
1352template<typename T>
1354{
1355 TTransform<T> A(*this);
1356 A.Scale3D *= InScale;
1357
1358 A.DiagnosticCheckNaN_Scale3D();
1359
1360 return A;
1361}
1362
1363
1367template<typename T>
1369{
1370 TTransform<T> A(*this);
1371 A.Scale3D *= InScale;
1372
1373 A.DiagnosticCheckNaN_Scale3D();
1374
1375 return A;
1376}
1377
1378
1380template<typename T>
1382{
1383 DiagnosticCheckNaN_All();
1384
1385 // if not, this won't work
1386 checkSlow(V.W == 0.f || V.W == 1.f);
1387
1388 //Transform using QST is following
1389 //QST(P) = Q*S*P*-Q + T where Q = quaternion, S = scale, T = translation
1390 TVector4<T> Transform = TVector4<T>(Rotation.RotateVector(TVector<T>(V)), 0.f);
1391 if (V.W == 1.f)
1392 {
1394 }
1395
1396 return Transform;
1397}
1398
1399
1401template<typename T>
1403{
1404 DiagnosticCheckNaN_All();
1405
1406 // if not, this won't work
1407 checkSlow(V.W == 0.f || V.W == 1.f);
1408
1409 //Transform using QST is following
1410 //QST(P) = Q*S*P*-Q + T where Q = quaternion, S = scale, T = translation
1411
1412 TVector4<T> Transform = TVector4<T>(Rotation.RotateVector(Scale3D*TVector<T>(V)), 0.f);
1413 if (V.W == 1.f)
1414 {
1416 }
1417
1418 return Transform;
1419}
1420
1421
1422template<typename T>
1424{
1425 DiagnosticCheckNaN_All();
1426 return Rotation.RotateVector(Scale3D*V) + Translation;
1427}
1428
1429
1430template<typename T>
1432{
1433 DiagnosticCheckNaN_All();
1434 return Rotation.RotateVector(V) + Translation;
1435}
1436
1437
1438template<typename T>
1440{
1441 DiagnosticCheckNaN_All();
1442 return Rotation.RotateVector(Scale3D*V);
1443}
1444
1445
1446template<typename T>
1448{
1449 DiagnosticCheckNaN_All();
1450 return Rotation.RotateVector(V);
1451}
1452
1453
1454// do backward operation when inverse, translation -> rotation -> scale
1455template<typename T>
1457{
1458 DiagnosticCheckNaN_All();
1459 return (Rotation.UnrotateVector(V - Translation)) * GetSafeScaleReciprocal(Scale3D);
1460}
1461
1462
1463// do backward operation when inverse, translation -> rotation
1464template<typename T>
1466{
1467 DiagnosticCheckNaN_All();
1468 return (Rotation.UnrotateVector(V - Translation));
1469}
1470
1471
1472// do backward operation when inverse, translation -> rotation -> scale
1473template<typename T>
1475{
1476 DiagnosticCheckNaN_All();
1477 return (Rotation.UnrotateVector(V)) * GetSafeScaleReciprocal(Scale3D);
1478}
1479
1480
1481// do backward operation when inverse, translation -> rotation
1482template<typename T>
1484{
1485 DiagnosticCheckNaN_All();
1486 return (Rotation.UnrotateVector(V));
1487}
1488
1489template<typename T>
1491{
1492 return GetRotation() * Q;
1493}
1494
1495template<typename T>
1497{
1498 return GetRotation().Inverse() * Q;
1499}
1500
1501template<typename T>
1503{
1505 Multiply(&Output, this, &Other);
1506 return Output;
1507}
1508
1509
1510template<typename T>
1515
1516
1517template<typename T>
1524
1525
1526template<typename T>
1532
1533
1534// x = 0, y = 1, z = 2
1535template<typename T>
1537{
1538 if (InAxis == EAxis::X)
1539 {
1540 return TransformVector(TVector<T>(1.f, 0.f, 0.f));
1541 }
1542 else if (InAxis == EAxis::Y)
1543 {
1544 return TransformVector(TVector<T>(0.f, 1.f, 0.f));
1545 }
1546
1547 return TransformVector(TVector<T>(0.f, 0.f, 1.f));
1548}
1549
1550
1551// x = 0, y = 1, z = 2
1552template<typename T>
1554{
1555 if (InAxis == EAxis::X)
1556 {
1557 return TransformVectorNoScale(TVector<T>(1.f, 0.f, 0.f));
1558 }
1559 else if (InAxis == EAxis::Y)
1560 {
1561 return TransformVectorNoScale(TVector<T>(0.f, 1.f, 0.f));
1562 }
1563
1564 return TransformVectorNoScale(TVector<T>(0.f, 0.f, 1.f));
1565}
1566
1567
1568template<typename T>
1569inline void TTransform<T>::Mirror(EAxis::Type MirrorAxis, EAxis::Type FlipAxis)
1570{
1571 // We do convert to Matrix for mirroring.
1572 TMatrix<T> M = ToMatrixWithScale();
1573 M.Mirror(MirrorAxis, FlipAxis);
1574 SetFromMatrix(M);
1575}
1576
1577
1580template<typename T>
1582{
1583 DiagnosticCheckNaN_Scale3D();
1584 return (float)Scale3D.GetAbsMax();
1585}
1586
1587
1589template<typename T>
1591{
1592 DiagnosticCheckNaN_Scale3D();
1593 return (float)Scale3D.GetAbsMin();
1594}
1595
1596
1597// mathematically if you have 0 scale, it should be infinite,
1598// however, in practice if you have 0 scale, and relative transform doesn't make much sense
1599// anymore because you should be instead of showing gigantic infinite mesh
1600// also returning BIG_NUMBER causes sequential NaN issues by multiplying
1601// so we hardcode as 0
1602template<typename T>
1604{
1606 if (FMath::Abs(InScale.X) <= Tolerance)
1607 {
1608 SafeReciprocalScale.X = 0.f;
1609 }
1610 else
1611 {
1612 SafeReciprocalScale.X = 1 / InScale.X;
1613 }
1614
1615 if (FMath::Abs(InScale.Y) <= Tolerance)
1616 {
1617 SafeReciprocalScale.Y = 0.f;
1618 }
1619 else
1620 {
1621 SafeReciprocalScale.Y = 1 / InScale.Y;
1622 }
1623
1624 if (FMath::Abs(InScale.Z) <= Tolerance)
1625 {
1626 SafeReciprocalScale.Z = 0.f;
1627 }
1628 else
1629 {
1630 SafeReciprocalScale.Z = 1 / InScale.Z;
1631 }
1632
1633 return SafeReciprocalScale;
1634}
1635
1636} // namespace UE::Math
1637} // namespace UE
1638
1639#endif
#define checkSlow(expr)
Definition AssertionMacros.h:332
#define check(expr)
Definition AssertionMacros.h:314
ENoInit
Definition CoreMiscDefines.h:158
#define TEXT(x)
Definition Platform.h:1272
#define UE_FORCEINLINE_HINT
Definition Platform.h:723
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
#define UE_SERIALIZE_VARIANT_FROM_MISMATCHED_TAG(AR_OR_SLOT, ALIAS, TYPE, ALT_TYPE)
Definition LargeWorldCoordinatesSerializer.h:9
#define logOrEnsureNanError(_FormatString_,...)
Definition LogMacros.h:436
#define ScalarRegister
Definition ScalarRegister.h:239
VectorType TransformVector(const TransformType &Transform, const VectorType &Vector)
Definition TransformCalculus.h:367
FORCEINLINE void VectorStore(const VectorRegister4Float &Vec, float *Dst)
Definition UnrealMathFPU.h:566
FORCEINLINE VectorRegister4Float VectorLoad(const float *Ptr)
Definition UnrealMathFPU.h:394
FORCEINLINE void VectorStoreFloat3(const VectorRegister4Float &Vec, float *Dst)
Definition UnrealMathFPU.h:594
#define UE_SMALL_NUMBER
Definition UnrealMathUtility.h:130
#define UE_KINDA_SMALL_NUMBER
Definition UnrealMathUtility.h:131
FORCEINLINE VectorRegister4Float VectorLoadFloat3_W0(const float *Ptr)
VectorLoadFloat3_W0.
Definition UnrealMathVectorCommon.h.inl:129
#define ZERO_ANIMWEIGHT_THRESH
Definition VectorRegister.h:133
typename UE::Math::VectorRegisterPrivate::TVectorRegisterTypeHelper< T >::Type TVectorRegisterType
Definition VectorRegister.h:49
uint32_t uint32
Definition binka_ue_file_header.h:6
bool ContainsNaN() const
Definition Vector.h:188
Definition Archive.h:1208
Definition NameTypes.h:617
Type
Definition Axis.h:11
@ Z
Definition Axis.h:15
@ Y
Definition Axis.h:14
@ X
Definition Axis.h:13
Definition AdvancedWidgetsModule.cpp:13
static constexpr UE_FORCEINLINE_HINT T Lerp(const T &A, const T &B, const U &Alpha)
Definition UnrealMathUtility.h:1116
static float Log2(float Value)
Definition UnrealMathUtility.h:722
Definition Matrix.h:43
void Mirror(EAxis::Type MirrorAxis, EAxis::Type FlipAxis)
Definition Matrix.inl:847
TVector< T > ExtractScaling(T Tolerance=UE_SMALL_NUMBER)
Definition Matrix.inl:467
TVector< T > GetScaledAxis(EAxis::Type Axis) const
Definition Matrix.inl:647
void SetAxis(int32 i, const TVector< T > &Axis)
Definition Matrix.inl:691
Definition Quat.h:39
static TQuat< T > FastLerp(const TQuat< T > &A, const TQuat< T > &B, const T Alpha)
Definition Quat.h:1373
TQuat< T > Inverse() const
Definition Quat.h:1264
static CORE_API const TQuat< T > Identity
Definition Quat.h:63
Definition Rotator.h:37
Definition TransformNonVectorized.h:39
CORE_API FString ToHumanReadableString() const
Definition Transform.cpp:35
void SetScale3D(const TVector< T > &NewScale3D)
Definition TransformNonVectorized.h:874
bool DebugEqualMatrix(const TMatrix< T > &Matrix) const
Definition Transform.cpp:212
TTransform< T > & operator+=(const TTransform< T > &Atom)
Definition TransformNonVectorized.h:443
TVector4< T > TransformFVector4NoScale(const TVector4< T > &V) const
Definition TransformNonVectorized.h:1381
TVector< T > InverseTransformVector(const TVector< T > &V) const
Definition TransformNonVectorized.h:1474
TVector< T > GetScaledAxis(EAxis::Type InAxis) const
Definition TransformNonVectorized.h:1536
TVector< T > InverseTransformVectorNoScale(const TVector< T > &V) const
Definition TransformNonVectorized.h:1483
void CopyTranslationAndScale3D(const TTransform< T > &SrcBA)
Definition TransformNonVectorized.h:1156
UE_FORCEINLINE_HINT bool RotationEquals(const TTransform< T > &Other, FReal Tolerance=UE_KINDA_SMALL_NUMBER) const
Definition TransformNonVectorized.h:703
TVector4< T > TransformFVector4(const TVector4< T > &V) const
Definition TransformNonVectorized.h:1402
friend Z_Construct_UScriptStruct_FTransform3d_Statics
Definition TransformNonVectorized.h:41
static UE_FORCEINLINE_HINT bool AreRotationsEqual(const TTransform< T > &A, const TTransform< T > &B, FReal Tolerance=UE_KINDA_SMALL_NUMBER)
Definition TransformNonVectorized.h:683
UE_FORCEINLINE_HINT void CopyTranslation(const TTransform< T > &Other)
Definition TransformNonVectorized.h:811
friend FArchive & operator<<(FArchive &Ar, TTransform< T > &M)
Definition TransformNonVectorized.h:619
void ScaleTranslation(const FReal &Scale)
Definition TransformNonVectorized.h:1252
UE_FORCEINLINE_HINT bool TranslationEquals(const TTransform< T > &Other, FReal Tolerance=UE_KINDA_SMALL_NUMBER) const
Definition TransformNonVectorized.h:709
T GetMaximumAxisScale() const
Definition TransformNonVectorized.h:1581
bool ContainsNaN() const
Definition TransformNonVectorized.h:598
static UE_FORCEINLINE_HINT TVector< T > AddTranslations(const TTransform< T > &A, const TTransform< T > &B)
Definition TransformNonVectorized.h:840
TVector< T > GetUnitAxis(EAxis::Type InAxis) const
Definition TransformNonVectorized.h:1553
TTransform< T > operator*(const TTransform< T > &Other) const
Definition TransformNonVectorized.h:1502
CORE_API TTransform< T > GetRelativeTransformReverse(const TTransform< T > &Other) const
Definition Transform.cpp:98
UE_FORCEINLINE_HINT TMatrix< T > ToInverseMatrixWithScale() const
Definition TransformNonVectorized.h:298
TransformVectorRegister GetRotationRegister() const
Definition TransformNonVectorized.h:905
UE_FORCEINLINE_HINT void DiagnosticCheck_IsValid() const
Definition TransformNonVectorized.h:109
UE_FORCEINLINE_HINT void operator*=(const TTransform< T > &Other)
Definition TransformNonVectorized.h:1511
UE_FORCEINLINE_HINT void CopyRotation(const TTransform< T > &Other)
Definition TransformNonVectorized.h:865
CORE_API TTransform< T > GetRelativeTransform(const TTransform< T > &Other) const
Definition Transform.cpp:169
UE_FORCEINLINE_HINT TTransform< T > operator*(T Mult) const
Definition TransformNonVectorized.h:457
UE_FORCEINLINE_HINT TRotator< T > Rotator() const
Definition TransformNonVectorized.h:576
void ConcatenateRotation(const TQuat< T > &DeltaRotation)
Definition TransformNonVectorized.h:820
TTransform(const TTransform< FArg > &From)
Definition TransformNonVectorized.h:1224
static TVector< T > GetSafeScaleReciprocal(const TVector< T > &InScale, FReal Tolerance=UE_SMALL_NUMBER)
Definition TransformNonVectorized.h:1603
TTransform(const TMatrix< T > &InMatrix)
Definition TransformNonVectorized.h:209
UE_FORCEINLINE_HINT FReal GetDeterminant() const
Definition TransformNonVectorized.h:582
TTransform(const TVector< T > &InX, const TVector< T > &InY, const TVector< T > &InZ, const TVector< T > &InTranslation)
Definition TransformNonVectorized.h:216
TTransform()
Definition TransformNonVectorized.h:113
void Accumulate(const TTransform< T > &Atom, FReal BlendWeight)
Definition TransformNonVectorized.h:958
TTransform< T > Inverse() const
Definition TransformNonVectorized.h:307
static CORE_API const TTransform< T > Identity
Definition TransformNonVectorized.h:58
UE_FORCEINLINE_HINT bool Scale3DEquals(const TTransform< T > &Other, FReal Tolerance=UE_KINDA_SMALL_NUMBER) const
Definition TransformNonVectorized.h:715
TTransform(const TRotator< T > &InRotation)
Definition TransformNonVectorized.h:168
void RemoveScaling(FReal Tolerance=UE_SMALL_NUMBER)
Definition TransformNonVectorized.h:1262
TTransform< T > GetScaled(T Scale) const
Definition TransformNonVectorized.h:1353
TVectorRegisterType< T > TransformVectorRegister
Definition TransformNonVectorized.h:45
void SetFromMatrix(const TMatrix< T > &InMatrix)
Definition TransformNonVectorized.h:1165
TVector< T > InverseTransformPositionNoScale(const TVector< T > &V) const
Definition TransformNonVectorized.h:1465
void BlendWith(const TTransform< T > &OtherAtom, float Alpha)
Definition TransformNonVectorized.h:405
UE_FORCEINLINE_HINT bool Equals(const TTransform< T > &Other, FReal Tolerance=UE_KINDA_SMALL_NUMBER) const
Definition TransformNonVectorized.h:721
void SetTranslationRegister(TransformVectorRegister InTranslation)
Definition TransformNonVectorized.h:909
TVector< T > InverseTransformPosition(const TVector< T > &V) const
Definition TransformNonVectorized.h:1456
TransformVectorRegister GetTranslationRegister() const
Definition TransformNonVectorized.h:901
UE_FORCEINLINE_HINT void DiagnosticCheckNaN_Rotate() const
Definition TransformNonVectorized.h:106
bool Serialize(FArchive &Ar)
Definition TransformNonVectorized.h:627
TVector< T > GetTranslation() const
Definition TransformNonVectorized.h:1120
void SetIdentity()
Definition TransformNonVectorized.h:770
void CopyRotationPart(const TTransform< T > &SrcBA)
Definition TransformNonVectorized.h:1142
TTransform(const TRotator< T > &InRotation, const TVector< T > &InTranslation, const TVector< T > &InScale3D=TVector< T >::OneVector)
Definition TransformNonVectorized.h:198
T GetMinimumAxisScale() const
Definition TransformNonVectorized.h:1590
CORE_API FString ToString() const
Definition Transform.cpp:50
void AccumulateWithShortestRotation(const TTransform< T > &DeltaAtom, FReal BlendWeight)
Definition TransformNonVectorized.h:979
TTransform(const TVector< T > &InTranslation)
Definition TransformNonVectorized.h:125
UE_FORCEINLINE_HINT bool Identical(const TTransform< T > *Other, uint32 PortFlags) const
Definition TransformNonVectorized.h:727
void LerpTranslationScale3D(const TTransform< T > &SourceAtom1, const TTransform< T > &SourceAtom2, ScalarRegister Alpha)
Definition TransformNonVectorized.h:1045
TTransform(ENoInit)
Definition TransformNonVectorized.h:136
TVector< T > Translation
Definition TransformNonVectorized.h:51
friend Z_Construct_UScriptStruct_FTransform3f_Statics
Definition TransformNonVectorized.h:40
friend Z_Construct_UScriptStruct_FTransform_Statics
Definition TransformNonVectorized.h:42
void Mirror(EAxis::Type MirrorAxis, EAxis::Type FlipAxis)
Definition TransformNonVectorized.h:1569
void SetIdentityZeroScale()
Definition TransformNonVectorized.h:783
void Accumulate(const TTransform< T > &SourceAtom)
Definition TransformNonVectorized.h:935
bool IsValid() const
Definition TransformNonVectorized.h:603
TMatrix< T > ToMatrixWithScale() const
Definition TransformNonVectorized.h:241
TTransform< T > GetScaled(TVector< T > Scale) const
Definition TransformNonVectorized.h:1368
TTransform(const TQuat< T > &InRotation, const TVector< T > &InTranslation, const TVector< T > &InScale3D=TVector< T >::OneVector)
Definition TransformNonVectorized.h:183
TQuat< T > GetRotation() const
Definition TransformNonVectorized.h:1109
bool SerializeFromMismatchedTag(FName StructTag, FArchive &Ar)
Definition TransformNonVectorized.h:633
void Blend(const TTransform< T > &Atom1, const TTransform< T > &Atom2, float Alpha)
Definition TransformNonVectorized.h:375
static UE_FORCEINLINE_HINT bool AreTranslationsEqual(const TTransform< T > &A, const TTransform< T > &B, FReal Tolerance=UE_KINDA_SMALL_NUMBER)
Definition TransformNonVectorized.h:689
UE_FORCEINLINE_HINT TQuat< T > TransformRotation(const TQuat< T > &Q) const
Definition TransformNonVectorized.h:1490
TTransform< T > operator*(const TQuat< T > &Other) const
Definition TransformNonVectorized.h:1518
TVector< T > TransformPositionNoScale(const TVector< T > &V) const
Definition TransformNonVectorized.h:1431
void ScaleTranslation(const TVector< T > &InScale3D)
Definition TransformNonVectorized.h:1243
UE_FORCEINLINE_HINT bool EqualsNoScale(const TTransform< T > &Other, FReal Tolerance=UE_KINDA_SMALL_NUMBER) const
Definition TransformNonVectorized.h:733
TTransform(const TQuat< T > &InRotation)
Definition TransformNonVectorized.h:155
void SetRotation(const TQuat< T > &NewRotation)
Definition TransformNonVectorized.h:858
TVector< T > GetScale3D() const
Definition TransformNonVectorized.h:1131
UE_FORCEINLINE_HINT TQuat< T > InverseTransformRotation(const TQuat< T > &Q) const
Definition TransformNonVectorized.h:1496
UE_FORCEINLINE_HINT TTransform< T > operator+(const TTransform< T > &Atom) const
Definition TransformNonVectorized.h:438
TVector< T > Scale3D
Definition TransformNonVectorized.h:53
void AccumulateWithAdditiveScale(const TTransform< T > &Atom, T BlendWeight)
Definition TransformNonVectorized.h:1023
CORE_API bool InitFromString(const FString &InSourceString)
Definition Transform.cpp:60
UE_FORCEINLINE_HINT bool IsRotationNormalized() const
Definition TransformNonVectorized.h:1068
TVector< T > TransformVectorNoScale(const TVector< T > &V) const
Definition TransformNonVectorized.h:1447
T FReal
Definition TransformNonVectorized.h:44
CORE_API void SetToRelativeTransform(const TTransform< T > &ParentTransform)
Definition Transform.cpp:130
void SetTranslationAndScale3D(const TVector< T > &NewTranslation, const TVector< T > &NewScale3D)
Definition TransformNonVectorized.h:891
void NormalizeRotation()
Definition TransformNonVectorized.h:1057
void MultiplyScale3D(const TVector< T > &Scale3DMultiplier)
Definition TransformNonVectorized.h:794
void AddToTranslation(const TVector< T > &DeltaTranslation)
Definition TransformNonVectorized.h:830
void operator*=(const TQuat< T > &Other)
Definition TransformNonVectorized.h:1527
UE_FORCEINLINE_HINT void CopyScale3D(const TTransform< T > &Other)
Definition TransformNonVectorized.h:881
void SetComponents(const TQuat< T > &InRotation, const TVector< T > &InTranslation, const TVector< T > &InScale3D)
Definition TransformNonVectorized.h:755
void SetRotationRegister(TransformVectorRegister InRotation)
Definition TransformNonVectorized.h:913
static bool AnyHasNegativeScale(const TVector< T > &InScale3D, const TVector< T > &InOtherScale3D)
Definition TransformNonVectorized.h:1235
UE_FORCEINLINE_HINT TVector< T > TransformVector(const TVector< T > &V) const
Definition TransformNonVectorized.h:1439
UE_FORCEINLINE_HINT TVector< T > TransformPosition(const TVector< T > &V) const
Definition TransformNonVectorized.h:1423
static UE_FORCEINLINE_HINT void Multiply(TTransform< T > *OutTransform, const TTransform< T > *A, const TTransform< T > *B)
Definition TransformNonVectorized.h:1311
UE_FORCEINLINE_HINT void DiagnosticCheckNaN_All() const
Definition TransformNonVectorized.h:108
void SetLocation(const TVector< T > &Origin)
Definition TransformNonVectorized.h:588
TTransform< T > & operator*=(T Mult)
Definition TransformNonVectorized.h:462
UE_FORCEINLINE_HINT TVector< T > GetLocation() const
Definition TransformNonVectorized.h:571
static UE_FORCEINLINE_HINT bool AreScale3DsEqual(const TTransform< T > &A, const TTransform< T > &B, FReal Tolerance=UE_KINDA_SMALL_NUMBER)
Definition TransformNonVectorized.h:695
TQuat< T > Rotation
Definition TransformNonVectorized.h:49
UE_FORCEINLINE_HINT void DiagnosticCheckNaN_Scale3D() const
Definition TransformNonVectorized.h:107
UE_FORCEINLINE_HINT void DiagnosticCheckNaN_Translate() const
Definition TransformNonVectorized.h:105
static UE_FORCEINLINE_HINT TVector< T > SubtractTranslations(const TTransform< T > &A, const TTransform< T > &B)
Definition TransformNonVectorized.h:849
void SetTranslation(const TVector< T > &NewTranslation)
Definition TransformNonVectorized.h:804
static void BlendFromIdentityAndAccumulate(TTransform< T > &FinalAtom, const TTransform< T > &SourceAtom, float BlendWeight)
Definition TransformNonVectorized.h:1085
TMatrix< T > ToMatrixNoScale() const
Definition TransformNonVectorized.h:320
CORE_API void DebugPrint() const
Definition Transform.cpp:29
Definition Vector4.h:30
T W
Definition Vector4.h:52
Definition Vector.h:51
T GetAbsMax() const
Definition Vector.h:1680
T GetAbsMin() const
Definition Vector.h:1692
T X
Definition Vector.h:62