Documentation for Quaternion

Former-commit-id: b19bd792823e1f49ff088fc95be26f0db185a8a6
This commit is contained in:
Gawaboumga 2015-12-30 15:33:26 +01:00
parent 40d3d6b235
commit 9efce81eac
2 changed files with 416 additions and 57 deletions

View File

@ -19,9 +19,9 @@ namespace Nz
public: public:
Quaternion() = default; Quaternion() = default;
Quaternion(T W, T X, T Y, T Z); Quaternion(T W, T X, T Y, T Z);
Quaternion(const T quat[4]);
Quaternion(T angle, const Vector3<T>& axis);
Quaternion(const EulerAngles<T>& angles); Quaternion(const EulerAngles<T>& angles);
Quaternion(T angle, const Vector3<T>& axis);
Quaternion(const T quat[4]);
//Quaternion(const Matrix3<T>& mat); //Quaternion(const Matrix3<T>& mat);
template<typename U> explicit Quaternion(const Quaternion<U>& quat); template<typename U> explicit Quaternion(const Quaternion<U>& quat);
Quaternion(const Quaternion& quat) = default; Quaternion(const Quaternion& quat) = default;
@ -47,9 +47,9 @@ namespace Nz
Quaternion& Normalize(T* length = nullptr); Quaternion& Normalize(T* length = nullptr);
Quaternion& Set(T W, T X, T Y, T Z); Quaternion& Set(T W, T X, T Y, T Z);
Quaternion& Set(const T quat[4]);
Quaternion& Set(T angle, const Vector3<T>& normalizedAxis);
Quaternion& Set(const EulerAngles<T>& angles); Quaternion& Set(const EulerAngles<T>& angles);
Quaternion& Set(T angle, const Vector3<T>& normalizedAxis);
Quaternion& Set(const T quat[4]);
//Quaternion& Set(const Matrix3<T>& mat); //Quaternion& Set(const Matrix3<T>& mat);
Quaternion& Set(const Quaternion& quat); Quaternion& Set(const Quaternion& quat);
template<typename U> Quaternion& Set(const Quaternion<U>& quat); template<typename U> Quaternion& Set(const Quaternion<U>& quat);
@ -60,7 +60,7 @@ namespace Nz
//Matrix3<T> ToRotationMatrix() const; //Matrix3<T> ToRotationMatrix() const;
String ToString() const; String ToString() const;
Quaternion& operator=(const Quaternion& quat); Quaternion& operator=(const Quaternion& quat) = default;
Quaternion operator+(const Quaternion& quat) const; Quaternion operator+(const Quaternion& quat) const;
Quaternion operator*(const Quaternion& quat) const; Quaternion operator*(const Quaternion& quat) const;

View File

@ -15,29 +15,67 @@
namespace Nz namespace Nz
{ {
/*!
* \class Nz::Quaternion<T>
* \brief Math class that represents an element of the quaternions
*
* \remark The quaternion is meant to be 'unit' to represent rotations in a three dimensional space
*/
/*!
* \brief Constructs a Quaternion<T> object from its components
*
* \param W W component
* \param X X component
* \param Y Y component
* \param Z Z component
*/
template<typename T> template<typename T>
Quaternion<T>::Quaternion(T W, T X, T Y, T Z) Quaternion<T>::Quaternion(T W, T X, T Y, T Z)
{ {
Set(W, X, Y, Z); Set(W, X, Y, Z);
} }
/*!
* \brief Constructs a Quaternion<T> object from a EulerAngles
*
* \param angles Easier representation of rotation of space
*
* \see EulerAngles
*/
template<typename T> template<typename T>
Quaternion<T>::Quaternion(const T quat[4]) Quaternion<T>::Quaternion(const EulerAngles<T>& angles)
{ {
Set(quat); Set(angles);
} }
/*!
* \brief Constructs a Quaternion<T> object from an angle and a direction
*
* \param angle Unit depends of NAZARA_MATH_ANGLE_RADIAN
* \param axis Vector3 which represents a direction, no need to be normalized
*/
template<typename T> template<typename T>
Quaternion<T>::Quaternion(T angle, const Vector3<T>& axis) Quaternion<T>::Quaternion(T angle, const Vector3<T>& axis)
{ {
Set(angle, axis); Set(angle, axis);
} }
/*!
* \brief Constructs a Quaternion<T> object from an array of four elements
*
* \param quat[4] quat[0] is W component, quat[1] is X component, quat[2] is Y component and quat[3] is Z component
*/
template<typename T> template<typename T>
Quaternion<T>::Quaternion(const EulerAngles<T>& angles) Quaternion<T>::Quaternion(const T quat[4])
{ {
Set(angles); Set(quat);
} }
/* /*
template<typename T> template<typename T>
Quaternion<T>::Quaternion(const Matrix3<T>& mat) Quaternion<T>::Quaternion(const Matrix3<T>& mat)
@ -45,6 +83,13 @@ namespace Nz
Set(mat); Set(mat);
} }
*/ */
/*!
* \brief Constructs a Quaternion<T> object from another type of Quaternion
*
* \param quat Quaternion of type U to convert to type T
*/
template<typename T> template<typename T>
template<typename U> template<typename U>
Quaternion<T>::Quaternion(const Quaternion<U>& quat) Quaternion<T>::Quaternion(const Quaternion<U>& quat)
@ -52,6 +97,11 @@ namespace Nz
Set(quat); Set(quat);
} }
/*!
* \brief Computes the w component of the quaternion to make it unit
* \return A reference to this quaternion
*/
template<typename T> template<typename T>
Quaternion<T>& Quaternion<T>::ComputeW() Quaternion<T>& Quaternion<T>::ComputeW()
{ {
@ -65,6 +115,15 @@ namespace Nz
return *this; return *this;
} }
/*!
* \brief Returns the rotational conjugate of this quaternion
* \return A reference to this quaternion
*
* The conjugate of a quaternion represents the same rotation in the opposite direction about the rotational axis
*
* \see GetConjugate
*/
template<typename T> template<typename T>
Quaternion<T>& Quaternion<T>::Conjugate() Quaternion<T>& Quaternion<T>::Conjugate()
{ {
@ -75,12 +134,28 @@ namespace Nz
return *this; return *this;
} }
/*!
* \brief Calculates the dot (scalar) product with two quaternions
* \return The value of the dot product
*
* \param quat The other quaternion to calculate the dot product with
*/
template<typename T> template<typename T>
T Quaternion<T>::DotProduct(const Quaternion& quat) const T Quaternion<T>::DotProduct(const Quaternion& quat) const
{ {
return w*quat.w + x*quat.x + y*quat.y + z*quat.z; return w * quat.w + x * quat.x + y * quat.y + z * quat.z;
} }
/*!
* \brief Gets the rotational conjugate of this quaternion
* \return A new quaternion which is the conjugate of this quaternion
*
* The conjugate of a quaternion represents the same rotation in the opposite direction about the rotational axis
*
* \see Conjugate
*/
template<typename T> template<typename T>
Quaternion<T> Quaternion<T>::GetConjugate() const Quaternion<T> Quaternion<T>::GetConjugate() const
{ {
@ -90,6 +165,15 @@ namespace Nz
return quat; return quat;
} }
/*!
* \brief Gets the inverse of this quaternion
* \return A new quaternion which is the inverse of this quaternion
*
* \remark If this quaternion is (0, 0, 0, 0), then it returns (0, 0, 0, 0)
*
* \see Inverse
*/
template<typename T> template<typename T>
Quaternion<T> Quaternion<T>::GetInverse() const Quaternion<T> Quaternion<T>::GetInverse() const
{ {
@ -99,6 +183,17 @@ namespace Nz
return quat; return quat;
} }
/*!
* \brief Gets the normalization of this quaternion
* \return A new quaternion which is the normalization of this quaternion
*
* \param length Optional argument to obtain the length's ratio of the quaternion and the unit-length
*
* \remark If this quaternion is (0, 0, 0, 0), then it returns (0, 0, 0, 0) and length is 0
*
* \see Normalize
*/
template<typename T> template<typename T>
Quaternion<T> Quaternion<T>::GetNormal(T* length) const Quaternion<T> Quaternion<T>::GetNormal(T* length) const
{ {
@ -108,6 +203,15 @@ namespace Nz
return quat; return quat;
} }
/*!
* \brief Inverts this quaternion
* \return A reference to this quaternion which is now inverted
*
* \remark If this quaternion is (0, 0, 0, 0), then it returns (0, 0, 0, 0)
*
* \see GetInverse
*/
template<typename T> template<typename T>
Quaternion<T>& Quaternion<T>::Inverse() Quaternion<T>& Quaternion<T>::Inverse()
{ {
@ -125,15 +229,34 @@ namespace Nz
return *this; return *this;
} }
/*!
* \brief Makes the quaternion (1, 0, 0, 0)
* \return A reference to this vector with components (1, 0, 0, 0)
*
* \see Unit
*/
template<typename T> template<typename T>
Quaternion<T>& Quaternion<T>::MakeIdentity() Quaternion<T>& Quaternion<T>::MakeIdentity()
{ {
return Set(F(1.0), F(0.0), F(0.0), F(0.0)); return Set(F(1.0), F(0.0), F(0.0), F(0.0));
} }
/*!
* \brief Makes this quaternion to the rotation required to rotate direction Vector3 from to direction Vector3 to
* \return A reference to this vector which is the rotation needed
*
* \param from Initial vector
* \param to Target vector
*
* \see RotationBetween
*/
template<typename T> template<typename T>
Quaternion<T>& Quaternion<T>::MakeRotationBetween(const Vector3<T>& from, const Vector3<T>& to) Quaternion<T>& Quaternion<T>::MakeRotationBetween(const Vector3<T>& from, const Vector3<T>& to)
{ {
// TODO (Gawaboumga): Replace by http://lolengine.net/blog/2013/09/18/beautiful-maths-quaternion-from-vectors ?
T dot = from.DotProduct(to); T dot = from.DotProduct(to);
if (NumberEquals(dot, F(-1.0))) if (NumberEquals(dot, F(-1.0)))
{ {
@ -157,28 +280,55 @@ namespace Nz
} }
} }
/*!
* \brief Makes the quaternion (0, 0, 0, 0)
* \return A reference to this vector with components (0, 0, 0, 0)
*
* \see Zero
*/
template<typename T> template<typename T>
Quaternion<T>& Quaternion<T>::MakeZero() Quaternion<T>& Quaternion<T>::MakeZero()
{ {
return Set(F(0.0), F(0.0), F(0.0), F(0.0)); return Set(F(0.0), F(0.0), F(0.0), F(0.0));
} }
/*!
* \brief Calculates the magnitude (length) of the quaternion
* \return The magnitude
*
* \see SquaredMagnitude
*/
template<typename T> template<typename T>
T Quaternion<T>::Magnitude() const T Quaternion<T>::Magnitude() const
{ {
return std::sqrt(SquaredMagnitude()); return std::sqrt(SquaredMagnitude());
} }
/*!
* \brief Normalizes the current quaternion
* \return A reference to this quaternion which is now normalized
*
* \param length Optional argument to obtain the length's ratio of the quaternion and the unit-length
*
* \remark If the quaternion is (0, 0, 0, 0), then it returns (0, 0, 0, 0) and length is 0
*
* \see GetNormal
*/
template<typename T> template<typename T>
Quaternion<T>& Quaternion<T>::Normalize(T* length) Quaternion<T>& Quaternion<T>::Normalize(T* length)
{ {
T norm = std::sqrt(SquaredMagnitude()); T norm = std::sqrt(SquaredMagnitude());
T invNorm = F(1.0) / norm; if (norm > F(0.0))
{
w *= invNorm; T invNorm = F(1.0) / norm;
x *= invNorm; w *= invNorm;
y *= invNorm; x *= invNorm;
z *= invNorm; y *= invNorm;
z *= invNorm;
}
if (length) if (length)
*length = norm; *length = norm;
@ -186,6 +336,16 @@ namespace Nz
return *this; return *this;
} }
/*!
* \brief Sets the components of the quaternion
* \return A reference to this quaternion
*
* \param W W component
* \param X X component
* \param Y Y component
* \param Z Z component
*/
template<typename T> template<typename T>
Quaternion<T>& Quaternion<T>::Set(T W, T X, T Y, T Z) Quaternion<T>& Quaternion<T>::Set(T W, T X, T Y, T Z)
{ {
@ -197,17 +357,29 @@ namespace Nz
return *this; return *this;
} }
template<typename T> /*!
Quaternion<T>& Quaternion<T>::Set(const T quat[4]) * \brief Sets this quaternion from rotation specified by Euler angle
{ * \return A reference to this quaternion
w = quat[0]; *
x = quat[1]; * \param angles Easier representation of rotation of space
y = quat[2]; *
z = quat[3]; * \see EulerAngles
*/
return *this; template<typename T>
Quaternion<T>& Quaternion<T>::Set(const EulerAngles<T>& angles)
{
return Set(angles.ToQuaternion());
} }
/*!
* \brief Sets this quaternion from rotation specified by axis and angle
* \return A reference to this quaternion
*
* \param angle Unit depends of NAZARA_MATH_ANGLE_RADIAN
* \param axis Vector3 which represents a direction, no need to be normalized
*/
template<typename T> template<typename T>
Quaternion<T>& Quaternion<T>::Set(T angle, const Vector3<T>& axis) Quaternion<T>& Quaternion<T>::Set(T angle, const Vector3<T>& axis)
{ {
@ -229,12 +401,46 @@ namespace Nz
return Normalize(); return Normalize();
} }
/*!
* \brief Sets the components of the quaternion from an array of four elements
* \return A reference to this quaternion
*
* \param quat[4] quat[0] is W component, quat[1] is X component, quat[2] is Y component and quat[3] is Z component
*/
template<typename T> template<typename T>
Quaternion<T>& Quaternion<T>::Set(const EulerAngles<T>& angles) Quaternion<T>& Quaternion<T>::Set(const T quat[4])
{ {
return Set(angles.ToQuaternion()); w = quat[0];
x = quat[1];
y = quat[2];
z = quat[3];
return *this;
} }
/*!
* \brief Sets the components of the quaternion from another quaternion
* \return A reference to this quaternion
*
* \param vec The other quaternion
*/
template<typename T>
Quaternion<T>& Quaternion<T>::Set(const Quaternion& quat)
{
std::memcpy(this, &quat, sizeof(Quaternion));
return *this;
}
/*!
* \brief Sets the components of the quaternion from another type of Quaternion
* \return A reference to this quaternion
*
* \param quat Quaternion of type U to convert its components
*/
template<typename T> template<typename T>
template<typename U> template<typename U>
Quaternion<T>& Quaternion<T>::Set(const Quaternion<U>& quat) Quaternion<T>& Quaternion<T>::Set(const Quaternion<U>& quat)
@ -247,36 +453,48 @@ namespace Nz
return *this; return *this;
} }
template<typename T> /*!
Quaternion<T>& Quaternion<T>::Set(const Quaternion& quat) * \brief Calculates the squared magnitude (length) of the quaternion
{ * \return The squared magnitude
std::memcpy(this, &quat, sizeof(Quaternion)); *
* \see Magnitude
return *this; */
}
template<typename T> template<typename T>
T Quaternion<T>::SquaredMagnitude() const T Quaternion<T>::SquaredMagnitude() const
{ {
return w*w + x*x + y*y + z*z; return w * w + x * x + y * y + z * z;
} }
/*!
* \brief Converts this quaternion to Euler angles representation
* \return EulerAngles which is the representation of this rotation
*
* \remark Rotation are "left-handed"
*/
template<typename T> template<typename T>
EulerAngles<T> Quaternion<T>::ToEulerAngles() const EulerAngles<T> Quaternion<T>::ToEulerAngles() const
{ {
T test = x*y + z*w; T test = x * y + z * w;
if (test > F(0.499)) if (test > F(0.499))
// singularity at north pole // singularity at north pole
return EulerAngles<T>(FromDegrees(F(90.0)), FromRadians(F(2.0) * std::atan2(x, w)), F(0.0)); return EulerAngles<T>(FromDegrees(F(90.0)), FromRadians(F(2.0) * std::atan2(x, w)), F(0.0));
if (test < F(-0.499)) if (test < F(-0.499))
// singularity at south pole
return EulerAngles<T>(FromDegrees(F(-90.0)), FromRadians(F(-2.0) * std::atan2(x, w)), F(0.0)); return EulerAngles<T>(FromDegrees(F(-90.0)), FromRadians(F(-2.0) * std::atan2(x, w)), F(0.0));
return EulerAngles<T>(FromRadians(std::atan2(F(2.0)*x*w - F(2.0)*y*z, F(1.0) - F(2.0)*x*x - F(2.0)*z*z)), return EulerAngles<T>(FromRadians(std::atan2(F(2.0) * x * w - F(2.0) * y * z, F(1.0) - F(2.0) * x * x - F(2.0) * z * z)),
FromRadians(std::atan2(F(2.0)*y*w - F(2.0)*x*z, F(1.0) - F(2.0)*y*y - F(2.0)*z*z)), FromRadians(std::atan2(F(2.0) * y * w - F(2.0) * x * z, F(1.0) - F(2.0) * y * y - F(2.0) * z * z)),
FromRadians(std::asin(F(2.0)*test))); FromRadians(std::asin(F(2.0) * test)));
} }
/*!
* \brief Gives a string representation
* \return A string representation of the object: "Quaternion(w | x, y, z)"
*/
template<typename T> template<typename T>
String Quaternion<T>::ToString() const String Quaternion<T>::ToString() const
{ {
@ -285,11 +503,12 @@ namespace Nz
return ss << "Quaternion(" << w << " | " << x << ", " << y << ", " << z << ')'; return ss << "Quaternion(" << w << " | " << x << ", " << y << ", " << z << ')';
} }
template<typename T> /*!
Quaternion<T>& Quaternion<T>::operator=(const Quaternion& quat) * \brief Adds the components of the quaternion with other quaternion
{ * \return A quaternion where components are the sum of this quaternion and the other one
return Set(quat); *
} * \param quat The other quaternion to add components with
*/
template<typename T> template<typename T>
Quaternion<T> Quaternion<T>::operator+(const Quaternion& quat) const Quaternion<T> Quaternion<T>::operator+(const Quaternion& quat) const
@ -303,18 +522,32 @@ namespace Nz
return result; return result;
} }
/*!
* \brief Multiplies of the quaternion with other quaternion
* \return A quaternion which is the product of those two according to operator* in quaternions
*
* \param quat The other quaternion to multiply with
*/
template<typename T> template<typename T>
Quaternion<T> Quaternion<T>::operator*(const Quaternion& quat) const Quaternion<T> Quaternion<T>::operator*(const Quaternion& quat) const
{ {
Quaternion result; Quaternion result;
result.w = w*quat.w - x*quat.x - y*quat.y - z*quat.z; result.w = w * quat.w - x * quat.x - y * quat.y - z * quat.z;
result.x = w*quat.x + x*quat.w + y*quat.z - z*quat.y; result.x = w * quat.x + x * quat.w + y * quat.z - z * quat.y;
result.y = w*quat.y + y*quat.w + z*quat.x - x*quat.z; result.y = w * quat.y + y * quat.w + z * quat.x - x * quat.z;
result.z = w*quat.z + z*quat.w + x*quat.y - y*quat.x; result.z = w * quat.z + z * quat.w + x * quat.y - y * quat.x;
return result; return result;
} }
/*!
* \brief Apply the quaternion to the Vector3
* \return A Vector3f which is the vector rotated by this quaternion
*
* \param vec The vector to multiply with
*/
template<typename T> template<typename T>
Vector3<T> Quaternion<T>::operator*(const Vector3<T>& vec) const Vector3<T> Quaternion<T>::operator*(const Vector3<T>& vec) const
{ {
@ -327,60 +560,123 @@ namespace Nz
return vec + uv + uuv; return vec + uv + uuv;
} }
/*!
* \brief Multiplies the components of the quaternion with a scalar
* \return A quaternion where components are the product of this quaternion and the scalar
*
* \param scale The scalar to multiply components with
*/
template<typename T> template<typename T>
Quaternion<T> Quaternion<T>::operator*(T scale) const Quaternion<T> Quaternion<T>::operator*(T scale) const
{ {
return Quaternion(w * scale, return Quaternion(w * scale,
x * scale, x * scale,
y * scale, y * scale,
z * scale); z * scale);
} }
/*!
* \brief Divides the quaternion with other quaternion
* \return A quaternion which is the quotient of those two according to operator* in quaternions
*
* \param quat The other quaternion to divide with
*/
template<typename T> template<typename T>
Quaternion<T> Quaternion<T>::operator/(const Quaternion& quat) const Quaternion<T> Quaternion<T>::operator/(const Quaternion& quat) const
{ {
return quat.GetConjugate() * (*this); return quat.GetConjugate() * (*this);
} }
/*!
* \brief Adds the components of the quaternion with other quaternion
* \return A reference to this quaternion where components are the sum of this quaternion and the other one
*
* \param quat The other quaternion to add components with
*/
template<typename T> template<typename T>
Quaternion<T>& Quaternion<T>::operator+=(const Quaternion& quat) Quaternion<T>& Quaternion<T>::operator+=(const Quaternion& quat)
{ {
return operator=(operator+(quat)); return operator=(operator+(quat));
} }
/*!
* \brief Multiplies of the quaternion with other quaternion
* \return A reference to this quaternion which is the product of those two according to operator* in quaternions
*
* \param quat The other quaternion to multiply with
*/
template<typename T> template<typename T>
Quaternion<T>& Quaternion<T>::operator*=(const Quaternion& quat) Quaternion<T>& Quaternion<T>::operator*=(const Quaternion& quat)
{ {
return operator=(operator*(quat)); return operator=(operator*(quat));
} }
/*!
* \brief Multiplies the components of the quaternion with a scalar
* \return A reference to this quaternion where components are the product of this quaternion and the scalar
*
* \param scale The scalar to multiply components with
*/
template<typename T> template<typename T>
Quaternion<T>& Quaternion<T>::operator*=(T scale) Quaternion<T>& Quaternion<T>::operator*=(T scale)
{ {
return operator=(operator*(scale)); return operator=(operator*(scale));
} }
/*!
* \brief Divides the quaternion with other quaternion
* \return A reference to this quaternion which is the quotient of those two according to operator* in quaternions
*
* \param quat The other quaternion to divide with
*/
template<typename T> template<typename T>
Quaternion<T>& Quaternion<T>::operator/=(const Quaternion& quat) Quaternion<T>& Quaternion<T>::operator/=(const Quaternion& quat)
{ {
return operator=(operator/(quat)); return operator=(operator/(quat));
} }
/*!
* \brief Compares the quaternion to other one
* \return true if the quaternions are the same
*
* \param vec Other quaternion to compare with
*/
template<typename T> template<typename T>
bool Quaternion<T>::operator==(const Quaternion& quat) const bool Quaternion<T>::operator==(const Quaternion& quat) const
{ {
return NumberEquals(w, quat.w) && return NumberEquals(w, quat.w) &&
NumberEquals(x, quat.x) && NumberEquals(x, quat.x) &&
NumberEquals(y, quat.y) && NumberEquals(y, quat.y) &&
NumberEquals(z, quat.z); NumberEquals(z, quat.z);
} }
/*!
* \brief Compares the quaternion to other one
* \return false if the quaternions are the same
*
* \param vec Other quaternion to compare with
*/
template<typename T> template<typename T>
bool Quaternion<T>::operator!=(const Quaternion& quat) const bool Quaternion<T>::operator!=(const Quaternion& quat) const
{ {
return !operator==(quat); return !operator==(quat);
} }
/*!
* \brief Shorthand for the quaternion (1, 0, 0, 0)
* \return A quaternion with components (1, 0, 0, 0)
*
* \see MakeIdentity
*/
template<typename T> template<typename T>
Quaternion<T> Quaternion<T>::Identity() Quaternion<T> Quaternion<T>::Identity()
{ {
@ -390,6 +686,20 @@ namespace Nz
return quaternion; return quaternion;
} }
/*!
* \brief Interpolates the quaternion to other one with a factor of interpolation
* \return A new quaternion which is the interpolation of two quaternions
*
* \param from Initial quaternion
* \param to Target quaternion
* \param interpolation Factor of interpolation
*
* \remark interpolation is meant to be between 0 and 1, other values are potentially undefined behavior
* \remark With NAZARA_DEBUG, a NazaraError is thrown and Zero() is returned
*
* \see Lerp, Slerp
*/
template<typename T> template<typename T>
Quaternion<T> Quaternion<T>::Lerp(const Quaternion& from, const Quaternion& to, T interpolation) Quaternion<T> Quaternion<T>::Lerp(const Quaternion& from, const Quaternion& to, T interpolation)
{ {
@ -410,12 +720,32 @@ namespace Nz
return interpolated; return interpolated;
} }
/*!
* \brief Gives the normalized quaternion
* \return A normalized quaternion from the quat
*
* \param quat Quaternion to normalize
* \param length Optional argument to obtain the length's ratio of the vector and the unit-length
*
* \see GetNormal
*/
template<typename T> template<typename T>
Quaternion<T> Quaternion<T>::Normalize(const Quaternion& quat, T* length) Quaternion<T> Quaternion<T>::Normalize(const Quaternion& quat, T* length)
{ {
return quat.GetNormal(length); return quat.GetNormal(length);
} }
/*!
* \brief Gets the rotation required to rotate direction Vector3 from to direction Vector3 to
* \return A quaternion which is the rotation needed between those two Vector3
*
* \param from Initial vector
* \param to Target vector
*
* \see MakeRotationBetween
*/
template<typename T> template<typename T>
Quaternion<T> Quaternion<T>::RotationBetween(const Vector3<T>& from, const Vector3<T>& to) Quaternion<T> Quaternion<T>::RotationBetween(const Vector3<T>& from, const Vector3<T>& to)
{ {
@ -425,6 +755,20 @@ namespace Nz
return quaternion; return quaternion;
} }
/*!
* \brief Interpolates spherically the quaternion to other one with a factor of interpolation
* \return A new quaternion which is the interpolation of two quaternions
*
* \param from Initial quaternion
* \param to Target quaternion
* \param interpolation Factor of interpolation
*
* \remark interpolation is meant to be between 0 and 1, other values are potentially undefined behavior
* \remark With NAZARA_DEBUG, a NazaraError is thrown and Zero() is returned
*
* \see Lerp
*/
template<typename T> template<typename T>
Quaternion<T> Quaternion<T>::Slerp(const Quaternion& from, const Quaternion& to, T interpolation) Quaternion<T> Quaternion<T>::Slerp(const Quaternion& from, const Quaternion& to, T interpolation)
{ {
@ -441,7 +785,7 @@ namespace Nz
T cosOmega = from.DotProduct(to); T cosOmega = from.DotProduct(to);
if (cosOmega < F(0.0)) if (cosOmega < F(0.0))
{ {
// On inverse tout // We invert everything
q.Set(-to.w, -to.x, -to.y, -to.z); q.Set(-to.w, -to.x, -to.y, -to.z);
cosOmega = -cosOmega; cosOmega = -cosOmega;
} }
@ -451,7 +795,7 @@ namespace Nz
T k0, k1; T k0, k1;
if (cosOmega > F(0.9999)) if (cosOmega > F(0.9999))
{ {
// Interpolation linéaire pour éviter une division par zéro // Linear interpolation to avoid division by zero
k0 = F(1.0) - interpolation; k0 = F(1.0) - interpolation;
k1 = interpolation; k1 = interpolation;
} }
@ -460,7 +804,7 @@ namespace Nz
T sinOmega = std::sqrt(F(1.0) - cosOmega*cosOmega); T sinOmega = std::sqrt(F(1.0) - cosOmega*cosOmega);
T omega = std::atan2(sinOmega, cosOmega); T omega = std::atan2(sinOmega, cosOmega);
// Pour éviter deux divisions // To avoid two divisions
sinOmega = F(1.0)/sinOmega; sinOmega = F(1.0)/sinOmega;
k0 = std::sin((F(1.0) - interpolation) * omega) * sinOmega; k0 = std::sin((F(1.0) - interpolation) * omega) * sinOmega;
@ -468,9 +812,16 @@ namespace Nz
} }
Quaternion result(k0 * from.w, k0 * from.x, k0 * from.y, k0 * from.z); Quaternion result(k0 * from.w, k0 * from.x, k0 * from.y, k0 * from.z);
return result += q*k1; return result += q * k1;
} }
/*!
* \brief Shorthand for the quaternion (0, 0, 0, 0)
* \return A quaternion with components (0, 0, 0, 0)
*
* \see MakeZero
*/
template<typename T> template<typename T>
Quaternion<T> Quaternion<T>::Zero() Quaternion<T> Quaternion<T>::Zero()
{ {
@ -481,6 +832,14 @@ namespace Nz
} }
} }
/*!
* \brief Output operator
* \return The stream
*
* \param out The stream
* \param quat The quaternion to output
*/
template<typename T> template<typename T>
std::ostream& operator<<(std::ostream& out, const Nz::Quaternion<T>& quat) std::ostream& operator<<(std::ostream& out, const Nz::Quaternion<T>& quat)
{ {