Quaternions provide a representation of a 3-dimensional orientation or rotation. Quaternions are especially useful when interpolating between angles to avoid Gimbal lock. For more information, see this description.
[MathFu] implements a quaternion as the [Quaternion][] class template which is constructed from one 3-dimensional [Vector][] and scalar component. The [Quaternion][] template is intended to be instanced with float
or double
floating point scalar types.
The Quaternions template takes a single argument which specifies the floating point type of each element in the class:
mathfu::Quaternion<float> quaternion;
For efficiency, [Quaternion][] is uninitialized when constructed. Constructors are provided to initialize the class from a set of scalars, a 3-dimensional [Vector][] and a scalar or another [Quaternion][].
For example, to initialize a [Quaternion][] using a set of scalars:
mathfu::Quaternion<float> quaternion(0.71f, 0.0f, 0.71f, 0.0f);
To initialize a [Quaternion][] from a scalar and 3-dimensional vector component:
mathfu::Quaternion<float> quaternion( 0.50f, mathfu::vec3(0.76f, 0.38f, 0.19f));
[Quaternion][] provides an array operator to retrieve elements of the object. The first index is the scalar component with the remaining 3 indices referring to elements in the vector component.
const mathfu::Quaternion<float> quaternion( 0.50f, mathfu::vec3(0.76f, 0.38f, 0.19f)); float s = quaternion[0]; float x = quaternion[1]; float y = quaternion[2]; float z = quaternion[3];
The array operator returns a reference to an element in the [Quaternion][] which can be updated:
mathfu::Quaternion<float> quaternion; quaternion[0] = 0.5f; quaternion[1] = 0.76f; quaternion[2] = 0.38f; quaternion[3] = 0.19f;
[Quaternion][] provides a number of ways to create a rotation or orientation:
For example, to create a [Quaternion][] which rotates PI / 2 radians around the X-axis:
mathfu::Quaternion<float> quaternion = mathfu::Quaternion<float>::FromAngleAxis( M_PI / 2.0f, mathfu::vec3(1.0f, 0.0f, 0.0f));
The rotation of PI / 2 radians around the X-axis can also be achieved with:
mathfu::Quaternion<float> quaternion = mathfu::Quaternion<float>::FromEulerAngles( mathfu::vec3(M_PI / 2.0f, 0.0f, 0.0f));
Similarly, a quaternion can be constructed from an existing rotation matrix using:
// Assuming rotation_matrix is an existing matrix. mathfu::Quaternion<float> quaternion = mathfu::Quaternion<float>::FromMatrix(rotation_matrix);
In addition, methods are provided to calculate an angle / axis pair, Euler angles, or rotation matrix from a [Quaternion][]:
For example, to calculate the angle and axis from a [Quaternion][]:
// Assuming "quaternion" is an existing float quaternion. float angle; mathfu::vec3 axis; quaternion.ToAngleAxis(&angle, &axis);
To calculate a vector of Euler angles from a [Quaternion][]
// Assuming "quaternion" is an existing float quaternion. mathfu::vec3 euler_angles = quaternion.ToEulerAngles();
Finally, to convert a [Quaternion][] to a rotation matrix:
// Assuming "quaternion" is an existing float quaternion. mathfu::Matrix<float, 3> rotation_matrix = quaternion.ToMatrix();
[Quaternion][] objects can be multiplied with each other to combine their rotations.
For example, if a quaternion that rotates by PI / 2 radians around the X axis is multiplied by itself it will result in a quaternion that rotates by PI radians around the X axis:
mathfu::Quaternion<float> quaternion_pi_by_2_around_x = mathfu::Quaternion<float>::FromAngleAxis( M_PI / 2.0f, mathfu::vec3(1.0f, 0.0f, 0.0f)); mathfu::Quaternion<float> quaternion_pi_around_x = quaternion_pi_by_2_around_x * quaternion_pi_by_2_around_x;
It's also possible to multiply a [Quaternion][] with a scalar to scale the existing rotation expressed by the object.
For example, if a quaternion that rotates by PI / 2 radians around the X axis is multiplied by 2 it will result in a quaternion that rotates by PI radians around the X axis:
mathfu::Quaternion<float> quaternion_pi_by_2_around_x = mathfu::Quaternion<float>::FromAngleAxis( M_PI / 2.0f, mathfu::vec3(1.0f, 0.0f, 0.0f)); mathfu::Quaternion<float> quaternion_pi_around_x = quaternion_pi_by_2_around_x * 2.0f;
In addition, [Quaternion][] provides the ability to perform spherical linear interpolation between two [Quaternion][] objects enabling smooth transitions between rotations while avoiding Gimbal lock.
For example, the rotation half way between two quaternions can be calculated by the following:
// Assuming "quaternion1" and "quaternion2" represent arbitrary rotations. mathfu::Quaternion<float> quaternion3 = mathfu::Quaternion<float>(quaternion1, quaternion2, 0.5f);
Finally, the inverse (opposite rotation) of a [Quaternion][] is calculated using [Quaternion::Inverse()](@ref mathfu::Quaternion::Inverse). For example, if a [Quaternion][] represents a rotation PI / 2 radians around the X axis the rotation -PI / 2 degrees around the X axis can be calculated by:
const mathfu::Quaternion<float> quaternion = mathfu::Quaternion<float>::FromAngleAxis( M_PI / 2.0f, mathfu::vec3(1.0f, 0.0f, 0.0f)); mathfu::Quaternion<float> inverse_rotation = quaternion.Inverse();
A rotation expressed by a [Quaternion][] is applied to a [Vector][] by multiplying the [Quaternion][] with the [Vector][].
For example, to rotate a [Vector][] by PI / 2 radians around the X axis:
const mathfu::vec3 vector(0.0f, 1.0f, 0.0f); const mathfu::Quaternion<float> quaternion = mathfu::Quaternion<float>::FromAngleAxis( M_PI / 2.0f, mathfu::vec3(1.0f, 0.0f, 0.0f)); mathfu::vec3 rotated_vector = quaternion * vector;
When applying rotations to a large number of vectors or points (e.g transforming a set of vertices) it is easier to use [Quaternion::ToMatrix()](@ref mathfu::Quaternion::ToMatrix) to calculate the rotation matrix and apply the same transform to the set of vectors.
[Quaternion]: @ref mathfu::Quaternion [MathFu]: @ref mathfu_overview [Matrix]: @ref mathfu::Matrix [Vector]: @ref mathfu::Vector