UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
TransformVectorized.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
6#include "CoreTypes.h"
7#include "Logging/LogMacros.h"
8#include "Math/Axis.h"
9#include "Math/MathFwd.h"
10#include "Math/Matrix.h"
11#include "Math/Quat.h"
12#include "Math/Rotator.h"
13#include "Math/ScalarRegister.h"
15#include "Math/Vector.h"
16#include "Math/Vector4.h"
17#include "Math/VectorRegister.h"
19#include "Misc/Build.h"
24#include "UObject/NameTypes.h"
25
26#if ENABLE_VECTORIZED_TRANSFORM
27
28struct Z_Construct_UScriptStruct_FTransform3d_Statics;
29struct Z_Construct_UScriptStruct_FTransform3f_Statics;
30struct Z_Construct_UScriptStruct_FTransform_Statics;
31
32namespace UE
33{
34namespace Math
35{
36 // Selector for alignment of TTransform based on template type used.
37 // The base has no 'Value' defined, you must define a specialized type below for types allowed as TTransform's template param.
38 template<typename T>
39 struct TAlignOfTransform { };
40
41 // Specializations for allowed TTransform::FReal types
42 template<> struct TAlignOfTransform<float> { enum { Value = FMath::Max<uint64>(16, alignof(TPersistentVectorRegisterType<float>)) }; };
43 template<> struct TAlignOfTransform<double> { enum { Value = FMath::Max<uint64>(16, alignof(TPersistentVectorRegisterType<double>)) }; };
44
60template<typename T>
61struct alignas( TAlignOfTransform<T>::Value ) TTransform
62{
63 // Can't have a UE_REQUIRES in the declaration because of the forward declarations, so check for allowed types here.
64 static_assert(std::is_floating_point_v<T>, "TTransform only supports float and double types.");
65
69
70 using FReal = T;
72
73protected:
80public:
84 CORE_API static const TTransform<T> Identity;
85
86#if ENABLE_NAN_DIAGNOSTIC
87 inline void DiagnosticCheckNaN_Scale3D() const
88 {
90 {
91 logOrEnsureNanError(TEXT("TTransform<T> Vectorized Scale3D contains NaN"));
93 }
94 }
95
96 inline void DiagnosticCheckNaN_Translate() const
97 {
99 {
100 logOrEnsureNanError(TEXT("TTransform<T> Vectorized Translation contains NaN"));
101 const_cast<TTransform<T>*>(this)->Translation = VectorZero();
102 }
103 }
104
105 inline void DiagnosticCheckNaN_Rotate() const
106 {
108 {
109 logOrEnsureNanError(TEXT("TTransform<T> Vectorized Rotation contains NaN"));
111 }
112 }
113
114 inline void DiagnosticCheckNaN_All() const
115 {
119 }
120
121 inline void DiagnosticCheck_IsValid() const
122 {
124 if (!IsValid())
125 {
126 logOrEnsureNanError(TEXT("TTransform Vectorized transform is not valid: %s"), *ToHumanReadableString());
127 }
128
129 }
130#else
136#endif
137
141 [[nodiscard]] inline TTransform()
142 {
143 // Rotation = {0,0,0,1)
145 // Translation = {0,0,0,0)
147 // Scale3D = {1,1,1,0);
149 }
150
156 [[nodiscard]] inline explicit TTransform(const TVector<T>& InTranslation)
157 {
158 // Rotation = {0,0,0,1) quaternion identity
160 //Translation = InTranslation;
162 // Scale3D = {1,1,1,0);
164
166 }
167
173 [[nodiscard]] inline explicit TTransform(const TQuat<T>& InRotation)
174 {
175 // Rotation = InRotation
177 // Translation = {0,0,0,0)
179 // Scale3D = {1,1,1,0);
181
183 }
184
190 [[nodiscard]] inline explicit TTransform(const TRotator<T>& InRotation)
191 {
193 // Rotation = InRotation
195 // Translation = {0,0,0,0)
197 // Scale3D = {1,1,1,0);
199
201 }
202
210 [[nodiscard]] inline TTransform(const TQuat<T>& InRotation, const TVector<T>& InTranslation, const TVector<T>& InScale3D = TVector<T>(1.f, 1.f, 1.f))
211 {
212 // Rotation = InRotation
214 // Translation = InTranslation
216 // Scale3D = InScale3D
218
220 }
221
233 {
235 }
236
244 [[nodiscard]] inline TTransform(const TRotator<T>& InRotation, const TVector<T>& InTranslation, const TVector<T>& InScale3D = TVector<T>(1.f, 1.f, 1.f))
245 {
247 // Rotation = InRotation
249 // Translation = InTranslation
251 // Scale3D = InScale3D
253
255 }
256
260 [[nodiscard]] inline explicit TTransform(ENoInit)
261 {
262 // Note: This can be used to track down initialization issues with bone transform arrays; but it will
263 // cause issues with transient fields such as RootMotionDelta that get initialized to 0 by default
264#if ENABLE_NAN_DIAGNOSTIC
265 FReal qnan = FMath::Log2(-5.3f);
266 check(FMath::IsNaN(qnan));
270#endif
271 }
272
276 [[nodiscard]] inline explicit TTransform(const TMatrix<T>& InMatrix)
277 {
280 }
281
283 [[nodiscard]] inline TTransform(const TVector<T>& InX, const TVector<T>& InY, const TVector<T>& InZ, const TVector<T>& InTranslation)
284 {
287 }
288
292 CORE_API void DebugPrint() const;
293
295 [[nodiscard]] bool DebugEqualMatrix(const TMatrix<T>& Matrix) const;
296
298 [[nodiscard]] CORE_API FString ToHumanReadableString() const;
299
300 [[nodiscard]] CORE_API FString ToString() const;
301
303 CORE_API bool InitFromString( const FString& InSourceString );
304
305
306 [[nodiscard]] inline TMatrix<T> ToMatrixWithScale() const
307 {
308
313
316
317 // OutMatrix.M[0][0] = (1.0f - (yy2 + zz2)) * Scale.X; // Diagonal.X
318 // OutMatrix.M[0][1] = (xy2 + wz2) * Scale.X; // Adds.X
319 // OutMatrix.M[0][2] = (xz2 - wy2) * Scale.X; // Subtracts.Z
320 // OutMatrix.M[0][3] = 0.0f; // DiagonalsXYZ_W0.W
324
325 // OutMatrix.M[1][0] = (xy2 - wz2) * Scale.Y; // Subtracts.X
326 // OutMatrix.M[1][1] = (1.0f - (xx2 + zz2)) * Scale.Y; // Diagonal.Y
327 // OutMatrix.M[1][2] = (yz2 + wx2) * Scale.Y; // Adds.Y
328 // OutMatrix.M[1][3] = 0.0f; // DiagonalsXYZ_W0.W
332
333 // OutMatrix.M[2][0] = (xz2 + wy2) * Scale.Z; // Adds.Z
334 // OutMatrix.M[2][1] = (yz2 - wx2) * Scale.Z; // Subtracts.Y
335 // OutMatrix.M[2][2] = (1.0f - (xx2 + yy2)) * Scale.Z; // Diagonals.Z
336 // OutMatrix.M[2][3] = 0.0f; // DiagonalsXYZ_W0.W
339
340 VectorStoreAligned(Row0, &(OutMatrix.M[0][0]));
341 VectorStoreAligned(Row1, &(OutMatrix.M[1][0]));
342 VectorStoreAligned(Row2, &(OutMatrix.M[2][0]));
343
344 // OutMatrix.M[3][0] = Translation.X;
345 // OutMatrix.M[3][1] = Translation.Y;
346 // OutMatrix.M[3][2] = Translation.Z;
347 // OutMatrix.M[3][3] = 1.0f;
349 VectorStoreAligned(Row3, &(OutMatrix.M[3][0]));
350
351 return OutMatrix;
352 }
353
358 {
359 // todo: optimize
360 return ToMatrixWithScale().Inverse();
361 }
362
366 [[nodiscard]] inline TTransform Inverse() const
367 {
368 // Replacement of Inverse of TMatrix<T>
370 {
371 return InverseFast();
372 }
373 else
374 {
376 }
377 }
378
382 [[nodiscard]] inline TMatrix<T> ToMatrixNoScale() const
383 {
388
391
392 // OutMatrix.M[0][0] = (1.0f - (yy2 + zz2)); // Diagonal.X
393 // OutMatrix.M[0][1] = (xy2 + wz2); // Adds.X
394 // OutMatrix.M[0][2] = (xz2 - wy2); // Subtracts.Z
395 // OutMatrix.M[0][3] = 0.0f; // DiagonalsXYZ_W0.W
399
400 // OutMatrix.M[1][0] = (xy2 - wz2); // Subtracts.X
401 // OutMatrix.M[1][1] = (1.0f - (xx2 + zz2)); // Diagonal.Y
402 // OutMatrix.M[1][2] = (yz2 + wx2); // Adds.Y
403 // OutMatrix.M[1][3] = 0.0f; // DiagonalsXYZ_W0.W
407
408 // OutMatrix.M[2][0] = (xz2 + wy2); // Adds.Z
409 // OutMatrix.M[2][1] = (yz2 - wx2); // Subtracts.Y
410 // OutMatrix.M[2][2] = (1.0f - (xx2 + yy2)); // Diagonals.Z
411 // OutMatrix.M[2][3] = 0.0f; // DiagonalsXYZ_W0.W
414
415 VectorStoreAligned(Row0, &(OutMatrix.M[0][0]));
416 VectorStoreAligned(Row1, &(OutMatrix.M[1][0]));
417 VectorStoreAligned(Row2, &(OutMatrix.M[2][0]));
418
419 // OutMatrix.M[3][0] = Translation.X;
420 // OutMatrix.M[3][1] = Translation.Y;
421 // OutMatrix.M[3][2] = Translation.Z;
422 // OutMatrix.M[3][3] = 1.0f;
424 VectorStoreAligned(Row3, &(OutMatrix.M[3][0]));
425
426 return OutMatrix;
427 }
428
430 inline void Blend(const TTransform<T>& Atom1, const TTransform<T>& Atom2, float Alpha)
431 {
432#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST) && WITH_EDITORONLY_DATA
433 // Check that all bone atoms coming from animation are normalized
434 check( Atom1.IsRotationNormalized() );
435 check( Atom2.IsRotationNormalized() );
436#endif
437
438 if( FMath::Abs(Alpha) <= ZERO_ANIMWEIGHT_THRESH )
439 {
440 // if blend is all the way for child1, then just copy its bone atoms
441 (*this) = Atom1;
442 }
443 else if( FMath::Abs(Alpha - 1.0f) <= ZERO_ANIMWEIGHT_THRESH )
444 {
445 // if blend is all the way for child2, then just copy its bone atoms
446 (*this) = Atom2;
447 }
448 else
449 {
450 // Simple linear interpolation for translation and scale.
452
453 Translation = FMath::Lerp<TransformVectorRegister>(Atom1.Translation, Atom2.Translation, BlendWeight);
454 Scale3D = FMath::Lerp<TransformVectorRegister>(Atom1.Scale3D, Atom2.Scale3D, BlendWeight);
455
456 TransformVectorRegister VRotation = VectorLerpQuat(Atom1.Rotation, Atom2.Rotation, BlendWeight);
457
458 // ..and renormalize
460
462 }
463 }
464
466 inline void BlendWith(const TTransform<T>& OtherAtom, float Alpha)
467 {
468#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST) && WITH_EDITORONLY_DATA
469 // Check that all bone atoms coming from animation are normalized
471 check( OtherAtom.IsRotationNormalized() );
472#endif
473
475 {
476 if( Alpha >= 1.f - ZERO_ANIMWEIGHT_THRESH )
477 {
478 // if blend is all the way for child2, then just copy its bone atoms
479 (*this) = OtherAtom;
480 }
481 else
482 {
483 // Simple linear interpolation for translation and scale.
485 Translation = FMath::Lerp<TransformVectorRegister>(Translation, OtherAtom.Translation, BlendWeight);
486
487 Scale3D = FMath::Lerp<TransformVectorRegister>(Scale3D, OtherAtom.Scale3D, BlendWeight);
488
490
491 // ..and renormalize
493
495 }
496 }
497 }
498
499
506 {
507 return TTransform<T>( VectorAdd(Rotation, Atom.Rotation), VectorAdd(Translation, Atom.Translation ), VectorAdd( Scale3D, Atom.Scale3D ) );
508 }
509
511 {
512 Translation = VectorAdd(Translation, Atom.Translation);
513 Rotation = VectorAdd(Rotation, Atom.Rotation);
514 Scale3D = VectorAdd(Scale3D, Atom.Scale3D);
515
516 return *this;
517 }
518
520 {
523 }
524
526 {
531
532 return *this;
533 }
534
535 [[nodiscard]] inline TTransform<T> operator*(const TTransform<T>& Other) const;
537 [[nodiscard]] inline TTransform<T> operator*(const TQuat<T>& Other) const;
538 inline void operator*=(const TQuat<T>& Other);
539
540 [[nodiscard]] inline static bool AnyHasNegativeScale(const TVector<T>& InScale3D, const TVector<T>& InOtherScale3D);
541 inline void ScaleTranslation(const TVector<T>& InScale3D);
542 inline void ScaleTranslation(const T& Scale);
543 inline void RemoveScaling(T Tolerance=UE_SMALL_NUMBER);
544 [[nodiscard]] inline float GetMaximumAxisScale() const;
545 [[nodiscard]] inline float GetMinimumAxisScale() const;
546 // Inverse does not work well with VQS format(in particular non-uniform), so removing it, but made two below functions to be used instead.
547
548 /*******************************************************************************************
549 * The below 2 functions are the ones to get delta transform and return TTransform<T> format that can be concatenated
550 * 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))
551 * So these 2 provides ways to fix this
552 * GetRelativeTransform returns this*Other(-1) and parameter is Other(not Other(-1))
553 * GetRelativeTransformReverse returns this(-1)*Other, and parameter is Other.
554 *******************************************************************************************/
561 CORE_API void SetToRelativeTransform(const TTransform<T>& ParentTransform);
562
563 [[nodiscard]] inline TVector4<T> TransformFVector4(const TVector4<T>& V) const;
565 [[nodiscard]] inline TVector<T> TransformPosition(const TVector<T>& V) const;
566 [[nodiscard]] inline TVector<T> TransformPositionNoScale(const TVector<T>& V) const;
567
568
570 [[nodiscard]] inline TVector<T> InverseTransformPosition(const TVector<T> &V) const;
571 [[nodiscard]] inline TVector<T> InverseTransformPositionNoScale(const TVector<T> &V) const;
572 [[nodiscard]] inline TVector<T> TransformVector(const TVector<T>& V) const;
573 [[nodiscard]] inline TVector<T> TransformVectorNoScale(const TVector<T>& V) const;
574
579 [[nodiscard]] inline TVector<T> InverseTransformVector(const TVector<T> &V) const;
580 [[nodiscard]] inline TVector<T> InverseTransformVectorNoScale(const TVector<T> &V) const;
581
587
593
594 [[nodiscard]] inline TTransform<T> GetScaled(T Scale) const;
595 [[nodiscard]] inline TTransform<T> GetScaled(TVector<T> Scale) const;
596 [[nodiscard]] inline TVector<T> GetScaledAxis(EAxis::Type InAxis) const;
597 [[nodiscard]] inline TVector<T> GetUnitAxis(EAxis::Type InAxis) const;
598 inline void Mirror(EAxis::Type MirrorAxis, EAxis::Type FlipAxis);
599 [[nodiscard]] inline static TVector<T> GetSafeScaleReciprocal(const TVector<T>& InScale, T Tolerance=UE_SMALL_NUMBER);
600
601
602 [[nodiscard]] UE_FORCEINLINE_HINT TVector<T> GetLocation() const
603 {
604 return GetTranslation();
605 }
606
607 [[nodiscard]] inline TRotator<T> Rotator() const
608 {
611 return OutRotation.Rotator();
612 }
613
615 [[nodiscard]] inline T GetDeterminant() const
616 {
617 //#todo - vectorized version of this
620 return OutScale3D.X * OutScale3D.Y * OutScale3D.Z;
621 }
622
624 inline void SetLocation(const TVector<T>& Origin)
625 {
628 }
629
634 [[nodiscard]] bool ContainsNaN() const
635 {
637 {
638 return true;
639 }
641 {
642 return true;
643 }
644
646 {
647 return true;
648 }
649 return false;
650 }
651
652 [[nodiscard]] inline bool IsValid() const
653 {
654 if ( ContainsNaN() )
655 {
656 return false;
657 }
658
659 if ( !IsRotationNormalized() )
660 {
661 return false;
662 }
663
664 return true;
665 }
666
667 // Serializer.
668 inline friend FArchive& operator<<(FArchive& Ar,TTransform<T>& M)
669 {
670 Ar << *reinterpret_cast<TQuat<T>*>(&(M.Rotation));
671 Ar << *reinterpret_cast<TVector<T>*>(&(M.Translation));
673
674 if (Ar.IsLoading())
675 {
676 M.Translation = VectorSet_W0(M.Translation);
677 M.Scale3D = VectorSet_W0(M.Scale3D);
678 }
679 return Ar;
680 }
681
682 bool Serialize(FArchive& Ar)
683 {
684 Ar << *this;
685 return true;
686 }
687
689 {
690 // FTransform3f/d are immutable, but FTransform is not and needs a per-property conversion
692 {
693 return false;
694 }
695
696 if constexpr (std::is_same_v<T, float>)
697 {
698 return UE_SERIALIZE_VARIANT_FROM_MISMATCHED_TAG(Ar, Transform, Transform3f, Transform3d);
699 }
700 else
701 {
702 return UE_SERIALIZE_VARIANT_FROM_MISMATCHED_TAG(Ar, Transform, Transform3d, Transform3f);
703 }
704 }
705
706 // Binary comparison operators.
707 /*
708 bool operator==( const TTransform<T>& Other ) const
709 {
710 return Rotation==Other.Rotation && Translation==Other.Translation && Scale3D==Other.Scale3D;
711 }
712 bool operator!=( const TTransform<T>& Other ) const
713 {
714 return Rotation!=Other.Rotation || Translation!=Other.Translation || Scale3D!=Other.Scale3D;
715 }
716 */
717
718private:
719
721 {
723 }
724
725 inline bool Private_RotationEquals(TransformVectorRegister InRotation, const FReal ToleranceScalar = UE_KINDA_SMALL_NUMBER) const
726 {
727 const TransformVectorRegister MyRotation = Rotation; // Load from persistent value, to avoid repeated loads.
729 // !( (FMath::Abs(X-Q.X) > Tolerance) || (FMath::Abs(Y-Q.Y) > Tolerance) || (FMath::Abs(Z-Q.Z) > Tolerance) || (FMath::Abs(W-Q.W) > Tolerance) )
731 // !( (FMath::Abs(X+Q.X) > Tolerance) || (FMath::Abs(Y+Q.Y) > Tolerance) || (FMath::Abs(Z+Q.Z) > Tolerance) || (FMath::Abs(W+Q.W) > Tolerance) )
733 return !VectorAnyGreaterThan(RotationSub, Tolerance) || !VectorAnyGreaterThan(RotationAdd, Tolerance);
734 }
735
736 inline bool Private_TranslationEquals(TransformVectorRegister InTranslation, const FReal ToleranceScalar = UE_KINDA_SMALL_NUMBER) const
737 {
739 // !( (FMath::Abs(X-V.X) > Tolerance) || (FMath::Abs(Y-V.Y) > Tolerance) || (FMath::Abs(Z-V.Z) > Tolerance) )
741 return !VectorAnyGreaterThan(TranslationDiff, Tolerance);
742 }
743
744 inline bool Private_Scale3DEquals(TransformVectorRegister InScale3D, const FReal ToleranceScalar = UE_KINDA_SMALL_NUMBER) const
745 {
747 // !( (FMath::Abs(X-V.X) > Tolerance) || (FMath::Abs(Y-V.Y) > Tolerance) || (FMath::Abs(Z-V.Z) > Tolerance) )
749 return !VectorAnyGreaterThan(ScaleDiff, Tolerance);
750 }
751
752public:
753
754 // 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.
756 {
757 return A.Private_RotationEquals(B.Rotation, Tolerance);
758 }
759
760 // Test if A's translation equals B's translation, within a tolerance. Preferred over "A.GetTranslation().Equals(B.GetTranslation())" because it avoids TransformVectorRegister->TVector<T> conversion.
762 {
763 return A.Private_TranslationEquals(B.Translation, Tolerance);
764 }
765
766 // Test if A's scale equals B's scale, within a tolerance. Preferred over "A.GetScale3D().Equals(B.GetScale3D())" because it avoids TransformVectorRegister->TVector<T> conversion.
768 {
769 return A.Private_Scale3DEquals(B.Scale3D, Tolerance);
770 }
771
772
773 // 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.
775 {
776 return AreRotationsEqual(*this, Other, Tolerance);
777 }
778
779 // Test if this Transform's translation equals another's translation, within a tolerance. Preferred over "GetTranslation().Equals(Other.GetTranslation())" because it avoids TransformVectorRegister->TVector<T> conversion.
781 {
782 return AreTranslationsEqual(*this, Other, Tolerance);
783 }
784
785 // Test if this Transform's scale equals another's scale, within a tolerance. Preferred over "GetScale3D().Equals(Other.GetScale3D())" because it avoids TransformVectorRegister->TVector<T> conversion.
787 {
788 return AreScale3DsEqual(*this, Other, Tolerance);
789 }
790
791 // Test if all components of the transforms are equal, within a tolerance.
793 {
794 return Private_TranslationEquals(Other.Translation, Tolerance) && Private_RotationEquals(Other.Rotation, Tolerance) && Private_Scale3DEquals(Other.Scale3D, Tolerance);
795 }
796
797 // Test if all components of the transform property are equal.
798 [[nodiscard]] UE_FORCEINLINE_HINT bool Identical(const TTransform<T>* Other, uint32 PortFlags) const
799 {
800 return Equals(*Other, 0.f);
801 }
802
803 // Test if rotation and translation components of the transforms are equal, within a tolerance.
805 {
806 return Private_TranslationEquals(Other.Translation, Tolerance) && Private_RotationEquals(Other.Rotation, Tolerance);
807 }
808
810 CORE_API static void Multiply(TTransform<T>* OutTransform, const TTransform<T>* A, const TTransform<T>* B);
811
818 inline void SetComponents(const TQuat<T>& InRotation, const TVector<T>& InTranslation, const TVector<T>& InScale3D)
819 {
823
825 }
826
833 inline void SetIdentity()
834 {
835 // Rotation = {0,0,0,1)
836 Rotation = GlobalVectorConstants::Float0001; //VectorSet_W1( VectorZero() );
837 // Translation = {0,0,0,0)
839 // Scale3D = {1,1,1,0);
840 Scale3D = GlobalVectorConstants::Float1110; //VectorSet_W0( VectorOne() );
841 }
842
849 inline void SetIdentityZeroScale()
850 {
851 // Rotation = {0,0,0,1)
852 Rotation = GlobalVectorConstants::Float0001; //VectorSet_W1( VectorZero() );
853 // Translation = {0,0,0,0)
855 // Scale3D = {0,0,0,0);
857 }
858
863 inline void MultiplyScale3D(const TVector<T>& Scale3DMultiplier)
864 {
867 }
868
873 inline void SetTranslation(const TVector<T>& NewTranslation)
874 {
875 Translation = VectorLoadFloat3_W0(&NewTranslation);
877 }
878
881 {
882 Translation = Other.Translation;
883 }
884
889 inline void ConcatenateRotation(const TQuat<T>& DeltaRotation)
890 {
893 }
894
899 inline void AddToTranslation(const TVector<T>& DeltaTranslation)
900 {
903 }
904
909 [[nodiscard]] inline static TVector<T> AddTranslations(const TTransform<T>& A, const TTransform<T>& B)
910 {
911 TVector<T> Result;
912 VectorStoreFloat3(VectorAdd(A.Translation, B.Translation), &Result);
913 return Result;
914 }
915
920 [[nodiscard]] inline static TVector<T> SubtractTranslations(const TTransform<T>& A, const TTransform<T>& B)
921 {
922 TVector<T> Result;
923 VectorStoreFloat3(VectorSubtract(A.Translation, B.Translation), &Result);
924 return Result;
925 }
926
931 inline void SetRotation(const TQuat<T>& NewRotation)
932 {
933 Rotation = VectorLoadAligned(&NewRotation);
935 }
936
939 {
940 Rotation = Other.Rotation;
941 }
942
947 inline void SetScale3D(const TVector<T>& NewScale3D)
948 {
951 }
952
955 {
956 Scale3D = Other.Scale3D;
957 }
958
964 inline void SetTranslationAndScale3D(const TVector<T>& NewTranslation, const TVector<T>& NewScale3D)
965 {
966 Translation = VectorLoadFloat3_W0(&NewTranslation);
968
971 }
972
973 // For low-level VectorRegister programming
975 {
976 return Translation;
977 }
979 {
980 return Rotation;
981 }
983 {
985 }
987 {
989 }
990
1008 inline void Accumulate(const TTransform<T>& SourceAtom)
1009 {
1010 // Rotation = SourceAtom.Rotation * Rotation;
1012
1013 // Translation += SourceAtom.Translation;
1014 // Scale *= SourceAtom.Scale;
1017
1019
1021 }
1022
1037 {
1038 // SourceAtom = Atom * BlendWeight;
1039 const TransformVectorRegister BlendWeight(BlendWeightScalar.Value);
1040 const TransformVectorRegister BlendedRotation = VectorMultiply(Atom.Rotation, BlendWeight);
1041 const TransformVectorRegister BlendedScale = VectorMultiply(Atom.Scale3D, BlendWeight);
1042
1043 // Rotation = SourceAtom.Rotation * Rotation;
1045
1046 // Translation += SourceAtom.Translation;
1047 // Scale *= SourceAtom.Scale;
1048 Translation = VectorMultiplyAdd(Atom.Translation, BlendWeight, Translation);
1050
1052 }
1064 {
1065 const TransformVectorRegister BlendWeight(BlendWeightScalar.Value);
1066 const TransformVectorRegister BlendedRotation = VectorMultiply(DeltaAtom.Rotation, BlendWeight);
1067
1069
1070 Translation = VectorMultiplyAdd(DeltaAtom.Translation, BlendWeight, Translation);
1071 Scale3D = VectorMultiplyAdd(DeltaAtom.Scale3D, BlendWeight, Scale3D);
1072
1074 }
1075
1095 {
1096 const TransformVectorRegister BlendWeight(BlendWeightScalar.Value);
1098
1099 // SourceAtom = Atom * BlendWeight;
1100 const TransformVectorRegister BlendedRotation = VectorMultiply(Atom.Rotation, BlendWeight);
1101
1102 // Rotation = SourceAtom.Rotation * Rotation;
1104
1105 // Translation += SourceAtom.Translation;
1106 // Scale *= SourceAtom.Scale;
1107 Translation = VectorMultiplyAdd(Atom.Translation, BlendWeight, Translation);
1108 Scale3D = VectorMultiply(Scale3D, VectorMultiplyAdd(Atom.Scale3D, BlendWeight, DefaultScale));
1109
1110
1112 }
1113
1125 {
1127 Translation = FMath::Lerp<TransformVectorRegister>(SourceAtom1.Translation, SourceAtom2.Translation, Alpha);
1128 Scale3D = FMath::Lerp<TransformVectorRegister>(SourceAtom1.Scale3D, SourceAtom2.Scale3D, Alpha);
1129
1132 }
1133
1137 inline void NormalizeRotation()
1138 {
1141 }
1142
1148 [[nodiscard]] inline bool IsRotationNormalized() const
1149 {
1152 }
1153
1167 {
1168 const TransformVectorRegister BlendWeight(BlendWeightScalar.Value);
1173
1174 // Blend rotation
1175 // To ensure the 'shortest route', we make sure the dot product between the both rotations is positive.
1176 // const float Bias = (|A.B| >= 0 ? 1 : -1)
1177 // BlendedAtom.Rotation = (B * Alpha) + (A * (Bias * (1.f - Alpha)));
1178 // BlendedAtom.Rotation.QuaternionNormalize();
1179 // Note: A = (0,0,0,1), which simplifies things a lot; only care about sign of B.W now, instead of doing a dot product
1181
1186
1187 // Normalize blended rotation ( result = (Q.Q >= 1e-8) ? (Q / |Q|) : (0,0,0,1) )
1189
1190 // FinalAtom.Rotation = BlendedAtom.Rotation * FinalAtom.Rotation;
1192
1193 // Blend translation and scale
1194 // BlendedAtom.Translation = Lerp(Zero, SourceAtom.Translation, Alpha);
1195 // BlendedAtom.Scale = Lerp(0, SourceAtom.Scale, Alpha);
1197 const TransformVectorRegister BlendedTranslation = FMath::Lerp<TransformVectorRegister>(Zero, SourceAtom.Translation, BlendWeight);
1198 const TransformVectorRegister BlendedScale3D = FMath::Lerp<TransformVectorRegister>(Zero, SourceAtom.Scale3D, BlendWeight);
1199
1200 // Apply translation and scale to final atom
1201 // FinalAtom.Translation += BlendedAtom.Translation
1202 // FinalAtom.Scale *= BlendedAtom.Scale
1203 FinalAtom.Translation = VectorAdd( FinalAtom.Translation, BlendedTranslation );
1204 FinalAtom.Scale3D = VectorMultiply( FinalAtom.Scale3D, VectorAdd(DefaultScale, BlendedScale3D));
1205 checkSlow( FinalAtom.IsRotationNormalized() );
1206 }
1207
1208
1214 [[nodiscard]] inline TQuat<T> GetRotation() const
1215 {
1219 return OutRotation;
1220 }
1221
1227 [[nodiscard]] inline TVector<T> GetTranslation() const
1228 {
1230 TVector<T> OutTranslation;
1232 return OutTranslation;
1233 }
1234
1240 [[nodiscard]] inline TVector<T> GetScale3D() const
1241 {
1243 TVector<T> OutScale3D;
1245 return OutScale3D;
1246 }
1247
1253 inline void CopyRotationPart(const TTransform<T>& SrcBA)
1254 {
1255 Rotation = SrcBA.Rotation;
1256 Scale3D = SrcBA.Scale3D;
1257
1260 }
1261
1268 {
1269 Translation = SrcBA.Translation;
1270 Scale3D = SrcBA.Scale3D;
1271
1274 }
1275
1276 void SetFromMatrix(const TMatrix<T>& InMatrix)
1277 {
1278 TMatrix<T> M = InMatrix;
1279
1280 // Get the 3D scale from the matrix
1281 TVector<T> InScale = M.ExtractScaling(0);
1283
1284 // If there is negative scaling going on, we handle that here
1285 if(InMatrix.Determinant() < 0.f)
1286 {
1287 // Assume it is along X and modify transform accordingly.
1288 // It doesn't actually matter which axis we choose, the 'appearance' will be the same
1290 M.SetAxis(0, -M.GetScaledAxis( EAxis::X ));
1291 }
1292
1295 TVector<T> InTranslation = InMatrix.GetOrigin();
1297
1298 // Normalize rotation
1300 }
1301
1302private:
1304 {
1305#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST) && WITH_EDITORONLY_DATA
1306 // Make sure Rotation is normalized when we turn it into a matrix.
1308#endif
1309
1311 if constexpr (std::is_same_v<T, double>)
1312 {
1313 One = VectorOneDouble();
1314 }
1315 else
1316 {
1317 One = VectorOne();
1318 }
1319
1320 const TransformVectorRegister MyRotation = Rotation; // Load from persistent value, to avoid repeated loads.
1323
1324 // The diagonal terms of the rotation matrix are:
1325 // (1 - (yy2 + zz2)) * scale
1326 // (1 - (xx2 + zz2)) * scale
1327 // (1 - (xx2 + yy2)) * scale
1333
1334 // Grouping the non-diagonal elements in the rotation block by operations:
1335 // ((x*y2,y*z2,x*z2) + (w*z2,w*x2,w*y2)) * scale.xyz and
1336 // ((x*y2,y*z2,x*z2) - (w*z2,w*x2,w*y2)) * scale.yxz
1337 // Rearranging so the LHS and RHS are in the same order as for +
1338 // ((x*y2,y*z2,x*z2) - (w*z2,w*x2,w*y2)) * scale.yxz
1339
1340 // RotBase = x*y2, y*z2, x*z2
1341 // RotOffset = w*z2, w*x2, w*y2
1345
1349
1350 // Adds = (RotBase + RotOffset)*Scale3D : (x*y2 + w*z2) * Scale3D.X , (y*z2 + w*x2) * Scale3D.Y, (x*z2 + w*y2) * Scale3D.Z
1351 // Subtracts = (RotBase - RotOffset)*Scale3DYZX : (x*y2 - w*z2) * Scale3D.Y , (y*z2 - w*x2) * Scale3D.Z, (x*z2 - w*y2) * Scale3D.X
1357 }
1358
1360 {
1361#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST) && WITH_EDITORONLY_DATA
1362 // Make sure Rotation is normalized when we turn it into a matrix.
1364#endif
1365 const TransformVectorRegister MyRotation = Rotation; // Load from persistent value, to avoid repeated loads.
1368
1369 // The diagonal terms of the rotation matrix are:
1370 // (1 - (yy2 + zz2))
1371 // (1 - (xx2 + zz2))
1372 // (1 - (xx2 + yy2))
1377
1378 // Grouping the non-diagonal elements in the rotation block by operations:
1379 // ((x*y2,y*z2,x*z2) + (w*z2,w*x2,w*y2)) and
1380 // ((x*y2,y*z2,x*z2) - (w*z2,w*x2,w*y2))
1381 // Rearranging so the LHS and RHS are in the same order as for +
1382 // ((x*y2,y*z2,x*z2) - (w*z2,w*x2,w*y2))
1383
1384 // RotBase = x*y2, y*z2, x*z2
1385 // RotOffset = w*z2, w*x2, w*y2
1389
1393
1394 // Adds = (RotBase + RotOffset): (x*y2 + w*z2) , (y*z2 + w*x2), (x*z2 + w*y2)
1395 // Subtracts = (RotBase - RotOffset) : (x*y2 - w*z2) , (y*z2 - w*x2), (x*z2 - w*y2)
1398 }
1399
1408 {
1409 // SafeReciprocalScale.X = (InScale.X == 0) ? 0.f : 1/InScale.X; // same for YZW
1410
1413
1414 //TransformVectorRegister( Vec1.x == Vec2.x ? 0xFFFFFFFF : 0, same for yzw )
1416
1417 //const TransformVectorRegister ScaleZeroMask = VectorCompareEQ(InScale, VectorZero());
1418
1419 // TransformVectorRegister( for each bit i: Mask[i] ? Vec1[i] : Vec2[i] )
1421
1422 return SafeReciprocalScale;
1423 }
1424
1426 [[nodiscard]] inline TTransform<T> InverseFast() const
1427 {
1428 // Inverse QST (A) = QST (~A)
1429 // Since A*~A = Identity,
1430 // A(P) = Q(A)*S(A)*P*-Q(A) + T(A)
1431 // ~A(A(P)) = Q(~A)*S(~A)*(Q(A)*S(A)*P*-Q(A) + T(A))*-Q(~A) + T(~A) = Identity
1432 // Q(~A)*Q(A)*S(~A)*S(A)*P*-Q(A)*-Q(~A) + Q(~A)*S(~A)*T(A)*-Q(~A) + T(~A) = Identity
1433 // [Q(~A)*Q(A)]*[S(~A)*S(A)]*P*-[Q(~A)*Q(A)] + [Q(~A)*S(~A)*T(A)*-Q(~A) + T(~A)] = I
1434
1435 // Identity Q = (0, 0, 0, 1) = Q(~A)*Q(A)
1436 // Identity Scale = 1 = S(~A)*S(A)
1437 // Identity Translation = (0, 0, 0) = [Q(~A)*S(~A)*T(A)*-Q(~A) + T(~A)]
1438
1439 // Q(~A) = Q(~A)
1440 // S(~A) = 1.f/S(A)
1441 // T(~A) = - (Q(~A)*S(~A)*T(A)*Q(A))
1444
1445 // Invert the scale
1447
1448 // Invert the rotation
1450
1451 // Invert the translation
1455
1456 return TTransform<T>(InvRotation, InvTranslation, InvScale);
1457 }
1458
1469 UE_FORCEINLINE_HINT static void MultiplyUsingMatrixWithScale(TTransform<T>* OutTransform, const TTransform<T>* A, const TTransform<T>* B);
1480 inline static void ConstructTransformFromMatrixWithDesiredScale(const TMatrix<T>& AMatrix, const TMatrix<T>& BMatrix, TransformVectorRegister DesiredScale, TTransform<T>& OutTransform);
1489 static void GetRelativeTransformUsingMatrixWithScale(TTransform<T>* OutTransform, const TTransform<T>* Base, const TTransform<T>* Relative);
1490
1491public:
1492
1493 // Conversion to other type.
1494 friend struct TTransform<double>;
1495 template<typename FArg UE_REQUIRES(!std::is_same_v<T, FArg> && std::is_same_v<T, float>)>
1496 explicit TTransform(const TTransform<FArg>& From)
1498 {
1499 }
1500
1501 friend struct TTransform<float>;
1502 template<typename FArg UE_REQUIRES(!std::is_same_v<T, FArg> && std::is_same_v<T, double>)>
1503 explicit TTransform(const TTransform<FArg>& From)
1505 {
1506 }
1507};
1508
1509#if !defined(_MSC_VER) || defined(__clang__) // MSVC can't forward declare explicit specializations
1512#endif
1513
1514
1515template<typename T>
1516inline bool TTransform<T>::AnyHasNegativeScale(const TVector<T>& InScale3D, const TVector<T>& InOtherScale3D)
1517{
1518 TransformVectorRegister VectorInScale3D = VectorLoadFloat3_W0(&InScale3D);
1519 TransformVectorRegister VectorInOtherScale3D = VectorLoadFloat3_W0(&InOtherScale3D);
1520
1522}
1523
1525template<typename T>
1526inline void TTransform<T>::ScaleTranslation(const TVector<T>& InScale3D)
1527{
1528 TransformVectorRegister VectorInScale3D = VectorLoadFloat3_W0(&InScale3D);
1530 DiagnosticCheckNaN_Translate();
1531}
1532
1534template<typename T>
1536{
1537 ScaleTranslation( TVector<T>(InScale) );
1538}
1539
1540// this function is from matrix, and all it does is to normalize rotation portion
1541template<typename T>
1542inline void TTransform<T>::RemoveScaling(T Tolerance/*=UE_SMALL_NUMBER*/)
1543{
1545 NormalizeRotation();
1546
1547 DiagnosticCheckNaN_Rotate();
1548 DiagnosticCheckNaN_Scale3D();
1549}
1550
1551template<typename T>
1552UE_FORCEINLINE_HINT void TTransform<T>::MultiplyUsingMatrixWithScale(TTransform<T>* OutTransform, const TTransform<T>* A, const TTransform<T>* B)
1553{
1554 ConstructTransformFromMatrixWithDesiredScale(A->ToMatrixWithScale(), B->ToMatrixWithScale(), VectorMultiply(A->Scale3D, B->Scale3D), *OutTransform);
1555}
1556
1557template<typename T>
1558inline void TTransform<T>::ConstructTransformFromMatrixWithDesiredScale(const UE::Math::TMatrix<T>& AMatrix, const UE::Math::TMatrix<T>& BMatrix, TransformVectorRegister DesiredScale, TTransform<T>& OutTransform)
1559{
1560 // the goal of using M is to get the correct orientation
1561 // but for translation, we still need scale
1562 UE::Math::TMatrix<T> M = AMatrix * BMatrix;
1563 M.RemoveScaling();
1564
1565 // apply negative scale back to axes
1566 TVector<T> SignedScale;
1568
1572
1573 // @note: if you have negative with 0 scale, this will return rotation that is identity
1574 // since matrix loses that axes
1576 Rotation.Normalize();
1577
1578 // set values back to output
1579 OutTransform.Scale3D = DesiredScale;
1580 OutTransform.Rotation = VectorLoadAligned(&Rotation);
1581
1582 // technically I could calculate this using TTransform<T> but then it does more quat multiplication
1583 // instead of using Scale in matrix multiplication
1584 // it's a question of between RemoveScaling vs using TTransform<T> to move translation
1585 TVector<T> Translation = M.GetOrigin();
1586 OutTransform.Translation = VectorLoadFloat3_W0(&Translation);
1587}
1588
1592template<typename T>
1594{
1595 TTransform<T> A(*this);
1596
1597 TransformVectorRegister VScale = VectorLoadFloat1(&InScale);
1598 A.Scale3D = VectorMultiply( A.Scale3D, VScale);
1599
1600 A.DiagnosticCheckNaN_Scale3D();
1601
1602 return A;
1603}
1604
1608template<typename T>
1609inline TTransform<T> TTransform<T>::GetScaled(TVector<T> InScale) const
1610{
1611 TTransform<T> A(*this);
1612
1613 TransformVectorRegister VScale = VectorLoadFloat3_W0(&InScale);
1614 A.Scale3D = VectorMultiply( A.Scale3D, VScale);
1615
1616 A.DiagnosticCheckNaN_Scale3D();
1617
1618 return A;
1619}
1620
1621template<typename T>
1623{
1624 DiagnosticCheckNaN_All();
1625
1626 // if not, this won't work
1627 checkSlow (V.W == 0.f || V.W == 1.f);
1628
1629 const TransformVectorRegister InputVector = VectorLoadAligned(&V);
1630
1631 //Transform using QST is following
1632 //QST(P) = Q.Rotate(S*P) + T where Q = quaternion, S = 1.0f, T = translation
1633
1634 //RotatedVec = Q.Rotate(V.X, V.Y, V.Z, 0.f)
1635 const TransformVectorRegister InputVectorW0 = VectorSet_W0(InputVector);
1636 const TransformVectorRegister RotatedVec = VectorQuaternionRotateVector(Rotation, InputVectorW0);
1637
1638 // NewVect.XYZ += Translation * W
1639 // NewVect.W += 1 * W
1640 const TransformVectorRegister WWWW = VectorReplicate(InputVector, 3);
1641 const TransformVectorRegister TranslatedVec = VectorMultiplyAdd(VectorSet_W1(Translation), WWWW, RotatedVec);
1642
1645 return NewVectOutput;
1646}
1647
1648template<typename T>
1650{
1651 DiagnosticCheckNaN_All();
1652
1653 // if not, this won't work
1654 checkSlow (V.W == 0.f || V.W == 1.f);
1655
1656 const TransformVectorRegister InputVector = VectorLoadAligned(&V);
1657
1658 //Transform using QST is following
1659 //QST(P) = Q.Rotate(S*P) + T where Q = quaternion, S = scale, T = translation
1660
1661 //RotatedVec = Q.Rotate(Scale*V.X, Scale*V.Y, Scale*V.Z, 0.f)
1662 const TransformVectorRegister InputVectorW0 = VectorSet_W0(InputVector);
1663 const TransformVectorRegister ScaledVec = VectorMultiply(Scale3D, InputVectorW0);
1664 const TransformVectorRegister RotatedVec = VectorQuaternionRotateVector(Rotation, ScaledVec);
1665
1666 // NewVect.XYZ += Translation * W
1667 // NewVect.W += 1 * W
1668 const TransformVectorRegister WWWW = VectorReplicate(InputVector, 3);
1669 const TransformVectorRegister TranslatedVec = VectorMultiplyAdd(VectorSet_W1(Translation), WWWW, RotatedVec);
1670
1673 return NewVectOutput;
1674}
1675
1676
1677template<typename T>
1678inline TVector<T> TTransform<T>::TransformPosition(const TVector<T>& V) const
1679{
1680 DiagnosticCheckNaN_All();
1681
1682 const TransformVectorRegister InputVectorW0 = VectorLoadFloat3_W0(&V);
1683
1684 //Transform using QST is following
1685 //QST(P) = Q.Rotate(S*P) + T where Q = quaternion, S = scale, T = translation
1686
1687 //RotatedVec = Q.Rotate(Scale*V.X, Scale*V.Y, Scale*V.Z, 0.f)
1688 const TransformVectorRegister ScaledVec = VectorMultiply(Scale3D, InputVectorW0);
1689 const TransformVectorRegister RotatedVec = VectorQuaternionRotateVector(Rotation, ScaledVec);
1690
1691 const TransformVectorRegister TranslatedVec = VectorAdd(RotatedVec, Translation);
1692
1693 TVector<T> Result;
1695 return Result;
1696}
1697
1698template<typename T>
1699inline TVector<T> TTransform<T>::TransformPositionNoScale(const TVector<T>& V) const
1700{
1701 DiagnosticCheckNaN_All();
1702
1703 const TransformVectorRegister InputVectorW0 = VectorLoadFloat3_W0(&V);
1704
1705 //Transform using QST is following
1706 //QST(P) = Q.Rotate(S*P) + T where Q = quaternion, S = 1.0f, T = translation
1707
1708 //RotatedVec = Q.Rotate(V.X, V.Y, V.Z, 0.f)
1709 const TransformVectorRegister RotatedVec = VectorQuaternionRotateVector(Rotation, InputVectorW0);
1710
1711 const TransformVectorRegister TranslatedVec = VectorAdd(RotatedVec, Translation);
1712
1713 TVector<T> Result;
1715 return Result;
1716}
1717
1718template<typename T>
1719inline TVector<T> TTransform<T>::TransformVector(const TVector<T>& V) const
1720{
1721 DiagnosticCheckNaN_All();
1722
1723 const TransformVectorRegister InputVectorW0 = VectorLoadFloat3_W0(&V);
1724
1725 //RotatedVec = Q.Rotate(Scale*V.X, Scale*V.Y, Scale*V.Z, 0.f)
1726 const TransformVectorRegister ScaledVec = VectorMultiply(Scale3D, InputVectorW0);
1727 const TransformVectorRegister RotatedVec = VectorQuaternionRotateVector(Rotation, ScaledVec);
1728
1729 TVector<T> Result;
1730 VectorStoreFloat3(RotatedVec, &Result);
1731 return Result;
1732}
1733
1734template<typename T>
1735inline TVector<T> TTransform<T>::TransformVectorNoScale(const TVector<T>& V) const
1736{
1737 DiagnosticCheckNaN_All();
1738
1739 const TransformVectorRegister InputVectorW0 = VectorLoadFloat3_W0(&V);
1740
1741 //RotatedVec = Q.Rotate(V.X, V.Y, V.Z, 0.f)
1742 const TransformVectorRegister RotatedVec = VectorQuaternionRotateVector(Rotation, InputVectorW0);
1743
1744 TVector<T> Result;
1745 VectorStoreFloat3(RotatedVec, &Result);
1746 return Result;
1747}
1748
1749// do backward operation when inverse, translation -> rotation -> scale
1750template<typename T>
1751inline TVector<T> TTransform<T>::InverseTransformPosition(const TVector<T> &V) const
1752{
1753 DiagnosticCheckNaN_All();
1754
1755 const TransformVectorRegister InputVector = VectorLoadFloat3_W0(&V);
1756
1757 // (V-Translation)
1758 const TransformVectorRegister TranslatedVec = VectorSet_W0(VectorSubtract(InputVector, Translation));
1759
1760 // ( Rotation.Inverse() * (V-Translation) )
1761 const TransformVectorRegister VR = VectorQuaternionInverseRotateVector(Rotation, TranslatedVec);
1762
1763 // GetSafeScaleReciprocal(Scale3D);
1764 const TransformVectorRegister SafeReciprocal = GetSafeScaleReciprocal(VectorSet_W1(Scale3D));
1765
1766 // ( Rotation.Inverse() * (V-Translation) ) * GetSafeScaleReciprocal(Scale3D);
1767 const TransformVectorRegister VResult = VectorMultiply(VR, SafeReciprocal);
1768
1769 TVector<T> Result;
1770 VectorStoreFloat3(VResult, &Result);
1771 return Result;
1772}
1773
1774// do backward operation when inverse, translation -> rotation
1775template<typename T>
1776inline TVector<T> TTransform<T>::InverseTransformPositionNoScale(const TVector<T> &V) const
1777{
1778 DiagnosticCheckNaN_All();
1779
1780 const TransformVectorRegister InputVector = VectorLoadFloat3_W0(&V);
1781
1782 // (V-Translation)
1783 const TransformVectorRegister TranslatedVec = VectorSet_W0(VectorSubtract(InputVector, Translation));
1784
1785 // ( Rotation.Inverse() * (V-Translation) )
1786 const TransformVectorRegister VResult = VectorQuaternionInverseRotateVector(Rotation, TranslatedVec);
1787
1788 TVector<T> Result;
1789 VectorStoreFloat3(VResult, &Result);
1790 return Result;
1791}
1792
1793
1794// do backward operation when inverse, translation -> rotation -> scale
1795template<typename T>
1796inline TVector<T> TTransform<T>::InverseTransformVector(const TVector<T> &V) const
1797{
1798 DiagnosticCheckNaN_All();
1799
1800 const TransformVectorRegister InputVector = VectorLoadFloat3_W0(&V);
1801
1802 // ( Rotation.Inverse() * V ) aka. TVector<T> TQuat<T>::operator*( const TVector<T>& V ) const
1803 const TransformVectorRegister VR = VectorQuaternionInverseRotateVector(Rotation, InputVector);
1804
1805 // GetSafeScaleReciprocal(Scale3D);
1806 const TransformVectorRegister SafeReciprocal = GetSafeScaleReciprocal(VectorSet_W1(Scale3D));
1807
1808 // ( Rotation.Inverse() * V) * GetSafeScaleReciprocal(Scale3D);
1809 const TransformVectorRegister VResult = VectorMultiply(VR, SafeReciprocal);
1810
1811 TVector<T> Result;
1812 VectorStoreFloat3(VResult, &Result);
1813 return Result;
1814}
1815
1816// do backward operation when inverse, translation -> rotation
1817template<typename T>
1818inline TVector<T> TTransform<T>::InverseTransformVectorNoScale(const TVector<T> &V) const
1819{
1820 DiagnosticCheckNaN_All();
1821
1822 TransformVectorRegister InputVector = VectorLoadFloat3_W0(&V);
1823
1824 // ( Rotation.Inverse() * V )
1825 TransformVectorRegister VResult = VectorQuaternionInverseRotateVector(Rotation, InputVector);
1826
1827 TVector<T> Result;
1828 VectorStoreFloat3(VResult, &Result);
1829 return Result;
1830}
1831
1832template<typename T>
1834{
1835 return GetRotation() * Q;
1836}
1837
1838template<typename T>
1840{
1841 return GetRotation().Inverse() * Q;
1842}
1843
1844template<typename T>
1846{
1848 Multiply(&Output, this, &Other);
1849 return Output;
1850}
1851
1852template<typename T>
1854{
1855 Multiply(this, this, &Other);
1856}
1857
1858template<typename T>
1860{
1862 Multiply(&Output, this, &OtherTransform);
1863 return Output;
1864}
1865
1866template<typename T>
1867inline void TTransform<T>::operator*=(const TQuat<T>& Other)
1868{
1870 Multiply(this, this, &OtherTransform);
1871}
1872
1873// x = 0, y = 1, z = 2
1874template<typename T>
1875inline TVector<T> TTransform<T>::GetScaledAxis(EAxis::Type InAxis) const
1876{
1877 if ( InAxis == EAxis::X )
1878 {
1879 return TransformVector(TVector<T>(1.f, 0.f, 0.f));
1880 }
1881 else if ( InAxis == EAxis::Y )
1882 {
1883 return TransformVector(TVector<T>(0.f, 1.f, 0.f));
1884 }
1885
1886 return TransformVector(TVector<T>(0.f, 0.f, 1.f));
1887}
1888
1889// x = 0, y = 1, z = 2
1890template<typename T>
1891inline TVector<T> TTransform<T>::GetUnitAxis(EAxis::Type InAxis) const
1892{
1893 if ( InAxis == EAxis::X )
1894 {
1895 return TransformVectorNoScale(TVector<T>(1.f, 0.f, 0.f));
1896 }
1897 else if ( InAxis == EAxis::Y )
1898 {
1899 return TransformVectorNoScale(TVector<T>(0.f, 1.f, 0.f));
1900 }
1901
1902 return TransformVectorNoScale(TVector<T>(0.f, 0.f, 1.f));
1903}
1904
1905template<typename T>
1906inline void TTransform<T>::Mirror(EAxis::Type MirrorAxis, EAxis::Type FlipAxis)
1907{
1908 // We do convert to Matrix for mirroring.
1909 UE::Math::TMatrix<T> M = ToMatrixWithScale();
1910 M.Mirror(MirrorAxis, FlipAxis);
1911 SetFromMatrix(M);
1912}
1913
1916template<typename T>
1917inline float TTransform<T>::GetMaximumAxisScale() const
1918{
1919 DiagnosticCheckNaN_Scale3D();
1920
1921 float Scale3DAbsMax;
1922 // Scale3DAbsXYZ1 = { Abs(X), Abs(Y)), Abs(Z), 0 }
1923 const TransformVectorRegister Scale3DAbsXYZ0 = VectorAbs(Scale3D);
1924 // Scale3DAbsYZX1 = { Abs(Y),Abs(Z)),Abs(X), 0 }
1925 const TransformVectorRegister Scale3DAbsYZX0 = VectorSwizzle(Scale3DAbsXYZ0, 1,2,0,3);
1926 // Scale3DAbsZXY1 = { Abs(Z),Abs(X)),Abs(Y), 0 }
1927 const TransformVectorRegister Scale3DAbsZXY0 = VectorSwizzle(Scale3DAbsXYZ0, 2,0,1,3);
1928 // t0 = { Max(Abs(X), Abs(Y)), Max(Abs(Y), Abs(Z)), Max(Abs(Z), Abs(X)), 0 }
1929 const TransformVectorRegister t0 = VectorMax(Scale3DAbsXYZ0, Scale3DAbsYZX0);
1930 // t1 = { Max(Abs(X), Abs(Y), Abs(Z)), Max(Abs(Y), Abs(Z), Abs(X)), Max(Abs(Z), Abs(X), Abs(Y)), 0 }
1931 const TransformVectorRegister t2 = VectorMax(t0, Scale3DAbsZXY0);
1932 // Scale3DAbsMax = Max(Abs(X), Abs(Y), Abs(Z));
1934
1935 return Scale3DAbsMax;
1936}
1937
1939template<typename T>
1940inline float TTransform<T>::GetMinimumAxisScale() const
1941{
1942 DiagnosticCheckNaN_Scale3D();
1943
1944 float Scale3DAbsMin;
1945 // Scale3DAbsXYZ1 = { Abs(X), Abs(Y)), Abs(Z), 0 }
1946 const TransformVectorRegister Scale3DAbsXYZ0 = VectorAbs(Scale3D);
1947 // Scale3DAbsYZX1 = { Abs(Y),Abs(Z)),Abs(X), 0 }
1948 const TransformVectorRegister Scale3DAbsYZX0 = VectorSwizzle(Scale3DAbsXYZ0, 1,2,0,3);
1949 // Scale3DAbsZXY1 = { Abs(Z),Abs(X)),Abs(Y), 0 }
1950 const TransformVectorRegister Scale3DAbsZXY0 = VectorSwizzle(Scale3DAbsXYZ0, 2,0,1,3);
1951 // t0 = { Min(Abs(X), Abs(Y)), Min(Abs(Y), Abs(Z)), Min(Abs(Z), Abs(X)), 0 }
1952 const TransformVectorRegister t0 = VectorMin(Scale3DAbsXYZ0, Scale3DAbsYZX0);
1953 // t1 = { Min(Abs(X), Abs(Y), Abs(Z)), Min(Abs(Y), Abs(Z), Abs(X)), Min(Abs(Z), Abs(X), Abs(Y)), 0 }
1954 const TransformVectorRegister t2 = VectorMin(t0, Scale3DAbsZXY0);
1955 // Scale3DAbsMax = Min(Abs(X), Abs(Y), Abs(Z));
1957
1958 return Scale3DAbsMin;
1959}
1960
1968template<typename T>
1969inline TVector<T> TTransform<T>::GetSafeScaleReciprocal(const TVector<T>& InScale, T Tolerance)
1970{
1971 TVector<T> SafeReciprocalScale;
1972 if (FMath::Abs(InScale.X) <= Tolerance)
1973 {
1974 SafeReciprocalScale.X = 0.f;
1975 }
1976 else
1977 {
1978 SafeReciprocalScale.X = 1.f/InScale.X;
1979 }
1980
1981 if (FMath::Abs(InScale.Y) <= Tolerance)
1982 {
1983 SafeReciprocalScale.Y = 0.f;
1984 }
1985 else
1986 {
1987 SafeReciprocalScale.Y = 1.f/InScale.Y;
1988 }
1989
1990 if (FMath::Abs(InScale.Z) <= Tolerance)
1991 {
1992 SafeReciprocalScale.Z = 0.f;
1993 }
1994 else
1995 {
1996 SafeReciprocalScale.Z = 1.f/InScale.Z;
1997 }
1998
1999 return SafeReciprocalScale;
2000}
2001
2002
2003} // namespace UE::Math
2004} // namespace UE
2005
2006
2007#endif // ENABLE_VECTORIZED_TRANSFORM
#define checkSlow(expr)
Definition AssertionMacros.h:332
#define check(expr)
Definition AssertionMacros.h:314
#define ensure( InExpression)
Definition AssertionMacros.h:464
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
@ One
Definition PropertyPathHelpersTest.h:16
#define ScalarRegister
Definition ScalarRegister.h:239
USkinnedMeshComponent float
Definition SkinnedMeshComponent.h:60
VectorType TransformVector(const TransformType &Transform, const VectorType &Vector)
Definition TransformCalculus.h:367
FORCEINLINE VectorRegister4Float VectorSubtract(const VectorRegister4Float &Vec1, const VectorRegister4Float &Vec2)
Definition UnrealMathFPU.h:731
FORCEINLINE uint32 VectorAnyGreaterThan(const VectorRegister4Float &Vec1, const VectorRegister4Float &Vec2)
Definition UnrealMathFPU.h:1917
FORCEINLINE VectorRegister4Float VectorMin(const VectorRegister4Float &Vec1, const VectorRegister4Float &Vec2)
Definition UnrealMathFPU.h:1686
FORCEINLINE VectorRegister4Float VectorDot4(const VectorRegister4Float &Vec1, const VectorRegister4Float &Vec2)
Definition UnrealMathFPU.h:901
FORCEINLINE VectorRegister4Float MakeVectorRegister(uint32 X, uint32 Y, uint32 Z, uint32 W)
Definition UnrealMathFPU.h:195
FORCEINLINE VectorRegister4Float VectorSet_W1(const VectorRegister4Float &Vec)
Definition UnrealMathFPU.h:1407
#define VectorShuffle(Vec1, Vec2, X, Y, Z, W)
Definition UnrealMathFPU.h:652
FORCEINLINE VectorRegister4Float VectorMultiply(const VectorRegister4Float &Vec1, const VectorRegister4Float &Vec2)
Definition UnrealMathFPU.h:758
FORCEINLINE VectorRegister4Float VectorMax(const VectorRegister4Float &Vec1, const VectorRegister4Float &Vec2)
Definition UnrealMathFPU.h:1713
FORCEINLINE VectorRegister4Float VectorLoadFloat1(const float *Ptr)
Definition UnrealMathFPU.h:468
VectorRegister4Float VectorLoadAligned(const float *Ptr)
Definition UnrealMathFPU.h:451
FORCEINLINE VectorRegister4Float VectorMultiplyAdd(const VectorRegister4Float &Vec1, const VectorRegister4Float &Vec2, const VectorRegister4Float &Vec3)
Definition UnrealMathFPU.h:786
FORCEINLINE VectorRegister4Float VectorSelect(const VectorRegister4Float &Mask, const VectorRegister4Float &Vec1, const VectorRegister4Float &Vec2)
Definition UnrealMathFPU.h:1105
FORCEINLINE VectorRegister4Double VectorOneDouble(void)
Definition UnrealMathFPU.h:351
FORCEINLINE VectorRegister4Float VectorCompareGE(const VectorRegister4Float &Vec1, const VectorRegister4Float &Vec2)
Definition UnrealMathFPU.h:1000
FORCEINLINE VectorRegister4Double MakeVectorRegisterDouble(uint64 X, uint64 Y, uint64 Z, uint64 W)
Definition UnrealMathFPU.h:185
FORCEINLINE VectorRegister4Float VectorSet_W0(const VectorRegister4Float &Vec)
Definition UnrealMathFPU.h:1391
FORCEINLINE VectorRegister4Float VectorNegate(const VectorRegister4Float &Vec)
Definition UnrealMathFPU.h:687
FORCEINLINE VectorRegister4Float VectorAbs(const VectorRegister4Float &Vec)
Definition UnrealMathFPU.h:661
FORCEINLINE VectorRegister4Float VectorAdd(const VectorRegister4Float &Vec1, const VectorRegister4Float &Vec2)
Definition UnrealMathFPU.h:704
void VectorStoreAligned(const VectorRegister4Float &Vec, float *Ptr)
Definition UnrealMathFPU.h:534
#define VectorSwizzle(Vec, X, Y, Z, W)
Definition UnrealMathFPU.h:639
FORCEINLINE VectorRegister4Float VectorQuaternionMultiply2(const VectorRegister4Float &Quat1, const VectorRegister4Float &Quat2)
Definition UnrealMathFPU.h:1517
bool VectorContainsNaNOrInfinite(const VectorRegister4Float &Vec)
Definition UnrealMathFPU.h:1960
FORCEINLINE void VectorStoreFloat3(const VectorRegister4Float &Vec, float *Dst)
Definition UnrealMathFPU.h:594
FORCEINLINE void VectorStoreFloat1(const VectorRegister4Float &Vec, float *Dst)
Definition UnrealMathFPU.h:610
FORCEINLINE VectorRegister4Float MakeVectorRegisterFloatFromDouble(const VectorRegister4Double &Vec4d)
Definition UnrealMathFPU.h:262
#define VectorReplicate(Vec, ElementIndex)
Definition UnrealMathFPU.h:627
FORCEINLINE VectorRegister4Float VectorSign(const VectorRegister4Float &Vec)
Definition UnrealMathFPU.h:2204
#define UE_SMALL_NUMBER
Definition UnrealMathUtility.h:130
#define UE_KINDA_SMALL_NUMBER
Definition UnrealMathUtility.h:131
FORCEINLINE VectorRegister4Float VectorAccumulateQuaternionShortestPath(VectorRegister4Float A, VectorRegister4Float B)
Definition UnrealMathVectorCommon.h.inl:571
FORCEINLINE VectorRegister4Float VectorZero(void)
Definition UnrealMathVectorCommon.h.inl:16
FORCEINLINE VectorRegister4Float VectorReciprocalAccurate(VectorRegister4Float Vec)
Definition UnrealMathVectorCommon.h.inl:391
FORCEINLINE VectorRegister4Float VectorNormalizeSafe(VectorRegister4Float Vector, VectorRegister4Float DefaultValue)
Definition UnrealMathVectorCommon.h.inl:425
FORCEINLINE uint32 VectorAnyLesserThan(VectorRegister4Float Vec1, VectorRegister4Float Vec2)
Definition UnrealMathVectorCommon.h.inl:450
FORCEINLINE VectorRegister4Float VectorOne(void)
Definition UnrealMathVectorCommon.h.inl:21
FORCEINLINE VectorRegister4Float VectorQuaternionInverse(VectorRegister4Float NormalizedQuat)
Definition UnrealMathVectorCommon.h.inl:723
FORCEINLINE VectorRegister4Float VectorQuaternionRotateVector(VectorRegister4Float Quat, VectorRegister4Float VectorW0)
Definition UnrealMathVectorCommon.h.inl:741
FORCEINLINE VectorRegister4Float VectorQuaternionInverseRotateVector(VectorRegister4Float Quat, VectorRegister4Float VectorW0)
Definition UnrealMathVectorCommon.h.inl:783
FORCEINLINE VectorRegister4Float VectorLerpQuat(VectorRegister4Float A, VectorRegister4Float B, VectorRegister4Float Alpha)
Definition UnrealMathVectorCommon.h.inl:660
FORCEINLINE VectorRegister4Float VectorLoadFloat3_W0(const float *Ptr)
VectorLoadFloat3_W0.
Definition UnrealMathVectorCommon.h.inl:129
FORCEINLINE VectorRegister4Float VectorNormalizeQuaternion(VectorRegister4Float UnnormalizedQuat)
Definition UnrealMathVectorCommon.h.inl:600
#define ZERO_ANIMWEIGHT_THRESH
Definition VectorRegister.h:133
std::conditional_t< std::is_same_v< T, float >, PersistentVectorRegister4Float, std::conditional_t< std::is_same_v< T, double >, PersistentVectorRegister4Double, void > > TPersistentVectorRegisterType
Definition VectorRegister.h:115
typename UE::Math::VectorRegisterPrivate::TVectorRegisterTypeHelper< T >::Type TVectorRegisterType
Definition VectorRegister.h:49
uint32_t uint32
Definition binka_ue_file_header.h:6
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
constexpr VectorRegister4Float FloatZero
Definition UnrealMathVectorConstants.h.inl:41
constexpr VectorRegister4Float ThreshQuatNormalized
Definition UnrealMathVectorConstants.h.inl:54
constexpr VectorRegister4Float SmallNumber
Definition UnrealMathVectorConstants.h.inl:53
constexpr VectorRegister4Float FloatMinus1_111
Definition UnrealMathVectorConstants.h.inl:49
constexpr VectorRegister4Float Float0001
Definition UnrealMathVectorConstants.h.inl:43
constexpr VectorRegister4Float Float1110
Definition UnrealMathVectorConstants.h.inl:45
constexpr float Tolerance
Definition StaticMesh.cpp:310
UE_STRING_CLASS Result(Forward< LhsType >(Lhs), RhsLen)
Definition String.cpp.inl:732
Definition AdvancedWidgetsModule.cpp:13
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 > GetScaledAxis(EAxis::Type Axis) const
Definition Matrix.inl:647
void SetAxis(int32 i, const TVector< T > &Axis)
Definition Matrix.inl:691
TVector< T > GetOrigin() const
Definition Matrix.inl:641
void RemoveScaling(T Tolerance=UE_SMALL_NUMBER)
Definition Matrix.inl:435
static UE_FORCEINLINE_HINT TQuat< T > MakeFromRotator(const TRotator< T > &R)
Definition Quat.h:122
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
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
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 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
static TVector< T > GetSafeScaleReciprocal(const TVector< T > &InScale, FReal Tolerance=UE_SMALL_NUMBER)
Definition TransformNonVectorized.h:1603
UE_FORCEINLINE_HINT FReal GetDeterminant() const
Definition TransformNonVectorized.h:582
TTransform()
Definition TransformNonVectorized.h:113
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
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
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
TVector< T > GetTranslation() const
Definition TransformNonVectorized.h:1120
void SetIdentity()
Definition TransformNonVectorized.h:770
void CopyRotationPart(const TTransform< T > &SrcBA)
Definition TransformNonVectorized.h:1142
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
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
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
bool IsValid() const
Definition TransformNonVectorized.h:603
TMatrix< T > ToMatrixWithScale() const
Definition TransformNonVectorized.h:241
TQuat< T > GetRotation() const
Definition TransformNonVectorized.h:1109
bool SerializeFromMismatchedTag(FName StructTag, FArchive &Ar)
Definition TransformNonVectorized.h:633
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
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
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
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
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