Add cubic bezier functions.
This commit is contained in:
44
Assets/Cryville/Common/Math/CubicBezier.cs
Normal file
44
Assets/Cryville/Common/Math/CubicBezier.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
using SMath = System.Math;
|
||||
|
||||
namespace Cryville.Common.Math {
|
||||
// Ported from https://github.com/arian/cubic-bezier/blob/master/index.js
|
||||
public static class CubicBezier {
|
||||
public static float Evaluate(float t, float x1, float y1, float x2, float y2, float epsilon) {
|
||||
float x = t, t0, t1, t2, tx, d2, i;
|
||||
for (t2 = x, i = 0; i < 8; i++) {
|
||||
tx = CurveX(t2, x1, x2) - x;
|
||||
if (SMath.Abs(tx) < epsilon) return CurveY(t2, y1, y2);
|
||||
d2 = DerivativeCurveX(t2, x1, x2);
|
||||
if (SMath.Abs(d2) < 1e-6) break;
|
||||
t2 -= tx / d2;
|
||||
}
|
||||
|
||||
t0 = 0; t1 = 1; t2 = x;
|
||||
|
||||
if (t2 < t0) return CurveY(t0, y1, y2);
|
||||
if (t2 > t1) return CurveY(t1, y1, y2);
|
||||
|
||||
while (t0 < t1) {
|
||||
tx = CurveX(t2, x1, x2);
|
||||
if (SMath.Abs(tx - x) < epsilon) return CurveY(t2, y1, y2);
|
||||
if (x > tx) t0 = t2;
|
||||
else t1 = t2;
|
||||
t2 = (t1 - t0) * .5f + t0;
|
||||
}
|
||||
|
||||
return CurveY(t2, y1, y2);
|
||||
}
|
||||
static float CurveX(float t, float x1, float x2) {
|
||||
float v = 1 - t;
|
||||
return 3 * v * v * t * x1 + 3 * v * t * t * x2 + t * t * t;
|
||||
}
|
||||
static float CurveY(float t, float y1, float y2) {
|
||||
float v = 1 - t;
|
||||
return 3 * v * v * t * y1 + 3 * v * t * t * y2 + t * t * t;
|
||||
}
|
||||
static float DerivativeCurveX(float t, float x1, float x2) {
|
||||
float v = 1 - t;
|
||||
return 3 * (2 * (t - 1) * t + v * v) * x1 + 3 * (-t * t * t + 2 * v * t) * x2;
|
||||
}
|
||||
}
|
||||
}
|
11
Assets/Cryville/Common/Math/CubicBezier.cs.meta
Normal file
11
Assets/Cryville/Common/Math/CubicBezier.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 17dd6f775fc965f43960da7166b55b87
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -1,4 +1,5 @@
|
||||
using Cryville.Common;
|
||||
using Cryville.Common.Math;
|
||||
using Cryville.Common.Pdt;
|
||||
using Cryville.Crtr.Event;
|
||||
using System;
|
||||
@@ -152,6 +153,11 @@ namespace Cryville.Crtr {
|
||||
_ctxops.Add(IdentifierManager.SharedInstance.Request("max"), new func_max(() => ContextSelfValue));
|
||||
_ctxops.Add(IdentifierManager.SharedInstance.Request("abs"), new func_abs(() => ContextSelfValue));
|
||||
_ctxops.Add(IdentifierManager.SharedInstance.Request("anim"), new func_anim(() => ContextSelfValue));
|
||||
_ctxops.Add(IdentifierManager.SharedInstance.Request("cubic_bezier"), new func_cubic_bezier(() => ContextSelfValue));
|
||||
_ctxops.Add(IdentifierManager.SharedInstance.Request("ease"), new func_cubic_bezier_fixed(0.25f, 0.1f, 0.25f, 1f, () => ContextSelfValue));
|
||||
_ctxops.Add(IdentifierManager.SharedInstance.Request("ease_in"), new func_cubic_bezier_fixed(0.42f, 0f, 1f, 1f, () => ContextSelfValue));
|
||||
_ctxops.Add(IdentifierManager.SharedInstance.Request("ease_out"), new func_cubic_bezier_fixed(0f, 0f, 0.58f, 1f, () => ContextSelfValue));
|
||||
_ctxops.Add(IdentifierManager.SharedInstance.Request("ease_in_out"), new func_cubic_bezier_fixed(0.42f, 0f, 0.58f, 1f, () => ContextSelfValue));
|
||||
|
||||
Func<int, PropSrc> cccb = k => ContextCascadeLookup(k);
|
||||
_ctxops.Add(IdentifierManager.SharedInstance.Request("attack_timing"), new func_attack_timing(cccb));
|
||||
@@ -533,6 +539,43 @@ namespace Cryville.Crtr {
|
||||
}
|
||||
}
|
||||
}
|
||||
class func_cubic_bezier : PdtOperator {
|
||||
readonly Func<PropSrc> _ctxcb;
|
||||
public func_cubic_bezier(Func<PropSrc> ctxcb) : base(5) {
|
||||
_ctxcb = ctxcb;
|
||||
}
|
||||
protected override unsafe void Execute() {
|
||||
float x1 = GetOperand(0).AsNumber(), y1 = GetOperand(1).AsNumber();
|
||||
float x2 = GetOperand(2).AsNumber(), y2 = GetOperand(3).AsNumber();
|
||||
float time;
|
||||
switch (LoadedOperandCount) {
|
||||
case 4: time = oputil.AsNumber(_ctxcb()); break;
|
||||
case 5: time = GetOperand(4).AsNumber(); break;
|
||||
default: throw new ArgumentException("Argument count not 4 or 5");
|
||||
}
|
||||
GetReturnFrame(PdtInternalType.Number, sizeof(float))
|
||||
.SetNumber(CubicBezier.Evaluate(time, x1, y1, x2, y2, 1e-5f));
|
||||
}
|
||||
}
|
||||
class func_cubic_bezier_fixed : PdtOperator {
|
||||
readonly float x1, y1, x2, y2;
|
||||
readonly Func<PropSrc> _ctxcb;
|
||||
public func_cubic_bezier_fixed(float x1, float y1, float x2, float y2, Func<PropSrc> ctxcb) : base(1) {
|
||||
this.x1 = x1; this.y1 = y1;
|
||||
this.x2 = x2; this.y2 = y2;
|
||||
_ctxcb = ctxcb;
|
||||
}
|
||||
protected override void Execute() {
|
||||
float time;
|
||||
switch (LoadedOperandCount) {
|
||||
case 0: time = oputil.AsNumber(_ctxcb()); break;
|
||||
case 1: time = GetOperand(0).AsNumber(); break;
|
||||
default: throw new ArgumentException("Argument count not 0 or 1");
|
||||
}
|
||||
GetReturnFrame(PdtInternalType.Number, sizeof(float))
|
||||
.SetNumber(CubicBezier.Evaluate(time, x1, y1, x2, y2, 1e-5f));
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
#region Judge Functions
|
||||
static readonly int _var_fn = IdentifierManager.SharedInstance.Request("fn");
|
||||
|
Reference in New Issue
Block a user