Skip to content

Commit

Permalink
Merge pull request #62791 from raulsntos/csharp-bezier-interpolation
Browse files Browse the repository at this point in the history
C#: Add `BezierInterpolate` method
  • Loading branch information
akien-mga authored Jul 7, 2022
2 parents f60cb29 + 71f99c6 commit 28a3dee
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 6 deletions.
22 changes: 22 additions & 0 deletions modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,28 @@ public static real_t CubicInterpolate(real_t from, real_t to, real_t pre, real_t
(-pre + 3.0f * from - 3.0f * to + post) * (weight * weight * weight));
}

/// <summary>
/// Returns the point at the given <paramref name="t"/> on a one-dimensional Bezier curve defined by
/// the given <paramref name="control1"/>, <paramref name="control2"/> and <paramref name="end"/> points.
/// </summary>
/// <param name="start">The start value for the interpolation.</param>
/// <param name="control1">Control point that defines the bezier curve.</param>
/// <param name="control2">Control point that defines the bezier curve.</param>
/// <param name="end">The destination value for the interpolation.</param>
/// <param name="t">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
/// <returns>The resulting value of the interpolation.</returns>
public static real_t BezierInterpolate(real_t start, real_t control1, real_t control2, real_t end, real_t t)
{
// Formula from Wikipedia article on Bezier curves
real_t omt = 1 - t;
real_t omt2 = omt * omt;
real_t omt3 = omt2 * omt;
real_t t2 = t * t;
real_t t3 = t2 * t;

return start * omt3 + control1 * omt2 * t * 3 + control2 * omt * t2 * 3 + end * t3;
}

/// <summary>
/// Converts an angle expressed in degrees to radians.
/// </summary>
Expand Down
28 changes: 25 additions & 3 deletions modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,27 @@ public Vector2 CubicInterpolate(Vector2 b, Vector2 preA, Vector2 postB, real_t w
);
}

/// <summary>
/// Returns the point at the given <paramref name="t"/> on a one-dimensional Bezier curve defined by this vector
/// and the given <paramref name="control1"/>, <paramref name="control2"/> and <paramref name="end"/> points.
/// </summary>
/// <param name="control1">Control point that defines the bezier curve.</param>
/// <param name="control2">Control point that defines the bezier curve.</param>
/// <param name="end">The destination vector.</param>
/// <param name="t">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
/// <returns>The interpolated vector.</returns>
public Vector2 BezierInterpolate(Vector2 control1, Vector2 control2, Vector2 end, real_t t)
{
// Formula from Wikipedia article on Bezier curves
real_t omt = 1 - t;
real_t omt2 = omt * omt;
real_t omt3 = omt2 * omt;
real_t t2 = t * t;
real_t t3 = t2 * t;

return this * omt3 + control1 * omt2 * t * 3 + control2 * omt * t2 * 3 + end * t3;
}

/// <summary>
/// Returns the normalized vector pointing from this vector to <paramref name="to"/>.
/// </summary>
Expand Down Expand Up @@ -522,9 +543,10 @@ public Vector2 Slerp(Vector2 to, real_t weight)
{
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 (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);
}
real_t startLength = Mathf.Sqrt(startLengthSquared);
real_t resultLength = Mathf.Lerp(startLength, Mathf.Sqrt(endLengthSquared), weight);
Expand Down
28 changes: 25 additions & 3 deletions modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,27 @@ public Vector3 CubicInterpolate(Vector3 b, Vector3 preA, Vector3 postB, real_t w
);
}

/// <summary>
/// Returns the point at the given <paramref name="t"/> on a one-dimensional Bezier curve defined by this vector
/// and the given <paramref name="control1"/>, <paramref name="control2"/> and <paramref name="end"/> points.
/// </summary>
/// <param name="control1">Control point that defines the bezier curve.</param>
/// <param name="control2">Control point that defines the bezier curve.</param>
/// <param name="end">The destination vector.</param>
/// <param name="t">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
/// <returns>The interpolated vector.</returns>
public Vector3 BezierInterpolate(Vector3 control1, Vector3 control2, Vector3 end, real_t t)
{
// Formula from Wikipedia article on Bezier curves
real_t omt = 1 - t;
real_t omt2 = omt * omt;
real_t omt3 = omt2 * omt;
real_t t2 = t * t;
real_t t3 = t2 * t;

return this * omt3 + control1 * omt2 * t * 3 + control2 * omt * t2 * 3 + end * t3;
}

/// <summary>
/// Returns the normalized vector pointing from this vector to <paramref name="to"/>.
/// </summary>
Expand Down Expand Up @@ -562,9 +583,10 @@ public Vector3 Slerp(Vector3 to, real_t weight)
{
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 (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);
}
real_t startLength = Mathf.Sqrt(startLengthSquared);
real_t resultLength = Mathf.Lerp(startLength, Mathf.Sqrt(endLengthSquared), weight);
Expand Down

0 comments on commit 28a3dee

Please sign in to comment.