@woosh/meep-engine 2.126.65 → 2.126.66

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "description": "Pure JavaScript game engine. Fully featured and production ready.",
6
6
  "type": "module",
7
7
  "author": "Alexander Goldring",
8
- "version": "2.126.65",
8
+ "version": "2.126.66",
9
9
  "main": "build/meep.module.js",
10
10
  "module": "build/meep.module.js",
11
11
  "exports": {
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Finds the parameter 't' of the nearest point on a 1D Hermite spline
3
+ * function graph to a reference point. The curve is defined by (t, p(t)).
4
+ * This version is optimized to avoid allocations.
5
+ *
6
+ * @param {number} ref_t - The 't' coordinate of the reference point.
7
+ * @param {number} ref_p - The 'p' coordinate of the reference point.
8
+ * @param {number} p0 - The start value of the spline (at t=0).
9
+ * @param {number} p1 - The end value of the spline (at t=1).
10
+ * @param {number} m0 - The tangent at the start.
11
+ * @param {number} m1 - The tangent at the end.
12
+ * @returns {number} The parameter 't' of the nearest point. This value is always in [0..1] range
13
+ */
14
+ export function spline3_hermite_nearest_point(ref_t: number, ref_p: number, p0: number, p1: number, m0: number, m1: number): number;
15
+ //# sourceMappingURL=spline3_hermite_nearest_point.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spline3_hermite_nearest_point.d.ts","sourceRoot":"","sources":["../../../../../src/core/math/spline/spline3_hermite_nearest_point.js"],"names":[],"mappings":"AAyBA;;;;;;;;;;;;GAYG;AACH,qDARW,MAAM,SACN,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,GACJ,MAAM,CAuFlB"}
@@ -0,0 +1,124 @@
1
+ import { spline3_hermite } from "./spline3_hermite.js";
2
+
3
+ /**
4
+ * Helper to evaluate a polynomial given its coefficients.
5
+ * @param {Float32Array} p - Polynomial coefficients [c0, c1, c2, ...]
6
+ * @param {number} t - The value at which to evaluate.
7
+ * @param {number} size
8
+ * @returns {number}
9
+ */
10
+ function polyval(p, t, size) {
11
+ let result = 0;
12
+
13
+ for (let i = size - 1; i >= 0; i--) {
14
+ result = result * t + p[i];
15
+ }
16
+
17
+ return result;
18
+ }
19
+
20
+ const quintic_coeffs = new Float32Array(6);
21
+ const quartic_coeffs = new Float32Array(5);
22
+
23
+ const NEWTON_STEPS = 3;
24
+ const START_ROOT_COUNT = 5;
25
+
26
+ /**
27
+ * Finds the parameter 't' of the nearest point on a 1D Hermite spline
28
+ * function graph to a reference point. The curve is defined by (t, p(t)).
29
+ * This version is optimized to avoid allocations.
30
+ *
31
+ * @param {number} ref_t - The 't' coordinate of the reference point.
32
+ * @param {number} ref_p - The 'p' coordinate of the reference point.
33
+ * @param {number} p0 - The start value of the spline (at t=0).
34
+ * @param {number} p1 - The end value of the spline (at t=1).
35
+ * @param {number} m0 - The tangent at the start.
36
+ * @param {number} m1 - The tangent at the end.
37
+ * @returns {number} The parameter 't' of the nearest point. This value is always in [0..1] range
38
+ */
39
+ export function spline3_hermite_nearest_point(
40
+ ref_t, ref_p,
41
+ p0, p1, m0, m1
42
+ ) {
43
+
44
+ // 1. Calculate polynomial coefficients A, B, C for p(t)
45
+ const A = 2 * p0 - 2 * p1 + m0 + m1;
46
+ const B = -3 * p0 + 3 * p1 - 2 * m0 - m1;
47
+ const C = m0;
48
+ const D_minus_Rp = p0 - ref_p;
49
+
50
+ // 2. Form the quintic polynomial f(t) = c5*t^5 + ... + c0
51
+
52
+ quintic_coeffs[0] = (C * D_minus_Rp - ref_t)
53
+ quintic_coeffs[1] = (C * C + 2 * B * D_minus_Rp + 1)
54
+ quintic_coeffs[2] = (3 * B * C + 3 * A * D_minus_Rp)
55
+ quintic_coeffs[3] = (4 * A * C + 2 * B * B)
56
+ quintic_coeffs[4] = (5 * A * B)
57
+ quintic_coeffs[5] = (3 * A * A)
58
+
59
+ // Derivative of the quintic (a quartic) for Newton's method
60
+
61
+ quartic_coeffs[0] = quintic_coeffs[1]
62
+ quartic_coeffs[1] = 2 * quintic_coeffs[2]
63
+ quartic_coeffs[2] = 3 * quintic_coeffs[3]
64
+ quartic_coeffs[3] = 4 * quintic_coeffs[4]
65
+ quartic_coeffs[4] = 5 * quintic_coeffs[5]
66
+
67
+
68
+ // 3. Initialize by checking the endpoints t=0 and t=1
69
+ let best_t = 0;
70
+ let dt = 0 - ref_t;
71
+ let dp = p0 - ref_p;
72
+ let min_dist_sq = dt * dt + dp * dp;
73
+
74
+ dt = 1 - ref_t;
75
+ dp = p1 - ref_p;
76
+ const dist_sq_at_1 = dt * dt + dp * dp;
77
+ if (dist_sq_at_1 < min_dist_sq) {
78
+ min_dist_sq = dist_sq_at_1;
79
+ best_t = 1;
80
+ }
81
+
82
+ // 4. Find roots and check them on the fly
83
+ const tolerance = 1e-7;
84
+
85
+
86
+ // Start Newton's method from several points to find multiple roots
87
+ for (let i = 0; i <= START_ROOT_COUNT; i++) {
88
+ let t = i / START_ROOT_COUNT; // Starting guess for the root
89
+
90
+ for (let j = NEWTON_STEPS; j > 0; j--) {
91
+
92
+ const f_t = polyval(quintic_coeffs, t, 6);
93
+ const fp_t = polyval(quartic_coeffs, t, 5);
94
+
95
+ if (Math.abs(fp_t) < tolerance) {
96
+ break;
97
+ }
98
+
99
+ const t_new = t - f_t / fp_t;
100
+
101
+ if (Math.abs(t_new - t) < tolerance) {
102
+ break;
103
+ }
104
+
105
+ t = t_new;
106
+ }
107
+
108
+ // Check if the found root is valid and yields a better distance
109
+ if (t > 0 && t < 1) {
110
+ // Endpoints already checked
111
+ const p = spline3_hermite(t, p0, p1, m0, m1);
112
+ const current_dt = t - ref_t;
113
+ const current_dp = p - ref_p;
114
+ const dist_sq = current_dt * current_dt + current_dp * current_dp;
115
+
116
+ if (dist_sq < min_dist_sq) {
117
+ min_dist_sq = dist_sq;
118
+ best_t = t;
119
+ }
120
+ }
121
+ }
122
+
123
+ return best_t;
124
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"AnimationCurve.d.ts","sourceRoot":"","sources":["../../../../../src/engine/animation/curve/AnimationCurve.js"],"names":[],"mappings":"AAqBA;;;;;;;;;;;;;;;;GAgBG;AACH;IAkXI;;;;OAIG;IACH,kBAHW,QAAQ,EAAE,GACR,cAAc,CAQ1B;IAED;;;;;;;;OAQG;IACH,6BANW,MAAM,eACN,MAAM,YACN,MAAM,aACN,MAAM,GACL,cAAc,CAUzB;IAED;;;;;;OAMG;IACH,4BALW,MAAM,YACN,MAAM,UACN,MAAM,GACL,cAAc,CAOzB;IAED;;;;;;;OAOG;IACH,0BANW,MAAM,eACN,MAAM,YACN,MAAM,aACN,MAAM,GACL,cAAc,CAYzB;IAjbD;;;;;OAKG;IACH,eAFU,QAAQ,EAAE,CAEV;IAEV;;;;;OAKG;IACH,SAHW,QAAQ,GACN,MAAM,CAiClB;IAED;;;OAGG;IACH,cAFW,QAAQ,EAAE,QAUpB;IAED;;;;OAIG;IACH,YAHW,QAAQ,GACN,OAAO,CAYnB;IAED;;OAEG;IACH,cAEC;IAGD;;;OAGG;IACH,WAFY,OAAO,CAIlB;IAED;;;OAGG;IACH,qBAEC;IAED;;;;OAIG;IACH,yBAUC;IAED;;;;OAIG;IACH,uBAUC;IAED;;;;OAIG;IACH,uBAcC;IAED;;;;OAIG;IACH,wBAHW,MAAM,GACJ,MAAM,CA0ClB;IAED;;;;OAIG;IACH,eAHW,MAAM,GACL,MAAM,CAoCjB;IAED;;;;OAIG;IACH,qBAFW,MAAM,QAmChB;IAED;;;;OAIG;IACH,sBAHW,MAAM,UACN,MAAM,QAWhB;IAED,0BAKC;IAGD;;;OAGG;IACH,YAFW,cAAc,QAIxB;IAED;;;OAGG;IACH,SAFY,cAAc,CAQzB;IAED;;;;OAIG;IACH,cAHW,cAAc,GACb,OAAO,CAIlB;IAED;;;OAGG;IACH,QAFY,MAAM,CAIjB;IAED;;MAIC;IAED;;aAeC;IAsEL;;;;OAIG;IACH,2BAFU,OAAO,CAEwB;CARxC;yBAhdwB,eAAe"}
1
+ {"version":3,"file":"AnimationCurve.d.ts","sourceRoot":"","sources":["../../../../../src/engine/animation/curve/AnimationCurve.js"],"names":[],"mappings":"AAqBA;;;;;;;;;;;;;;;;GAgBG;AACH;IAkXI;;;;OAIG;IACH,kBAHW,QAAQ,EAAE,GACR,cAAc,CAQ1B;IAED;;;;;;;;OAQG;IACH,6BANW,MAAM,eACN,MAAM,YACN,MAAM,aACN,MAAM,GACL,cAAc,CAUzB;IAED;;;;;;OAMG;IACH,4BALW,MAAM,YACN,MAAM,UACN,MAAM,GACL,cAAc,CAOzB;IAED;;;;;;;OAOG;IACH,0BANW,MAAM,eACN,MAAM,YACN,MAAM,aACN,MAAM,GACL,cAAc,CAezB;IApbD;;;;;OAKG;IACH,eAFU,QAAQ,EAAE,CAEV;IAEV;;;;;OAKG;IACH,SAHW,QAAQ,GACN,MAAM,CAiClB;IAED;;;OAGG;IACH,cAFW,QAAQ,EAAE,QAUpB;IAED;;;;OAIG;IACH,YAHW,QAAQ,GACN,OAAO,CAYnB;IAED;;OAEG;IACH,cAEC;IAGD;;;OAGG;IACH,WAFY,OAAO,CAIlB;IAED;;;OAGG;IACH,qBAEC;IAED;;;;OAIG;IACH,yBAUC;IAED;;;;OAIG;IACH,uBAUC;IAED;;;;OAIG;IACH,uBAcC;IAED;;;;OAIG;IACH,wBAHW,MAAM,GACJ,MAAM,CA0ClB;IAED;;;;OAIG;IACH,eAHW,MAAM,GACL,MAAM,CAoCjB;IAED;;;;OAIG;IACH,qBAFW,MAAM,QAmChB;IAED;;;;OAIG;IACH,sBAHW,MAAM,UACN,MAAM,QAWhB;IAED,0BAKC;IAGD;;;OAGG;IACH,YAFW,cAAc,QAIxB;IAED;;;OAGG;IACH,SAFY,cAAc,CAQzB;IAED;;;;OAIG;IACH,cAHW,cAAc,GACb,OAAO,CAIlB;IAED;;;OAGG;IACH,QAFY,MAAM,CAIjB;IAED;;MAIC;IAED;;aAeC;IAyEL;;;;OAIG;IACH,2BAFU,OAAO,CAEwB;CARxC;yBAndwB,eAAe"}
@@ -464,7 +464,10 @@ export class AnimationCurve {
464
464
  timeStart = 0, valueStart = 0,
465
465
  timeEnd = 1, valueEnd = 1
466
466
  ) {
467
- const tangent = valueEnd - valueStart;
467
+ const time_delta = timeEnd - timeStart;
468
+
469
+ // tangent needs to be normalized
470
+ const tangent = time_delta === 0 ? 0 : (valueEnd - valueStart) / time_delta;
468
471
 
469
472
  return AnimationCurve.from([
470
473
  Keyframe.from(timeStart, valueStart, 0, tangent),
@@ -0,0 +1,13 @@
1
+ /**
2
+ * NOTE: this operation has O(n) complexity, where n is the number of keys in the curve.
3
+ * @param {AnimationCurve} curve
4
+ * @param {number} ref_time
5
+ * @param {number} ref_value
6
+ * @returns {number} time of the nearest point on the curve
7
+ * @see AnimationCurve
8
+ * @example
9
+ * const nearest_time = animation_curve_nearest_point(curve, 0.5, 10);
10
+ * const nearest_value = curve.evaluate(nearest_time);
11
+ */
12
+ export function animation_curve_nearest_point(curve: AnimationCurve, ref_time: number, ref_value: number): number;
13
+ //# sourceMappingURL=animation_curve_nearest_point.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"animation_curve_nearest_point.d.ts","sourceRoot":"","sources":["../../../../../src/engine/animation/curve/animation_curve_nearest_point.js"],"names":[],"mappings":"AAMA;;;;;;;;;;GAUG;AACH,+EARW,MAAM,aACN,MAAM,GACJ,MAAM,CA2DlB"}
@@ -0,0 +1,71 @@
1
+ import { v2_distance_sqr } from "../../../core/geom/vec2/v2_distance_sqr.js";
2
+ import { inverseLerp } from "../../../core/math/inverseLerp.js";
3
+ import { lerp } from "../../../core/math/lerp.js";
4
+ import { spline3_hermite } from "../../../core/math/spline/spline3_hermite.js";
5
+ import { spline3_hermite_nearest_point } from "../../../core/math/spline/spline3_hermite_nearest_point.js";
6
+
7
+ /**
8
+ * NOTE: this operation has O(n) complexity, where n is the number of keys in the curve.
9
+ * @param {AnimationCurve} curve
10
+ * @param {number} ref_time
11
+ * @param {number} ref_value
12
+ * @returns {number} time of the nearest point on the curve
13
+ * @see AnimationCurve
14
+ * @example
15
+ * const nearest_time = animation_curve_nearest_point(curve, 0.5, 10);
16
+ * const nearest_value = curve.evaluate(nearest_time);
17
+ */
18
+ export function animation_curve_nearest_point(curve, ref_time, ref_value) {
19
+
20
+ const keys = curve.keys;
21
+ const key_count = keys.length;
22
+
23
+ if (key_count === 0) {
24
+ // special case: empty curve
25
+ return ref_time;
26
+ }
27
+
28
+ if (key_count === 1) {
29
+ // special case: single key
30
+ return keys[0].time;
31
+ }
32
+
33
+ let nearest_time = keys[0].time;
34
+ let nearest_value = keys[0].value;
35
+ let nearest_distance_sqr = v2_distance_sqr(nearest_time, nearest_value, ref_time, ref_value);
36
+
37
+ for (let i = 0; i <= key_count - 2; i++) {
38
+ const key0 = keys[i];
39
+ const key1 = keys[i + 1];
40
+
41
+ const time_delta = key1.time - key0.time;
42
+
43
+ // Normalize reference time to the segment's [0, 1] space
44
+ const ref_t = inverseLerp(key0.time, key1.time, ref_time);
45
+
46
+ // Scale tangents by the segment duration
47
+ const m0 = key0.outTangent * time_delta;
48
+ const m1 = key1.inTangent * time_delta;
49
+
50
+ const t = spline3_hermite_nearest_point(
51
+ ref_t, ref_value,
52
+ key0.value, key1.value,
53
+ m0, m1
54
+ );
55
+
56
+ // De-normalize the resulting time back to the global timeline
57
+ const curve_time = lerp(key0.time, key1.time, t);
58
+ const curve_value = spline3_hermite(t, key0.value, key1.value, m0, m1);
59
+
60
+ const distance_sqr = v2_distance_sqr(curve_time, curve_value, ref_time, ref_value);
61
+
62
+ if (distance_sqr < nearest_distance_sqr) {
63
+ nearest_time = curve_time;
64
+ nearest_value = curve_value;
65
+ nearest_distance_sqr = distance_sqr;
66
+ }
67
+
68
+ }
69
+
70
+ return nearest_time;
71
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"animation_curve_subdivide.d.ts","sourceRoot":"","sources":["../../../../../src/engine/animation/curve/animation_curve_subdivide.js"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AACH,+CAVW,QAAQ,QACR,QAAQ,QACR,QAAQ,KACR,MAAM,GACJ,QAAQ,CA2CpB"}
1
+ {"version":3,"file":"animation_curve_subdivide.d.ts","sourceRoot":"","sources":["../../../../../src/engine/animation/curve/animation_curve_subdivide.js"],"names":[],"mappings":"AAKA;;;;;;;;;;;;GAYG;AACH,+CAVW,QAAQ,QACR,QAAQ,QACR,QAAQ,KACR,MAAM,GACJ,QAAQ,CAqDpB"}
@@ -1,3 +1,4 @@
1
+ import { assert } from "../../../core/assert.js";
1
2
  import { lerp } from "../../../core/math/lerp.js";
2
3
  import { spline3_hermite } from "../../../core/math/spline/spline3_hermite.js";
3
4
  import { spline3_hermite_derivative } from "../../../core/math/spline/spline3_hermite_derivative.js";
@@ -21,6 +22,16 @@ export function animation_curve_subdivide(
21
22
  key1,
22
23
  t
23
24
  ) {
25
+ assert.isObject(out, 'out');
26
+ assert.isObject(key0, 'key0');
27
+ assert.isObject(key1, 'key1');
28
+
29
+ assert.equal(out.isKeyframe,true,'out.isKeyframe !== true');
30
+ assert.equal(key0.isKeyframe,true,'key0.isKeyframe !== true');
31
+ assert.equal(key1.isKeyframe,true,'key1.isKeyframe !== true');
32
+
33
+ assert.isNumber(t, 't');
34
+ assert.ok(t >= 0 && t <= 1);
24
35
 
25
36
  const v0 = key0.value;
26
37
  const v1 = key1.value;