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 rotation(const Vector3<T>& normalizedFrom, const Vector3<T>& normalizedTo) -> Quaternion<T> new in Git master
Quaternion rotating from a vector to another.
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 = decltype(Implementation::QuaternionConverter<T, U>::from(std::declval<U>()))>
Quaternion(const U& other) explicit constexpr
Construct a quaternion from external representation.
template<class U, class = decltype(Implementation::QuaternionConverter<T, U>::to(std::declval<Quaternion<T>>()))>
operator U() const explicit constexpr
Convert the 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>::rotation(const Vector3<T>& normalizedFrom, const Vector3<T>& normalizedTo) new in Git master

Quaternion rotating from a vector to another.

Parameters
normalizedFrom Normalized vector from which to rotate
normalizedTo Normalized vector to which to rotate

Returns a quaternion that transforms normalizedFrom into normalizedTo. Expects that both vectors are normalized. If the vectors are parallel, returns an identity quaternion, if they're antiparallel, picks an arbitrary rotation axis.

Based on The Shortest Arc Quaternion by Stan Melax, Game Programming Gems 1, page 214.

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> halfAngle(const Quaternion<T>& normalizedA, const Quaternion<T>& normalizedB)

Half-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>
Debug& operator<<(Debug& debug, const Quaternion<T>& value)

Debug output operator.