From 8675ff0a745836263d09565e5ab729fc02abf760 Mon Sep 17 00:00:00 2001 From: Andrew Jacob Date: Mon, 7 Feb 2022 22:58:43 -0700 Subject: [PATCH] Allow C# Vector2/3 slerp values to have any length --- .../GodotSharp/GodotSharp/Core/Vector2.cs | 24 +++++++++--------- .../GodotSharp/GodotSharp/Core/Vector3.cs | 25 +++++++++---------- 2 files changed, 24 insertions(+), 25 deletions(-) diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs index 1f5282e88f8..fa7838633c3 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs @@ -512,24 +512,24 @@ namespace Godot /// Returns the result of the spherical linear interpolation between /// this vector and by amount . /// - /// Note: Both vectors must be normalized. + /// This method also handles interpolating the lengths if the input vectors have different lengths. + /// For the special case of one or both input vectors having zero length, this method behaves like [method lerp]. /// - /// The destination vector for interpolation. Must be normalized. + /// The destination vector for interpolation. /// A value on the range of 0.0 to 1.0, representing the amount of interpolation. /// The resulting vector of the interpolation. public Vector2 Slerp(Vector2 to, real_t weight) { -#if DEBUG - if (!IsNormalized()) - { - throw new InvalidOperationException("Vector2.Slerp: From vector is not normalized."); + real_t startLengthSquared = LengthSquared(); + real_t endLengthSquared = to.LengthSquared(); + if (startLengthSquared == 0.0 || endLengthSquared == 0.0) { + // Zero length vectors have no angle, so the best we can do is either lerp or throw an error. + return Lerp(to, weight); } - if (!to.IsNormalized()) - { - throw new InvalidOperationException($"Vector2.Slerp: `{nameof(to)}` is not normalized."); - } -#endif - return Rotated(AngleTo(to) * weight); + real_t startLength = Mathf.Sqrt(startLengthSquared); + real_t resultLength = Mathf.Lerp(startLength, Mathf.Sqrt(endLengthSquared), weight); + real_t angle = AngleTo(to); + return Rotated(angle * weight) * (resultLength / startLength); } /// diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs index 433a5d9dc9c..0faf13f8b7d 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs @@ -549,25 +549,24 @@ namespace Godot /// Returns the result of the spherical linear interpolation between /// this vector and by amount . /// - /// Note: Both vectors must be normalized. + /// This method also handles interpolating the lengths if the input vectors have different lengths. + /// For the special case of one or both input vectors having zero length, this method behaves like [method lerp]. /// - /// The destination vector for interpolation. Must be normalized. + /// The destination vector for interpolation. /// A value on the range of 0.0 to 1.0, representing the amount of interpolation. /// The resulting vector of the interpolation. public Vector3 Slerp(Vector3 to, real_t weight) { -#if DEBUG - if (!IsNormalized()) - { - throw new InvalidOperationException("Vector3.Slerp: From vector is not normalized."); + real_t startLengthSquared = LengthSquared(); + real_t endLengthSquared = to.LengthSquared(); + if (startLengthSquared == 0.0 || endLengthSquared == 0.0) { + // Zero length vectors have no angle, so the best we can do is either lerp or throw an error. + return Lerp(to, weight); } - if (!to.IsNormalized()) - { - throw new InvalidOperationException($"Vector3.Slerp: `{nameof(to)}` is not normalized."); - } -#endif - real_t theta = AngleTo(to); - return Rotated(Cross(to), theta * weight); + real_t startLength = Mathf.Sqrt(startLengthSquared); + real_t resultLength = Mathf.Lerp(startLength, Mathf.Sqrt(endLengthSquared), weight); + real_t angle = AngleTo(to); + return Rotated(Cross(to).Normalized(), angle * weight) * (resultLength / startLength); } ///