From b354f7f87d61f576cf1f8c04e68642890cb79e41 Mon Sep 17 00:00:00 2001 From: SirLynix Date: Fri, 17 Mar 2023 19:24:57 +0100 Subject: [PATCH] Math/Quaternion: Fix RotationBetween not handling parallel vectors --- include/Nazara/Math/Quaternion.inl | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/include/Nazara/Math/Quaternion.inl b/include/Nazara/Math/Quaternion.inl index c3b1f9431..af2835d5d 100644 --- a/include/Nazara/Math/Quaternion.inl +++ b/include/Nazara/Math/Quaternion.inl @@ -268,11 +268,30 @@ namespace Nz template Quaternion& Quaternion::MakeRotationBetween(const Vector3& from, const Vector3& to) { - // Based on: http://lolengine.net/blog/2013/09/18/beautiful-maths-quaternion-from-vectors - T norm = std::sqrt(from.GetSquaredLength() * to.GetSquaredLength()); - Vector3 crossProduct = from.CrossProduct(to); - Set(norm + from.DotProduct(to), crossProduct.x, crossProduct.y, crossProduct.z); - return Normalize(); + T dot = from.DotProduct(to); + if (dot < T(-0.999999)) + { + Vector3 crossProduct; + if (from.DotProduct(Vector3::UnitX()) < T(0.999999)) + crossProduct = Vector3::UnitX().CrossProduct(from); + else + crossProduct = Vector3::UnitY().CrossProduct(from); + + crossProduct.Normalize(); + Set(Pi, crossProduct); + return *this; + } + else if (dot > T(0.999999)) + { + Set(T(1.0), T(0.0), T(0.0), T(0.0)); + return *this; + } + else + { + Vector3 crossProduct = from.CrossProduct(to); + Set(T(1) + dot, crossProduct.x, crossProduct.y, crossProduct.z); + return Normalize(); + } } /*!