diff --git a/include/Nazara/Audio/AudioDevice.hpp b/include/Nazara/Audio/AudioDevice.hpp index 54522d23f..4535b8466 100644 --- a/include/Nazara/Audio/AudioDevice.hpp +++ b/include/Nazara/Audio/AudioDevice.hpp @@ -35,7 +35,7 @@ namespace Nz virtual float GetGlobalVolume() const = 0; virtual Vector3f GetListenerDirection(Vector3f* up = nullptr) const = 0; virtual Vector3f GetListenerPosition() const = 0; - virtual Quaternionf GetListenerRotation(Vector3f* up = nullptr) const = 0; + virtual Quaternionf GetListenerRotation() const = 0; virtual Vector3f GetListenerVelocity() const = 0; virtual float GetSpeedOfSound() const = 0; diff --git a/include/Nazara/Math/Angle.hpp b/include/Nazara/Math/Angle.hpp index 7dab28956..ad0227d39 100644 --- a/include/Nazara/Math/Angle.hpp +++ b/include/Nazara/Math/Angle.hpp @@ -55,6 +55,9 @@ namespace Nz constexpr Angle& operator=(const Angle&) = default; + constexpr const Angle& operator+() const; + constexpr Angle operator-() const; + constexpr Angle operator+(const Angle& other) const; constexpr Angle operator-(const Angle& other) const; constexpr Angle operator*(T scalar) const; diff --git a/include/Nazara/Math/Angle.inl b/include/Nazara/Math/Angle.inl index 88a9546d5..5d9726118 100644 --- a/include/Nazara/Math/Angle.inl +++ b/include/Nazara/Math/Angle.inl @@ -381,6 +381,27 @@ namespace Nz return ToRadianAngle(); }*/ + + /*! + * \brief Helps to represent the sign of the angle + * \return A constant reference to this angle + */ + template + constexpr const Angle& Angle::operator+() const + { + return *this; + } + + /*! + * \brief Negates the angle + * \return An angle with a negated value + */ + template + constexpr Angle Angle::operator-() const + { + return Angle(-value); + } + /*! * \brief Addition operator * \return Adds two angles together diff --git a/include/Nazara/Math/Quaternion.hpp b/include/Nazara/Math/Quaternion.hpp index ac16dc173..a50a1bc27 100644 --- a/include/Nazara/Math/Quaternion.hpp +++ b/include/Nazara/Math/Quaternion.hpp @@ -83,6 +83,7 @@ namespace Nz static Quaternion Identity(); static Quaternion Lerp(const Quaternion& from, const Quaternion& to, T interpolation); + static Quaternion LookAt(const Vector3& forward, const Vector3& up); static Quaternion Normalize(const Quaternion& quat, T* length = nullptr); static Quaternion RotationBetween(const Vector3& from, const Vector3& to); static Quaternion Slerp(const Quaternion& from, const Quaternion& to, T interpolation); diff --git a/include/Nazara/Math/Quaternion.inl b/include/Nazara/Math/Quaternion.inl index 8358593b9..27f6d8d2a 100644 --- a/include/Nazara/Math/Quaternion.inl +++ b/include/Nazara/Math/Quaternion.inl @@ -705,7 +705,6 @@ namespace Nz * * \see Lerp, Slerp */ - template Quaternion Quaternion::Lerp(const Quaternion& from, const Quaternion& to, T interpolation) { @@ -726,6 +725,33 @@ namespace Nz return interpolated; } + template + Quaternion Quaternion::LookAt(const Vector3& forward, const Vector3& up) + { + // From https://gamedev.stackexchange.com/questions/53129/quaternion-look-at-with-up-vector + + Vector3 forward_w(1, 0, 0); + Vector3 axis = Vector3::CrossProduct(forward, forward_w); + RadianAngle angle = std::acos(Vector3::DotProduct(forward, forward_w)); + + Vector3 third = Vector3::CrossProduct(axis, forward_w); + if (Vector3::DotProduct(third, forward) < 0) + angle = -angle; + + Quaternion q1 = Quaternion(angle, axis); + + Vector3 up_l = q1 * up; + Vector3 right = Vector3::Normalize(Vector3::CrossProduct(forward, up)); + Vector3 up_w = Vector3::Normalize(Vector3::CrossProduct(right, forward)); + + Vector3 axis2 = Vector3::CrossProduct(up_l, up_w); + RadianAngle angle2 = std::acos(Vector3::DotProduct(forward, forward_w)); + + Quaternion q2 = Quaternion(angle2, axis2); + + return q2 * q1; + } + /*! * \brief Gives the normalized quaternion * \return A normalized quaternion from the quat diff --git a/src/Nazara/Audio/OpenALDevice.cpp b/src/Nazara/Audio/OpenALDevice.cpp index 64ab3bac4..1443633bf 100644 --- a/src/Nazara/Audio/OpenALDevice.cpp +++ b/src/Nazara/Audio/OpenALDevice.cpp @@ -157,7 +157,7 @@ namespace Nz * * \see GetListenerDirection */ - Quaternionf OpenALDevice::GetListenerRotation(Vector3f* up) const + Quaternionf OpenALDevice::GetListenerRotation() const { MakeContextCurrent(); @@ -165,11 +165,9 @@ namespace Nz m_library.alGetListenerfv(AL_ORIENTATION, orientation); Vector3f forward(orientation[0], orientation[1], orientation[2]); + Vector3f up(orientation[3], orientation[4], orientation[5]); - if (up) - up->Set(orientation[3], orientation[4], orientation[5]); - - return Quaternionf::RotationBetween(Vector3f::Forward(), forward); + return Quaternionf::LookAt(forward, up); } /*!