File size: 5,522 Bytes
7b853a5 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 | /*
* SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "Vector.h"
namespace Math
{
class alignas(16) Quaternion
{
public:
static Quaternion const Identity;
// Calculate the rotation required to align the source vector to the target vector (shortest path)
static Quaternion FromRotationBetweenNormalizedVectors(const Vector& sourceVector, const Vector& targetVector);
// Calculate the rotation required to align one vector onto another but also taking account a fallback rotation axis for opposite parallel vectors
static Quaternion FromRotationBetweenNormalizedVectors(const Vector& sourceVector, const Vector& targetVector, const Vector& fallbackRotationAxis);
// Calculate the rotation required to align the source vector to the target vector (shortest path)
static Quaternion FromRotationBetweenVectors(const Vector& sourceVector, const Vector& targetVector);
// Normalized LERP - not accurate - only use for really short distances
static Quaternion NLerp(const Quaternion& from, const Quaternion& to, float t);
// Standard and accurate Spherical LERP - based on DirectX Math
static Quaternion SLerp(const Quaternion& from, const Quaternion& to, float t);
// Fast approximation of a Spherical LERP - based on "A fast and accurate estimate for SLERP" by David Eberly
static Quaternion FastSLerp(const Quaternion& from, const Quaternion& to, float t);
// Spherical quadrangle/cubic interpolation for quaternions
static Quaternion SQuad(const Quaternion& q0, const Quaternion& q1, const Quaternion& q2, const Quaternion& q3, float t);
// Calculate the shortest delta quaternion needed to rotate 'from' onto 'to'
static Quaternion Delta(const Quaternion& from, const Quaternion& to);
// Simple vector dot product between two quaternions
static Vector Dot(const Quaternion& q0, const Quaternion& q1);
// Calculate the angular distance between two quaternions
static Radians Distance(const Quaternion& q0, const Quaternion& q1);
// Calculate look rotation given forward and up vectors
static Quaternion LookRotation(const Vector& forward, const Vector& up);
public:
Quaternion() = default;
explicit Quaternion(NoInit_t);
explicit Quaternion(IdentityInit_t);
explicit Quaternion(const Vector& v);
explicit Quaternion(float ix, float iy, float iz, float iw);
explicit Quaternion(const Float4& v);
explicit Quaternion(const Vector& axis, Radians angle);
explicit Quaternion(AxisAngle axisAngle);
explicit Quaternion(const EulerAngles& eulerAngles);
explicit Quaternion(Radians rotX, Radians rotY, Radians rotZ);
operator __m128& ();
operator const __m128& () const;
Float4 ToFloat4() const;
Vector ToVector() const;
Vector Length();
float GetLength() const;
// Get the angle this rotation represents around the specified axis
Radians GetAngle() const;
AxisAngle ToAxisAngle() const;
EulerAngles ToEulerAngles() const;
Vector RotateVector(const Vector& vector) const;
Vector RotateVectorInverse(const Vector& vector) const;
Quaternion& Conjugate();
Quaternion GetConjugate() const;
Quaternion& Negate();
Quaternion GetNegated() const;
Quaternion& Invert();
Quaternion GetInverse() const;
Quaternion& Normalize();
Quaternion GetNormalized() const;
Vector XAxis() const noexcept;
Vector YAxis() const noexcept;
Vector ZAxis() const noexcept;
// Ensure that this rotation is the shortest in terms of the angle (i.e. -5 instead of 355)
Quaternion& MakeShortestPath();
// Ensure that this rotation is the shortest in terms of the angle (i.e. -5 instead of 355)
Quaternion GetShortestPath() const;
// This function will return the estimated normalized quaternion, this is not super accurate but a lot faster (use with care)
Quaternion& NormalizeInaccurate();
// This function will return the estimated normalized quaternion, this is not super accurate but a lot faster (use with care)
Quaternion GetNormalizedInaccurate() const;
bool IsNormalized() const;
bool IsIdentity() const;
// Concatenate the rotation of this onto rhs and return the result i.e. first rotate by rhs then by this
// This means order of rotation is right-to-left: child-rotation * parent-rotation
Quaternion operator*(const Quaternion& rhs) const;
Quaternion& operator*=(const Quaternion& rhs);
// Is the distance between this quaternion and another one under the threshold?
bool IsNearEqual(const Quaternion& rhs, Radians const threshold = Math::DegreesToRadians) const;
// Exact equality
bool operator==(const Quaternion& rhs) const;
// Exact equality
bool operator!=(const Quaternion& rhs) const;
private:
Vector GetSplatW() const;
float GetW() const;
Quaternion& operator=(const Vector& v) = delete;
public:
__m128 m_data;
};
static_assert(sizeof(Vector) == 16, "Quaternion size must be 16 bytes!");
}
#include "Quaternion.inl"
|