UNPKG

@woosh/meep-engine

Version:

Pure JavaScript game engine. Fully featured and production ready.

110 lines (92 loc) 3.11 kB
import { assert } from "../../assert.js"; import { spline3_hermite } from "./spline3_hermite.js"; /** * Compute the parameter values `t` at which a cubic Hermite spline reaches its * minimum and maximum on `[0, 1]`. `t_at_min` is written to * `result[result_offset]`, `t_at_max` to `result[result_offset + result_stride]`. * Both values lie in `[0, 1]`. * * Companion to {@link spline3_hermite_bounds}, which writes the values; this * one writes the parameters at which those values are reached. Either function * does its own critical-point search — call whichever you actually need. * * @param {number[]|Float32Array|Float64Array} result * @param {number} result_offset * @param {number} result_stride * @param {number} p0 * @param {number} p1 * @param {number} m0 * @param {number} m1 * * @author Alex Goldring * @copyright Company Named Limited (c) 2025 */ export function spline3_hermite_bounds_t( result, result_offset, result_stride, p0, p1, m0, m1 ) { assert.greaterThan(result_stride, 0, 'result_stride must be greater than 0'); assert.isInteger(result_stride, 'result_stride'); // Derivative of the Hermite polynomial: // 3 t² (m0 + m1 + 2 p0 - 2 p1) - 2 t (2 m0 + m1 + 3 p0 - 3 p1) + m0 const a = 3 * (m0 + m1 + 2 * p0 - 2 * p1); const b = -2 * (2 * m0 + m1 + 3 * p0 - 3 * p1); const c = m0; let min, max, t_at_min, t_at_max; if (p0 <= p1) { min = p0; t_at_min = 0; max = p1; t_at_max = 1; } else { min = p1; t_at_min = 1; max = p0; t_at_max = 0; } if (Math.abs(a) < 1e-12) { if (Math.abs(b) >= 1e-12) { const t = -c / b; if (0 < t && t < 1) { const value = spline3_hermite(t, p0, p1, m0, m1); if (value < min) { min = value; t_at_min = t; } if (value > max) { max = value; t_at_max = t; } } } } else { const b2ac = b * b - 4 * c * a; if (b2ac >= 0) { const sqrtb2ac = Math.sqrt(b2ac); const t1 = (-b + sqrtb2ac) / (2 * a); if (0 < t1 && t1 < 1) { const value = spline3_hermite(t1, p0, p1, m0, m1); if (value < min) { min = value; t_at_min = t1; } if (value > max) { max = value; t_at_max = t1; } } const t2 = (-b - sqrtb2ac) / (2 * a); if (0 < t2 && t2 < 1) { const value = spline3_hermite(t2, p0, p1, m0, m1); if (value < min) { min = value; t_at_min = t2; } if (value > max) { max = value; t_at_max = t2; } } } } result[result_offset] = t_at_min; result[result_offset + result_stride] = t_at_max; }