babylon-mmd
Version:
babylon.js mmd loader and runtime
66 lines (59 loc) • 1.79 kB
JavaScript
/**
* Cubic Bezier Interpolation for MMD animation curves
* @param x1 X1
* @param x2 X2
* @param y1 Y1
* @param y2 Y2
* @param x Weight
* @returns Interpolated value
*/
export function BezierInterpolate(x1, x2, y1, y2, x) {
/*
Cubic Bezier curves
https://en.wikipedia.org/wiki/B%C3%A9zier_curve#Cubic_B.C3.A9zier_curves
B(t) = ( 1 - t ) ^ 3 * P0
+ 3 * ( 1 - t ) ^ 2 * t * P1
+ 3 * ( 1 - t ) * t^2 * P2
+ t ^ 3 * P3
( 0 <= t <= 1 )
MMD uses Cubic Bezier curves for bone and camera animation interpolation.
http://d.hatena.ne.jp/edvakf/20111016/1318716097
x = ( 1 - t ) ^ 3 * x0
+ 3 * ( 1 - t ) ^ 2 * t * x1
+ 3 * ( 1 - t ) * t^2 * x2
+ t ^ 3 * x3
y = ( 1 - t ) ^ 3 * y0
+ 3 * ( 1 - t ) ^ 2 * t * y1
+ 3 * ( 1 - t ) * t^2 * y2
+ t ^ 3 * y3
( x0 = 0, y0 = 0 )
( x3 = 1, y3 = 1 )
( 0 <= t, x1, x2, y1, y2 <= 1 )
Here solves this equation with Bisection method,
https://en.wikipedia.org/wiki/Bisection_method
gets t, and then calculate y.
f(t) = 3 * ( 1 - t ) ^ 2 * t * x1
+ 3 * ( 1 - t ) * t^2 * x2
+ t ^ 3 - x = 0
(Another option: Newton's method https://en.wikipedia.org/wiki/Newton%27s_method)
*/
let c = 0.5;
let t = c;
let s = 1.0 - t;
const loop = 15;
const eps = 1e-5;
const math = Math;
let sst3, stt3, ttt;
for (let i = 0; i < loop; ++i) {
sst3 = 3.0 * s * s * t;
stt3 = 3.0 * s * t * t;
ttt = t * t * t;
const ft = (sst3 * x1) + (stt3 * x2) + (ttt) - x;
if (math.abs(ft) < eps)
break;
c *= 0.5;
t += (ft < 0) ? c : -c;
s = 1.0 - t;
}
return (sst3 * y1) + (stt3 * y2) + ttt;
}