Enoki provides a vectorizable type for quaternion arithmetic. To use it, include the following header:
#include <enoki/quaternion.h>
The following example shows how to define and perform basic arithmetic using
enoki::Quaternion vectorized over 4-wide packets.
/* Declare underlying packet type, could just be 'float' for scalar arithmetic */
using FloatP = Packet<float, 4>;
/* Define vectorized quaternion type */
using QuaternionP = Quaternion<FloatP>;
QuaternionP a = QuaternionP(1.f, 0.f, 0.f, 0.f);
QuaternionP b = QuaternionP(0.f, 1.f, 0.f, 0.f);
/* Compute several rotations that interpolate between 'a' and 'b' */
FloatP t = linspace<FloatP>(0.f, 1.f);
QuaternionP c = slerp(a, b, t);
std::cout << "Interpolated quaternions:" << std::endl;
std::cout << c << std::endl << std::endl;
/* Turn into a 4x4 homogeneous coordinate rotation matrix packet */
using MatrixP = Matrix<FloatP, 4>;
MatrixP c_rot = quat_to_matrix<Matrix4P>(c);
std::cout << "Rotation matrices:" << std::endl;
std::cout << c_rot << std::endl << std::endl;
/* Round trip: turn the rotation matrices back into rotation quaternions */
QuaternionP c2 = matrix_to_quat(c_rot);
if (hsum(abs(c-c2)) < 1e-6f)
std::cout << "Test passed." << std::endl;
else
std::cout << "Test failed." << std::endl;
/* Prints:
Interpolated quaternions:
[0 + 1i + 0j + 0k,
0 + 0.866025i + 0.5j + 0k,
0 + 0.5i + 0.866025j + 0k,
0 - 4.37114e-08i + 1j + 0k]
Rotation matrices:
[[[1, 0, 0, 0],
[0, -1, 0, 0],
[0, 0, -1, 0],
[0, 0, 0, 1]],
[[0.5, 0.866025, 0, 0],
[0.866025, -0.5, 0, 0],
[0, 0, -1, 0],
[0, 0, 0, 1]],
[[-0.5, 0.866025, 0, 0],
[0.866025, 0.5, 0, 0],
[0, 0, -1, 0],
[0, 0, 0, 1]],
[[-1, -8.74228e-08, 0, 0],
[-8.74228e-08, 1, 0, 0],
[-0, 0, -1, 0],
[0, 0, 0, 1]]]
Test passed.
*/
Type>Quaternion : StaticArrayImpl<Type, 4>¶The class enoki::Quaternion is a 4D Enoki array whose
components are of type Type. Various arithmetic operators (e.g.
multiplication) and transcendental functions are overloaded so that they
provide the correct behavior for quaternion-valued inputs.
Quaternion(Type x, Type y, Type z, Type w)¶Initialize a new enoki::Quaternion instance with the value
\(x\mathbf{i} + y\mathbf{j} + z\mathbf{k} + w\)
Warning
Note the different order convention compared to
Complex::Complex().
Quaternion(Array<Type, 3> imag, Type real)¶Creates a enoki::Quaternion instance from the given
imaginary and real inputs.
Warning
Note the different order convention compared to
Complex::Complex().
Quaternion(Type f)¶Creates a real-valued enoki::Quaternion instance from f.
This constructor effectively changes the broadcasting behavior of
non-quaternion inputs—for instance, the snippet
auto value_a = zero<Array<float, 4>>();
auto value_q = zero<Quaternion<float>>();
value_a += 1.f; value_q += 1.f;
std::cout << "value_a = "<< value_a << ", value_q = " << value_q << std::endl;
prints value_a = [1, 1, 1, 1], value_q = 1 + 0i + 0j + 0k, which is
the desired behavior for quaternions. For standard Enoki arrays, the
number 1.f is broadcast to all four components.
T>real(Quaternion<T> q)¶Extracts the real part of q.
T>imag(Quaternion<T> q)¶Extracts the imaginary part of q.
T>abs(Quaternion<T> q)¶Compute the absolute value of q.
T>sqrt(Quaternion<T> q)¶Compute the square root of q.
T>conj(Quaternion<T> q)¶Evaluates the quaternion conjugate of q.
T>rcp(Quaternion<T> q)¶Evaluates the quaternion reciprocal of q.
Only a few arithmetic operators need to be overridden to support quaternion arithmetic. The rest are automatically provided by Enoki’s existing operators and broadcasting rules.
T>operator*(Quaternion<T> q0, Quaternion<T> q1)¶Evaluates the quaternion product of q1 and z2.
T>operator/(Quaternion<T> q0, Quaternion<T> q1)¶Evaluates the quaternion division of q1 and z2.
operator<<(std::ostream &os, const Quaternion<T> &z)¶Sends the quaternion number q to the stream os using the format
1 + 2i + 3j + 4k.
T>exp(Quaternion<T> q)¶Evaluates the quaternion exponential of q.
T>log(Quaternion<T> q)¶Evaluates the quaternion logarithm of q.
T>pow(Quaternion<T> q0, Quaternion<T> q1)¶Evaluates the quaternion power of q0 raised to the q1.