@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
68 lines (57 loc) • 2.19 kB
JavaScript
import { assert } from "../../../core/assert.js";
import { lerp } from "../../../core/math/lerp.js";
import { spline3_hermite } from "../../../core/math/spline/spline3_hermite.js";
import { spline3_hermite_derivative } from "../../../core/math/spline/spline3_hermite_derivative.js";
/**
* Subdivide a curve segment by introducing a new keyframe at a given normalized time.
* Subdivision does not alter the curve shape in any way, it is intended primarily for editing purposes.
*
* @param {Keyframe} out keyframe to be added at the point of subdivision, its tangents, time and value will be overwritten
* @param {Keyframe} key0 start of the segment
* @param {Keyframe} key1 end of the segment
* @param {number} t normalized time in [0..1] between key0 and key1 where new frame is to be inserted
* @returns {Keyframe} `out`, for convenience
*
* @see AnimationCurve
* @example
* const new_frame = animation_curve_subdivide(new Keyframe(), key0, key1, 0.5);
* curve.add(new_frame);
*/
export function animation_curve_subdivide(
out,
key0,
key1,
t
) {
assert.isObject(out, 'out');
assert.isObject(key0, 'key0');
assert.isObject(key1, 'key1');
assert.equal(out.isKeyframe,true,'out.isKeyframe !== true');
assert.equal(key0.isKeyframe,true,'key0.isKeyframe !== true');
assert.equal(key1.isKeyframe,true,'key1.isKeyframe !== true');
assert.isNumber(t, 't');
assert.ok(t >= 0 && t <= 1);
const v0 = key0.value;
const v1 = key1.value;
const time_span = key1.time - key0.time;
// Note that Keyframe tangents are normalized, so we denomalize them before using them
const m0 = key0.outTangent * time_span;
const m1 = key1.inTangent * time_span;
const xm = spline3_hermite(
t,
v0, v1,
m0, m1
);
const vm = spline3_hermite_derivative(
t,
v0, v1,
m0, m1
);
out.time = lerp(key0.time, key1.time, t);
out.value = xm;
// re-normalize tangent
const new_tangent = vm / time_span;
out.inTangent = new_tangent;
out.outTangent = new_tangent;
return out;
}