Quaternion Manual

About

maxon::Quaternion is a MAXON API class used to represent quaternions and deliver standard mathematical operations. Unit quaternions, also known as versors, provide a convenient mathematical notation for representing orientations and rotations of objects in three dimensions. Compared to Euler angles they are simpler to compose and avoid the problem of gimbal lock. Compared to rotation matrices they are more compact, more numerically stable, and may be more efficient.

// This example shows how to use a quaternion to rotate a point in a left-handed coordinate system.
// define the point to rotate
const maxon::Vector point (1, 0, 0);
DiagnosticOutput(diagIDString + "start point: @", point);
// define the rotation angle
const maxon::Float rotAngle(90);
// define the rotation axis
const maxon::Vector rotAxis(0, 0, 1);
// create a quaternion representing the point
const maxon::Quaternion<maxon::Float> quaternionPointA(point, 0);
DiagnosticOutput(diagIDString + "quaternionPointA: @", quaternionPointA);
// create the quaternion represention the rotation (q)
const maxon::Float a = rotAxis.x * sin(maxon::DegToRad(rotAngle/2));
const maxon::Float b = rotAxis.y * sin(maxon::DegToRad(rotAngle/2));
const maxon::Float c = rotAxis.z * sin(maxon::DegToRad(rotAngle/2));
const maxon::Float d = cos(maxon::DegToRad(rotAngle/2));
const maxon::Quaternion<maxon::Float> quaternion(a, b, c, d);
DiagnosticOutput(diagIDString + "quaternion: @", quaternion);
// get the conjugated quaternion (q')
const maxon::Quaternion<maxon::Float> quaternionCnj = quaternion.GetConjugate();
DiagnosticOutput(diagIDString + "quaternionCnj: @", quaternionCnj);
// get the rotated point p1 = q * p * q'
const maxon::Quaternion<maxon::Float> quanterionPointARot = quaternion * quaternionPointA * quaternionCnj;
DiagnosticOutput(diagIDString + "quanterionPointARot: @", quanterionPointARot);
// extract the rotation point
const maxon::Vector rotPoint = quanterionPointARot.v;
DiagnosticOutput(diagIDString + "rotated point: @", rotPoint);

Creation and initialization

A maxon::Quaternion instance can be created on the stack and initialized through the proper method using a numerical data type as template:

// This example allocates a few maxon::Quaternion objects showing the different allocation methods.
// just allocate an zero-valued quaternion object
const maxon::Quaternion<maxon::Float> zeroQuaternion;
// just allocate a quaternion object defining the vectorial part and the real part
const maxon::Vector vectorVal(1.0, 1.0, 0);
const maxon::Float floatVal(1.5);
const maxon::Quaternion<maxon::Float> vectorRealQuaternion(vectorVal, floatVal);
// just allocate a quaternion object defining the four components used to value vectorial and real part
const maxon::Float a = 0.2; // 1st vectorial component
const maxon::Float b = 0.4; // 2nd vectorial component
const maxon::Float c = 0.6; // 3rd vectorial component
const maxon::Float d = 0.8; // this the real part
const maxon::Quaternion<maxon::Float> fourComponentsQuaternion(a, b, c, d);

Standard operations

The maxon::Quaternion class delivers a set of standard mathematical operators to perform calculation with quaternion. The operators deliver are:

// This example shows how to perform simple mathematical operations between quaternions.
// just allocate a constant quaternion using the four components
const maxon::Quaternion<maxon::Float> quaternionA(1, 0, 0, 12);
DiagnosticOutput(diagIDString + "quaternionA: @", quaternionA);
// just allocate a quaternion equal to the previous one
maxon::Quaternion<maxon::Float> quaternionB = quaternionA;
DiagnosticOutput(diagIDString + "quaternionB: @", quaternionB);
// sum A to B
quaternionB += quaternionA;
DiagnosticOutput(diagIDString + "quaternionB += quaternionA: @", quaternionB);
// subtract A to B
quaternionB -= quaternionA;
DiagnosticOutput(diagIDString + "quaternionB -= quaternionA: @", quaternionB);
// sum A and B
const maxon::Quaternion<maxon::Float> quaternionAsumB = quaternionA + quaternionB;
DiagnosticOutput(diagIDString + "quaternionAsumB : @", quaternionAsumB);
// subtract A and B
const maxon::Quaternion<maxon::Float> quaternionAdifB = quaternionA - quaternionB;
DiagnosticOutput(diagIDString + "quaternionAdifB: @", quaternionAdifB);
// multiply A and B
const maxon::Quaternion<maxon::Float> quaternionAprdB = quaternionA * quaternionB;
DiagnosticOutput(diagIDString + "quaternionAprdB: @", quaternionAprdB);
// multiply B and A
const maxon::Quaternion<maxon::Float> quaternionBprdA = quaternionB * quaternionA;
DiagnosticOutput(diagIDString + "quaternionBprdA: @", quaternionBprdA);
// scale A by scalar s
const maxon::Float scalar = 2;
const maxon::Quaternion<maxon::Float> quaternionAscaled = quaternionA * scalar;
DiagnosticOutput(diagIDString + "quaternionAscaled: @", quaternionAscaled);

Get and Set operations

The maxon::Quaternion class is provided with a number of get methods to retrieve useful data from a maxon::Quaternion instance:

// This example shows how to use the "get" methods provided with maxon::Quaternion.
// just allocate a constant quaternion using the four components
// representing a rotation of 90 deg around Y-axis in left-handed c.sys
const maxon::Quaternion<maxon::Float> quatY90 (0, sin(PI05/2), 0, cos(PI05/2));
// get the rotation matrix associated with the quaternion
const maxon::Matrix rotMat = quatY90.GetMatrix();
// get the axis and rotation angle associated with the quaternion
maxon::Vector rotAxis;
maxon::Float rotAngle;
quatY90.GetAxisRotation(rotAxis, rotAngle) iferr_return;
// get the squared length of the quaternion
const maxon::Float valSqLength = quatY90.GetSquaredLength();
// get the length of the quaternion
const maxon::Float valLength = quatY90.GetLength();
// get the normalized quaternion
// get the inverse quaternion
// get the conjugate quaternion
const maxon::Quaternion<maxon::Float> quatConjugated = quatY90.GetConjugate();
// get the natural log quaternion
// get the exponential equaternion
// get the quaternion elevated to the given power
const maxon::Quaternion<maxon::Float> quatPow = quatY90.GetPow(3.0) iferr_return;
// get the dot product of two quaternion
const maxon::Float valDotProduct = maxon::Quaternion<maxon::Float>::GetDot(quatY90, quatConjugated);
// get the linear interpolation of the given quaternion and the given blend ratio
const maxon::Quaternion<maxon::Float> quatX90 (sin(PI05/2), 0, 0, cos(PI05/2));
// get the spherical linear interpolation of the given quaternion and the given blend ratio
const maxon::Quaternion<maxon::Float> quatSLERP = maxon::Quaternion<maxon::Float>::GetSlerp(quatY90, quatX90, 0.5) iferr_return;
// get the spherical quadrangle interpolation of a sequence of quaternions qi and qi+1 using the passed blend parameter
const maxon::Quaternion<maxon::Float> quatA (1, 0, 0, 1);
const maxon::Quaternion<maxon::Float> quatAp1 (1, 1, 0, 1);
const maxon::Quaternion<maxon::Float> quatB (0, 0, 1, 1);
const maxon::Quaternion<maxon::Float> quatBp1 (0, 1, 1, 1);
const maxon::Quaternion<maxon::Float> quatSQUAD = maxon::Quaternion<maxon::Float>::GetSquad(quatA, quatAp1, quatB, quatBp1, 0.4) iferr_return;
// get the inner quaternion from a sequance of quaternions qi-1, qi and qi+1
const maxon::Quaternion<maxon::Float> quatCm1 (-1, 1, 0, 1);
const maxon::Quaternion<maxon::Float> quatC (1, 1, 0, 1);
const maxon::Quaternion<maxon::Float> quatCp1 (2, 1, 0, 1);
const maxon::Quaternion<maxon::Float> quatInner = maxon::Quaternion<maxon::Float>::GetInnerQuaternion(quatCm1, quatC, quatCp1) iferr_return;
// get the spline quaternion from a sequence of quaternions
const maxon::Quaternion<maxon::Float> quatDm1 (0, 0, 0, 1);
const maxon::Quaternion<maxon::Float> quatD (1, 0, 0, 1);
const maxon::Quaternion<maxon::Float> quatDp1 (2, 0, 0, 2);
const maxon::Quaternion<maxon::Float> quatDp2 (3, 0, 0, 2);
const maxon::Quaternion<maxon::Float> quatSpline = maxon::Quaternion<maxon::Float>::GetSpline(quatDm1, quatD, quatDp1, quatDp2, 0.75) iferr_return;

The maxon::Quaternion class is provided with a number of "set" methods to define a maxon::Quaternion instance:

// This example shows how to use the "set" methods provided with maxon::Quaternion.
// allocate a constant transformation matrix representing
// a rotation of 90 deg around Y-axis in left-handed c.sys
const maxon::SqMat3<maxon::Vector> mat3x3(maxon::Vector(0, 0, 1), maxon::Vector(0, 1, 0), maxon::Vector(-1.0, 0.0, 0.0));
// allocate a quaternion and set the values accordingly to the matrix defined
quatA.SetMatrix(mat3x3);
// allocate a Eulerian rotation vector (each component of the vector
// represents a rotation around an axis) represeting a rotation of 90 deg
// around Y-axis in left-handed c.sys
const maxon::Vector rotVet (0.0, PI05, 0.0);
// allocate a quaternion and set the values accordingly to the vector defined
quatB.SetRotation(rotVet);
// allocate a vector representing a rotation axis and value representing the rotation amount
const maxon::Vector rotAxis (0.0, 1.0, 0.0);
const maxon::Float rotAngle(PI05);
// allocate a quaternion and set the values accordingly to the axis and angle defined
quatC.SetAxisRotation(rotAxis, rotAngle);

The maxon::Quaternion class can be used to easily perform a rotation on a geometrical entity.

// allocate a point on X-axis
const maxon::Vector point_on_X (1.0, 0.0, 0.0);
// define the rotation around the Y-axis
const maxon::Vector axis_Y (0.0, 1.0, 0.0);
// define the rotation amount in radians
const maxon::Float rot_angle (PI05);
// allocate and define the quaternion used to rotate the point
rotate_on_Y.SetAxisRotation(axis_Y, rot_angle);
// the new point should now be on the Z-axis
const maxon::Vector point_on_Z = rotate_on_Y.GetMatrix() * point_on_X;

Conversion

A maxon::Quaternion instance can be converted to maxon::String using:

// This example shows how to convert a maxon::Quaternion to maxon::String.
// just allocate a complex object
const maxon::Quaternion<maxon::Float> quatA(1, 1, 0, 1);
const maxon::String stringQuaternion = quatA.ToString(nullptr);
DiagnosticOutput(diagIDString + "quatA: @", quatA);
DiagnosticOutput(diagIDString + "quatA.ToString(): @", stringQuaternion);

Utilities

A maxon::Quaternion instance can be read from and written to disk by serializing the data contained using the conventional functions.

// This example shows how to store and retrieve a maxon::Quaternion from a file.
const maxon::Quaternion<maxon::Float> savedQuat(1, 1, 0, 1);
// file URL
const maxon::Url url = (targetFolder + "quaternion.txt"_s)iferr_return;
const maxon::Id fileID("net.maxonexample.quaternion");
// save to file
// read from file
maxon::ReadDocument(url, fileID, loadedQuat) iferr_return;

Further Reading

maxon::ReadDocument
std::enable_if< GetCollectionKind< T >::value==COLLECTION_KIND::ARRAY, Result< void > >::type ReadDocument(const Url &url, const Id &id, T &object, const DataDictionary &dict=DataDictionary())
Definition: io.h:35
maxon::Quaternion::GetConjugate
QuaternionType GetConjugate() const
Definition: quaternion.h:422
maxon::Quaternion::GetLerp
static Result< QuaternionType > GetLerp(const QuaternionType &q1, const QuaternionType &q2, const ValueType t)
Definition: quaternion.h:472
Quaternion
Definition: c4d_quaternion.h:17
maxon::Mat3< Vector >
maxon::WriteDocument
Result< void > WriteDocument(const Url &url, const Id &id, const T &object, IOFORMAT format=IOFORMAT::DEFAULT, const DataDictionary &dict=DataDictionary())
Definition: io.h:67
maxon
The maxon namespace contains all declarations of the MAXON API.
Definition: c4d_basedocument.h:27
maxon::Quaternion::SetRotation
void SetRotation(const VectorType &rotation)
Definition: quaternion.h:341
Float
maxon::Float Float
Definition: ge_sys_math.h:51
maxon::String
Definition: string.h:1197
maxon::Quaternion::GetDot
static ValueType GetDot(const QuaternionType &q1, const QuaternionType &q2)
Calculates the dot product of two quaternions.
Definition: quaternion.h:467
maxon::Id
Definition: apibaseid.h:273
iferr_return
#define iferr_return
Definition: resultbase.h:1434
maxon::Float
Float64 Float
Definition: apibase.h:193
DiagnosticOutput
#define DiagnosticOutput(formatString,...)
Definition: debugdiagnostics.h:168
maxon::Url
Definition: url.h:819
maxon::Quaternion::SetAxisRotation
void SetAxisRotation(const VectorType &axis, const ValueType rotation)
Definition: quaternion.h:352
maxon::Vec3< Float, 1 >
maxon::IOFORMAT::JSON
@ JSON
maxon::Quaternion::GetExp
Result< QuaternionType > GetExp() const
Definition: quaternion.h:442
maxon::Quaternion::GetNormalized
Result< QuaternionType > GetNormalized() const
Definition: quaternion.h:399
maxon::Quaternion::ToString
String ToString(const FormatStatement *formatStatement) const
Definition: quaternion.h:570
maxon::Quaternion::SetMatrix
void SetMatrix(const MatrixType &m)
Definition: quaternion.h:321
maxon::Quaternion::GetLog
Result< QuaternionType > GetLog() const
Definition: quaternion.h:427
maxon::Quaternion::GetPow
Result< QuaternionType > GetPow(const ValueType &t) const
Definition: quaternion.h:456
maxon::Quaternion::GetMatrix
MatrixType GetMatrix() const
Derives a rotation matrix from the quaternion.
Definition: quaternion.h:358
maxon::DegToRad
MAXON_ATTRIBUTE_FORCE_INLINE Float32 DegToRad(Float32 r)
Converts float value from degrees to radians.
Definition: apibasemath.h:483
maxon::Quaternion::v
VectorType v
direction vector component
Definition: quaternion.h:237
PI05
static const Float64 PI05
floating point constant: 0.5 * PI
Definition: apibasemath.h:148
maxon::SqMat3
General 3×3 matrix template consisting of three column vectors v1, v2, v3.
Definition: matrix.h:14
maxon::Quaternion::GetInverse
Result< QuaternionType > GetInverse() const
Definition: quaternion.h:408
maxon::Quaternion
Definition: quaternion.h:24