UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
Quat.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"
9#include "Logging/LogMacros.h"
10#include "Math/MathFwd.h" // IWYU pragma: export
11#include "Math/Vector.h"
12#include "Math/VectorRegister.h"
13#include "Math/Rotator.h"
14#include "Math/Matrix.h"
17
18class Error;
19
20namespace UE
21{
22namespace Math
23{
24
37template<typename T>
38struct alignas(16) TQuat
39{
40 // Can't have a UE_REQUIRES in the declaration because of the forward declarations, so check for allowed types here.
41 static_assert(std::is_floating_point_v<T>, "TQuat only supports float and double types.");
42
43public:
45 using FReal = T;
47
49 T X;
50
52 T Y;
53
55 T Z;
56
58 T W;
59
60public:
61
64
65public:
66
68 [[nodiscard]] TQuat() = default;
69
76
85 [[nodiscard]] inline TQuat(T InX, T InY, T InZ, T InW);
86
90 template<typename DummyT = T UE_REQUIRES(std::is_arithmetic_v<T>)>
91 [[nodiscard]] explicit inline TQuat(T V)
92 : X(V)
93 , Y(V)
94 , Z(V)
95 , W(V)
96 {
98 }
99
100protected:
107
108public:
109
114
120 explicit TQuat(const TRotator<T>& R);
121
123 {
124 return TQuat<T>(R);
125 }
126
132 explicit TQuat(const TMatrix<T>& M);
133
141
142public:
143
151 [[nodiscard]] inline TQuat<T> operator+(const TQuat<T>& Q) const;
152
160 inline TQuat<T> operator+=(const TQuat<T>& Q);
161
169 [[nodiscard]] inline TQuat<T> operator-(const TQuat<T>& Q) const;
170
176 [[nodiscard]] inline TQuat<T> operator-() const;
177
185 [[nodiscard]] inline bool Equals(const TQuat<T>& Q, T Tolerance=UE_KINDA_SMALL_NUMBER) const;
186
195
203 inline TQuat<T> operator-=(const TQuat<T>& Q);
204
214 [[nodiscard]] inline TQuat<T> operator*(const TQuat<T>& Q) const;
215
225 inline TQuat<T> operator*=(const TQuat<T>& Q);
226
235
246
253 template<typename FArg UE_REQUIRES(std::is_arithmetic_v<FArg>)>
255 {
256#if PLATFORM_ENABLE_VECTORINTRINSICS
260#else
261 X *= Scale;
262 Y *= Scale;
263 Z *= Scale;
264 W *= Scale;
265#endif // PLATFORM_ENABLE_VECTORINTRINSICS
266
268 return *this;
269 }
270
277 template<typename FArg UE_REQUIRES(std::is_arithmetic_v<FArg>)>
278 [[nodiscard]] inline TQuat<T> operator*(const FArg Scale) const
279 {
280#if PLATFORM_ENABLE_VECTORINTRINSICS
283 return TQuat(VectorMultiply(A, B));
284#else
285 return TQuat(Scale * X, Scale * Y, Scale * Z, Scale * W);
286#endif // PLATFORM_ENABLE_VECTORINTRINSICS
287 }
288
295 template<typename FArg UE_REQUIRES(std::is_arithmetic_v<FArg>)>
297 {
298#if PLATFORM_ENABLE_VECTORINTRINSICS
302#else
303 const T Recip = T(1.0f) / Scale;
304 X *= Recip;
305 Y *= Recip;
306 Z *= Recip;
307 W *= Recip;
308#endif // PLATFORM_ENABLE_VECTORINTRINSICS
309
311 return *this;
312 }
313
320 template<typename FArg UE_REQUIRES(std::is_arithmetic_v<FArg>)>
321 [[nodiscard]] inline TQuat<T> operator/(const FArg Scale) const
322 {
323#if PLATFORM_ENABLE_VECTORINTRINSICS
326 return TQuat(VectorDivide(A, B));
327#else
328 const T Recip = 1.0f / Scale;
329 return TQuat(X * Recip, Y * Recip, Z * Recip, W * Recip);
330#endif // PLATFORM_ENABLE_VECTORINTRINSICS
331 }
332
337 [[nodiscard]] bool Identical(const TQuat* Q, const uint32 PortFlags) const;
338
348 [[nodiscard]] bool operator==(const TQuat<T>& Q) const;
349
356 [[nodiscard]] bool operator!=(const TQuat<T>& Q) const;
357
364 [[nodiscard]] T operator|(const TQuat<T>& Q) const;
365
366public:
367
375
378
385 inline void Normalize(T Tolerance = UE_SMALL_NUMBER);
386
393 [[nodiscard]] inline TQuat<T> GetNormalized(T Tolerance = UE_SMALL_NUMBER) const;
394
395 // Return true if this quaternion is normalized
396 [[nodiscard]] bool IsNormalized() const;
397
404
411
418
428 void ToAxisAndAngle(TVector<T>& Axis, float& Angle) const;
429 void ToAxisAndAngle(TVector<T>& Axis, double& Angle) const;
430
440
447
457
465 [[nodiscard]] CORE_API T GetTwistAngle(const TVector<T>& TwistAxis) const;
466
474
482
488 [[nodiscard]] CORE_API TQuat<T> Log() const;
489
495 [[nodiscard]] CORE_API TQuat<T> Exp() const;
496
502
508
514
517
520
523
526
529
532
535
538
541
543 CORE_API void ToMatrix(TMatrix<T>& Mat) const;
544
551
553 [[nodiscard]] T AngularDistance(const TQuat<T>& Q) const;
554
560 CORE_API bool NetSerialize(FArchive& Ar, class UPackageMap* Map, bool& bOutSuccess);
561
567 [[nodiscard]] bool ContainsNaN() const;
568
574 [[nodiscard]] FString ToString() const;
575
584 bool InitFromString(const FString& InSourceString);
585
586public:
587
588#if ENABLE_NAN_DIAGNOSTIC
589 inline void DiagnosticCheckNaN() const
590 {
591 if (ContainsNaN())
592 {
593 logOrEnsureNanError(TEXT("Quat contains NaN: %s"), *ToString());
594 *const_cast<TQuat*>(this) = TQuat<T>(0.f, 0.f, 0.f, 1.f);
595 }
596 }
597
598 inline void DiagnosticCheckNaN(const TCHAR* Message) const
599 {
600 if (ContainsNaN())
601 {
602 logOrEnsureNanError(TEXT("%s: Quat contains NaN: %s"), Message, *ToString());
603 *const_cast<TQuat*>(this) = TQuat<T>(0.f, 0.f, 0.f, 1.f);
604 }
605 }
606#else
608 UE_FORCEINLINE_HINT void DiagnosticCheckNaN(const TCHAR* Message) const {}
609#endif
610
611public:
612
620
625
630
636 [[nodiscard]] static inline T Error(const TQuat<T>& Q1, const TQuat<T>& Q2);
637
641 [[nodiscard]] static inline T ErrorAutoNormalize(const TQuat<T>& A, const TQuat<T>& B);
642
647 [[nodiscard]] static inline TQuat<T> FastLerp(const TQuat<T>& A, const TQuat<T>& B, const T Alpha);
648
653 [[nodiscard]] static inline TQuat<T> FastBilerp(const TQuat<T>& P00, const TQuat<T>& P10, const TQuat<T>& P01, const TQuat<T>& P11, T FracX, T FracY);
654
655
658
661 {
662 return Slerp_NotNormalized(Quat1, Quat2, Slerp).GetNormalized();
663 }
664
671
678 {
679 return SlerpFullPath_NotNormalized(quat1, quat2, Alpha).GetNormalized();
680 }
681
686 [[nodiscard]] static CORE_API TQuat<T> Squad(const TQuat<T>& quat1, const TQuat<T>& tang1, const TQuat<T>& quat2, const TQuat<T>& tang2, T Alpha);
687
692 [[nodiscard]] static CORE_API TQuat<T> SquadFullPath(const TQuat<T>& quat1, const TQuat<T>& tang1, const TQuat<T>& quat2, const TQuat<T>& tang2, T Alpha);
693
703 static CORE_API void CalcTangents(const TQuat<T>& PrevP, const TQuat<T>& P, const TQuat<T>& NextP, T Tension, TQuat<T>& OutTan);
704
706
707 // Converts to euler angles (in rads) in verse conventions
709
710public:
711
713 {
714 Ar << (TQuat<T>&)*this;
715 return true;
716 }
717
719 {
720 if constexpr (std::is_same_v<T, float>)
721 {
722 return UE_SERIALIZE_VARIANT_FROM_MISMATCHED_TAG(Ar, Quat, Quat4f, Quat4d);
723 }
724 else
725 {
726 return UE_SERIALIZE_VARIANT_FROM_MISMATCHED_TAG(Ar, Quat, Quat4d, Quat4f);
727 }
728 }
729
730 // Conversion to other type.
731 template<typename FArg UE_REQUIRES(!std::is_same_v<T, FArg>)>
732 explicit TQuat(const TQuat<FArg>& From)
733 : TQuat<T>((T)From.X, (T)From.Y, (T)From.Z, (T)From.W)
734 {
735 }
736};
737
746{
747 return Ar << F.X << F.Y << F.Z << F.W;
748}
749
751{
753 {
754 return Ar << F.X << F.Y << F.Z << F.W;
755 }
756 else
757 {
758 checkf(Ar.IsLoading(), TEXT("float -> double conversion applied outside of load!"));
759 // Stored as floats, so serialize float and copy.
760 float X, Y, Z, W;
761 Ar << X << Y << Z << W;
762 if(Ar.IsLoading())
763 {
764 F = TQuat<double>(X, Y, Z, W);
765 }
766 }
767 return Ar;
768}
769
770#if !defined(_MSC_VER) || defined(__clang__) // MSVC can't forward declare explicit specializations
771template<> CORE_API const FQuat4f FQuat4f::Identity;
772template<> CORE_API const FQuat4d FQuat4d::Identity;
773#endif
774/* TQuat inline functions
775 *****************************************************************************/
776template<typename T>
778{
779 // If Matrix is NULL, return Identity quaternion. If any of them is 0, you won't be able to construct rotation
780 // if you have two plane at least, we can reconstruct the frame using cross product, but that's a bit expensive op to do here
781 // for now, if you convert to matrix from 0 scale and convert back, you'll lose rotation. Don't do that.
782 if (M.GetScaledAxis(EAxis::X).IsNearlyZero() || M.GetScaledAxis(EAxis::Y).IsNearlyZero() || M.GetScaledAxis(EAxis::Z).IsNearlyZero())
783 {
784 *this = TQuat<T>::Identity;
785 return;
786 }
787
788#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
789 // Make sure the Rotation part of the Matrix is unit length.
790 // Changed to this (same as RemoveScaling) from RotDeterminant as using two different ways of checking unit length matrix caused inconsistency.
791 if (!ensure((FMath::Abs(1.f - M.GetScaledAxis(EAxis::X).SizeSquared()) <= UE_KINDA_SMALL_NUMBER) && (FMath::Abs(1.f - M.GetScaledAxis(EAxis::Y).SizeSquared()) <= UE_KINDA_SMALL_NUMBER) && (FMath::Abs(1.f - M.GetScaledAxis(EAxis::Z).SizeSquared()) <= UE_KINDA_SMALL_NUMBER)))
792 {
793 *this = TQuat<T>::Identity;
794 return;
795 }
796#endif
797
798 //const MeReal *const t = (MeReal *) tm;
799 T s;
800
801 // Check diagonal (trace)
802 const T tr = M.M[0][0] + M.M[1][1] + M.M[2][2];
803
804 if (tr > 0.0f)
805 {
806 T InvS = FMath::InvSqrt(tr + T(1.f));
807 this->W = T(T(0.5f) * (T(1.f) / InvS));
808 s = T(0.5f) * InvS;
809
810 this->X = ((M.M[1][2] - M.M[2][1]) * s);
811 this->Y = ((M.M[2][0] - M.M[0][2]) * s);
812 this->Z = ((M.M[0][1] - M.M[1][0]) * s);
813 }
814 else
815 {
816 // diagonal is negative
817 int32 i = 0;
818
819 if (M.M[1][1] > M.M[0][0])
820 i = 1;
821
822 if (M.M[2][2] > M.M[i][i])
823 i = 2;
824
825 static constexpr int32 nxt[3] = { 1, 2, 0 };
826 const int32 j = nxt[i];
827 const int32 k = nxt[j];
828
829 s = M.M[i][i] - M.M[j][j] - M.M[k][k] + T(1.0f);
830
831 T InvS = FMath::InvSqrt(s);
832
833 T qt[4];
834 qt[i] = T(0.5f) * (T(1.f) / InvS);
835
836 s = T(0.5f) * InvS;
837
838 qt[3] = (M.M[j][k] - M.M[k][j]) * s;
839 qt[j] = (M.M[i][j] + M.M[j][i]) * s;
840 qt[k] = (M.M[i][k] + M.M[k][i]) * s;
841
842 this->X = qt[0];
843 this->Y = qt[1];
844 this->Z = qt[2];
845 this->W = qt[3];
846
847 DiagnosticCheckNaN();
848 }
849}
850
851
852template<typename T>
854{
855 *this = R.Quaternion();
856 DiagnosticCheckNaN();
857}
858
859template<typename T>
861{
862 return RotateVector(V);
863}
864
865/* TQuat inline functions
866 *****************************************************************************/
867
868template<typename T>
872
873template<typename T>
874inline TQuat<T>::TQuat(T InX, T InY, T InZ, T InW)
875 : X(InX)
876 , Y(InY)
877 , Z(InZ)
878 , W(InW)
879{
880 static_assert(TIsFloatingPoint<T>::Value);
882}
883
884template<typename T>
886{
887 VectorStoreAligned(V, this);
888 DiagnosticCheckNaN();
889}
890
891
892template<typename T>
894{
895 return FString::Printf(TEXT("X=%.9f Y=%.9f Z=%.9f W=%.9f"), X, Y, Z, W);
896}
897
898template<typename T>
899inline bool TQuat<T>::InitFromString(const FString& InSourceString)
900{
901 X = Y = Z = 0.f;
902 W = 1.f;
903
904 const bool bSuccess
908 && FParse::Value(*InSourceString, TEXT("W="), W);
909 DiagnosticCheckNaN();
910 return bSuccess;
911}
912
913template<typename T>
915{
916 const T half_a = 0.5f * AngleRad;
917 T s, c;
918 FMath::SinCos(&s, &c, half_a);
919
920 X = s * Axis.X;
921 Y = s * Axis.Y;
922 Z = s * Axis.Z;
923 W = c;
924
925 DiagnosticCheckNaN();
926}
927
928
929template<typename T>
931{
932#if PLATFORM_ENABLE_VECTORINTRINSICS
935 return TQuat(VectorAdd(A, B));
936#else
937 return TQuat(X + Q.X, Y + Q.Y, Z + Q.Z, W + Q.W);
938#endif // PLATFORM_ENABLE_VECTORINTRINSICS
939}
940
941
942template<typename T>
944{
945#if PLATFORM_ENABLE_VECTORINTRINSICS
949#else
950 this->X += Q.X;
951 this->Y += Q.Y;
952 this->Z += Q.Z;
953 this->W += Q.W;
954#endif // PLATFORM_ENABLE_VECTORINTRINSICS
955
956 DiagnosticCheckNaN();
957
958 return *this;
959}
960
961
962template<typename T>
964{
965#if PLATFORM_ENABLE_VECTORINTRINSICS
968 return TQuat(VectorSubtract(A, B));
969#else
970 return TQuat(X - Q.X, Y - Q.Y, Z - Q.Z, W - Q.W);
971#endif // PLATFORM_ENABLE_VECTORINTRINSICS
972}
973
974template<typename T>
976{
977#if PLATFORM_ENABLE_VECTORINTRINSICS
978 return TQuat(VectorNegate(VectorLoadAligned(this)));
979#else
980 return TQuat(-X, -Y, -Z, -W);
981#endif
982}
983
984template<typename T>
985inline bool TQuat<T>::Equals(const TQuat<T>& Q, T Tolerance) const
986{
987#if PLATFORM_ENABLE_VECTORINTRINSICS
991
995#else
996 return (FMath::Abs(X - Q.X) <= Tolerance && FMath::Abs(Y - Q.Y) <= Tolerance && FMath::Abs(Z - Q.Z) <= Tolerance && FMath::Abs(W - Q.W) <= Tolerance)
997 || (FMath::Abs(X + Q.X) <= Tolerance && FMath::Abs(Y + Q.Y) <= Tolerance && FMath::Abs(Z + Q.Z) <= Tolerance && FMath::Abs(W + Q.W) <= Tolerance);
998#endif // PLATFORM_ENABLE_VECTORINTRINSICS
999}
1000
1001template<typename T>
1003{
1004 return Equals(TQuat<T>::Identity, Tolerance);
1005}
1006
1007template<typename T>
1009{
1010#if PLATFORM_ENABLE_VECTORINTRINSICS
1014#else
1015 this->X -= Q.X;
1016 this->Y -= Q.Y;
1017 this->Z -= Q.Z;
1018 this->W -= Q.W;
1019#endif // PLATFORM_ENABLE_VECTORINTRINSICS
1020
1021 DiagnosticCheckNaN();
1022
1023 return *this;
1024}
1025
1026
1027template<typename T>
1029{
1030 TQuat<T> Result;
1031 VectorQuaternionMultiply(&Result, this, &Q);
1032
1033 Result.DiagnosticCheckNaN();
1034
1035 return Result;
1036}
1037
1038
1039template<typename T>
1041{
1045 VectorStoreAligned(Result, this);
1046
1047 DiagnosticCheckNaN();
1048
1049 return *this;
1050}
1051
1052
1053// Global operator for (float * Quat)
1054template<typename T>
1056{
1057 return Q.operator*(Scale);
1058}
1059
1060// Global operator for (double * Quat)
1061template<typename T>
1063{
1064 return Q.operator*(Scale);
1065}
1066
1067template<typename T>
1068UE_FORCEINLINE_HINT bool TQuat<T>::Identical(const TQuat* Q, const uint32 PortFlags) const
1069{
1070 return X == Q->X && Y == Q->Y && Z == Q->Z && W == Q->W;
1071}
1072
1073template<typename T>
1074inline bool TQuat<T>::operator==(const TQuat<T>& Q) const
1075{
1076#if PLATFORM_ENABLE_VECTORINTRINSICS
1079 return VectorMaskBits(VectorCompareEQ(A, B)) == 0x0F;
1080#else
1081 return X == Q.X && Y == Q.Y && Z == Q.Z && W == Q.W;
1082#endif // PLATFORM_ENABLE_VECTORINTRINSICS
1083}
1084
1085
1086template<typename T>
1087inline bool TQuat<T>::operator!=(const TQuat<T>& Q) const
1088{
1089#if PLATFORM_ENABLE_VECTORINTRINSICS
1092 return VectorMaskBits(VectorCompareNE(A, B)) != 0x00;
1093#else
1094 return X != Q.X || Y != Q.Y || Z != Q.Z || W != Q.W;
1095#endif // PLATFORM_ENABLE_VECTORINTRINSICS
1096}
1097
1098
1099template<typename T>
1101{
1102 return X * Q.X + Y * Q.Y + Z * Q.Z + W * Q.W;
1103}
1104
1105
1106template<typename T>
1107inline void TQuat<T>::Normalize(T Tolerance)
1108{
1109#if PLATFORM_ENABLE_VECTORINTRINSICS
1111
1115 const QuatVectorRegister NormalizedVector = VectorMultiply(InvLength, Vector);
1117
1118 VectorStoreAligned(Result, this);
1119#else
1120 const T SquareSum = X * X + Y * Y + Z * Z + W * W;
1121
1122 if (SquareSum >= Tolerance)
1123 {
1124 const T Scale = FMath::InvSqrt(SquareSum);
1125
1126 X *= Scale;
1127 Y *= Scale;
1128 Z *= Scale;
1129 W *= Scale;
1130 }
1131 else
1132 {
1133 *this = TQuat<T>::Identity;
1134 }
1135#endif // PLATFORM_ENABLE_VECTORINTRINSICS
1136}
1137
1138
1139template<typename T>
1140inline TQuat<T> TQuat<T>::GetNormalized(T Tolerance) const
1141{
1142 TQuat<T> Result(*this);
1143 Result.Normalize(Tolerance);
1144 return Result;
1145}
1146
1147
1148template<typename T>
1149inline bool TQuat<T>::IsNormalized() const
1150{
1151#if PLATFORM_ENABLE_VECTORINTRINSICS
1155#else
1156 return (FMath::Abs(1.f - SizeSquared()) < UE_THRESH_QUAT_NORMALIZED);
1157#endif // PLATFORM_ENABLE_VECTORINTRINSICS
1158}
1159
1160
1161template<typename T>
1163{
1164 return FMath::Sqrt(X * X + Y * Y + Z * Z + W * W);
1165}
1166
1167template<typename T>
1169{
1170 return (X * X + Y * Y + Z * Z + W * W);
1171}
1172
1173template<typename T>
1175{
1176 return T(2.0) * FMath::Acos(W);
1177}
1178
1179
1180template<typename T>
1182{
1183 Angle = (float)GetAngle();
1184 Axis = GetRotationAxis();
1185}
1186
1187template<typename T>
1188inline void TQuat<T>::ToAxisAndAngle(TVector<T>& Axis, double& Angle) const
1189{
1190 Angle = (double)GetAngle();
1191 Axis = GetRotationAxis();
1192}
1193
1194template<typename T>
1196{
1197 checkSlow(IsNormalized());
1198 TQuat<T> RotQ = Log();
1199 return TVector<T>(RotQ.X * 2.0f, RotQ.Y * 2.0f, RotQ.Z * 2.0f);
1200}
1201
1202template<typename T>
1204{
1205 TQuat<T> RotQ(RotationVector.X * 0.5f, RotationVector.Y * 0.5f, RotationVector.Z * 0.5f, 0.0f);
1206 return RotQ.Exp();
1207}
1208
1209template<typename T>
1211{
1212#if PLATFORM_ENABLE_VECTORINTRINSICS
1213 TVector<T> V;
1216 VectorStoreFloat3(R, &V);
1217 return V;
1218#else
1219 const T SquareSum = X * X + Y * Y + Z * Z;
1221 {
1223 }
1224 const T Scale = FMath::InvSqrt(SquareSum);
1225 return TVector<T>(X * Scale, Y * Scale, Z * Scale);
1226#endif // PLATFORM_ENABLE_VECTORINTRINSICS
1227}
1228
1229template<typename T>
1231{
1232 T InnerProd = X*Q.X + Y*Q.Y + Z*Q.Z + W*Q.W;
1233 return FMath::Acos((2 * InnerProd * InnerProd) - 1.f);
1234}
1235
1236
1237template<typename T>
1239{
1240 // http://people.csail.mit.edu/bkph/articles/Quaternions.pdf
1241 // V' = V + 2w(Q x V) + (2Q x (Q x V))
1242 // refactor:
1243 // V' = V + w(2(Q x V)) + (Q x (2(Q x V)))
1244 // T = 2(Q x V);
1245 // V' = V + w*(T) + (Q x T)
1246
1247 const TVector<T> Q(X, Y, Z);
1248 const TVector<T> TT = 2.f * TVector<T>::CrossProduct(Q, V);
1249 const TVector<T> Result = V + (W * TT) + TVector<T>::CrossProduct(Q, TT);
1250 return Result;
1251}
1252
1253template<typename T>
1255{
1256 const TVector<T> Q(-X, -Y, -Z); // Inverse
1257 const TVector<T> TT = 2.f * TVector<T>::CrossProduct(Q, V);
1258 const TVector<T> Result = V + (W * TT) + TVector<T>::CrossProduct(Q, TT);
1259 return Result;
1260}
1261
1262
1263template<typename T>
1265{
1266 checkSlow(IsNormalized());
1267
1268#if PLATFORM_ENABLE_VECTORINTRINSICS
1270#else
1271 return TQuat(-X, -Y, -Z, W);
1272#endif // PLATFORM_ENABLE_VECTORINTRINSICS
1273}
1274
1275template<typename T>
1277{
1278 const T DotResult = (OtherQuat | *this);
1279 const T Bias = FMath::FloatSelect(DotResult, T(1.0f), T(-1.0f));
1280
1281 X *= Bias;
1282 Y *= Bias;
1283 Z *= Bias;
1284 W *= Bias;
1285}
1286
1287template<typename T>
1289{
1290 TQuat<T> Result(*this);
1291 Result.EnforceShortestArcWith(OtherQuat);
1292 return Result;
1293}
1294
1295template<typename T>
1297{
1298 return RotateVector(TVector<T>(1.f, 0.f, 0.f));
1299}
1300
1301
1302template<typename T>
1304{
1305 return RotateVector(TVector<T>(0.f, 1.f, 0.f));
1306}
1307
1308
1309template<typename T>
1311{
1312 return RotateVector(TVector<T>(0.f, 0.f, 1.f));
1313}
1314
1315
1316template<typename T>
1318{
1319 return GetAxisX();
1320}
1321
1322template<typename T>
1324{
1325 return GetAxisY();
1326}
1327
1328template<typename T>
1330{
1331 return GetAxisZ();
1332}
1333
1334template<typename T>
1336{
1337 return GetAxisX();
1338}
1339
1340template<typename T>
1342{
1343 TMatrix<T> R;
1344 ToMatrix(R);
1345 return R;
1346}
1347
1348template<typename T>
1349inline T TQuat<T>::Error(const TQuat<T>& Q1, const TQuat<T>& Q2)
1350{
1351 const T cosom = FMath::Abs(Q1.X * Q2.X + Q1.Y * Q2.Y + Q1.Z * Q2.Z + Q1.W * Q2.W);
1352 return (FMath::Abs(cosom) < 0.9999999f) ? FMath::Acos(cosom)*(1.f / UE_PI) : 0.0f;
1353}
1354
1355
1356template<typename T>
1358{
1359 TQuat<T> Q1 = A;
1360 Q1.Normalize();
1361
1362 TQuat<T> Q2 = B;
1363 Q2.Normalize();
1364
1365 return TQuat<T>::Error(Q1, Q2);
1366}
1367
1372template<typename T>
1373inline TQuat<T> TQuat<T>::FastLerp(const TQuat<T>& A, const TQuat<T>& B, const T Alpha)
1374{
1375 // To ensure the 'shortest route', we make sure the dot product between the both rotations is positive.
1376 const T DotResult = (A | B);
1377 const T Bias = FMath::FloatSelect(DotResult, T(1.0f), T(-1.0f));
1378 return (B * Alpha) + (A * (Bias * (1.f - Alpha)));
1379}
1380
1381
1382template<typename T>
1384{
1385 return TQuat<T>::FastLerp(
1388 FracY
1389 );
1390}
1391
1392
1393template<typename T>
1394inline bool TQuat<T>::ContainsNaN() const
1395{
1396 return (!FMath::IsFinite(X) ||
1397 !FMath::IsFinite(Y) ||
1398 !FMath::IsFinite(Z) ||
1399 !FMath::IsFinite(W)
1400 );
1401}
1402
1409template<typename T>
1411{
1412 // Note: this assumes there's no padding in Quat that could contain uncompared data.
1413 static_assert(sizeof(TQuat<T>) == sizeof(T[4]), "Unexpected padding in TQuat");
1414 return FCrc::MemCrc_DEPRECATED(&Quat, sizeof(Quat));
1415}
1416
1417template<typename T>
1419{
1420 auto ThreeAxisRot = [](T R11, T R12, T R21, T R31, T R32, T Euler[])
1421 {
1422 Euler[0] = FMath::Atan2(R31, R32);
1423 Euler[1] = FMath::Asin(R21);
1424 Euler[2] = FMath::Atan2(R11, R12);
1425 };
1426
1427 T Euler[3];
1428 ThreeAxisRot(2*(Y*Z + W*X),
1429 W*W - X*X + Y*Y - Z*Z,
1430 -2*(X*Y - W*Z),
1431 2*(X*Z + W*Y),
1432 W*W + X*X - Y*Y - Z*Z,
1433 Euler);
1434 // Going from left-handed to right-handed
1435 return {Euler[0], -Euler[1], -Euler[2]};
1436}
1437
1438template<typename T>
1451
1452} // namespace UE::Math
1453} // namespace UE
1454
1456
1457template<> struct TIsPODType<FQuat4f> { enum { Value = true }; };
1458template<> struct TIsPODType<FQuat4d> { enum { Value = true }; };
1459template<> struct TIsUECoreVariant<FQuat4f> { enum { Value = true }; };
1460template<> struct TIsUECoreVariant<FQuat4d> { enum { Value = true }; };
1461template<> struct TCanBulkSerialize<FQuat4f> { enum { Value = true }; };
1462template<> struct TCanBulkSerialize<FQuat4d> { enum { Value = true }; };
1465
1466// Forward declare all explicit specializations (in UnrealMath.cpp)
1467template<> CORE_API FRotator3f FQuat4f::Rotator() const;
1468template<> CORE_API FRotator3d FQuat4d::Rotator() const;
1469
1470
1471/* FMath inline functions
1472 *****************************************************************************/
1473
1474 // TCustomLerp for FMath::Lerp()
1475template<typename T>
1476struct TCustomLerp< UE::Math::TQuat<T> >
1477{
1478 constexpr static bool Value = true;
1480
1481 template<class U>
1482 static UE_FORCEINLINE_HINT QuatType Lerp(const QuatType& A, const QuatType& B, const U& Alpha)
1483 {
1484 return QuatType::Slerp(A, B, (T)Alpha);
1485 }
1486
1487 template<class U>
1488 static inline QuatType BiLerp(const QuatType& P00, const QuatType& P10, const QuatType& P01, const QuatType& P11, const U& FracX, const U& FracY)
1489 {
1490 QuatType Result;
1491
1492 Result = Lerp(
1493 QuatType::Slerp_NotNormalized(P00, P10, (T)FracX),
1494 QuatType::Slerp_NotNormalized(P01, P11, (T)FracX),
1495 (T)FracY
1496 );
1497
1498 return Result;
1499 }
1500
1501 template<class U>
1502 static UE_FORCEINLINE_HINT QuatType CubicInterp(const QuatType& P0, const QuatType& T0, const QuatType& P1, const QuatType& T1, const U& A)
1503 {
1504 return QuatType::Squad(P0, T0, P1, T1, (T)A);
1505 }
1506
1507};
#define checkSlow(expr)
Definition AssertionMacros.h:332
#define ensure( InExpression)
Definition AssertionMacros.h:464
#define checkf(expr, format,...)
Definition AssertionMacros.h:315
bool bSuccess
Definition ConvexDecomposition3.cpp:819
EForceInit
Definition CoreMiscDefines.h:154
@ ForceInitToZero
Definition CoreMiscDefines.h:156
#define TEXT(x)
Definition Platform.h:1272
FPlatformTypes::TCHAR TCHAR
Either ANSICHAR or WIDECHAR, depending on whether the platform supports wide characters or the requir...
Definition Platform.h:1135
FPlatformTypes::int32 int32
A 32-bit signed integer.
Definition Platform.h:1125
#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 X(Name, Desc)
Definition FormatStringSan.h:47
#define UE_SERIALIZE_VARIANT_FROM_MISMATCHED_TAG(AR_OR_SLOT, ALIAS, TYPE, ALT_TYPE)
Definition LargeWorldCoordinatesSerializer.h:9
#define UE_DECLARE_LWC_TYPE(...)
Definition LargeWorldCoordinates.h:27
#define logOrEnsureNanError(_FormatString_,...)
Definition LogMacros.h:436
#define DECLARE_INTRINSIC_TYPE_LAYOUT(T)
Definition MemoryLayout.h:760
USkinnedMeshComponent float
Definition SkinnedMeshComponent.h:60
auto ToMatrix(const TransformType &Transform) -> decltype(Transform.ToMatrix())
Definition TransformCalculus3D.h:99
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 VectorDot4(const VectorRegister4Float &Vec1, const VectorRegister4Float &Vec2)
Definition UnrealMathFPU.h:901
FORCEINLINE VectorRegister4Float VectorSetFloat1(float F)
Definition UnrealMathFPU.h:518
FORCEINLINE void VectorQuaternionMultiply(VectorRegister4Float *RESTRICT Result, const VectorRegister4Float *RESTRICT Quat1, const VectorRegister4Float *RESTRICT Quat2)
Definition UnrealMathFPU.h:1431
FORCEINLINE VectorRegister4Float VectorDivide(const VectorRegister4Float &Vec1, const VectorRegister4Float &Vec2)
Definition UnrealMathFPU.h:834
FORCEINLINE VectorRegister4Float VectorMultiply(const VectorRegister4Float &Vec1, const VectorRegister4Float &Vec2)
Definition UnrealMathFPU.h:758
FORCEINLINE VectorRegister4Float VectorLoadFloat1(const float *Ptr)
Definition UnrealMathFPU.h:468
VectorRegister4Float VectorLoadAligned(const float *Ptr)
Definition UnrealMathFPU.h:451
FORCEINLINE VectorRegister4Float VectorSelect(const VectorRegister4Float &Mask, const VectorRegister4Float &Vec1, const VectorRegister4Float &Vec2)
Definition UnrealMathFPU.h:1105
FORCEINLINE VectorRegister4Float VectorCompareGE(const VectorRegister4Float &Vec1, const VectorRegister4Float &Vec2)
Definition UnrealMathFPU.h:1000
FORCEINLINE VectorRegister4Float VectorSet_W0(const VectorRegister4Float &Vec)
Definition UnrealMathFPU.h:1391
FORCEINLINE int32 VectorMaskBits(const VectorRegister4Float &Vec1)
Definition UnrealMathFPU.h:1075
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
FORCEINLINE VectorRegister4Float VectorQuaternionMultiply2(const VectorRegister4Float &Quat1, const VectorRegister4Float &Quat2)
Definition UnrealMathFPU.h:1517
FORCEINLINE void VectorStoreFloat3(const VectorRegister4Float &Vec, float *Dst)
Definition UnrealMathFPU.h:594
FORCEINLINE VectorRegister4Float VectorCompareEQ(const VectorRegister4Float &Vec1, const VectorRegister4Float &Vec2)
Definition UnrealMathFPU.h:923
FORCEINLINE VectorRegister4Float VectorCompareNE(const VectorRegister4Float &Vec1, const VectorRegister4Float &Vec2)
Definition UnrealMathFPU.h:948
#define UE_PI
Definition UnrealMathUtility.h:129
#define UE_SMALL_NUMBER
Definition UnrealMathUtility.h:130
#define UE_THRESH_QUAT_NORMALIZED
Definition UnrealMathUtility.h:215
#define UE_KINDA_SMALL_NUMBER
Definition UnrealMathUtility.h:131
FORCEINLINE VectorRegister4Float VectorNormalizeSafe(VectorRegister4Float Vector, VectorRegister4Float DefaultValue)
Definition UnrealMathVectorCommon.h.inl:425
FORCEINLINE VectorRegister4Float VectorOne(void)
Definition UnrealMathVectorCommon.h.inl:21
FORCEINLINE VectorRegister4Float VectorQuaternionInverse(VectorRegister4Float NormalizedQuat)
Definition UnrealMathVectorCommon.h.inl:723
FORCEINLINE VectorRegister4Float VectorReciprocalSqrtAccurate(VectorRegister4Float Vec)
Definition UnrealMathVectorCommon.h.inl:375
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
UE_FORCEINLINE_HINT bool IsLoading() const
Definition Archive.h:236
UE_FORCEINLINE_HINT FPackageFileVersion UEVer() const
Definition Archive.h:204
Definition NameTypes.h:617
Definition CoreNet.h:191
@ Z
Definition Axis.h:15
@ Y
Definition Axis.h:14
@ X
Definition Axis.h:13
constexpr VectorRegister4Float ThreshQuatNormalized
Definition UnrealMathVectorConstants.h.inl:54
constexpr VectorRegister4Float Float1000
Definition UnrealMathVectorConstants.h.inl:44
constexpr VectorRegister4Float Float0001
Definition UnrealMathVectorConstants.h.inl:43
uint32 GetTypeHash(const TBox< T > &Box)
Definition Box.h:1008
FArchive & operator<<(FArchive &Ar, TBoxSphereBounds< float, float > &Bounds)
Definition BoxSphereBounds.h:396
UE_FORCEINLINE_HINT TQuat< T > operator*(const float Scale, const TQuat< T > &Q)
Definition Quat.h:1055
Definition AdvancedWidgetsModule.cpp:13
static CORE_API uint32 MemCrc_DEPRECATED(const void *Data, int32 Length, uint32 CRC=0)
Definition Crc.cpp:592
static constexpr void SinCos(std::decay_t< T > *ScalarSin, std::decay_t< T > *ScalarCos, T Value)
Definition UnrealMathUtility.h:753
static CORE_API bool Value(const TCHAR *Stream, const TCHAR *Match, FName &Name)
Definition Parse.cpp:584
Definition Array.h:45
@ Value
Definition Array.h:46
static UE_FORCEINLINE_HINT QuatType CubicInterp(const QuatType &P0, const QuatType &T0, const QuatType &P1, const QuatType &T1, const U &A)
Definition Quat.h:1502
static QuatType BiLerp(const QuatType &P00, const QuatType &P10, const QuatType &P01, const QuatType &P11, const U &FracX, const U &FracY)
Definition Quat.h:1488
static UE_FORCEINLINE_HINT QuatType Lerp(const QuatType &A, const QuatType &B, const U &Alpha)
Definition Quat.h:1482
Definition UnrealMathUtility.h:261
static constexpr bool Value
Definition UnrealMathUtility.h:262
Definition IsFloatingPoint.h:12
Definition IsPODType.h:12
@ Value
Definition IsPODType.h:13
Definition IsUECoreType.h:19
@ Value
Definition IsUECoreType.h:20
Definition Tuple.h:652
Definition Matrix.h:43
T M[4][4]
Definition Matrix.h:49
TVector< T > GetScaledAxis(EAxis::Type Axis) const
Definition Matrix.inl:647
Definition Quat.h:39
static TQuat MakeFromLUFEuler(const TTuple< T, T, T > &InLUFEuler)
Definition Quat.h:1439
void ToAxisAndAngle(TVector< T > &Axis, float &Angle) const
Definition Quat.h:1181
T operator|(const TQuat< T > &Q) const
Definition Quat.h:1100
void ToAxisAndAngle(TVector< T > &Axis, double &Angle) const
Definition Quat.h:1188
static TQuat< T > FastLerp(const TQuat< T > &A, const TQuat< T > &B, const T Alpha)
Definition Quat.h:1373
static CORE_API TQuat< T > Slerp_NotNormalized(const TQuat< T > &Quat1, const TQuat< T > &Quat2, T Slerp)
Definition UnrealMath.cpp:1226
UE_FORCEINLINE_HINT TVector< T > GetUpVector() const
Definition Quat.h:1329
TQuat< T > operator-() const
Definition Quat.h:975
bool SerializeFromMismatchedTag(FName StructTag, FArchive &Ar)
Definition Quat.h:718
static CORE_API TQuat< T > FindBetweenNormals(const TVector< T > &Normal1, const TVector< T > &Normal2)
Definition UnrealMath.cpp:1440
T W
Definition Quat.h:58
static UE_FORCEINLINE_HINT TQuat< T > FindBetween(const TVector< T > &Vector1, const TVector< T > &Vector2)
Definition Quat.h:616
static CORE_API TQuat< T > FindBetweenVectors(const TVector< T > &Vector1, const TVector< T > &Vector2)
Definition UnrealMath.cpp:1447
CORE_API TRotator< T > Rotator() const
static CORE_API TQuat< T > SlerpFullPath_NotNormalized(const TQuat< T > &quat1, const TQuat< T > &quat2, T Alpha)
Definition UnrealMath.cpp:1258
TQuat(T V)
Definition Quat.h:91
static CORE_API TQuat< T > MakeFromEuler(const TVector< T > &Euler)
Definition UnrealMath.cpp:787
UE_FORCEINLINE_HINT TVector< T > GetAxisZ() const
Definition Quat.h:1310
UE_FORCEINLINE_HINT TVector< T > Vector() const
Definition Quat.h:1335
TVectorRegisterType< T > QuatVectorRegister
Definition Quat.h:46
TVector< T > UnrotateVector(TVector< T > V) const
Definition Quat.h:1254
static UE_FORCEINLINE_HINT TQuat< T > MakeFromVectorRegister(QuatVectorRegister V)
Definition Quat.h:110
static UE_FORCEINLINE_HINT TQuat< T > MakeFromRotator(const TRotator< T > &R)
Definition Quat.h:122
static TQuat< T > MakeFromRotationVector(const TVector< T > &RotationVector)
Definition Quat.h:1203
UE_FORCEINLINE_HINT void DiagnosticCheckNaN(const TCHAR *Message) const
Definition Quat.h:608
bool ContainsNaN() const
Definition Quat.h:1394
TQuat(QuatVectorRegister V)
Definition Quat.h:885
bool Serialize(FArchive &Ar)
Definition Quat.h:712
TQuat< T > GetNormalized(T Tolerance=UE_SMALL_NUMBER) const
Definition Quat.h:1140
UE_FORCEINLINE_HINT TVector< T > GetRightVector() const
Definition Quat.h:1323
bool Identical(const TQuat *Q, const uint32 PortFlags) const
Definition Quat.h:1068
TQuat< T > Inverse() const
Definition Quat.h:1264
UE_FORCEINLINE_HINT TVector< T > GetAxisX() const
Definition Quat.h:1296
bool operator!=(const TQuat< T > &Q) const
Definition Quat.h:1087
static T Error(const TQuat< T > &Q1, const TQuat< T > &Q2)
Definition Quat.h:1349
TQuat< T > operator-(const TQuat< T > &Q) const
Definition Quat.h:963
TQuat(T InX, T InY, T InZ, T InW)
Definition Quat.h:874
static CORE_API TQuat< T > SquadFullPath(const TQuat< T > &quat1, const TQuat< T > &tang1, const TQuat< T > &quat2, const TQuat< T > &tang2, T Alpha)
Definition UnrealMath.cpp:1292
static UE_FORCEINLINE_HINT TQuat< T > Slerp(const TQuat< T > &Quat1, const TQuat< T > &Quat2, T Slerp)
Definition Quat.h:660
TQuat< T > operator+(const TQuat< T > &Q) const
Definition Quat.h:930
CORE_API bool NetSerialize(FArchive &Ar, class UPackageMap *Map, bool &bOutSuccess)
Definition UnrealMath.cpp:1320
TVector< T > RotateVector(TVector< T > V) const
Definition Quat.h:1238
void EnforceShortestArcWith(const TQuat< T > &OtherQuat)
Definition Quat.h:1276
bool IsNormalized() const
Definition Quat.h:1149
T AngularDistance(const TQuat< T > &Q) const
Definition Quat.h:1230
CORE_API TVector< T > Euler() const
Definition UnrealMath.cpp:1314
UE_FORCEINLINE_HINT TMatrix< T > ToMatrix() const
Definition Quat.h:1341
TQuat< T > operator*=(const TQuat< T > &Q)
Definition Quat.h:1040
static TQuat< T > FastBilerp(const TQuat< T > &P00, const TQuat< T > &P10, const TQuat< T > &P01, const TQuat< T > &P11, T FracX, T FracY)
Definition Quat.h:1383
UE_FORCEINLINE_HINT TVector< T > GetForwardVector() const
Definition Quat.h:1317
bool InitFromString(const FString &InSourceString)
Definition Quat.h:899
UE_FORCEINLINE_HINT TVector< T > GetAxisY() const
Definition Quat.h:1303
T Y
Definition Quat.h:52
CORE_API T GetTwistAngle(const TVector< T > &TwistAxis) const
Definition UnrealMath.cpp:816
TQuat()=default
UE_FORCEINLINE_HINT T GetAngle() const
Definition Quat.h:1174
UE_FORCEINLINE_HINT TQuat(EForceInit)
Definition Quat.h:869
TQuat(TVector< T > Axis, T AngleRad)
Definition Quat.h:914
UE_FORCEINLINE_HINT void DiagnosticCheckNaN() const
Definition Quat.h:607
TQuat< T > GetShortestArcWith(const TQuat< T > &OtherQuat) const
Definition Quat.h:1288
static UE_FORCEINLINE_HINT TQuat< T > SlerpFullPath(const TQuat< T > &quat1, const TQuat< T > &quat2, T Alpha)
Definition Quat.h:677
TVector< T > GetRotationAxis() const
Definition Quat.h:1210
T Z
Definition Quat.h:55
TQuat(const TQuat< FArg > &From)
Definition Quat.h:732
static CORE_API const TQuat< T > Identity
Definition Quat.h:63
CORE_API void ToSwingTwist(const TVector< T > &InTwistAxis, TQuat< T > &OutSwing, TQuat< T > &OutTwist) const
Definition UnrealMath.cpp:793
CORE_API TQuat< T > Log() const
Definition UnrealMath.cpp:1454
static T ErrorAutoNormalize(const TQuat< T > &A, const TQuat< T > &B)
Definition Quat.h:1357
TQuat< T > operator*(const FArg Scale) const
Definition Quat.h:278
UE_FORCEINLINE_HINT T Size() const
Definition Quat.h:1162
T X
Definition Quat.h:49
TQuat< T > operator/=(const FArg Scale)
Definition Quat.h:296
FString ToString() const
Definition Quat.h:893
UE_FORCEINLINE_HINT bool IsIdentity(T Tolerance=UE_SMALL_NUMBER) const
Definition Quat.h:1002
TTuple< T, T, T > ToLUFEuler() const
Definition Quat.h:1418
TQuat< T > operator-=(const TQuat< T > &Q)
Definition Quat.h:1008
TQuat(const TRotator< T > &R)
Definition Quat.h:853
TQuat< T > operator*=(const FArg Scale)
Definition Quat.h:254
CORE_API TQuat< T > Exp() const
Definition UnrealMath.cpp:1483
TQuat< T > operator+=(const TQuat< T > &Q)
Definition Quat.h:943
T FReal
Definition Quat.h:45
bool operator==(const TQuat< T > &Q) const
Definition Quat.h:1074
TVector< T > ToRotationVector() const
Definition Quat.h:1195
static CORE_API TQuat< T > Squad(const TQuat< T > &quat1, const TQuat< T > &tang1, const TQuat< T > &quat2, const TQuat< T > &tang2, T Alpha)
Definition UnrealMath.cpp:1280
bool Equals(const TQuat< T > &Q, T Tolerance=UE_KINDA_SMALL_NUMBER) const
Definition Quat.h:985
void Normalize(T Tolerance=UE_SMALL_NUMBER)
Definition Quat.h:1107
TVector< T > operator*(const TVector< T > &V) const
Definition Quat.h:860
static CORE_API void CalcTangents(const TQuat< T > &PrevP, const TQuat< T > &P, const TQuat< T > &NextP, T Tension, TQuat< T > &OutTan)
Definition UnrealMath.cpp:1302
TQuat(const TMatrix< T > &M)
Definition Quat.h:777
TQuat< T > operator*(const TQuat< T > &Q) const
Definition Quat.h:1028
UE_FORCEINLINE_HINT T SizeSquared() const
Definition Quat.h:1168
TQuat< T > operator/(const FArg Scale) const
Definition Quat.h:321
Definition Rotator.h:37
Definition Vector.h:51
static UE_FORCEINLINE_HINT TVector< T > CrossProduct(const TVector< T > &A, const TVector< T > &B)
Definition Vector.h:1541