// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0.If a copy of the MPL was not distributed with this
// file, You can obtain one at https ://mozilla.org/MPL/2.0/.
#ifndef QUATERNION_H
#define QUATERNION_H
#include "Vector3.h"
extern "C" {
///
/// A quaternion
///
/// This is a C-style implementation
typedef struct Quat {
///
/// The x component
///
float x;
///
/// The y component
///
float y;
///
/// The z component
///
float z;
///
/// The w component
///
float w;
} Quat;
}
///
/// A quaternion
///
struct Quaternion : Quat {
public:
///
/// Create a new identity quaternion
///
Quaternion();
///
/// create a new quaternion with the given values
///
/// x component
/// y component
/// z component
/// w component
Quaternion(float _x, float _y, float _z, float _w);
///
/// Create a quaternion from C-style Quat
///
///
Quaternion(Quat q);
~Quaternion();
///
/// An identity quaternion
///
const static Quaternion identity;
///
/// Convert to unit quaternion
///
/// This will preserve the orientation,
/// but ensures that it is a unit quaternion.
void Normalize();
///
/// Convert to unity quaternion
///
/// The quaternion to convert
/// A unit quaternion
/// This will preserve the orientation,
/// but ensures that it is a unit quaternion.
static Quaternion Normalize(const Quaternion& q);
///
/// Convert to euler angles
///
/// The quaternion to convert
/// A vector containing euler angles
/// The euler angles performed in the order: Z, X, Y
static Vector3 ToAngles(const Quaternion& q);
///
/// Rotate a vector using this quaterion
///
/// The vector to rotate
/// The rotated vector
Vector3 operator*(const Vector3& vector) const;
///
/// Multiply this quaternion with another quaternion
///
/// The quaternion to multiply with
/// The resulting rotation
/// The result will be this quaternion rotated according to
/// the give rotation.
Quaternion operator*(const Quaternion& rotation) const;
///
/// Check the equality of two quaternions
///
/// The quaternion to compare to
/// True when the components of the quaternions are
/// identical Note that this does not compare the rotations
/// themselves. Two quaternions with the same rotational effect may have
/// different components. Use Quaternion::Angle to check if the rotations are
/// the same.
bool operator==(const Quaternion& quaternion);
///
/// The inverse of quaterion
///
/// The quaternion for which the inverse is
/// needed The inverted quaternion
static Quaternion Inverse(Quaternion quaternion);
///
/// A rotation which looks in the given direction
///
/// The look direction
/// The up direction
/// The look rotation
static Quaternion LookRotation(const Vector3& forward,
const Vector3& upwards);
///
/// Creates a quaternion with the given forward direction with up =
/// Vector3::up
///
/// The look direction
/// The rotation for this direction
/// For the rotation, Vector::up is used for the up direction.
/// Note: if the forward direction == Vector3::up, the result is
/// Quaternion::identity
static Quaternion LookRotation(const Vector3& forward);
///
/// Calculat the rotation from on vector to another
///
/// The from direction
/// The to direction
/// The rotation from the first to the second vector
static Quaternion FromToRotation(Vector3 fromDirection, Vector3 toDirection);
///
/// Rotate form one orientation to anther with a maximum amount of degrees
///
/// The from rotation
/// The destination rotation
/// The maximum amount of degrees to
/// rotate The possibly limited rotation
static Quaternion RotateTowards(const Quaternion& from,
const Quaternion& to,
float maxDegreesDelta);
///
/// Convert an angle/axis representation to a quaternion
///
/// The angle
/// The axis
/// The resulting quaternion
static Quaternion AngleAxis(float angle, const Vector3& axis);
///
/// Convert this quaternion to angle/axis representation
///
/// A pointer to the angle for the result
/// A pointer to the axis for the result
void ToAngleAxis(float* angle, Vector3* axis);
///
/// Get the angle between two orientations
///
/// The first orientation
/// The second orientation
/// The smallest angle in degrees between the two
/// orientations
static float Angle(Quaternion orientation1, Quaternion orientation2);
///
/// Sherical lerp between two rotations
///
/// The first rotation
/// The second rotation
/// The factor between 0 and 1.
/// The resulting rotation
/// A factor 0 returns rotation1, factor1 returns rotation2.
static Quaternion Slerp(const Quaternion& rotation1,
const Quaternion& rotation2,
float factor);
///
/// Unclamped sherical lerp between two rotations
///
/// The first rotation
/// The second rotation
/// The factor
/// The resulting rotation
/// A factor 0 returns rotation1, factor1 returns rotation2.
/// Values outside the 0..1 range will result in extrapolated rotations
static Quaternion SlerpUnclamped(const Quaternion& rotation1,
const Quaternion& rotation2,
float factor);
///
/// Create a rotation from euler angles
///
/// The angle around the right axis
/// The angle around the upward axis
/// The angle around the forward axis
/// The resulting quaternion
/// Rotation are appied in the order Z, X, Y.
static Quaternion Euler(float x, float y, float z);
///
/// Create a rotation from a vector containing euler angles
///
/// Vector with the euler angles
/// The resulting quaternion
/// Rotation are appied in the order Z, X, Y.
static Quaternion Euler(Vector3 eulerAngles);
///
/// Create a rotation from euler angles
///
/// The angle around the right axis
/// The angle around the upward axis
/// The angle around the forward axis
/// The resulting quaternion
/// Rotation are appied in the order X, Y, Z.
static Quaternion EulerXYZ(float x, float y, float z);
///
/// Create a rotation from a vector containing euler angles
///
/// Vector with the euler angles
/// The resulting quaternion
/// Rotation are appied in the order X, Y, Z.
static Quaternion EulerXYZ(Vector3 eulerAngles);
///
/// Returns the angle of around the give axis for a rotation
///
/// The axis around which the angle should be
/// computed The source rotation
/// The signed angle around the axis
static float GetAngleAround(Vector3 axis, Quaternion rotation);
///
/// Returns the rotation limited around the given axis
///
/// The axis which which the rotation should be
/// limited The source rotation
/// The rotation around the given axis
static Quaternion GetRotationAround(Vector3 axis, Quaternion rotation);
///
/// Swing-twist decomposition of a rotation
///
/// The base direction for the decomposition
/// The source rotation
/// A pointer to the quaternion for the swing
/// result A pointer to the quaternion for the
/// twist result
static void GetSwingTwist(Vector3 axis,
Quaternion rotation,
Quaternion* swing,
Quaternion* twist);
///
/// Calculate the dot product of two quaternions
///
/// The first rotation
/// The second rotation
///
static float Dot(Quaternion rotation1, Quaternion rotation2);
private:
float GetLength() const;
float GetLengthSquared() const;
static float GetLengthSquared(const Quaternion& q);
void ToAxisAngleRad(const Quaternion& q, Vector3* const axis, float* angle);
static Quaternion FromEulerRad(Vector3 euler);
static Quaternion FromEulerRadXYZ(Vector3 euler);
Vector3 xyz() const;
};
#endif