C#: Add CubicInterpolateInTime
This commit is contained in:
parent
4c5cefe4fe
commit
623f4a52ca
5 changed files with 170 additions and 1 deletions
|
@ -175,7 +175,8 @@ namespace Godot
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cubic interpolates between two values by a normalized value with pre and post values.
|
||||
/// Cubic interpolates between two values by the factor defined in <paramref name="weight"/>
|
||||
/// with pre and post values.
|
||||
/// </summary>
|
||||
/// <param name="from">The start value for interpolation.</param>
|
||||
/// <param name="to">The destination value for interpolation.</param>
|
||||
|
@ -192,6 +193,33 @@ namespace Godot
|
|||
(-pre + 3.0f * from - 3.0f * to + post) * (weight * weight * weight));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cubic interpolates between two values by the factor defined in <paramref name="weight"/>
|
||||
/// with pre and post values.
|
||||
/// It can perform smoother interpolation than <see cref="CubicInterpolate"/>
|
||||
/// by the time values.
|
||||
/// </summary>
|
||||
/// <param name="from">The start value for interpolation.</param>
|
||||
/// <param name="to">The destination value for interpolation.</param>
|
||||
/// <param name="pre">The value which before "from" value for interpolation.</param>
|
||||
/// <param name="post">The value which after "to" value for interpolation.</param>
|
||||
/// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
|
||||
/// <param name="toT"></param>
|
||||
/// <param name="preT"></param>
|
||||
/// <param name="postT"></param>
|
||||
/// <returns>The resulting value of the interpolation.</returns>
|
||||
public static real_t CubicInterpolateInTime(real_t from, real_t to, real_t pre, real_t post, real_t weight, real_t toT, real_t preT, real_t postT)
|
||||
{
|
||||
/* Barry-Goldman method */
|
||||
real_t t = Lerp(0.0f, toT, weight);
|
||||
real_t a1 = Lerp(pre, from, preT == 0 ? 0.0f : (t - preT) / -preT);
|
||||
real_t a2 = Lerp(from, to, toT == 0 ? 0.5f : t / toT);
|
||||
real_t a3 = Lerp(to, post, postT - toT == 0 ? 1.0f : (t - toT) / (postT - toT));
|
||||
real_t b1 = Lerp(a1, a2, toT - preT == 0 ? 0.0f : (t - preT) / (toT - preT));
|
||||
real_t b2 = Lerp(a2, a3, postT == 0 ? 1.0f : t / postT);
|
||||
return Lerp(b1, b2, toT == 0 ? 0.5f : t / toT);
|
||||
}
|
||||
|
||||
/// <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.
|
||||
|
|
|
@ -195,6 +195,75 @@ namespace Godot
|
|||
return q1.Slerp(q2, weight);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs a spherical cubic interpolation between quaternions <paramref name="preA"/>, this quaternion,
|
||||
/// <paramref name="b"/>, and <paramref name="postB"/>, by the given amount <paramref name="weight"/>.
|
||||
/// It can perform smoother interpolation than <see cref="SphericalCubicInterpolate"/>
|
||||
/// by the time values.
|
||||
/// </summary>
|
||||
/// <param name="b">The destination quaternion.</param>
|
||||
/// <param name="preA">A quaternion before this quaternion.</param>
|
||||
/// <param name="postB">A quaternion after <paramref name="b"/>.</param>
|
||||
/// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
|
||||
/// <param name="bT"></param>
|
||||
/// <param name="preAT"></param>
|
||||
/// <param name="postBT"></param>
|
||||
/// <returns>The interpolated quaternion.</returns>
|
||||
public Quaternion SphericalCubicInterpolateInTime(Quaternion b, Quaternion preA, Quaternion postB, real_t weight, real_t bT, real_t preAT, real_t postBT)
|
||||
{
|
||||
#if DEBUG
|
||||
if (!IsNormalized())
|
||||
{
|
||||
throw new InvalidOperationException("Quaternion is not normalized");
|
||||
}
|
||||
if (!b.IsNormalized())
|
||||
{
|
||||
throw new ArgumentException("Argument is not normalized", nameof(b));
|
||||
}
|
||||
#endif
|
||||
|
||||
// Align flip phases.
|
||||
Quaternion fromQ = new Basis(this).GetRotationQuaternion();
|
||||
Quaternion preQ = new Basis(preA).GetRotationQuaternion();
|
||||
Quaternion toQ = new Basis(b).GetRotationQuaternion();
|
||||
Quaternion postQ = new Basis(postB).GetRotationQuaternion();
|
||||
|
||||
// Flip quaternions to shortest path if necessary.
|
||||
bool flip1 = Math.Sign(fromQ.Dot(preQ)) < 0;
|
||||
preQ = flip1 ? -preQ : preQ;
|
||||
bool flip2 = Math.Sign(fromQ.Dot(toQ)) < 0;
|
||||
toQ = flip2 ? -toQ : toQ;
|
||||
bool flip3 = flip2 ? toQ.Dot(postQ) <= 0 : Math.Sign(toQ.Dot(postQ)) < 0;
|
||||
postQ = flip3 ? -postQ : postQ;
|
||||
|
||||
// Calc by Expmap in fromQ space.
|
||||
Quaternion lnFrom = new Quaternion(0, 0, 0, 0);
|
||||
Quaternion lnTo = (fromQ.Inverse() * toQ).Log();
|
||||
Quaternion lnPre = (fromQ.Inverse() * preQ).Log();
|
||||
Quaternion lnPost = (fromQ.Inverse() * postQ).Log();
|
||||
Quaternion ln = new Quaternion(
|
||||
Mathf.CubicInterpolateInTime(lnFrom.x, lnTo.x, lnPre.x, lnPost.x, weight, bT, preAT, postBT),
|
||||
Mathf.CubicInterpolateInTime(lnFrom.y, lnTo.y, lnPre.y, lnPost.y, weight, bT, preAT, postBT),
|
||||
Mathf.CubicInterpolateInTime(lnFrom.z, lnTo.z, lnPre.z, lnPost.z, weight, bT, preAT, postBT),
|
||||
0);
|
||||
Quaternion q1 = fromQ * ln.Exp();
|
||||
|
||||
// Calc by Expmap in toQ space.
|
||||
lnFrom = (toQ.Inverse() * fromQ).Log();
|
||||
lnTo = new Quaternion(0, 0, 0, 0);
|
||||
lnPre = (toQ.Inverse() * preQ).Log();
|
||||
lnPost = (toQ.Inverse() * postQ).Log();
|
||||
ln = new Quaternion(
|
||||
Mathf.CubicInterpolateInTime(lnFrom.x, lnTo.x, lnPre.x, lnPost.x, weight, bT, preAT, postBT),
|
||||
Mathf.CubicInterpolateInTime(lnFrom.y, lnTo.y, lnPre.y, lnPost.y, weight, bT, preAT, postBT),
|
||||
Mathf.CubicInterpolateInTime(lnFrom.z, lnTo.z, lnPre.z, lnPost.z, weight, bT, preAT, postBT),
|
||||
0);
|
||||
Quaternion q2 = toQ * ln.Exp();
|
||||
|
||||
// To cancel error made by Expmap ambiguity, do blends.
|
||||
return q1.Slerp(q2, weight);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the dot product of two quaternions.
|
||||
/// </summary>
|
||||
|
|
|
@ -215,6 +215,29 @@ namespace Godot
|
|||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs a cubic interpolation between vectors <paramref name="preA"/>, this vector,
|
||||
/// <paramref name="b"/>, and <paramref name="postB"/>, by the given amount <paramref name="weight"/>.
|
||||
/// It can perform smoother interpolation than <see cref="CubicInterpolate"/>
|
||||
/// by the time values.
|
||||
/// </summary>
|
||||
/// <param name="b">The destination vector.</param>
|
||||
/// <param name="preA">A vector before this vector.</param>
|
||||
/// <param name="postB">A vector after <paramref name="b"/>.</param>
|
||||
/// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
|
||||
/// <param name="t"></param>
|
||||
/// <param name="preAT"></param>
|
||||
/// <param name="postBT"></param>
|
||||
/// <returns>The interpolated vector.</returns>
|
||||
public Vector2 CubicInterpolateInTime(Vector2 b, Vector2 preA, Vector2 postB, real_t weight, real_t t, real_t preAT, real_t postBT)
|
||||
{
|
||||
return new Vector2
|
||||
(
|
||||
Mathf.CubicInterpolateInTime(x, b.x, preA.x, postB.x, weight, t, preAT, postBT),
|
||||
Mathf.CubicInterpolateInTime(y, b.y, preA.y, postB.y, weight, t, preAT, postBT)
|
||||
);
|
||||
}
|
||||
|
||||
/// <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.
|
||||
|
|
|
@ -208,6 +208,30 @@ namespace Godot
|
|||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs a cubic interpolation between vectors <paramref name="preA"/>, this vector,
|
||||
/// <paramref name="b"/>, and <paramref name="postB"/>, by the given amount <paramref name="weight"/>.
|
||||
/// It can perform smoother interpolation than <see cref="CubicInterpolate"/>
|
||||
/// by the time values.
|
||||
/// </summary>
|
||||
/// <param name="b">The destination vector.</param>
|
||||
/// <param name="preA">A vector before this vector.</param>
|
||||
/// <param name="postB">A vector after <paramref name="b"/>.</param>
|
||||
/// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
|
||||
/// <param name="t"></param>
|
||||
/// <param name="preAT"></param>
|
||||
/// <param name="postBT"></param>
|
||||
/// <returns>The interpolated vector.</returns>
|
||||
public Vector3 CubicInterpolateInTime(Vector3 b, Vector3 preA, Vector3 postB, real_t weight, real_t t, real_t preAT, real_t postBT)
|
||||
{
|
||||
return new Vector3
|
||||
(
|
||||
Mathf.CubicInterpolateInTime(x, b.x, preA.x, postB.x, weight, t, preAT, postBT),
|
||||
Mathf.CubicInterpolateInTime(y, b.y, preA.y, postB.y, weight, t, preAT, postBT),
|
||||
Mathf.CubicInterpolateInTime(z, b.z, preA.z, postB.z, weight, t, preAT, postBT)
|
||||
);
|
||||
}
|
||||
|
||||
/// <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.
|
||||
|
|
|
@ -192,6 +192,31 @@ namespace Godot
|
|||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs a cubic interpolation between vectors <paramref name="preA"/>, this vector,
|
||||
/// <paramref name="b"/>, and <paramref name="postB"/>, by the given amount <paramref name="weight"/>.
|
||||
/// It can perform smoother interpolation than <see cref="CubicInterpolate"/>
|
||||
/// by the time values.
|
||||
/// </summary>
|
||||
/// <param name="b">The destination vector.</param>
|
||||
/// <param name="preA">A vector before this vector.</param>
|
||||
/// <param name="postB">A vector after <paramref name="b"/>.</param>
|
||||
/// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
|
||||
/// <param name="t"></param>
|
||||
/// <param name="preAT"></param>
|
||||
/// <param name="postBT"></param>
|
||||
/// <returns>The interpolated vector.</returns>
|
||||
public Vector4 CubicInterpolateInTime(Vector4 b, Vector4 preA, Vector4 postB, real_t weight, real_t t, real_t preAT, real_t postBT)
|
||||
{
|
||||
return new Vector4
|
||||
(
|
||||
Mathf.CubicInterpolateInTime(x, b.x, preA.x, postB.x, weight, t, preAT, postBT),
|
||||
Mathf.CubicInterpolateInTime(y, b.y, preA.y, postB.y, weight, t, preAT, postBT),
|
||||
Mathf.CubicInterpolateInTime(y, b.z, preA.z, postB.z, weight, t, preAT, postBT),
|
||||
Mathf.CubicInterpolateInTime(w, b.w, preA.w, postB.w, weight, t, preAT, postBT)
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the normalized vector pointing from this vector to <paramref name="to"/>.
|
||||
/// </summary>
|
||||
|
|
Loading…
Reference in a new issue