Added EulerXYZ
This commit is contained in:
parent
d3e2ded5d7
commit
00b62c9baa
@ -8,248 +8,278 @@
|
|||||||
#include "Vector3.h"
|
#include "Vector3.h"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A quaternion
|
/// A quaternion
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// This is a C-style implementation
|
/// This is a C-style implementation
|
||||||
typedef struct Quat {
|
typedef struct Quat {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The x component
|
/// The x component
|
||||||
/// </summary>
|
/// </summary>
|
||||||
float x;
|
float x;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The y component
|
/// The y component
|
||||||
/// </summary>
|
/// </summary>
|
||||||
float y;
|
float y;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The z component
|
/// The z component
|
||||||
/// </summary>
|
/// </summary>
|
||||||
float z;
|
float z;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The w component
|
/// The w component
|
||||||
/// </summary>
|
/// </summary>
|
||||||
float w;
|
float w;
|
||||||
} Quat;
|
} Quat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A quaternion
|
/// A quaternion
|
||||||
/// </summary>
|
/// </summary>
|
||||||
struct Quaternion : Quat {
|
struct Quaternion : Quat {
|
||||||
public:
|
public:
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new identity quaternion
|
/// Create a new identity quaternion
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Quaternion();
|
Quaternion();
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// create a new quaternion with the given values
|
/// create a new quaternion with the given values
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="_x">x component</param>
|
/// <param name="_x">x component</param>
|
||||||
/// <param name="_y">y component</param>
|
/// <param name="_y">y component</param>
|
||||||
/// <param name="_z">z component</param>
|
/// <param name="_z">z component</param>
|
||||||
/// <param name="_w">w component</param>
|
/// <param name="_w">w component</param>
|
||||||
Quaternion(float _x, float _y, float _z, float _w);
|
Quaternion(float _x, float _y, float _z, float _w);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a quaternion from C-style Quat
|
/// Create a quaternion from C-style Quat
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="q"></param>
|
/// <param name="q"></param>
|
||||||
Quaternion(Quat q);
|
Quaternion(Quat q);
|
||||||
~Quaternion();
|
~Quaternion();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// An identity quaternion
|
/// An identity quaternion
|
||||||
/// </summary>
|
/// </summary>
|
||||||
const static Quaternion identity;
|
const static Quaternion identity;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Convert to unit quaternion
|
/// Convert to unit quaternion
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// This will preserve the orientation,
|
/// This will preserve the orientation,
|
||||||
/// but ensures that it is a unit quaternion.
|
/// but ensures that it is a unit quaternion.
|
||||||
void Normalize();
|
void Normalize();
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Convert to unity quaternion
|
/// Convert to unity quaternion
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="q">The quaternion to convert</param>
|
/// <param name="q">The quaternion to convert</param>
|
||||||
/// <returns>A unit quaternion</returns>
|
/// <returns>A unit quaternion</returns>
|
||||||
/// This will preserve the orientation,
|
/// This will preserve the orientation,
|
||||||
/// but ensures that it is a unit quaternion.
|
/// but ensures that it is a unit quaternion.
|
||||||
static Quaternion Normalize(const Quaternion& q);
|
static Quaternion Normalize(const Quaternion& q);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Convert to euler angles
|
/// Convert to euler angles
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="q">The quaternion to convert</param>
|
/// <param name="q">The quaternion to convert</param>
|
||||||
/// <returns>A vector containing euler angles</returns>
|
/// <returns>A vector containing euler angles</returns>
|
||||||
/// The euler angles performed in the order: Z, X, Y
|
/// The euler angles performed in the order: Z, X, Y
|
||||||
static Vector3 ToAngles(const Quaternion& q);
|
static Vector3 ToAngles(const Quaternion& q);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Rotate a vector using this quaterion
|
/// Rotate a vector using this quaterion
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="vector">The vector to rotate</param>
|
/// <param name="vector">The vector to rotate</param>
|
||||||
/// <returns>The rotated vector</returns>
|
/// <returns>The rotated vector</returns>
|
||||||
Vector3 operator *(const Vector3& vector) const;
|
Vector3 operator*(const Vector3& vector) const;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Multiply this quaternion with another quaternion
|
/// Multiply this quaternion with another quaternion
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="rotation">The quaternion to multiply with</param>
|
/// <param name="rotation">The quaternion to multiply with</param>
|
||||||
/// <returns>The resulting rotation</returns>
|
/// <returns>The resulting rotation</returns>
|
||||||
/// The result will be this quaternion rotated according to
|
/// The result will be this quaternion rotated according to
|
||||||
/// the give rotation.
|
/// the give rotation.
|
||||||
Quaternion operator *(const Quaternion& rotation) const;
|
Quaternion operator*(const Quaternion& rotation) const;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Check the equality of two quaternions
|
/// Check the equality of two quaternions
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="quaternion">The quaternion to compare to</param>
|
/// <param name="quaternion">The quaternion to compare to</param>
|
||||||
/// <returns>True when the components of the quaternions are identical</returns>
|
/// <returns>True when the components of the quaternions are
|
||||||
/// Note that this does not compare the rotations themselves.
|
/// identical</returns> Note that this does not compare the rotations
|
||||||
/// Two quaternions with the same rotational effect may have different
|
/// themselves. Two quaternions with the same rotational effect may have
|
||||||
/// components. Use Quaternion::Angle to check if the rotations are the same.
|
/// different components. Use Quaternion::Angle to check if the rotations are
|
||||||
bool operator ==(const Quaternion& quaternion);
|
/// the same.
|
||||||
|
bool operator==(const Quaternion& quaternion);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The inverse of quaterion
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="quaternion">The quaternion for which the inverse is
|
||||||
|
/// needed</param> <returns>The inverted quaternion</returns>
|
||||||
|
static Quaternion Inverse(Quaternion quaternion);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The inverse of quaterion
|
/// A rotation which looks in the given direction
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="quaternion">The quaternion for which the inverse is needed</param>
|
/// <param name="forward">The look direction</param>
|
||||||
/// <returns>The inverted quaternion</returns>
|
/// <param name="upwards">The up direction</param>
|
||||||
static Quaternion Inverse(Quaternion quaternion);
|
/// <returns>The look rotation</returns>
|
||||||
|
static Quaternion LookRotation(const Vector3& forward,
|
||||||
|
const Vector3& upwards);
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a quaternion with the given forward direction with up =
|
||||||
|
/// Vector3::up
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="forward">The look direction</param>
|
||||||
|
/// <returns>The rotation for this direction</returns>
|
||||||
|
/// 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);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A rotation which looks in the given direction
|
/// Calculat the rotation from on vector to another
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="forward">The look direction</param>
|
/// <param name="fromDirection">The from direction</param>
|
||||||
/// <param name="upwards">The up direction</param>
|
/// <param name="toDirection">The to direction</param>
|
||||||
/// <returns>The look rotation</returns>
|
/// <returns>The rotation from the first to the second vector</returns>
|
||||||
static Quaternion LookRotation(const Vector3& forward, const Vector3& upwards);
|
static Quaternion FromToRotation(Vector3 fromDirection, Vector3 toDirection);
|
||||||
/// <summary>
|
|
||||||
/// Creates a quaternion with the given forward direction with up = Vector3::up
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="forward">The look direction</param>
|
|
||||||
/// <returns>The rotation for this direction</returns>
|
|
||||||
/// 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);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Calculat the rotation from on vector to another
|
/// Rotate form one orientation to anther with a maximum amount of degrees
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="fromDirection">The from direction</param>
|
/// <param name="from">The from rotation</param>
|
||||||
/// <param name="toDirection">The to direction</param>
|
/// <param name="to">The destination rotation</param>
|
||||||
/// <returns>The rotation from the first to the second vector</returns>
|
/// <param name="maxDegreesDelta">The maximum amount of degrees to
|
||||||
static Quaternion FromToRotation(Vector3 fromDirection, Vector3 toDirection);
|
/// rotate</param> <returns>The possibly limited rotation</returns>
|
||||||
|
static Quaternion RotateTowards(const Quaternion& from,
|
||||||
|
const Quaternion& to,
|
||||||
|
float maxDegreesDelta);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Rotate form one orientation to anther with a maximum amount of degrees
|
/// Convert an angle/axis representation to a quaternion
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="from">The from rotation</param>
|
/// <param name="angle">The angle</param>
|
||||||
/// <param name="to">The destination rotation</param>
|
/// <param name="axis">The axis</param>
|
||||||
/// <param name="maxDegreesDelta">The maximum amount of degrees to rotate</param>
|
/// <returns>The resulting quaternion</returns>
|
||||||
/// <returns>The possibly limited rotation</returns>
|
static Quaternion AngleAxis(float angle, const Vector3& axis);
|
||||||
static Quaternion RotateTowards(const Quaternion& from, const Quaternion& to, float maxDegreesDelta);
|
/// <summary>
|
||||||
|
/// Convert this quaternion to angle/axis representation
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="angle">A pointer to the angle for the result</param>
|
||||||
|
/// <param name="axis">A pointer to the axis for the result</param>
|
||||||
|
void ToAngleAxis(float* angle, Vector3* axis);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Convert an angle/axis representation to a quaternion
|
/// Get the angle between two orientations
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="angle">The angle</param>
|
/// <param name="orientation1">The first orientation</param>
|
||||||
/// <param name="axis">The axis</param>
|
/// <param name="orientation2">The second orientation</param>
|
||||||
/// <returns>The resulting quaternion</returns>
|
/// <returns>The smallest angle in degrees between the two
|
||||||
static Quaternion AngleAxis(float angle, const Vector3& axis);
|
/// orientations</returns>
|
||||||
/// <summary>
|
static float Angle(Quaternion orientation1, Quaternion orientation2);
|
||||||
/// Convert this quaternion to angle/axis representation
|
/// <summary>
|
||||||
/// </summary>
|
/// Sherical lerp between two rotations
|
||||||
/// <param name="angle">A pointer to the angle for the result</param>
|
/// </summary>
|
||||||
/// <param name="axis">A pointer to the axis for the result</param>
|
/// <param name="rotation1">The first rotation</param>
|
||||||
void ToAngleAxis(float* angle, Vector3* axis);
|
/// <param name="rotation2">The second rotation</param>
|
||||||
|
/// <param name="factor">The factor between 0 and 1.</param>
|
||||||
|
/// <returns>The resulting rotation</returns>
|
||||||
|
/// A factor 0 returns rotation1, factor1 returns rotation2.
|
||||||
|
static Quaternion Slerp(const Quaternion& rotation1,
|
||||||
|
const Quaternion& rotation2,
|
||||||
|
float factor);
|
||||||
|
/// <summary>
|
||||||
|
/// Unclamped sherical lerp between two rotations
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="rotation1">The first rotation</param>
|
||||||
|
/// <param name="rotation2">The second rotation</param>
|
||||||
|
/// <param name="factor">The factor</param>
|
||||||
|
/// <returns>The resulting rotation</returns>
|
||||||
|
/// 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);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get the angle between two orientations
|
/// Create a rotation from euler angles
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="orientation1">The first orientation</param>
|
/// <param name="x">The angle around the right axis</param>
|
||||||
/// <param name="orientation2">The second orientation</param>
|
/// <param name="y">The angle around the upward axis</param>
|
||||||
/// <returns>The smallest angle in degrees between the two orientations</returns>
|
/// <param name="z">The angle around the forward axis</param>
|
||||||
static float Angle(Quaternion orientation1, Quaternion orientation2);
|
/// <returns>The resulting quaternion</returns>
|
||||||
/// <summary>
|
/// Rotation are appied in the order Z, X, Y.
|
||||||
/// Sherical lerp between two rotations
|
static Quaternion Euler(float x, float y, float z);
|
||||||
/// </summary>
|
/// <summary>
|
||||||
/// <param name="rotation1">The first rotation</param>
|
/// Create a rotation from a vector containing euler angles
|
||||||
/// <param name="rotation2">The second rotation</param>
|
/// </summary>
|
||||||
/// <param name="factor">The factor between 0 and 1.</param>
|
/// <param name="eulerAngles">Vector with the euler angles</param>
|
||||||
/// <returns>The resulting rotation</returns>
|
/// <returns>The resulting quaternion</returns>
|
||||||
/// A factor 0 returns rotation1, factor1 returns rotation2.
|
/// Rotation are appied in the order Z, X, Y.
|
||||||
static Quaternion Slerp(const Quaternion& rotation1, const Quaternion& rotation2, float factor);
|
static Quaternion Euler(Vector3 eulerAngles);
|
||||||
/// <summary>
|
|
||||||
/// Unclamped sherical lerp between two rotations
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="rotation1">The first rotation</param>
|
|
||||||
/// <param name="rotation2">The second rotation</param>
|
|
||||||
/// <param name="factor">The factor</param>
|
|
||||||
/// <returns>The resulting rotation</returns>
|
|
||||||
/// 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);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a rotation from euler angles
|
/// Create a rotation from euler angles
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="x">The angle around the right axis</param>
|
/// <param name="x">The angle around the right axis</param>
|
||||||
/// <param name="y">The angle around the upward axis</param>
|
/// <param name="y">The angle around the upward axis</param>
|
||||||
/// <param name="z">The angle around the forward axis</param>
|
/// <param name="z">The angle around the forward axis</param>
|
||||||
/// <returns>The resulting quaternion</returns>
|
/// <returns>The resulting quaternion</returns>
|
||||||
/// Rotation are appied in the order z, X, Y.
|
/// Rotation are appied in the order X, Y, Z.
|
||||||
static Quaternion Euler(float x, float y, float z);
|
static Quaternion EulerXYZ(float x, float y, float z);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a rotation from a vector containing euler angles
|
/// Create a rotation from a vector containing euler angles
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="eulerAngles">Vector with the euler angles</param>
|
/// <param name="eulerAngles">Vector with the euler angles</param>
|
||||||
/// <returns>The resulting quaternion</returns>
|
/// <returns>The resulting quaternion</returns>
|
||||||
/// Rotation are appied in the order z, X, Y.
|
/// Rotation are appied in the order X, Y, Z.
|
||||||
static Quaternion Euler(Vector3 eulerAngles);
|
static Quaternion EulerXYZ(Vector3 eulerAngles);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the angle of around the give axis for a rotation
|
/// Returns the angle of around the give axis for a rotation
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="axis">The axis around which the angle should be computed</param>
|
/// <param name="axis">The axis around which the angle should be
|
||||||
/// <param name="rotation">The source rotation</param>
|
/// computed</param> <param name="rotation">The source rotation</param>
|
||||||
/// <returns>The signed angle around the axis</returns>
|
/// <returns>The signed angle around the axis</returns>
|
||||||
static float GetAngleAround(Vector3 axis, Quaternion rotation);
|
static float GetAngleAround(Vector3 axis, Quaternion rotation);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the rotation limited around the given axis
|
/// Returns the rotation limited around the given axis
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="axis">The axis which which the rotation should be limited</param>
|
/// <param name="axis">The axis which which the rotation should be
|
||||||
/// <param name="rotation">The source rotation</param>
|
/// limited</param> <param name="rotation">The source rotation</param>
|
||||||
/// <returns>The rotation around the given axis</returns>
|
/// <returns>The rotation around the given axis</returns>
|
||||||
static Quaternion GetRotationAround(Vector3 axis, Quaternion rotation);
|
static Quaternion GetRotationAround(Vector3 axis, Quaternion rotation);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Swing-twist decomposition of a rotation
|
/// Swing-twist decomposition of a rotation
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="axis">The base direction for the decomposition</param>
|
/// <param name="axis">The base direction for the decomposition</param>
|
||||||
/// <param name="rotation">The source rotation</param>
|
/// <param name="rotation">The source rotation</param>
|
||||||
/// <param name="swing">A pointer to the quaternion for the swing result</param>
|
/// <param name="swing">A pointer to the quaternion for the swing
|
||||||
/// <param name="twist">A pointer to the quaternion for the twist result</param>
|
/// result</param> <param name="twist">A pointer to the quaternion for the
|
||||||
static void GetSwingTwist(Vector3 axis, Quaternion rotation, Quaternion* swing, Quaternion* twist);
|
/// twist result</param>
|
||||||
|
static void GetSwingTwist(Vector3 axis,
|
||||||
|
Quaternion rotation,
|
||||||
|
Quaternion* swing,
|
||||||
|
Quaternion* twist);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Calculate the dot product of two quaternions
|
/// Calculate the dot product of two quaternions
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="rotation1">The first rotation</param>
|
/// <param name="rotation1">The first rotation</param>
|
||||||
/// <param name="rotation2">The second rotation</param>
|
/// <param name="rotation2">The second rotation</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
static float Dot(Quaternion rotation1, Quaternion rotation2);
|
static float Dot(Quaternion rotation1, Quaternion rotation2);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float GetLength() const;
|
float GetLength() const;
|
||||||
float GetLengthSquared() const;
|
float GetLengthSquared() const;
|
||||||
static float GetLengthSquared(const Quaternion& q);
|
static float GetLengthSquared(const Quaternion& q);
|
||||||
|
|
||||||
void ToAxisAngleRad(const Quaternion& q, Vector3* const axis, float* angle);
|
void ToAxisAngleRad(const Quaternion& q, Vector3* const axis, float* angle);
|
||||||
static Quaternion FromEulerRad(Vector3 euler);
|
static Quaternion FromEulerRad(Vector3 euler);
|
||||||
|
static Quaternion FromEulerRadXYZ(Vector3 euler);
|
||||||
|
|
||||||
|
Vector3 xyz() const;
|
||||||
Vector3 xyz() const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -2,40 +2,40 @@
|
|||||||
// License, v. 2.0.If a copy of the MPL was not distributed with this
|
// 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/.
|
// file, You can obtain one at https ://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
#include <math.h>
|
|
||||||
#include <float.h>
|
|
||||||
#include "Quaternion.h"
|
#include "Quaternion.h"
|
||||||
|
#include <float.h>
|
||||||
|
#include <math.h>
|
||||||
#include "Vector3.h"
|
#include "Vector3.h"
|
||||||
|
|
||||||
void CopyQuat(const Quat& q1, Quat& q2) {
|
void CopyQuat(const Quat& q1, Quat& q2) {
|
||||||
q2.x = q1.x;
|
q2.x = q1.x;
|
||||||
q2.y = q1.y;
|
q2.y = q1.y;
|
||||||
q2.z = q1.z;
|
q2.z = q1.z;
|
||||||
q2.w = q1.w;
|
q2.w = q1.w;
|
||||||
}
|
}
|
||||||
|
|
||||||
const float Deg2Rad = 0.0174532924F;
|
const float Deg2Rad = 0.0174532924F;
|
||||||
const float Rad2Deg = 57.29578F;
|
const float Rad2Deg = 57.29578F;
|
||||||
|
|
||||||
Quaternion::Quaternion() {
|
Quaternion::Quaternion() {
|
||||||
x = 0;
|
x = 0;
|
||||||
y = 0;
|
y = 0;
|
||||||
z = 0;
|
z = 0;
|
||||||
w = 1;
|
w = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Quaternion::Quaternion(float _x, float _y, float _z, float _w) {
|
Quaternion::Quaternion(float _x, float _y, float _z, float _w) {
|
||||||
x = _x;
|
x = _x;
|
||||||
y = _y;
|
y = _y;
|
||||||
z = _z;
|
z = _z;
|
||||||
w = _w;
|
w = _w;
|
||||||
}
|
}
|
||||||
|
|
||||||
Quaternion::Quaternion(Quat q) {
|
Quaternion::Quaternion(Quat q) {
|
||||||
x = q.x;
|
x = q.x;
|
||||||
y = q.y;
|
y = q.y;
|
||||||
z = q.z;
|
z = q.z;
|
||||||
w = q.w;
|
w = q.w;
|
||||||
}
|
}
|
||||||
|
|
||||||
Quaternion::~Quaternion() {}
|
Quaternion::~Quaternion() {}
|
||||||
@ -43,334 +43,366 @@ Quaternion::~Quaternion() {}
|
|||||||
const Quaternion Quaternion::identity = Quaternion(0, 0, 0, 1);
|
const Quaternion Quaternion::identity = Quaternion(0, 0, 0, 1);
|
||||||
|
|
||||||
Vector3 Quaternion::xyz() const {
|
Vector3 Quaternion::xyz() const {
|
||||||
return Vector3(x, y, z);
|
return Vector3(x, y, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
float Quaternion::GetLength() const {
|
float Quaternion::GetLength() const {
|
||||||
return sqrtf(x * x + y * y + z * z + w * w);
|
return sqrtf(x * x + y * y + z * z + w * w);
|
||||||
}
|
}
|
||||||
|
|
||||||
float Quaternion::GetLengthSquared() const {
|
float Quaternion::GetLengthSquared() const {
|
||||||
return x * x + y * y + z * z + w * w;
|
return x * x + y * y + z * z + w * w;
|
||||||
}
|
}
|
||||||
float Quaternion::GetLengthSquared(const Quaternion& q) {
|
float Quaternion::GetLengthSquared(const Quaternion& q) {
|
||||||
return q.x * q.x + q.y * q.y + q.z * q.z + q.w * q.w;
|
return q.x * q.x + q.y * q.y + q.z * q.z + q.w * q.w;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Quaternion::Normalize() {
|
void Quaternion::Normalize() {
|
||||||
float length = GetLength();
|
float length = GetLength();
|
||||||
x /= length;
|
x /= length;
|
||||||
y /= length;
|
y /= length;
|
||||||
z /= length;
|
z /= length;
|
||||||
w /= length;
|
w /= length;
|
||||||
}
|
}
|
||||||
|
|
||||||
Quaternion Quaternion::Normalize(const Quaternion& q) {
|
Quaternion Quaternion::Normalize(const Quaternion& q) {
|
||||||
Quaternion result;
|
Quaternion result;
|
||||||
float length = q.GetLength();
|
float length = q.GetLength();
|
||||||
result = Quaternion(q.x / length, q.y / length, q.z / length, q.w / length);
|
result = Quaternion(q.x / length, q.y / length, q.z / length, q.w / length);
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
float Quaternion::Dot(Quaternion a, Quaternion b) {
|
float Quaternion::Dot(Quaternion a, Quaternion b) {
|
||||||
return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w;
|
return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3 Quaternion::ToAngles(const Quaternion& q1) {
|
Vector3 Quaternion::ToAngles(const Quaternion& q1) {
|
||||||
float test = q1.x * q1.y + q1.z * q1.w;
|
float test = q1.x * q1.y + q1.z * q1.w;
|
||||||
if (test > 0.499) { // singularity at north pole
|
if (test > 0.499) { // singularity at north pole
|
||||||
return Vector3(
|
return Vector3(0, 2 * (float)atan2(q1.x, q1.w) * Rad2Deg, 90);
|
||||||
0,
|
} else if (test < -0.499) { // singularity at south pole
|
||||||
2 * (float)atan2(q1.x, q1.w) * Rad2Deg,
|
return Vector3(0, -2 * (float)atan2(q1.x, q1.w) * Rad2Deg, -90);
|
||||||
90
|
} else {
|
||||||
);
|
float sqx = q1.x * q1.x;
|
||||||
}
|
float sqy = q1.y * q1.y;
|
||||||
else if (test < -0.499) { // singularity at south pole
|
float sqz = q1.z * q1.z;
|
||||||
return Vector3(
|
|
||||||
0,
|
|
||||||
-2 * (float)atan2(q1.x, q1.w) * Rad2Deg,
|
|
||||||
-90
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
float sqx = q1.x * q1.x;
|
|
||||||
float sqy = q1.y * q1.y;
|
|
||||||
float sqz = q1.z * q1.z;
|
|
||||||
|
|
||||||
return Vector3(
|
return Vector3(
|
||||||
atan2f(2 * q1.x * q1.w - 2 * q1.y * q1.z, 1 - 2 * sqx - 2 * sqz) * Rad2Deg,
|
atan2f(2 * q1.x * q1.w - 2 * q1.y * q1.z, 1 - 2 * sqx - 2 * sqz) *
|
||||||
atan2f(2 * q1.y * q1.w - 2 * q1.x * q1.z, 1 - 2 * sqy - 2 * sqz) * Rad2Deg,
|
Rad2Deg,
|
||||||
asinf(2 * test) * Rad2Deg
|
atan2f(2 * q1.y * q1.w - 2 * q1.x * q1.z, 1 - 2 * sqy - 2 * sqz) *
|
||||||
);
|
Rad2Deg,
|
||||||
}
|
asinf(2 * test) * Rad2Deg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Quaternion Quaternion::operator *(const Quaternion& r2) const {
|
Quaternion Quaternion::operator*(const Quaternion& r2) const {
|
||||||
return Quaternion(
|
return Quaternion(
|
||||||
this->x * r2.w + this->y * r2.z - this->z * r2.y + this->w * r2.x,
|
this->x * r2.w + this->y * r2.z - this->z * r2.y + this->w * r2.x,
|
||||||
-this->x * r2.z + this->y * r2.w + this->z * r2.x + this->w * r2.y,
|
-this->x * r2.z + this->y * r2.w + this->z * r2.x + this->w * r2.y,
|
||||||
this->x * r2.y - this->y * r2.x + this->z * r2.w + this->w * r2.z,
|
this->x * r2.y - this->y * r2.x + this->z * r2.w + this->w * r2.z,
|
||||||
-this->x * r2.x - this->y * r2.y - this->z * r2.z + this->w * r2.w
|
-this->x * r2.x - this->y * r2.y - this->z * r2.z + this->w * r2.w);
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Vector3 Quaternion::operator *(const Vector3& p) const {
|
Vector3 Quaternion::operator*(const Vector3& p) const {
|
||||||
float num = this->x * 2;
|
float num = this->x * 2;
|
||||||
float num2 = this->y * 2;
|
float num2 = this->y * 2;
|
||||||
float num3 = this->z * 2;
|
float num3 = this->z * 2;
|
||||||
float num4 = this->x * num;
|
float num4 = this->x * num;
|
||||||
float num5 = this->y * num2;
|
float num5 = this->y * num2;
|
||||||
float num6 = this->z * num3;
|
float num6 = this->z * num3;
|
||||||
float num7 = this->x * num2;
|
float num7 = this->x * num2;
|
||||||
float num8 = this->x * num3;
|
float num8 = this->x * num3;
|
||||||
float num9 = this->y * num3;
|
float num9 = this->y * num3;
|
||||||
float num10 = this->w * num;
|
float num10 = this->w * num;
|
||||||
float num11 = this->w * num2;
|
float num11 = this->w * num2;
|
||||||
float num12 = this->w * num3;
|
float num12 = this->w * num3;
|
||||||
Vector3 result = Vector3::zero;
|
Vector3 result = Vector3::zero;
|
||||||
result.x = (1 - (num5 + num6)) * p.x + (num7 - num12) * p.y + (num8 + num11) * p.z;
|
result.x =
|
||||||
result.y = (num7 + num12) * p.x + (1 - (num4 + num6)) * p.y + (num9 - num10) * p.z;
|
(1 - (num5 + num6)) * p.x + (num7 - num12) * p.y + (num8 + num11) * p.z;
|
||||||
result.z = (num8 - num11) * p.x + (num9 + num10) * p.y + (1 - (num4 + num5)) * p.z;
|
result.y =
|
||||||
return result;
|
(num7 + num12) * p.x + (1 - (num4 + num6)) * p.y + (num9 - num10) * p.z;
|
||||||
|
result.z =
|
||||||
|
(num8 - num11) * p.x + (num9 + num10) * p.y + (1 - (num4 + num5)) * p.z;
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Quaternion::operator==(const Quaternion& q) {
|
bool Quaternion::operator==(const Quaternion& q) {
|
||||||
return (this->x == q.x && this->y == q.y && this->z == q.z && this->w == q.w);
|
return (this->x == q.x && this->y == q.y && this->z == q.z && this->w == q.w);
|
||||||
}
|
}
|
||||||
|
|
||||||
Quaternion Quaternion::Inverse(Quaternion r) {
|
Quaternion Quaternion::Inverse(Quaternion r) {
|
||||||
float n = sqrtf(r.x * r.x + r.y * r.y + r.z * r.z + r.w * r.w);
|
float n = sqrtf(r.x * r.x + r.y * r.y + r.z * r.z + r.w * r.w);
|
||||||
return Quaternion(-r.x / n, -r.y / n, -r.z / n, r.w / n);
|
return Quaternion(-r.x / n, -r.y / n, -r.z / n, r.w / n);
|
||||||
}
|
}
|
||||||
|
|
||||||
Quaternion Quaternion::LookRotation(const Vector3& forward) {
|
Quaternion Quaternion::LookRotation(const Vector3& forward) {
|
||||||
Vector3 up = Vector3(0, 1, 0);
|
Vector3 up = Vector3(0, 1, 0);
|
||||||
return LookRotation(forward, up);
|
return LookRotation(forward, up);
|
||||||
}
|
}
|
||||||
Quaternion Quaternion::LookRotation(const Vector3& forward, const Vector3& up) {
|
Quaternion Quaternion::LookRotation(const Vector3& forward, const Vector3& up) {
|
||||||
Vector3 nForward = Vector3::Normalize(forward);
|
Vector3 nForward = Vector3::Normalize(forward);
|
||||||
Vector3 nRight = Vector3::Normalize(Vector3::Cross(up, nForward));
|
Vector3 nRight = Vector3::Normalize(Vector3::Cross(up, nForward));
|
||||||
Vector3 nUp = Vector3::Cross(nForward, nRight);
|
Vector3 nUp = Vector3::Cross(nForward, nRight);
|
||||||
float m00 = nRight.x;
|
float m00 = nRight.x;
|
||||||
float m01 = nRight.y;
|
float m01 = nRight.y;
|
||||||
float m02 = nRight.z;
|
float m02 = nRight.z;
|
||||||
float m10 = nUp.x;
|
float m10 = nUp.x;
|
||||||
float m11 = nUp.y;
|
float m11 = nUp.y;
|
||||||
float m12 = nUp.z;
|
float m12 = nUp.z;
|
||||||
float m20 = nForward.x;
|
float m20 = nForward.x;
|
||||||
float m21 = nForward.y;
|
float m21 = nForward.y;
|
||||||
float m22 = nForward.z;
|
float m22 = nForward.z;
|
||||||
|
|
||||||
|
float num8 = (m00 + m11) + m22;
|
||||||
float num8 = (m00 + m11) + m22;
|
Quaternion quaternion = Quaternion();
|
||||||
Quaternion quaternion = Quaternion();
|
if (num8 > 0) {
|
||||||
if (num8 > 0) {
|
float num = sqrtf(num8 + 1);
|
||||||
float num = sqrtf(num8 + 1);
|
quaternion.w = num * 0.5f;
|
||||||
quaternion.w = num * 0.5f;
|
num = 0.5f / num;
|
||||||
num = 0.5f / num;
|
quaternion.x = (m12 - m21) * num;
|
||||||
quaternion.x = (m12 - m21) * num;
|
quaternion.y = (m20 - m02) * num;
|
||||||
quaternion.y = (m20 - m02) * num;
|
quaternion.z = (m01 - m10) * num;
|
||||||
quaternion.z = (m01 - m10) * num;
|
return quaternion;
|
||||||
return quaternion;
|
}
|
||||||
}
|
if ((m00 >= m11) && (m00 >= m22)) {
|
||||||
if ((m00 >= m11) && (m00 >= m22)) {
|
float num7 = sqrtf(((1 + m00) - m11) - m22);
|
||||||
float num7 = sqrtf(((1 + m00) - m11) - m22);
|
float num4 = 0.5F / num7;
|
||||||
float num4 = 0.5F / num7;
|
quaternion.x = 0.5f * num7;
|
||||||
quaternion.x = 0.5f * num7;
|
quaternion.y = (m01 + m10) * num4;
|
||||||
quaternion.y = (m01 + m10) * num4;
|
quaternion.z = (m02 + m20) * num4;
|
||||||
quaternion.z = (m02 + m20) * num4;
|
quaternion.w = (m12 - m21) * num4;
|
||||||
quaternion.w = (m12 - m21) * num4;
|
return quaternion;
|
||||||
return quaternion;
|
}
|
||||||
}
|
if (m11 > m22) {
|
||||||
if (m11 > m22) {
|
float num6 = sqrtf(((1 + m11) - m00) - m22);
|
||||||
float num6 = sqrtf(((1 + m11) - m00) - m22);
|
float num3 = 0.5F / num6;
|
||||||
float num3 = 0.5F / num6;
|
quaternion.x = (m10 + m01) * num3;
|
||||||
quaternion.x = (m10 + m01) * num3;
|
quaternion.y = 0.5F * num6;
|
||||||
quaternion.y = 0.5F * num6;
|
quaternion.z = (m21 + m12) * num3;
|
||||||
quaternion.z = (m21 + m12) * num3;
|
quaternion.w = (m20 - m02) * num3;
|
||||||
quaternion.w = (m20 - m02) * num3;
|
return quaternion;
|
||||||
return quaternion;
|
}
|
||||||
}
|
float num5 = sqrtf(((1 + m22) - m00) - m11);
|
||||||
float num5 = sqrtf(((1 + m22) - m00) - m11);
|
float num2 = 0.5F / num5;
|
||||||
float num2 = 0.5F / num5;
|
quaternion.x = (m20 + m02) * num2;
|
||||||
quaternion.x = (m20 + m02) * num2;
|
quaternion.y = (m21 + m12) * num2;
|
||||||
quaternion.y = (m21 + m12) * num2;
|
quaternion.z = 0.5F * num5;
|
||||||
quaternion.z = 0.5F * num5;
|
quaternion.w = (m01 - m10) * num2;
|
||||||
quaternion.w = (m01 - m10) * num2;
|
return quaternion;
|
||||||
return quaternion;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Quaternion Quaternion::FromToRotation(Vector3 fromDirection, Vector3 toDirection) {
|
Quaternion Quaternion::FromToRotation(Vector3 fromDirection,
|
||||||
Vector3 axis = Vector3::Cross(fromDirection, toDirection);
|
Vector3 toDirection) {
|
||||||
axis = Vector3::Normalize(axis);
|
Vector3 axis = Vector3::Cross(fromDirection, toDirection);
|
||||||
float angle = Vector3::SignedAngle(fromDirection, toDirection, axis);
|
axis = Vector3::Normalize(axis);
|
||||||
Quaternion rotation = Quaternion::AngleAxis(angle, axis);
|
float angle = Vector3::SignedAngle(fromDirection, toDirection, axis);
|
||||||
return rotation;
|
Quaternion rotation = Quaternion::AngleAxis(angle, axis);
|
||||||
|
return rotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
Quaternion Quaternion::RotateTowards(const Quaternion& from, const Quaternion& to, float maxDegreesDelta) {
|
Quaternion Quaternion::RotateTowards(const Quaternion& from,
|
||||||
float num = Quaternion::Angle(from, to);
|
const Quaternion& to,
|
||||||
if (num == 0) {
|
float maxDegreesDelta) {
|
||||||
return to;
|
float num = Quaternion::Angle(from, to);
|
||||||
}
|
if (num == 0) {
|
||||||
float t = (float)fmin(1, maxDegreesDelta / num);
|
return to;
|
||||||
return SlerpUnclamped(from, to, t);
|
}
|
||||||
|
float t = (float)fmin(1, maxDegreesDelta / num);
|
||||||
|
return SlerpUnclamped(from, to, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
Quaternion Quaternion::AngleAxis(float angle, const Vector3& axis) {
|
Quaternion Quaternion::AngleAxis(float angle, const Vector3& axis) {
|
||||||
if (Vector3::SqrMagnitude(axis) == 0.0)
|
if (Vector3::SqrMagnitude(axis) == 0.0)
|
||||||
return Quaternion();
|
return Quaternion();
|
||||||
|
|
||||||
Quaternion result = Quaternion();
|
Quaternion result = Quaternion();
|
||||||
float radians = angle * Deg2Rad;
|
float radians = angle * Deg2Rad;
|
||||||
radians *= 0.5;
|
radians *= 0.5;
|
||||||
|
|
||||||
Vector3 axis2 = axis * (float)sin(radians);
|
Vector3 axis2 = axis * (float)sin(radians);
|
||||||
result.x = axis2.x;
|
result.x = axis2.x;
|
||||||
result.y = axis2.y;
|
result.y = axis2.y;
|
||||||
result.z = axis2.z;
|
result.z = axis2.z;
|
||||||
result.w = (float)cos(radians);
|
result.w = (float)cos(radians);
|
||||||
|
|
||||||
return Quaternion::Normalize(result);
|
return Quaternion::Normalize(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
float Quaternion::Angle(Quaternion a, Quaternion b) {
|
float Quaternion::Angle(Quaternion a, Quaternion b) {
|
||||||
float f = Quaternion::Dot(a, b);
|
float f = Quaternion::Dot(a, b);
|
||||||
return (float)acos(fmin(fabs(f), 1)) * 2 * Rad2Deg;
|
return (float)acos(fmin(fabs(f), 1)) * 2 * Rad2Deg;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Quaternion::ToAngleAxis(float* angle, Vector3* axis)
|
void Quaternion::ToAngleAxis(float* angle, Vector3* axis) {
|
||||||
{
|
Quaternion::ToAxisAngleRad(*this, axis, angle);
|
||||||
Quaternion::ToAxisAngleRad(*this, axis, angle);
|
*angle *= Rad2Deg;
|
||||||
*angle *= Rad2Deg;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Quaternion::ToAxisAngleRad(const Quaternion& q, Vector3* const axis, float* angle)
|
void Quaternion::ToAxisAngleRad(const Quaternion& q,
|
||||||
{
|
Vector3* const axis,
|
||||||
Quaternion q1 = (fabs(q.w) > 1.0f) ? Quaternion::Normalize(q) : q;
|
float* angle) {
|
||||||
*angle = 2.0f * acosf(q1.w); // angle
|
Quaternion q1 = (fabs(q.w) > 1.0f) ? Quaternion::Normalize(q) : q;
|
||||||
float den = sqrtf(1.0F - q1.w * q1.w);
|
*angle = 2.0f * acosf(q1.w); // angle
|
||||||
if (den > 0.0001f)
|
float den = sqrtf(1.0F - q1.w * q1.w);
|
||||||
{
|
if (den > 0.0001f) {
|
||||||
*axis = q1.xyz() / den;
|
*axis = q1.xyz() / den;
|
||||||
}
|
} else {
|
||||||
else
|
// This occurs when the angle is zero.
|
||||||
{
|
// Not a problem: just set an arbitrary normalized axis.
|
||||||
// This occurs when the angle is zero.
|
*axis = Vector3(1, 0, 0);
|
||||||
// Not a problem: just set an arbitrary normalized axis.
|
}
|
||||||
*axis = Vector3(1, 0, 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Quaternion Quaternion::SlerpUnclamped(const Quaternion& a, const Quaternion& b, float t) {
|
Quaternion Quaternion::SlerpUnclamped(const Quaternion& a,
|
||||||
// if either input is zero, return the other.
|
const Quaternion& b,
|
||||||
if (Quaternion::GetLengthSquared(a) == 0.0) {
|
float t) {
|
||||||
if (Quaternion::GetLengthSquared(b) == 0.0) {
|
// if either input is zero, return the other.
|
||||||
return Quaternion();
|
if (Quaternion::GetLengthSquared(a) == 0.0) {
|
||||||
}
|
if (Quaternion::GetLengthSquared(b) == 0.0) {
|
||||||
return b;
|
return Quaternion();
|
||||||
}
|
}
|
||||||
else if (Quaternion::GetLengthSquared(b) == 0.0f) {
|
return b;
|
||||||
return a;
|
} else if (Quaternion::GetLengthSquared(b) == 0.0f) {
|
||||||
}
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
const Vector3 axyz = a.xyz();
|
const Vector3 axyz = a.xyz();
|
||||||
const Vector3 bxyz = b.xyz();
|
const Vector3 bxyz = b.xyz();
|
||||||
float cosHalfAngle = a.w * b.w + Vector3::Dot(axyz, bxyz);
|
float cosHalfAngle = a.w * b.w + Vector3::Dot(axyz, bxyz);
|
||||||
|
|
||||||
Quaternion b2 = b;
|
Quaternion b2 = b;
|
||||||
if (cosHalfAngle >= 1.0f || cosHalfAngle <= -1.0f) {
|
if (cosHalfAngle >= 1.0f || cosHalfAngle <= -1.0f) {
|
||||||
// angle = 0.0f, so just return one input.
|
// angle = 0.0f, so just return one input.
|
||||||
return a;
|
return a;
|
||||||
}
|
} else if (cosHalfAngle < 0.0f) {
|
||||||
else if (cosHalfAngle < 0.0f) {
|
b2.x = -b.x;
|
||||||
b2.x = -b.x;
|
b2.y = -b.y;
|
||||||
b2.y = -b.y;
|
b2.z = -b.z;
|
||||||
b2.z = -b.z;
|
b2.w = -b.w;
|
||||||
b2.w = -b.w;
|
cosHalfAngle = -cosHalfAngle;
|
||||||
cosHalfAngle = -cosHalfAngle;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
float blendA;
|
float blendA;
|
||||||
float blendB;
|
float blendB;
|
||||||
if (cosHalfAngle < 0.99f) {
|
if (cosHalfAngle < 0.99f) {
|
||||||
// do proper slerp for big angles
|
// do proper slerp for big angles
|
||||||
float halfAngle = acosf(cosHalfAngle);
|
float halfAngle = acosf(cosHalfAngle);
|
||||||
float sinHalfAngle = sinf(halfAngle);
|
float sinHalfAngle = sinf(halfAngle);
|
||||||
float oneOverSinHalfAngle = 1.0F / sinHalfAngle;
|
float oneOverSinHalfAngle = 1.0F / sinHalfAngle;
|
||||||
blendA = sinf(halfAngle * (1.0F - t)) * oneOverSinHalfAngle;
|
blendA = sinf(halfAngle * (1.0F - t)) * oneOverSinHalfAngle;
|
||||||
blendB = sinf(halfAngle * t) * oneOverSinHalfAngle;
|
blendB = sinf(halfAngle * t) * oneOverSinHalfAngle;
|
||||||
}
|
} else {
|
||||||
else {
|
// do lerp if angle is really small.
|
||||||
// do lerp if angle is really small.
|
blendA = 1.0f - t;
|
||||||
blendA = 1.0f - t;
|
blendB = t;
|
||||||
blendB = t;
|
}
|
||||||
}
|
Vector3 v = axyz * blendA + b2.xyz() * blendB;
|
||||||
Vector3 v = axyz * blendA + b2.xyz() * blendB;
|
Quaternion result = Quaternion(v.x, v.y, v.z, blendA * a.w + blendB * b2.w);
|
||||||
Quaternion result = Quaternion(v.x, v.y, v.z, blendA * a.w + blendB * b2.w);
|
if (result.GetLengthSquared() > 0.0f)
|
||||||
if (result.GetLengthSquared() > 0.0f)
|
return Quaternion::Normalize(result);
|
||||||
return Quaternion::Normalize(result);
|
else
|
||||||
else
|
return Quaternion();
|
||||||
return Quaternion();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Quaternion Quaternion::Slerp(const Quaternion& a, const Quaternion& b, float t) {
|
Quaternion Quaternion::Slerp(const Quaternion& a,
|
||||||
if (t > 1) t = 1;
|
const Quaternion& b,
|
||||||
if (t < 0) t = 0;
|
float t) {
|
||||||
return Quaternion::SlerpUnclamped(a, b, t);
|
if (t > 1)
|
||||||
|
t = 1;
|
||||||
|
if (t < 0)
|
||||||
|
t = 0;
|
||||||
|
return Quaternion::SlerpUnclamped(a, b, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
Quaternion Quaternion::Euler(float x, float y, float z) {
|
Quaternion Quaternion::Euler(float x, float y, float z) {
|
||||||
return Quaternion::Euler(Vector3(x, y, z));
|
return Quaternion::Euler(Vector3(x, y, z));
|
||||||
}
|
}
|
||||||
Quaternion Quaternion::Euler(Vector3 euler) {
|
Quaternion Quaternion::Euler(Vector3 euler) {
|
||||||
return Quaternion::FromEulerRad(euler * Deg2Rad);
|
return Quaternion::FromEulerRad(euler * Deg2Rad);
|
||||||
}
|
}
|
||||||
|
|
||||||
Quaternion Quaternion::FromEulerRad(Vector3 euler) {
|
Quaternion Quaternion::FromEulerRad(Vector3 euler) {
|
||||||
float yaw = euler.x;
|
float yaw = euler.x;
|
||||||
float pitch = euler.y;
|
float pitch = euler.y;
|
||||||
float roll = euler.z;
|
float roll = euler.z;
|
||||||
float rollOver2 = roll * 0.5f;
|
float rollOver2 = roll * 0.5f;
|
||||||
float sinRollOver2 = (float)sin((float)rollOver2);
|
float sinRollOver2 = (float)sin((float)rollOver2);
|
||||||
float cosRollOver2 = (float)cos((float)rollOver2);
|
float cosRollOver2 = (float)cos((float)rollOver2);
|
||||||
float pitchOver2 = pitch * 0.5f;
|
float pitchOver2 = pitch * 0.5f;
|
||||||
float sinPitchOver2 = (float)sin((float)pitchOver2);
|
float sinPitchOver2 = (float)sin((float)pitchOver2);
|
||||||
float cosPitchOver2 = (float)cos((float)pitchOver2);
|
float cosPitchOver2 = (float)cos((float)pitchOver2);
|
||||||
float yawOver2 = yaw * 0.5f;
|
float yawOver2 = yaw * 0.5f;
|
||||||
float sinYawOver2 = (float)sin((float)yawOver2);
|
float sinYawOver2 = (float)sin((float)yawOver2);
|
||||||
float cosYawOver2 = (float)cos((float)yawOver2);
|
float cosYawOver2 = (float)cos((float)yawOver2);
|
||||||
Quaternion result;
|
Quaternion result;
|
||||||
result.w = cosYawOver2 * cosPitchOver2 * cosRollOver2 + sinYawOver2 * sinPitchOver2 * sinRollOver2;
|
result.w = cosYawOver2 * cosPitchOver2 * cosRollOver2 +
|
||||||
result.x = sinYawOver2 * cosPitchOver2 * cosRollOver2 + cosYawOver2 * sinPitchOver2 * sinRollOver2;
|
sinYawOver2 * sinPitchOver2 * sinRollOver2;
|
||||||
result.y = cosYawOver2 * sinPitchOver2 * cosRollOver2 - sinYawOver2 * cosPitchOver2 * sinRollOver2;
|
result.x = sinYawOver2 * cosPitchOver2 * cosRollOver2 +
|
||||||
result.z = cosYawOver2 * cosPitchOver2 * sinRollOver2 - sinYawOver2 * sinPitchOver2 * cosRollOver2;
|
cosYawOver2 * sinPitchOver2 * sinRollOver2;
|
||||||
return result;
|
result.y = cosYawOver2 * sinPitchOver2 * cosRollOver2 -
|
||||||
|
sinYawOver2 * cosPitchOver2 * sinRollOver2;
|
||||||
|
result.z = cosYawOver2 * cosPitchOver2 * sinRollOver2 -
|
||||||
|
sinYawOver2 * sinPitchOver2 * cosRollOver2;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Quaternion Quaternion::EulerXYZ(float x, float y, float z) {
|
||||||
|
return Quaternion::EulerXYZ(Vector3(x, y, z));
|
||||||
|
}
|
||||||
|
Quaternion Quaternion::EulerXYZ(Vector3 euler) {
|
||||||
|
return Quaternion::FromEulerRadXYZ(euler * Deg2Rad);
|
||||||
|
}
|
||||||
|
Quaternion Quaternion::FromEulerRadXYZ(Vector3 euler) {
|
||||||
|
float yaw = euler.x;
|
||||||
|
float pitch = euler.y;
|
||||||
|
float roll = euler.z;
|
||||||
|
float rollOver2 = roll * 0.5f;
|
||||||
|
float sinRollOver2 = (float)sin((float)rollOver2);
|
||||||
|
float cosRollOver2 = (float)cos((float)rollOver2);
|
||||||
|
float pitchOver2 = pitch * 0.5f;
|
||||||
|
float sinPitchOver2 = (float)sin((float)pitchOver2);
|
||||||
|
float cosPitchOver2 = (float)cos((float)pitchOver2);
|
||||||
|
float yawOver2 = yaw * 0.5f;
|
||||||
|
float sinYawOver2 = (float)sin((float)yawOver2);
|
||||||
|
float cosYawOver2 = (float)cos((float)yawOver2);
|
||||||
|
Quaternion result;
|
||||||
|
result.w = cosYawOver2 * cosPitchOver2 * cosRollOver2 +
|
||||||
|
sinYawOver2 * sinPitchOver2 * sinRollOver2;
|
||||||
|
result.x = sinYawOver2 * cosPitchOver2 * cosRollOver2 -
|
||||||
|
cosYawOver2 * sinPitchOver2 * sinRollOver2;
|
||||||
|
result.y = cosYawOver2 * sinPitchOver2 * cosRollOver2 +
|
||||||
|
sinYawOver2 * cosPitchOver2 * sinRollOver2;
|
||||||
|
result.z = cosYawOver2 * cosPitchOver2 * sinRollOver2 -
|
||||||
|
sinYawOver2 * sinPitchOver2 * cosRollOver2;
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
float Quaternion::GetAngleAround(Vector3 axis, Quaternion rotation) {
|
float Quaternion::GetAngleAround(Vector3 axis, Quaternion rotation) {
|
||||||
Quaternion secondaryRotation = GetRotationAround(axis, rotation);
|
Quaternion secondaryRotation = GetRotationAround(axis, rotation);
|
||||||
float rotationAngle;
|
float rotationAngle;
|
||||||
Vector3 rotationAxis;
|
Vector3 rotationAxis;
|
||||||
secondaryRotation.ToAngleAxis(&rotationAngle, &rotationAxis);
|
secondaryRotation.ToAngleAxis(&rotationAngle, &rotationAxis);
|
||||||
|
|
||||||
// Do the axis point in opposite directions?
|
// Do the axis point in opposite directions?
|
||||||
if (Vector3::Dot(axis, rotationAxis) < 0)
|
if (Vector3::Dot(axis, rotationAxis) < 0)
|
||||||
rotationAngle = -rotationAngle;
|
rotationAngle = -rotationAngle;
|
||||||
|
|
||||||
return rotationAngle;
|
return rotationAngle;
|
||||||
}
|
}
|
||||||
|
|
||||||
Quaternion Quaternion::GetRotationAround(Vector3 axis, Quaternion rotation) {
|
Quaternion Quaternion::GetRotationAround(Vector3 axis, Quaternion rotation) {
|
||||||
Vector3 ra = Vector3(rotation.x, rotation.y, rotation.z); // rotation axis
|
Vector3 ra = Vector3(rotation.x, rotation.y, rotation.z); // rotation axis
|
||||||
Vector3 p = Vector3::Project(ra, axis); // return projection ra on to axis (parallel component)
|
Vector3 p = Vector3::Project(
|
||||||
Quaternion twist = Quaternion(p.x, p.y, p.z, rotation.w);
|
ra, axis); // return projection ra on to axis (parallel component)
|
||||||
twist = Quaternion::Normalize(twist);
|
Quaternion twist = Quaternion(p.x, p.y, p.z, rotation.w);
|
||||||
return twist;
|
twist = Quaternion::Normalize(twist);
|
||||||
|
return twist;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Quaternion::GetSwingTwist(Vector3 axis, Quaternion rotation, Quaternion* swing, Quaternion* twist) {
|
void Quaternion::GetSwingTwist(Vector3 axis,
|
||||||
*twist = GetRotationAround(axis, rotation);
|
Quaternion rotation,
|
||||||
*swing = rotation * Quaternion::Inverse(*twist);
|
Quaternion* swing,
|
||||||
|
Quaternion* twist) {
|
||||||
|
*twist = GetRotationAround(axis, rotation);
|
||||||
|
*swing = rotation * Quaternion::Inverse(*twist);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user