Merge pull request #80225 from ettiSurreal/rotate-toward

Add `rotate_toward` and `angle_difference` methods.
This commit is contained in:
Rémi Verschelde
2023-10-02 13:15:49 +02:00
6 changed files with 158 additions and 12 deletions

View File

@@ -133,6 +133,38 @@ namespace Godot
return Math.Acosh(s);
}
/// <summary>
/// Returns the difference between the two angles,
/// in range of -<see cref="Pi"/>, <see cref="Pi"/>.
/// When <paramref name="from"/> and <paramref name="to"/> are opposite,
/// returns -<see cref="Pi"/> if <paramref name="from"/> is smaller than <paramref name="to"/>,
/// or <see cref="Pi"/> otherwise.
/// </summary>
/// <param name="from">The start angle.</param>
/// <param name="to">The destination angle.</param>
/// <returns>The difference between the two angles.</returns>
public static float AngleDifference(float from, float to)
{
float difference = (to - from) % MathF.Tau;
return ((2.0f * difference) % MathF.Tau) - difference;
}
/// <summary>
/// Returns the difference between the two angles,
/// in range of -<see cref="Pi"/>, <see cref="Pi"/>.
/// When <paramref name="from"/> and <paramref name="to"/> are opposite,
/// returns -<see cref="Pi"/> if <paramref name="from"/> is smaller than <paramref name="to"/>,
/// or <see cref="Pi"/> otherwise.
/// </summary>
/// <param name="from">The start angle.</param>
/// <param name="to">The destination angle.</param>
/// <returns>The difference between the two angles.</returns>
public static double AngleDifference(double from, double to)
{
double difference = (to - from) % Math.Tau;
return ((2.0 * difference) % Math.Tau) - difference;
}
/// <summary>
/// Returns the arc sine of <paramref name="s"/> in radians.
/// Use to get the angle of sine <paramref name="s"/>.
@@ -1093,9 +1125,7 @@ namespace Godot
/// <returns>The resulting angle of the interpolation.</returns>
public static float LerpAngle(float from, float to, float weight)
{
float difference = (to - from) % MathF.Tau;
float distance = ((2 * difference) % MathF.Tau) - difference;
return from + (distance * weight);
return from + AngleDifference(from, to) * weight;
}
/// <summary>
@@ -1110,9 +1140,7 @@ namespace Godot
/// <returns>The resulting angle of the interpolation.</returns>
public static double LerpAngle(double from, double to, double weight)
{
double difference = (to - from) % Math.Tau;
double distance = ((2 * difference) % Math.Tau) - difference;
return from + (distance * weight);
return from + AngleDifference(from, to) * weight;
}
/// <summary>
@@ -1428,6 +1456,38 @@ namespace Godot
return Lerp(outFrom, outTo, InverseLerp(inFrom, inTo, value));
}
/// <summary>
/// Rotates <paramref name="from"/> toward <paramref name="to"/> by the <paramref name="delta"/> amount. Will not go past <paramref name="to"/>.
/// Similar to <see cref="MoveToward(float, float, float)"/> but interpolates correctly when the angles wrap around <see cref="Tau"/>.
/// If <paramref name="delta"/> is negative, this function will rotate away from <paramref name="to"/>, toward the opposite angle, and will not go past the opposite angle.
/// </summary>
/// <param name="from">The start angle.</param>
/// <param name="to">The angle to move towards.</param>
/// <param name="delta">The amount to move by.</param>
/// <returns>The angle after moving.</returns>
public static float RotateToward(float from, float to, float delta)
{
float difference = AngleDifference(from, to);
float absDifference = Math.Abs(difference);
return from + Math.Clamp(delta, absDifference - MathF.PI, absDifference) * (difference >= 0.0f ? 1.0f : -1.0f);
}
/// <summary>
/// Rotates <paramref name="from"/> toward <paramref name="to"/> by the <paramref name="delta"/> amount. Will not go past <paramref name="to"/>.
/// Similar to <see cref="MoveToward(double, double, double)"/> but interpolates correctly when the angles wrap around <see cref="Tau"/>.
/// If <paramref name="delta"/> is negative, this function will rotate away from <paramref name="to"/>, toward the opposite angle, and will not go past the opposite angle.
/// </summary>
/// <param name="from">The start angle.</param>
/// <param name="to">The angle to move towards.</param>
/// <param name="delta">The amount to move by.</param>
/// <returns>The angle after moving.</returns>
public static double RotateToward(double from, double to, double delta)
{
double difference = AngleDifference(from, to);
double absDifference = Math.Abs(difference);
return from + Math.Clamp(delta, absDifference - Math.PI, absDifference) * (difference >= 0.0 ? 1.0 : -1.0);
}
/// <summary>
/// Rounds <paramref name="s"/> to the nearest whole number,
/// with halfway cases rounded towards the nearest multiple of two.