Math/Angle: Adds conversion to euler angles and quaternions
This commit is contained in:
parent
1114bb0fdd
commit
1ee75f2699
|
|
@ -18,6 +18,9 @@ namespace Nz
|
||||||
{
|
{
|
||||||
struct SerializationContext;
|
struct SerializationContext;
|
||||||
|
|
||||||
|
template<typename T> class EulerAngles;
|
||||||
|
template<typename T> class Quaternion;
|
||||||
|
|
||||||
template<AngleUnit Unit, typename T>
|
template<AngleUnit Unit, typename T>
|
||||||
class Angle
|
class Angle
|
||||||
{
|
{
|
||||||
|
|
@ -45,13 +48,20 @@ namespace Nz
|
||||||
template<typename U> Angle& Set(const Angle<Unit, U>& Angle);
|
template<typename U> Angle& Set(const Angle<Unit, U>& Angle);
|
||||||
|
|
||||||
Angle<AngleUnit::Degree, T> ToDegrees() const;
|
Angle<AngleUnit::Degree, T> ToDegrees() const;
|
||||||
|
EulerAngles<T> ToEulerAngles() const;
|
||||||
|
Quaternion<T> ToQuaternion() const;
|
||||||
Angle<AngleUnit::Radian, T> ToRadians() const;
|
Angle<AngleUnit::Radian, T> ToRadians() const;
|
||||||
String ToString() const;
|
String ToString() const;
|
||||||
|
|
||||||
|
operator EulerAngles<T>() const;
|
||||||
|
operator Quaternion<T>() const;
|
||||||
|
|
||||||
Angle& operator=(const Angle&) = default;
|
Angle& operator=(const Angle&) = default;
|
||||||
|
|
||||||
Angle operator+(const Angle& other) const;
|
Angle operator+(const Angle& other) const;
|
||||||
Angle operator-(const Angle& other) const;
|
Angle operator-(const Angle& other) const;
|
||||||
|
Angle operator*(T scalar) const;
|
||||||
|
Angle operator/(T divider) const;
|
||||||
|
|
||||||
Angle& operator+=(const Angle& other);
|
Angle& operator+=(const Angle& other);
|
||||||
Angle& operator-=(const Angle& other);
|
Angle& operator-=(const Angle& other);
|
||||||
|
|
|
||||||
|
|
@ -319,6 +319,58 @@ namespace Nz
|
||||||
return Detail::AngleUtils<Unit>::ToString(angle);
|
return Detail::AngleUtils<Unit>::ToString(angle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Shortcut allowing implicit conversion to Euler angles
|
||||||
|
* \return Euler Angles representing a 2D rotation by this angle
|
||||||
|
*
|
||||||
|
* \see ToEulerAngles
|
||||||
|
*/
|
||||||
|
template<AngleUnit Unit, typename T>
|
||||||
|
Angle<Unit, T>::operator EulerAngles<T>() const
|
||||||
|
{
|
||||||
|
return ToEulerAngles();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Shortcut allowing implicit conversion to Quaternion
|
||||||
|
* \return Quaternion representing a 2D rotation by this angle
|
||||||
|
*
|
||||||
|
* \see ToQuaternion
|
||||||
|
*/
|
||||||
|
template<AngleUnit Unit, typename T>
|
||||||
|
Angle<Unit, T>::operator Quaternion<T>() const
|
||||||
|
{
|
||||||
|
return ToQuaternion();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Converts the angle to an Euler Angles representation
|
||||||
|
* \return A 2D rotation expressed in Euler angles
|
||||||
|
*
|
||||||
|
* This will assume two-dimensional usage, and will set the angle value (as degrees) as the roll value of the Euler Angles, leaving pitch and yaw to zero
|
||||||
|
*/
|
||||||
|
template<AngleUnit Unit, typename T>
|
||||||
|
EulerAngles<T> Angle<Unit, T>::ToEulerAngles() const
|
||||||
|
{
|
||||||
|
return EulerAngles<T>(0, 0, ToDegrees().angle);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Converts the angle to a Quaternion representation
|
||||||
|
* \return A 2D rotation expressed with Quaternion
|
||||||
|
*
|
||||||
|
* This will assume two-dimensional usage, as if the angle was first converted to Euler Angles and then to a Quaternion
|
||||||
|
*
|
||||||
|
* \see ToEulerAngles
|
||||||
|
*/
|
||||||
|
template<AngleUnit Unit, typename T>
|
||||||
|
Quaternion<T> Angle<Unit, T>::ToQuaternion() const
|
||||||
|
{
|
||||||
|
auto halfAngle = Angle(*this) / 2.f;
|
||||||
|
auto sincos = halfAngle.GetSinCos();
|
||||||
|
return Quaternion<T>(sincos.second, 0, 0, sincos.first);
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Addition operator
|
* \brief Addition operator
|
||||||
* \return Adds two angles together
|
* \return Adds two angles together
|
||||||
|
|
@ -343,6 +395,30 @@ namespace Nz
|
||||||
return Angle(angle - other.angle);
|
return Angle(angle - other.angle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Multiplication operator
|
||||||
|
* \return A copy of the angle, scaled by the multiplier
|
||||||
|
*
|
||||||
|
* \param scalar Multiplier
|
||||||
|
*/
|
||||||
|
template<AngleUnit Unit, typename T>
|
||||||
|
Angle<Unit, T> Angle<Unit, T>::operator*(T scalar) const
|
||||||
|
{
|
||||||
|
return Angle(angle * scalar);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Divides the angle by a scalar
|
||||||
|
* \return A copy of the angle, divided by the divider
|
||||||
|
*
|
||||||
|
* \param divider Divider
|
||||||
|
*/
|
||||||
|
template<AngleUnit Unit, typename T>
|
||||||
|
Angle<Unit, T> Angle<Unit, T>::operator/(T divider) const
|
||||||
|
{
|
||||||
|
return Angle(angle / divider);
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Adds an angle by another
|
* \brief Adds an angle by another
|
||||||
* \return A reference to the angle
|
* \return A reference to the angle
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
#include <Nazara/Math/Angle.hpp>
|
#include <Nazara/Math/Angle.hpp>
|
||||||
|
#include <Nazara/Math/EulerAngles.hpp>
|
||||||
|
#include <Nazara/Math/Quaternion.hpp>
|
||||||
#include <Catch/catch.hpp>
|
#include <Catch/catch.hpp>
|
||||||
|
|
||||||
SCENARIO("Angle", "[MATH][ANGLE]")
|
SCENARIO("Angle", "[MATH][ANGLE]")
|
||||||
|
|
@ -37,16 +39,33 @@ SCENARIO("Angle", "[MATH][ANGLE]")
|
||||||
CHECK(angle.GetSin() == Approx(1.f).margin(0.0001f));
|
CHECK(angle.GetSin() == Approx(1.f).margin(0.0001f));
|
||||||
CHECK(angle.GetCos() == Approx(0.f).margin(0.0001f));
|
CHECK(angle.GetCos() == Approx(0.f).margin(0.0001f));
|
||||||
}
|
}
|
||||||
|
AND_WHEN("We compute sin/cos at the same time")
|
||||||
}
|
|
||||||
AND_WHEN("We compute it at the same time")
|
|
||||||
{
|
|
||||||
auto sincos = angle.GetSinCos();
|
|
||||||
|
|
||||||
THEN("It should also be equal to 1 and 0")
|
|
||||||
{
|
{
|
||||||
CHECK(sincos.first == Approx(1.f).margin(0.0001f));
|
auto sincos = angle.GetSinCos();
|
||||||
CHECK(sincos.second == Approx(0.f).margin(0.0001f));
|
|
||||||
|
THEN("It should also be equal to 1 and 0")
|
||||||
|
{
|
||||||
|
CHECK(sincos.first == Approx(1.f).margin(0.0001f));
|
||||||
|
CHECK(sincos.second == Approx(0.f).margin(0.0001f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WHEN("We get the Euler Angles representation of this angle")
|
||||||
|
{
|
||||||
|
Nz::EulerAnglesf eulerAngles = angle;
|
||||||
|
THEN("It should be equivalent to a 2D rotation by this angle")
|
||||||
|
{
|
||||||
|
CHECK(eulerAngles == Nz::EulerAnglesf(0.f, 0.f, 90.f));
|
||||||
|
}
|
||||||
|
AND_WHEN("We get the Quaternion representation of this angle")
|
||||||
|
{
|
||||||
|
Nz::Quaternionf quat = angle;
|
||||||
|
|
||||||
|
THEN("It should be equivalent to a 2D rotation by this angle")
|
||||||
|
{
|
||||||
|
CHECK(quat == eulerAngles.ToQuaternion());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -131,6 +150,24 @@ SCENARIO("Angle", "[MATH][ANGLE]")
|
||||||
CHECK(sincos.second == Approx(-1.f).margin(0.0001f));
|
CHECK(sincos.second == Approx(-1.f).margin(0.0001f));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WHEN("We get the Euler Angles representation of this angle")
|
||||||
|
{
|
||||||
|
Nz::EulerAnglesf eulerAngles = angle;
|
||||||
|
THEN("It should be equivalent to a 2D rotation by this angle")
|
||||||
|
{
|
||||||
|
CHECK(eulerAngles == Nz::EulerAnglesf(0.f, 0.f, -180.f));
|
||||||
|
}
|
||||||
|
AND_WHEN("We get the Quaternion representation of this angle")
|
||||||
|
{
|
||||||
|
Nz::Quaternionf quat = angle;
|
||||||
|
|
||||||
|
THEN("It should be equivalent to a 2D rotation by this angle")
|
||||||
|
{
|
||||||
|
CHECK(quat == eulerAngles.ToQuaternion());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GIVEN("A radian angle of 7pi")
|
GIVEN("A radian angle of 7pi")
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue