template<class T>
Magnum::Math::Quaternion class

Quaternion.

Template parameters
T Underlying data type

Represents 3D rotation. Usually denoted as the following in equations, with $ \boldsymbol{q}_V $ being the vector() part and $ q_S $ being the scalar() part:

\[ q = [\boldsymbol{q}_V, q_S] \]

See 2D and 3D transformations for a brief introduction.

Public types

using Type = T
Underlying data type.

Public static functions

static auto rotation(Rad<T> angle, const Vector3<T>& normalizedAxis) -> Quaternion<T>
Rotation quaternion.
static auto reflection(const Vector3<T>& normal) -> Quaternion<T> new in Git master
Reflection quaternion.
static auto fromMatrix(const Matrix3x3<T>& matrix) -> Quaternion<T>
Create a quaternion from a rotation matrix.

Constructors, destructors, conversion operators

Quaternion() constexpr noexcept
Default constructor.
Quaternion(IdentityInitT) explicit constexpr noexcept
Construct an identity quaternion.
Quaternion(ZeroInitT) explicit constexpr noexcept
Construct a zero-initialized quaternion.
Quaternion(Magnum::NoInitT) explicit noexcept
Construct without initializing the contents.
Quaternion(const Vector3<T>& vector, T scalar) constexpr noexcept
Construct from a vector and a scalar.
Quaternion(const Vector3<T>& vector) explicit constexpr noexcept
Construct from a vector.
template<class U>
Quaternion(const Quaternion<U>& other) explicit constexpr noexcept
Construct from a quaternion of different type.
template<class U, class V = decltype(Implementation::QuaternionConverter<T, U>::from(std::declval<U>()))>
Quaternion(const U& other) explicit constexpr
Construct quaternion from external representation.
template<class U, class V = decltype(Implementation::QuaternionConverter<T, U>::to(std::declval<Quaternion<T>>()))>
operator U() const explicit constexpr
Convert quaternion to external representation.

Public functions

auto data() -> T*
Raw data.
auto data() const -> const T*
auto operator==(const Quaternion<T>& other) const -> bool
Equality comparison.
auto operator!=(const Quaternion<T>& other) const -> bool
Non-equality comparison.
auto isNormalized() const -> bool
Whether the quaternion is normalized.
auto vector() -> Vector3<T>&
Vector part ( $ \boldsymbol{q}_V $ )
auto vector() const -> const Vector3<T> constexpr
auto scalar() -> T&
Scalar part ( $ q_S $ )
auto scalar() const -> T constexpr
auto angle() const -> Rad<T>
Rotation angle of a unit quaternion.
auto axis() const -> Vector3<T>
Rotation axis of a unit quaternion.
auto toMatrix() const -> Matrix3x3<T>
Convert to a rotation matrix.
auto toEuler() const -> Vector3<Rad<T>> new in 2020.06
Convert to an euler vector.
auto operator+() const -> Quaternion<T> new in Git master
Promotion.
auto operator-() const -> Quaternion<T>
Negated quaternion.
auto operator+=(const Quaternion<T>& other) -> Quaternion<T>&
Add and assign a quaternion.
auto operator+(const Quaternion<T>& other) const -> Quaternion<T>
Add a quaternion.
auto operator-=(const Quaternion<T>& other) -> Quaternion<T>&
Subtract and assign a quaternion.
auto operator-(const Quaternion<T>& other) const -> Quaternion<T>
Subtract a quaternion.
auto operator*=(T scalar) -> Quaternion<T>&
Multiply with a scalar and assign.
auto operator*(T scalar) const -> Quaternion<T>
Multiply with a scalar.
auto operator/=(T scalar) -> Quaternion<T>&
Divide with a scalar and assign.
auto operator/(T scalar) const -> Quaternion<T>
Divide with a scalar.
auto operator*(const Quaternion<T>& other) const -> Quaternion<T>
Multiply with a quaternion.
auto dot() const -> T
Dot product of the quaternion.
auto length() const -> T
Quaternion length.
auto normalized() const -> Quaternion<T>
Normalized quaternion (of unit length)
auto conjugated() const -> Quaternion<T>
Conjugated quaternion.
auto inverted() const -> Quaternion<T>
Inverted quaternion.
auto invertedNormalized() const -> Quaternion<T>
Inverted normalized quaternion.
auto transformVector(const Vector3<T>& vector) const -> Vector3<T>
Rotate a vector with a quaternion.
auto transformVectorNormalized(const Vector3<T>& vector) const -> Vector3<T>
Rotate a vector with a normalized quaternion.
auto reflectVector(const Vector3<T>& vector) const -> Vector3<T> new in Git master
Reflect a vector with a reflection quaternion.

Function documentation

template<class T>
static Quaternion<T> Magnum::Math::Quaternion<T>::rotation(Rad<T> angle, const Vector3<T>& normalizedAxis)

Rotation quaternion.

Parameters
angle Rotation angle (counterclockwise)
normalizedAxis Normalized rotation axis

Expects that the rotation axis is normalized.

\[ q = [\boldsymbol a \cdot \sin(\frac{\theta}{2}), \cos(\frac{\theta}{2})] \]

template<class T>
static Quaternion<T> Magnum::Math::Quaternion<T>::reflection(const Vector3<T>& normal) new in Git master

Reflection quaternion.

Parameters
normal Normal of the plane through which to reflect

Expects that the normal is normalized.

\[ q = [\boldsymbol n, 0] \]

Note that reflection quaternions behave differently from usual rotations, in particular they can't be concatenated together with usual quaternion multiplication, toMatrix() will not create a reflection matrix out of them and transformVector() will not do a proper reflection either, you have to use reflectVector() instead. See its documentation for more information.

template<class T>
static Quaternion<T> Magnum::Math::Quaternion<T>::fromMatrix(const Matrix3x3<T>& matrix)

Create a quaternion from a rotation matrix.

Expects that the matrix is a pure rotation, i.e. orthogonal and without any reflection. See Matrix4::rotation() const for an example of how to extract rotation, reflection and scaling components from a 3D transformation matrix.

template<class T>
Magnum::Math::Quaternion<T>::Quaternion() constexpr noexcept

Default constructor.

Equivalent to Quaternion(IdentityInitT).

template<class T>
Magnum::Math::Quaternion<T>::Quaternion(IdentityInitT) explicit constexpr noexcept

Construct an identity quaternion.

Creates unit quaternion.

\[ q = [\boldsymbol 0, 1] \]

template<class T>
Magnum::Math::Quaternion<T>::Quaternion(const Vector3<T>& vector, T scalar) constexpr noexcept

Construct from a vector and a scalar.

\[ q = [\boldsymbol v, s] \]

template<class T>
Magnum::Math::Quaternion<T>::Quaternion(const Vector3<T>& vector) explicit constexpr noexcept

Construct from a vector.

To be used in transformations later.

\[ q = [\boldsymbol v, 0] \]

template<class T> template<class U>
Magnum::Math::Quaternion<T>::Quaternion(const Quaternion<U>& other) explicit constexpr noexcept

Construct from a quaternion of different type.

Performs only default casting on the values, no rounding or anything else.

template<class T>
T* Magnum::Math::Quaternion<T>::data()

Raw data.

Contrary to what Doxygen shows, returns reference to an one-dimensional fixed-size array of four elements, i.e. T(&)[4], vector part first, scalar after.

template<class T>
const T* Magnum::Math::Quaternion<T>::data() const

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

template<class T>
bool Magnum::Math::Quaternion<T>::isNormalized() const

Whether the quaternion is normalized.

Quaternion is normalized if it has unit length:

\[ |q \cdot q - 1| < 2 \epsilon + \epsilon^2 \cong 2 \epsilon \]

template<class T>
const Vector3<T> Magnum::Math::Quaternion<T>::vector() const constexpr

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

template<class T>
T Magnum::Math::Quaternion<T>::scalar() const constexpr

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

template<class T>
Rad<T> Magnum::Math::Quaternion<T>::angle() const

Rotation angle of a unit quaternion.

Expects that the quaternion is normalized.

\[ \theta = 2 \cdot \arccos(q_S) \]

template<class T>
Vector3<T> Magnum::Math::Quaternion<T>::axis() const

Rotation axis of a unit quaternion.

Expects that the quaternion is normalized.

\[ \boldsymbol a = \frac{\boldsymbol q_V}{\sqrt{1 - q_S^2}} \]

If the angle() is zero, the returned axis is a NaN vector, indicating that the axis is arbitrary. In other words, rotating by a zero angle around any axis will always give back a $ [\boldsymbol 0, 1] $ quaternion. To always get a unit vector back, you do the following, replace it with an X axis for a zero angle:

Quaternion a = ;
Rad angle = a.angle();
Vector3 axis = angle == 0.0_radf ? Vector3::xAxis() : a.axis();

template<class T>
Matrix3x3<T> Magnum::Math::Quaternion<T>::toMatrix() const

Convert to a rotation matrix.

template<class T>
Vector3<Rad<T>> Magnum::Math::Quaternion<T>::toEuler() const new in 2020.06

Convert to an euler vector.

Expects that the quaternion is normalized. Returns the angles in an XYZ order, you can combine them back to a quaternion like this:

Rad x, y, z;
Quaternion a =
    Quaternion::rotation(z, Vector3::zAxis())*
    Quaternion::rotation(y, Vector3::yAxis())*
    Quaternion::rotation(x, Vector3::xAxis());

template<class T>
Quaternion<T> Magnum::Math::Quaternion<T>::operator+() const new in Git master

Promotion.

Returns the value as-is.

template<class T>
Quaternion<T> Magnum::Math::Quaternion<T>::operator-() const

Negated quaternion.

\[ -q = [-\boldsymbol q_V, -q_S] \]

template<class T>
Quaternion<T>& Magnum::Math::Quaternion<T>::operator+=(const Quaternion<T>& other)

Add and assign a quaternion.

The computation is done in-place.

\[ p + q = [\boldsymbol p_V + \boldsymbol q_V, p_S + q_S] \]

template<class T>
Quaternion<T> Magnum::Math::Quaternion<T>::operator+(const Quaternion<T>& other) const

Add a quaternion.

template<class T>
Quaternion<T>& Magnum::Math::Quaternion<T>::operator-=(const Quaternion<T>& other)

Subtract and assign a quaternion.

The computation is done in-place.

\[ p - q = [\boldsymbol p_V - \boldsymbol q_V, p_S - q_S] \]

template<class T>
Quaternion<T> Magnum::Math::Quaternion<T>::operator-(const Quaternion<T>& other) const

Subtract a quaternion.

template<class T>
Quaternion<T>& Magnum::Math::Quaternion<T>::operator*=(T scalar)

Multiply with a scalar and assign.

The computation is done in-place.

\[ q \cdot a = [\boldsymbol q_V \cdot a, q_S \cdot a] \]

template<class T>
Quaternion<T> Magnum::Math::Quaternion<T>::operator*(T scalar) const

Multiply with a scalar.

template<class T>
Quaternion<T>& Magnum::Math::Quaternion<T>::operator/=(T scalar)

Divide with a scalar and assign.

The computation is done in-place.

\[ \frac q a = [\frac {\boldsymbol q_V} a, \frac {q_S} a] \]

template<class T>
Quaternion<T> Magnum::Math::Quaternion<T>::operator/(T scalar) const

Divide with a scalar.

template<class T>
Quaternion<T> Magnum::Math::Quaternion<T>::operator*(const Quaternion<T>& other) const

Multiply with a quaternion.

\[ p q = [p_S \boldsymbol q_V + q_S \boldsymbol p_V + \boldsymbol p_V \times \boldsymbol q_V, p_S q_S - \boldsymbol p_V \cdot \boldsymbol q_V] \]

template<class T>
T Magnum::Math::Quaternion<T>::dot() const

Dot product of the quaternion.

Should be used instead of length() for comparing quaternion length with other values, because it doesn't compute the square root.

\[ q \cdot q = \boldsymbol q_V \cdot \boldsymbol q_V + q_S^2 \]

template<class T>
T Magnum::Math::Quaternion<T>::length() const

Quaternion length.

See also dot() const which is faster for comparing length with other values.

\[ |q| = \sqrt{q \cdot q} \]

template<class T>
Quaternion<T> Magnum::Math::Quaternion<T>::normalized() const

Normalized quaternion (of unit length)

template<class T>
Quaternion<T> Magnum::Math::Quaternion<T>::conjugated() const

Conjugated quaternion.

\[ q^* = [-\boldsymbol q_V, q_S] \]

template<class T>
Quaternion<T> Magnum::Math::Quaternion<T>::inverted() const

Inverted quaternion.

See invertedNormalized() which is faster for normalized quaternions.

\[ q^{-1} = \frac{q^*}{|q|^2} = \frac{q^*}{q \cdot q} \]

template<class T>
Quaternion<T> Magnum::Math::Quaternion<T>::invertedNormalized() const

Inverted normalized quaternion.

Equivalent to conjugated(). Expects that the quaternion is normalized.

\[ q^{-1} = \frac{q^*}{|q|^2} = q^* \]

template<class T>
Vector3<T> Magnum::Math::Quaternion<T>::transformVector(const Vector3<T>& vector) const

Rotate a vector with a quaternion.

See transformVectorNormalized(), which is faster for normalized quaternions.

\[ v' = qvq^{-1} = q [\boldsymbol v, 0] q^{-1} \]

Note that this function will not give the correct result for quaternions created with reflection(), for those use reflectVector() instead.

template<class T>
Vector3<T> Magnum::Math::Quaternion<T>::transformVectorNormalized(const Vector3<T>& vector) const

Rotate a vector with a normalized quaternion.

Faster alternative to transformVector(), expects that the quaternion is normalized. Done using the following equation:

\[ \begin{array}{rcl} \boldsymbol t & = & 2 (\boldsymbol q_V \times \boldsymbol v) \\ \boldsymbol v' & = & \boldsymbol v + q_S \boldsymbol t + \boldsymbol q_V \times \boldsymbol t \end{array} \]

Which is equivalent to the common equation (source: https://molecularmusings.wordpress.com/2013/05/24/a-faster-quaternion-vector-multiplication/):

\[ v' = qvq^{-1} = qvq^* = q [\boldsymbol v, 0] q^* \]

template<class T>
Vector3<T> Magnum::Math::Quaternion<T>::reflectVector(const Vector3<T>& vector) const new in Git master

Reflect a vector with a reflection quaternion.

Compared to the usual vector transformation performed with rotation quaternions and transformVector(), the reflection is done like this:

\[ v' = qvq = q [\boldsymbol v, 0] q \]

You can use reflection() to create a quaternion reflecting along given normal. Note that it's **not possible to combine reflections and rotations with the usual quaternion multiplication. Assuming a (normalized) rotation quaternion $ r $ , a combined rotation and reflection of vector $ v $ would look like this instead:

\[ v' = rqvqr^{-1} = rqvqr^* = rq [\boldsymbol v, 0] qr^* \]

See also quaternion reflection at Euclidean Space.

template<class T> template<class T>
T dot(const Quaternion<T>& a, const Quaternion<T>& b)

Dot product between two quaternions.

\[ p \cdot q = \boldsymbol p_V \cdot \boldsymbol q_V + p_S q_S \]

template<class T> template<class T>
Rad<T> angle(const Quaternion<T>& normalizedA, const Quaternion<T>& normalizedB)

Angle between normalized quaternions.

Expects that both quaternions are normalized.

\[ \theta = \arccos \left( \frac{p \cdot q}{|p| |q|} \right) = \arccos(p \cdot q) \]

To avoid numerical issues when two complex numbers are very close to each other, the dot product is clamped to the $ [-1, +1] $ range before being passed to $ \arccos $ .

template<class T> template<class T>
Quaternion<T> lerp(const Quaternion<T>& normalizedA, const Quaternion<T>& normalizedB, T t)

Linear interpolation of two quaternions.

Parameters
normalizedA First quaternion
normalizedB Second quaternion
t Interpolation phase (from range $ [0; 1] $ )

Expects that both quaternions are normalized.

\[ q_{LERP} = \frac{(1 - t) q_A + t q_B}{|(1 - t) q_A + t q_B|} \]

Note that this function does not check for shortest path interpolation, see lerpShortestPath(const Quaternion<T>&, const Quaternion<T>&, T) for an alternative.

template<class T> template<class T>
Quaternion<T> lerpShortestPath(const Quaternion<T>& normalizedA, const Quaternion<T>& normalizedB, T t)

Linear shortest-path interpolation of two quaternions.

Parameters
normalizedA First quaternion
normalizedB Second quaternion
t Interpolation phase (from range $ [0; 1] $ )

Unlike lerp(const Quaternion<T>&, const Quaternion<T>&, T), this interpolates on the shortest path at some performance expense. Expects that both quaternions are normalized.

\[ \begin{array}{rcl} d & = & q_A \cdot q_B \\[5pt] q'_A & = & \begin{cases} \phantom{-}q_A, & d \ge 0 \\ -q_A, & d < 0 \end{cases} \\[15pt] q_{LERP} & = & \cfrac{(1 - t) q'_A + t q_B}{|(1 - t) q'_A + t q_B|} \end{array} \]

template<class T> template<class T>
Quaternion<T> slerp(const Quaternion<T>& normalizedA, const Quaternion<T>& normalizedB, T t)

Spherical linear interpolation of two quaternions.

Parameters
normalizedA First quaternion
normalizedB Second quaternion
t Interpolation phase (from range $ [0; 1] $ )

Expects that both quaternions are normalized. If the quaternions are nearly the same or one is a negation of the other, it falls back to a linear interpolation (shortest-path to avoid a degenerate case of returning a zero quaternion for $ t = 0.5 $ ), but without post-normalization as the interpolation result can still be considered sufficiently normalized:

\[ \begin{array}{rcl} d & = & q_A \cdot q_B \\[5pt] q_{SLERP} & = & (1 - t) \left\{ \begin{array}{lr} \phantom{-}q_A, & d \ge 0 \\ -q_A, & d < 0 \end{array} \right\} + t q_B, ~ {\color{m-primary} \text{if} ~ |d| \ge 1 - \frac{\epsilon}{2}} \end{array} \]

Otherwise, the interpolation is performed as:

\[ \begin{array}{rcl} \theta & = & \arccos \left( \frac{q_A \cdot q_B}{|q_A| |q_B|} \right) = \arccos(q_A \cdot q_B) = \arccos(d) \\[5pt] q_{SLERP} & = & \cfrac{\sin((1 - t) \theta) q_A + \sin(t \theta) q_B}{\sin(\theta)} \end{array} \]

Note that this function does not check for shortest path interpolation, see slerpShortestPath(const Quaternion<T>&, const Quaternion<T>&, T) for an alternative.

template<class T> template<class T>
Quaternion<T> slerpShortestPath(const Quaternion<T>& normalizedA, const Quaternion<T>& normalizedB, T t)

Spherical linear shortest-path interpolation of two quaternions.

Parameters
normalizedA First quaternion
normalizedB Second quaternion
t Interpolation phase (from range $ [0; 1] $ )

Unlike slerp(const Quaternion<T>&, const Quaternion<T>&, T) this function interpolates on the shortest path. Expects that both quaternions are normalized. If the quaternions are nearly the same or one is a negation of the other, it falls back to a linear interpolation (shortest-path to avoid a degenerate case of returning a zero quaternion for $ t = 0.5 $ ) but without post-normalization as the interpolation result can still be considered sufficiently normalized:

\[ \begin{array}{rcl} d & = & q_A \cdot q_B \\[15pt] q'_A & = & \begin{cases} \phantom{-}q_A, & d \ge 0 \\ -q_A, & d < 0 \end{cases} \\[15pt] q_{SLERP} & = & (1 - t) q'_A + t q_B, ~ {\color{m-primary} \text{if} ~ |d| \ge 1 - \frac{\epsilon}{2}} \end{array} \]

Otherwise, the interpolation is performed as:

\[ \begin{array}{rcl} \theta & = & \arccos \left( \frac{|q'_A \cdot q_B|}{|q'_A| |q_B|} \right) = \arccos(|q'_A \cdot q_B|) = \arccos(|d|) \\[5pt] q_{SLERP} & = & \cfrac{\sin((1 - t) \theta) q'_A + \sin(t \theta) q_B}{\sin(\theta)} \end{array} \]

template<class T> template<class T>
Quaternion<T> operator*(T scalar, const Quaternion<T>& quaternion)

Multiply a scalar with a quaternion.

Same as Quaternion::operator*(T) const.

template<class T> template<class T>
Quaternion<T> operator/(T scalar, const Quaternion<T>& quaternion)

Divide a quaternion with a scalar and invert.

\[ \frac a q = [\frac a {\boldsymbol q_V}, \frac a {q_S}] \]

template<class T> template<class T>
Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug& debug, const Quaternion<T>& value)

Debug output operator.