UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
Quaternion.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5#include "Math/Quat.h" // Engine types
6#include "VectorTypes.h"
7#include "MatrixTypes.h"
8#include "IndexTypes.h"
9
10// ported from geometry3Sharp Quaternion
11
12namespace UE
13{
14namespace Geometry
15{
16
17using namespace UE::Math;
18
19
20template<typename RealType>
22{
23 union
24 {
25 struct
26 {
27 // note: in Wm5 version, this is a 4-element arraY stored in order (w,x,y,z).
28 RealType X;
29 RealType Y;
30 RealType Z;
31 RealType W;
32 };
33
34 UE_DEPRECATED(all, "For internal use only")
35 RealType XYZW[4];
36 };
37
39 TQuaternion(RealType X, RealType Y, RealType Z, RealType W);
40 explicit TQuaternion(const RealType* Values);
42 TQuaternion(const TQuaternion& Copy) = default;
43 TQuaternion& operator=(const TQuaternion& Copy) = default;
47 TQuaternion(const TVector<RealType>& Axis, RealType Angle, bool bAngleIsDegrees);
48 TQuaternion(const TVector<RealType>& From, const TVector<RealType>& To);
49 TQuaternion(const TQuaternion<RealType>& From, const TQuaternion<RealType>& To, RealType InterpT);
51
52 void SetAxisAngleD(const TVector<RealType>& Axis, RealType AngleDeg);
53 void SetAxisAngleR(const TVector<RealType>& Axis, RealType AngleRad);
54 void SetFromTo(const TVector<RealType>& From, const TVector<RealType>& To);
55 void SetToSlerp(TQuaternion<RealType> From, TQuaternion<RealType> To, RealType InterpT);
57
58 static TQuaternion<RealType> Zero() { return TQuaternion<RealType>((RealType)0, (RealType)0, (RealType)0, (RealType)0); }
59 static TQuaternion<RealType> Identity() { return TQuaternion<RealType>((RealType)0, (RealType)0, (RealType)0, (RealType)1); }
60
67 const RealType& operator[](int i) const
68 {
70 return XYZW[i];
72 }
73
74 // Test whether quaternions represent the same rotation w/in a tolerance. (Note: Considers the negative representation of the same rotation as equal.)
76 // Test whether the quaternion is EpsilonEqual to the identity quaternion (i.e., W=1 or W=-1, within tolerance)
77 bool IsIdentity(RealType Tolerance = TMathUtil<RealType>::ZeroTolerance) const
78 {
79 return EpsilonEqual(Identity(), Tolerance);
80 }
81
82 RealType Length() const { return (RealType)sqrt(X*X + Y*Y + Z*Z + W*W); }
83 RealType SquaredLength() const { return X*X + Y*Y + Z*Z + W*W; }
84
89
90 RealType Normalize(const RealType epsilon = 0);
91 TQuaternion<RealType> Normalized(const RealType epsilon = 0) const;
92
93 RealType Dot(const TQuaternion<RealType>& Other) const;
94
97
99
101 {
102 return TQuaternion<RealType>(-X, -Y, -Z, -W);
103 }
104
105
106 // available for porting:
107 // SetFromRotationMatrix(FMatrix3f)
108
109
110 explicit inline operator FQuat4f() const
111 {
112 FQuat4f Quat;
113 Quat.X = (float)X;
114 Quat.Y = (float)Y;
115 Quat.Z = (float)Z;
116 Quat.W = (float)W;
117 return Quat;
118 }
119 explicit inline operator FQuat4d() const
120 {
121 FQuat4d Quat;
122 Quat.X = (double)X;
123 Quat.Y = (double)Y;
124 Quat.Z = (double)Z;
125 Quat.W = (double)W;
126 return Quat;
127 }
128 explicit inline operator FRotator() const
129 {
130 return ((FQuat)*this).Rotator();
131 }
132 explicit inline TQuaternion(const FQuat4f& Quat)
133 {
134 X = (RealType)Quat.X;
135 Y = (RealType)Quat.Y;
136 Z = (RealType)Quat.Z;
137 W = (RealType)Quat.W;
138 }
139 explicit inline TQuaternion(const FQuat4d& Quat)
140 {
141 X = (RealType)Quat.X;
142 Y = (RealType)Quat.Y;
143 Z = (RealType)Quat.Z;
144 W = (RealType)Quat.W;
145 }
146 explicit inline TQuaternion(const FRotator& Rotator)
147 {
149 X = (RealType)Quat.X;
150 Y = (RealType)Quat.Y;
151 Z = (RealType)Quat.Z;
152 W = (RealType)Quat.W;
153 }
154 explicit inline operator UE::Math::TVector4<RealType>() const
155 {
157 }
158};
159
160
161
164
165
166
167
168template<typename RealType>
170{
171 X = Y = Z = 0; W = 1;
172}
173
174template<typename RealType>
175TQuaternion<RealType>::TQuaternion(RealType x, RealType y, RealType z, RealType w)
176{
177 X = x;
178 Y = y;
179 Z = z;
180 W = w;
181}
182
183template<typename RealType>
185{
186 X = Values[0];
187 Y = Values[1];
188 Z = Values[2];
189 W = Values[3];
190}
191
192template<typename RealType>
193template<typename RealType2>
195{
196 X = (RealType)Copy.X;
197 Y = (RealType)Copy.Y;
198 Z = (RealType)Copy.Z;
199 W = (RealType)Copy.W;
200}
201
202template<typename RealType>
208
209template<typename RealType>
211{
212 X = Y = Z = 0; W = 1;
213 SetFromTo(From, To);
214}
215
216template<typename RealType>
218{
219 X = Y = Z = 0; W = 1;
220 SetToSlerp(From, To, InterpT);
221}
222
223template<typename RealType>
229
230
231
232
233
234template<typename RealType>
235RealType TQuaternion<RealType>::Normalize(const RealType Epsilon)
236{
237 RealType length = Length();
238 if (length > Epsilon)
239 {
240 RealType invLength = ((RealType)1) / length;
241 X *= invLength;
242 Y *= invLength;
243 Z *= invLength;
244 W *= invLength;
245 return invLength;
246 }
247 X = Y = Z = W = (RealType)0;
248 return 0;
249}
250
251template<typename RealType>
253{
254 RealType length = Length();
255 if (length > Epsilon)
256 {
257 RealType invLength = ((RealType)1) / length;
259 }
260 return Zero();
261}
262
263template<typename RealType>
265{
266 return X * Other.X + Y * Other.Y + Z * Other.Z + W * Other.W;
267}
268
269
270template<typename RealType>
272{
273 RealType W = A.W * B.W - A.X * B.X - A.Y * B.Y - A.Z * B.Z;
274 RealType X = A.W * B.X + A.X * B.W + A.Y * B.Z - A.Z * B.Y;
275 RealType Y = A.W * B.Y + A.Y * B.W + A.Z * B.X - A.X * B.Z;
276 RealType Z = A.W * B.Z + A.Z * B.W + A.X * B.Y - A.Y * B.X;
277 return TQuaternion<RealType>(X, Y, Z, W);
278}
279
280
281template<typename RealType>
283{
284 return TQuaternion<RealType>(Scalar * Q.X, Scalar * Q.Y, Scalar * Q.Z, Scalar * Q.W);
285}
286
287template<typename RealType>
289{
290 return TQuaternion<RealType>(Scalar * Q.X, Scalar * Q.Y, Scalar * Q.Z, Scalar * Q.W);
291}
292
293
294template<typename RealType>
296{
297 return TQuaternion<RealType>(A.X + B.X, A.Y + B.Y, A.Z + B.Z, A.W + B.W);
298}
299
300
301template<typename RealType>
303{
304 return TQuaternion<RealType>(A.X - B.X, A.Y - B.Y, A.Z - B.Z, A.W - B.W);
305}
306
307template<typename RealType>
309{
310 //return q.ToRotationMatrix() * v;
311 // inline-expansion of above:
312 RealType twoX = (RealType)2*Q.X; RealType twoY = (RealType)2*Q.Y; RealType twoZ = (RealType)2*Q.Z;
313 RealType twoWX = twoX * Q.W; RealType twoWY = twoY * Q.W; RealType twoWZ = twoZ * Q.W;
314 RealType twoXX = twoX * Q.X; RealType twoXY = twoY * Q.X; RealType twoXZ = twoZ * Q.X;
315 RealType twoYY = twoY * Q.Y; RealType twoYZ = twoZ * Q.Y; RealType twoZZ = twoZ * Q.Z;
316 return TVector<RealType>(
317 V.X * ((RealType)1 - (twoYY + twoZZ)) + V.Y * (twoXY - twoWZ) + V.Z * (twoXZ + twoWY),
318 V.X * (twoXY + twoWZ) + V.Y * ((RealType)1 - (twoXX + twoZZ)) + V.Z * (twoYZ - twoWX),
319 V.X * (twoXZ - twoWY) + V.Y * (twoYZ + twoWX) + V.Z * ((RealType)1 - (twoXX + twoYY))); ;
320}
321
322
323template<typename RealType>
325{
326 RealType norm = SquaredLength();
327 if (norm > 0)
328 {
329 RealType invNorm = (RealType)1 / norm;
330 RealType qX = -X * invNorm, qY = -Y * invNorm, qZ = -Z * invNorm, qW = W * invNorm;
331 RealType twoX = (RealType)2 * qX; RealType twoY = (RealType)2 * qY; RealType twoZ = (RealType)2 * qZ;
332 RealType twoWX = twoX * qW; RealType twoWY = twoY * qW; RealType twoWZ = twoZ * qW;
333 RealType twoXX = twoX * qX; RealType twoXY = twoY * qX; RealType twoXZ = twoZ * qX;
334 RealType twoYY = twoY * qY; RealType twoYZ = twoZ * qY; RealType twoZZ = twoZ * qZ;
335 return TVector<RealType>(
336 V.X * ((RealType)1 - (twoYY + twoZZ)) + V.Y * (twoXY - twoWZ) + V.Z * (twoXZ + twoWY),
337 V.X * (twoXY + twoWZ) + V.Y * ((RealType)1 - (twoXX + twoZZ)) + V.Z * (twoYZ - twoWX),
338 V.X * (twoXZ - twoWY) + V.Y * (twoYZ + twoWX) + V.Z * ((RealType)1 - (twoXX + twoYY)));
339 }
341}
342
343
344template<typename RealType>
346{
347 RealType twoY = (RealType)2 * Y; RealType twoZ = (RealType)2 * Z;
348 RealType twoWY = twoY * W; RealType twoWZ = twoZ * W;
349 RealType twoXY = twoY * X; RealType twoXZ = twoZ * X;
350 RealType twoYY = twoY * Y; RealType twoZZ = twoZ * Z;
351 return TVector<RealType>((RealType)1 - (twoYY + twoZZ), twoXY + twoWZ, twoXZ - twoWY);
352}
353
354template<typename RealType>
356{
357 RealType twoX = (RealType)2 * X; RealType twoY = (RealType)2 * Y; RealType twoZ = (RealType)2 * Z;
358 RealType twoWX = twoX * W; RealType twoWZ = twoZ * W; RealType twoXX = twoX * X;
359 RealType twoXY = twoY * X; RealType twoYZ = twoZ * Y; RealType twoZZ = twoZ * Z;
360 return TVector<RealType>(twoXY - twoWZ, (RealType)1 - (twoXX + twoZZ), twoYZ + twoWX);
361}
362
363template<typename RealType>
365{
366 RealType twoX = (RealType)2 * X; RealType twoY = (RealType)2 * Y; RealType twoZ = (RealType)2 * Z;
367 RealType twoWX = twoX * W; RealType twoWY = twoY * W; RealType twoXX = twoX * X;
368 RealType twoXZ = twoZ * X; RealType twoYY = twoY * Y; RealType twoYZ = twoZ * Y;
369 return TVector<RealType>(twoXZ + twoWY, twoYZ - twoWX, (RealType)1 - (twoXX + twoYY));
370}
371
372template<typename RealType>
374{
375 RealType twoX = (RealType)2 * X; RealType twoY = (RealType)2 * Y; RealType twoZ = (RealType)2 * Z;
376 RealType twoWX = twoX * W; RealType twoWY = twoY * W; RealType twoWZ = twoZ * W;
377 RealType twoXX = twoX * X; RealType twoXY = twoY * X; RealType twoXZ = twoZ * X;
378 RealType twoYY = twoY * Y; RealType twoYZ = twoZ * Y; RealType twoZZ = twoZ * Z;
379 XOut = TVector<RealType>((RealType)1 - (twoYY + twoZZ), twoXY + twoWZ, twoXZ - twoWY);
380 YOut = TVector<RealType>(twoXY - twoWZ, (RealType)1 - (twoXX + twoZZ), twoYZ + twoWX);
381 ZOut = TVector<RealType>(twoXZ + twoWY, twoYZ - twoWX, (RealType)1 - (twoXX + twoYY));
382}
383
384
385template<typename RealType>
387{
388 RealType norm = SquaredLength();
389 if (norm > (RealType)0)
390 {
391 RealType invNorm = (RealType)1 / norm;
393 -X * invNorm, -Y * invNorm, -Z * invNorm, W * invNorm);
394 }
396}
397
398
399template<typename RealType>
404
405template<typename RealType>
407{
408 RealType halfAngle = (RealType)0.5 * AngleRad;
409 RealType sn = (RealType)sin(halfAngle);
410 W = (RealType)cos(halfAngle);
411 X = (sn * Axis.X);
412 Y = (sn * Axis.Y);
413 Z = (sn * Axis.Z);
414}
415
416
417
418// this function can take non-normalized vectors vFrom and vTo (normalizes internally)
419template<typename RealType>
421{
422 // [TODO] this page seems to have optimized version:
423 // http://lolengine.net/blog/2013/09/18/beautiful-maths-quaternion-from-vectors
424
425 // [RMS] not ideal to explicitly normalize here, but if we don't,
426 // output TQuaternion is not normalized and this causes problems,
427 // eg like drift if we do repeated SetFromTo()
430 W = from.Dot(bisector);
431 if (W != 0)
432 {
434 X = cross.X;
435 Y = cross.Y;
436 Z = cross.Z;
437 }
438 else
439 {
440 RealType invLength;
441 if ( (RealType)fabs(from.X) >= (RealType)fabs(from.Y))
442 {
443 // V1.X or V1.Z is the largest magnitude component.
444 invLength = ((RealType)1 / (RealType)sqrt(from.X * from.X + from.Z * from.Z));
445 X = -from.Z * invLength;
446 Y = 0;
447 Z = +from.X * invLength;
448 }
449 else
450 {
451 // V1.Y or V1.Z is the largest magnitude component.
452 invLength = ((RealType)1 / (RealType)sqrt(from.Y * from.Y + from.Z * from.Z));
453 X = 0;
454 Y = +from.Z * invLength;
455 Z = -from.Y * invLength;
456 }
457 }
458 Normalize(); // just to be safe...
459}
460
461
462
463template<typename RealType>
465{
466 From.Normalize();
467 To.Normalize();
468 RealType cs = From.Dot(To);
469
470 // Q and -Q are equivalent, but if we try to Slerp between them we will get nonsense instead of
471 // just returning Q. Depending on how the Quaternion was constructed it is possible
472 // that the sign flips. So flip it back.
473 if (cs < (RealType)-0.99)
474 {
475 From = -From;
476 }
477
478 RealType angle = TMathUtil<RealType>::ACos(cs);
480 {
481 RealType sn = TMathUtil<RealType>::Sin(angle);
482 RealType invSn = (RealType)1 / sn;
483 RealType tAngle = InterpT * angle;
486 X = coeff0 * From.X + coeff1 * To.X;
487 Y = coeff0 * From.Y + coeff1 * To.Y;
488 Z = coeff0 * From.Z + coeff1 * To.Z;
489 W = coeff0 * From.W + coeff1 * To.W;
490 }
491 else
492 {
493 X = From.X;
494 Y = From.Y;
495 Z = From.Z;
496 W = From.W;
497 }
498
499 Normalize(); // be safe
500}
501
502
503
504template<typename RealType>
506{
507 // Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course notes
508 // article "TQuaternion Calculus and Fast Animation".
509 FIndex3i next(1, 2, 0);
510
511 RealType trace = RotationMatrix(0,0) + RotationMatrix(1,1) + RotationMatrix(2, 2);
512 RealType root;
513
514 if (trace > 0)
515 {
516 // |w| > 1/2, may as well choose w > 1/2
517 root = (RealType)sqrt(trace + (RealType)1); // 2w
518 W = ((RealType)0.5) * root;
519 root = ((RealType)0.5) / root; // 1/(4w)
520 X = (RotationMatrix(2, 1) - RotationMatrix(1, 2)) * root;
521 Y = (RotationMatrix(0, 2) - RotationMatrix(2, 0)) * root;
522 Z = (RotationMatrix(1, 0) - RotationMatrix(0, 1)) * root;
523 }
524 else
525 {
526 // |w| <= 1/2
527 int i = 0;
528 if (RotationMatrix(1, 1) > RotationMatrix(0, 0))
529 {
530 i = 1;
531 }
532 if (RotationMatrix(2, 2) > RotationMatrix(i, i))
533 {
534 i = 2;
535 }
536 int j = next[i];
537 int k = next[j];
538
539 root = (RealType)sqrt(RotationMatrix(i, i) - RotationMatrix(j, j) - RotationMatrix(k, k) + (RealType)1);
540
542 quat[i] = ((RealType)0.5) * root;
543 root = ((RealType)0.5) / root;
544 W = (RotationMatrix(k, j) - RotationMatrix(j, k)) * root;
545 quat[j] = (RotationMatrix(j, i) + RotationMatrix(i, j)) * root;
546 quat[k] = (RotationMatrix(k, i) + RotationMatrix(i, k)) * root;
547 X = quat.X; Y = quat.Y; Z = quat.Z;
548 }
549
550 Normalize(); // we prefer normalized TQuaternions...
551}
552
553
554
555
556template<typename RealType>
558{
559 RealType twoX = 2 * X; RealType twoY = 2 * Y; RealType twoZ = 2 * Z;
560 RealType twoWX = twoX * W; RealType twoWY = twoY * W; RealType twoWZ = twoZ * W;
561 RealType twoXX = twoX * X; RealType twoXY = twoY * X; RealType twoXZ = twoZ * X;
562 RealType twoYY = twoY * Y; RealType twoYZ = twoZ * Y; RealType twoZZ = twoZ * Z;
564 m.Row0 = TVector<RealType>(1 - (twoYY + twoZZ), twoXY - twoWZ, twoXZ + twoWY);
565 m.Row1 = TVector<RealType>(twoXY + twoWZ, 1 - (twoXX + twoZZ), twoYZ - twoWX);
566 m.Row2 = TVector<RealType>(twoXZ - twoWY, twoYZ + twoWX, 1 - (twoXX + twoYY));
567 return m;
568}
569
570
571
572template<typename RealType>
574{
575 return
576 ((RealType)fabs(X - Other.X) <= Tolerance &&
577 (RealType)fabs(Y - Other.Y) <= Tolerance &&
578 (RealType)fabs(Z - Other.Z) <= Tolerance &&
579 (RealType)fabs(W - Other.W) <= Tolerance)
580 ||
581 ((RealType)fabs(X + Other.X) <= Tolerance &&
582 (RealType)fabs(Y + Other.Y) <= Tolerance &&
583 (RealType)fabs(Z + Other.Z) <= Tolerance &&
584 (RealType)fabs(W + Other.W) <= Tolerance);
585}
586
587
588} // end namespace UE::Geometry
589} // end namespace UE
#define UE_DEPRECATED(Version, Message)
Definition CoreMiscDefines.h:302
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
#define PRAGMA_ENABLE_DEPRECATION_WARNINGS
Definition GenericPlatformCompilerPreSetup.h:12
#define PRAGMA_DISABLE_DEPRECATION_WARNINGS
Definition GenericPlatformCompilerPreSetup.h:8
UE::Math::TQuat< double > FQuat4d
Definition MathFwd.h:63
UE::Math::TQuat< float > FQuat4f
Definition MathFwd.h:76
UE::Math::TRotator< double > FRotator
Definition MathFwd.h:57
int next(int i, int n)
Definition RecastMesh.cpp:164
USkinnedMeshComponent float
Definition SkinnedMeshComponent.h:60
Definition MathUtil.h:150
static RealType Sin(const RealType Value)
Definition MathUtil.h:366
static RealType ACos(const RealType Value)
Definition MathUtil.h:378
UE::Math::TVector2< T > Normalized(const UE::Math::TVector2< T > &Vector, const T Epsilon=0)
Definition VectorTypes.h:61
TQuaternion< double > FQuaterniond
Definition Quaternion.h:163
TQuaternion< float > FQuaternionf
Definition Quaternion.h:162
TQuaternion< RealType > operator+(const TQuaternion< RealType > &A, const TQuaternion< RealType > &B)
Definition Quaternion.h:295
Definition Sphere.cpp:10
UE_FORCEINLINE_HINT TQuat< T > operator*(const float Scale, const TQuat< T > &Q)
Definition Quat.h:1055
Definition AdvancedWidgetsModule.cpp:13
Definition IndexTypes.h:158
Definition MatrixTypes.h:17
static TMatrix3< RealType > Zero()
Definition MatrixTypes.h:82
Definition Quaternion.h:22
void SetToSlerp(TQuaternion< RealType > From, TQuaternion< RealType > To, RealType InterpT)
Definition Quaternion.h:464
static TQuaternion< RealType > Identity()
Definition Quaternion.h:59
const RealType & operator[](int i) const
Definition Quaternion.h:67
constexpr TQuaternion< RealType > operator-() const
Definition Quaternion.h:100
TQuaternion(const FQuat4f &Quat)
Definition Quaternion.h:132
void SetAxisAngleD(const TVector< RealType > &Axis, RealType AngleDeg)
Definition Quaternion.h:400
TQuaternion()
Definition Quaternion.h:169
TMatrix3< RealType > ToRotationMatrix() const
Definition Quaternion.h:557
TQuaternion< RealType > Normalized(const RealType epsilon=0) const
Definition Quaternion.h:252
void GetAxes(TVector< RealType > &X, TVector< RealType > &Y, TVector< RealType > &Z) const
Definition Quaternion.h:373
RealType W
Definition Quaternion.h:31
TQuaternion< RealType > Inverse() const
Definition Quaternion.h:386
TVector< RealType > AxisZ() const
Definition Quaternion.h:364
TVector< RealType > AxisX() const
Definition Quaternion.h:345
TVector< RealType > InverseMultiply(const TVector< RealType > &Other) const
Definition Quaternion.h:324
RealType & operator[](int i)
Definition Quaternion.h:61
RealType SquaredLength() const
Definition Quaternion.h:83
TQuaternion(const FRotator &Rotator)
Definition Quaternion.h:146
RealType X
Definition Quaternion.h:28
RealType Z
Definition Quaternion.h:30
TVector< RealType > AxisY() const
Definition Quaternion.h:355
TQuaternion(const FQuat4d &Quat)
Definition Quaternion.h:139
RealType Length() const
Definition Quaternion.h:82
RealType XYZW[4]
Definition Quaternion.h:35
bool IsIdentity(RealType Tolerance=TMathUtil< RealType >::ZeroTolerance) const
Definition Quaternion.h:77
RealType Normalize(const RealType epsilon=0)
Definition Quaternion.h:235
void SetFromRotationMatrix(const TMatrix3< RealType > &RotationMatrix)
Definition Quaternion.h:505
RealType Dot(const TQuaternion< RealType > &Other) const
Definition Quaternion.h:264
bool EpsilonEqual(const TQuaternion< RealType > &Other, RealType Tolerance=TMathUtil< RealType >::ZeroTolerance) const
Definition Quaternion.h:573
void SetAxisAngleR(const TVector< RealType > &Axis, RealType AngleRad)
Definition Quaternion.h:406
void SetFromTo(const TVector< RealType > &From, const TVector< RealType > &To)
Definition Quaternion.h:420
static TQuaternion< RealType > Zero()
Definition Quaternion.h:58
RealType Y
Definition Quaternion.h:29
T X
Definition Quat.h:49
Definition Vector4.h:30
Definition Vector.h:51
T Z
Definition Vector.h:68
static TVector< T > Zero()
Definition Vector.h:112
T Y
Definition Vector.h:65
UE_FORCEINLINE_HINT TVector< T > Cross(const TVector< T > &V2) const
Definition Vector.h:1535
T X
Definition Vector.h:62