// 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" namespace Passer { namespace LinearAlgebra { 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 destructor /// ~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; }; } // namespace LinearAlgebra } // namespace Passer using namespace Passer::LinearAlgebra; #endif