From 3760c8b5c4c22ec04266daededa0560d4c8a9349 Mon Sep 17 00:00:00 2001 From: Lynix Date: Fri, 13 Dec 2019 17:23:01 +0100 Subject: [PATCH] Utility/Node: Fix negative scaling not affecting rotation --- ChangeLog.md | 1 + include/Nazara/Utility/Node.hpp | 2 ++ src/Nazara/Utility/Node.cpp | 35 +++++++++++++++++++++++++++++---- 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index f00da9c5f..00f8b937a 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -205,6 +205,7 @@ Nazara Engine: - ⚠ Removed all Set methods from math classes taking their own type (e.g. Box::Set(Box)) - Added Matrix4::Decompose - ⚠ Node::Get[Position|Rotation|Scale] now defaults to local space +- Fixed Node rotation when using a negative scale Nazara Development Kit: - Added ImageWidget (#139) diff --git a/include/Nazara/Utility/Node.hpp b/include/Nazara/Utility/Node.hpp index e4cb3cfb2..da36997ec 100644 --- a/include/Nazara/Utility/Node.hpp +++ b/include/Nazara/Utility/Node.hpp @@ -105,6 +105,8 @@ namespace Nz virtual void UpdateDerived() const; virtual void UpdateTransformMatrix() const; + static Quaternionf ScaleQuaternion(const Vector3f& scale, Quaternionf quaternion); + mutable std::vector m_childs; mutable Matrix4f m_transformMatrix; mutable Quaternionf m_derivedRotation; diff --git a/src/Nazara/Utility/Node.cpp b/src/Nazara/Utility/Node.cpp index 2832df42d..c14c81d13 100644 --- a/src/Nazara/Utility/Node.cpp +++ b/src/Nazara/Utility/Node.cpp @@ -574,7 +574,7 @@ namespace Nz if (!m_derivedUpdated) UpdateDerived(); - return m_derivedPosition + (m_derivedScale * (m_derivedRotation * localPosition)); + return m_derivedPosition + (m_derivedScale * (ScaleQuaternion(m_derivedScale, m_derivedRotation) * localPosition)); } Quaternionf Node::ToGlobalRotation(const Quaternionf& localRotation) const @@ -582,7 +582,7 @@ namespace Nz if (!m_derivedUpdated) UpdateDerived(); - return m_derivedRotation * localRotation; + return ScaleQuaternion(m_derivedScale, m_derivedRotation) * localRotation; } Vector3f Node::ToGlobalScale(const Vector3f& localScale) const @@ -598,7 +598,7 @@ namespace Nz if (!m_derivedUpdated) UpdateDerived(); - return (m_derivedRotation.GetConjugate()*(globalPosition - m_derivedPosition))/m_derivedScale; + return (m_derivedScale, m_derivedRotation.GetConjugate()*(globalPosition - m_derivedPosition))/m_derivedScale; } Quaternionf Node::ToLocalRotation(const Quaternionf& globalRotation) const @@ -688,7 +688,11 @@ namespace Nz if (m_inheritRotation) { - m_derivedRotation = m_parent->m_derivedRotation * m_initialRotation * m_rotation; + Quaternionf rotation = m_initialRotation * m_rotation; + if (m_inheritScale) + rotation = ScaleQuaternion(m_parent->m_derivedScale, rotation); + + m_derivedRotation = m_parent->m_derivedRotation * rotation; m_derivedRotation.Normalize(); } else @@ -716,4 +720,27 @@ namespace Nz m_transformMatrix.MakeTransform(m_derivedPosition, m_derivedRotation, m_derivedScale); m_transformMatrixUpdated = true; } + + Quaternionf Node::ScaleQuaternion(const Vector3f& scale, Quaternionf quaternion) + { + if (std::signbit(scale.x)) + { + quaternion.z = -quaternion.z; + quaternion.y = -quaternion.y; + } + + if (std::signbit(scale.y)) + { + quaternion.x = -quaternion.x; + quaternion.z = -quaternion.z; + } + + if (std::signbit(scale.z)) + { + quaternion.x = -quaternion.x; + quaternion.y = -quaternion.y; + } + + return quaternion; + } }