@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
90 lines (73 loc) • 3.1 kB
JavaScript
import { catmull_rom_compute_T } from "./catmull_rom_compute_T.js";
/**
* Computes derivative of Catmull Rom spline
* @param {number[]} result_value
* @param {number} result_value_offset
* @param {number[]} result_derivative
* @param {number} result_derivative_offset
* @param {number[]} p0 spline point 0
* @param {number[]} p1 spline point 1
* @param {number[]} p2 spline point 2
* @param {number[]} p3 spline point 3
* @param {number} dimensions number of dimensions in the input and output vectors
* @param {number} f between 0..1
* @param {number} alpha between 0..1
*/
export function computeNonuniformCaltmullRomSplineDerivative(
result_value, result_value_offset,
result_derivative, result_derivative_offset,
p0, p1, p2, p3,
dimensions, f, alpha
) {
/*
@see https://math.stackexchange.com/questions/843595/how-can-i-calculate-the-derivative-of-a-catmull-rom-spline-with-nonuniform-param
@see http://denkovacs.com/2016/02/catmull-rom-spline-derivatives/
@see https://en.wikipedia.org/wiki/Centripetal_Catmull%E2%80%93Rom_spline
*/
const half_alpha = alpha * 0.5;
// calculate T
const t0 = 0;
let t_01 = catmull_rom_compute_T(p0, p1, dimensions, half_alpha);
let t_02 = catmull_rom_compute_T(p1, p2, dimensions, half_alpha);
let t_03 = catmull_rom_compute_T(p2, p3, dimensions, half_alpha);
// safety check for repeated points, to prevent division by 0
if (t_01 < 1e-4) {
t_01 = 1;
}
if (t_02 < 1e-4) {
t_02 = t_01;
}
if (t_03 < 1e-4) {
t_03 = t_02;
}
const t1 = t_01 + t0;
const t2 = t_02 + t1;
const t3 = t_03 + t2;
/**
* Interpolation between points 1 and 2
* @type {number}
*/
const t = t1 * (1 - f) + t2 * f;
for (let i = 0; i < dimensions; i++) {
// read vector values for the dimension
const v0 = p0[i];
const v1 = p1[i];
const v2 = p2[i];
const v3 = p3[i];
const A1 = (t1 - t) / (t1 - t0) * v0 + (t - t0) / (t1 - t0) * v1;
const A2 = (t2 - t) / (t2 - t1) * v1 + (t - t1) / (t2 - t1) * v2;
const A3 = (t3 - t) / (t3 - t2) * v2 + (t - t2) / (t3 - t2) * v3;
const B1 = (t2 - t) / (t2 - t0) * A1 + (t - t0) / (t2 - t0) * A2;
const B2 = (t3 - t) / (t3 - t1) * A2 + (t - t1) / (t3 - t1) * A3;
const C = (t2 - t) / (t2 - t1) * B1 + (t - t1) / (t2 - t1) * B2;
result_value[result_value_offset + i] = C;
// derivatives
const dA1 = (v1 - v0) / (t1 - t0)
const dA2 = (v2 - v1) / (t2 - t1);
const dA3 = (v3 - v2) / (t3 - t2);
const dB1 = (A2 - A1) / (t2 - t0) + dA1 * (t2 - t) / (t2 - t0) + dA2 * (t - t0) / (t2 - t0);
const dB2 = (A3 - A2) / (t3 - t1) + dA2 * (t3 - t) / (t3 - t1) + dA3 * (t - t1) / (t3 - t1);
const dC = (B2 - B1) / (t2 - t1) + dB1 * (t2 - t) / (t2 - t1) + dB2 * (t - t1) / (t2 - t1);
result_derivative[result_derivative_offset + i] = dC;
}
}