@woosh/meep-engine 2.92.9 → 2.92.11

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.
Files changed (35) hide show
  1. package/build/meep.cjs +7 -13
  2. package/build/meep.min.js +1 -1
  3. package/build/meep.module.js +7 -13
  4. package/package.json +1 -1
  5. package/src/core/bvh2/binary/2/BinaryUint32BVH.d.ts.map +1 -1
  6. package/src/core/bvh2/binary/2/BinaryUint32BVH.js +4 -0
  7. package/src/core/math/interval/NumericInterval.d.ts +3 -3
  8. package/src/core/math/interval/NumericInterval.d.ts.map +1 -1
  9. package/src/core/math/interval/NumericInterval.js +7 -13
  10. package/src/core/math/interval/NumericInterval.spec.js +9 -0
  11. package/src/core/math/max3.spec.js +2 -0
  12. package/src/core/math/min3.spec.js +2 -0
  13. package/src/core/math/spline/spline_bezier3_bounds.js +3 -3
  14. package/src/core/math/spline/spline_hermite3.d.ts +11 -0
  15. package/src/core/math/spline/spline_hermite3.d.ts.map +1 -0
  16. package/src/core/math/spline/spline_hermite3.js +21 -0
  17. package/src/core/math/spline/spline_hermite3_bounds.d.ts +17 -0
  18. package/src/core/math/spline/spline_hermite3_bounds.d.ts.map +1 -0
  19. package/src/core/math/spline/spline_hermite3_bounds.js +95 -0
  20. package/src/core/math/spline/spline_hermite3_bounds.spec.d.ts +2 -0
  21. package/src/core/math/spline/spline_hermite3_bounds.spec.d.ts.map +1 -0
  22. package/src/core/math/spline/spline_hermite3_bounds.spec.js +37 -0
  23. package/src/engine/animation/curve/AnimationCurve.d.ts.map +1 -1
  24. package/src/engine/animation/curve/AnimationCurve.js +10 -16
  25. package/src/engine/animation/curve/AnimationCurve.spec.js +11 -0
  26. package/src/engine/animation/curve/compression/prototypeCurveCompression.js +13 -2
  27. package/src/engine/animation/curve/compute_curve_aabb.d.ts.map +1 -1
  28. package/src/engine/animation/curve/compute_curve_aabb.js +25 -4
  29. package/src/engine/animation/curve/draw/build_plot_entity_from_array.d.ts.map +1 -1
  30. package/src/engine/animation/curve/draw/build_plot_entity_from_array.js +10 -2
  31. package/src/engine/animation/curve/prototypeGLTF.js +14 -14
  32. package/src/engine/graphics/canvas/canvas2d_draw_label.d.ts +4 -1
  33. package/src/engine/graphics/canvas/canvas2d_draw_label.d.ts.map +1 -1
  34. package/src/engine/graphics/canvas/canvas2d_draw_label.js +10 -4
  35. package/src/engine/graphics/geometry/buffered/query/GeometrySpatialQueryAccelerator.js +2 -2
@@ -54355,13 +54355,6 @@ function inverseLerp(a, b, value) {
54355
54355
  return scaledValue / range;
54356
54356
  }
54357
54357
 
54358
- /**
54359
- *
54360
- * @param {number} min
54361
- * @param {number} max
54362
- * @constructor
54363
- */
54364
-
54365
54358
  class NumericInterval {
54366
54359
  /**
54367
54360
  *
@@ -54435,9 +54428,9 @@ class NumericInterval {
54435
54428
  }
54436
54429
 
54437
54430
  /**
54438
- * Performs inverse linear interpolation on a given input
54439
- * @param {number} v
54440
- * @returns {number}
54431
+ * Compute normalized position of input within this interval, where result is 0 if input is equal to `min`, and 1 when input is equal to `max`
54432
+ * @param {number} v value to be normalized
54433
+ * @returns {number} value between 0..1 if input is within [min,max] range, otherwise result will be extrapolated proportionately outside the 0,1 region
54441
54434
  */
54442
54435
  normalizeValue(v) {
54443
54436
  return inverseLerp(this.min, this.max, v);
@@ -54465,7 +54458,7 @@ class NumericInterval {
54465
54458
  * @returns {number}
54466
54459
  */
54467
54460
  computeAverage() {
54468
- return (this.min + this.max) / 2;
54461
+ return (this.min + this.max) * 0.5;
54469
54462
  }
54470
54463
 
54471
54464
  /**
@@ -55268,6 +55261,7 @@ class BinaryUint32BVH {
55268
55261
  * @param {number} count
55269
55262
  */
55270
55263
  setLeafCount(count) {
55264
+
55271
55265
  this.__node_count_leaf = count;
55272
55266
 
55273
55267
  const twoLeafLimit = ceilPowerOfTwo(count);
@@ -66306,14 +66300,14 @@ class GeometrySpatialQueryAccelerator {
66306
66300
  * @returns {BinaryUint32BVH}
66307
66301
  */
66308
66302
  __buildBVH(geometry) {
66303
+ const bvh = new BinaryUint32BVH();
66304
+
66309
66305
  const position_attribute = geometry.getAttribute('position');
66310
66306
  const index_attribute = geometry.getIndex();
66311
66307
 
66312
66308
  const de_interleaved_position_attribute = deinterleaveBufferAttribute(position_attribute);
66313
66309
  const vertices = de_interleaved_position_attribute.array;
66314
66310
 
66315
- const bvh = new BinaryUint32BVH();
66316
-
66317
66311
  if (index_attribute === undefined || index_attribute === null) {
66318
66312
  bvh32_from_unindexed_geometry(bvh, vertices);
66319
66313
  } else {
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "description": "Fully featured ECS game engine written in JavaScript",
6
6
  "type": "module",
7
7
  "author": "Alexander Goldring",
8
- "version": "2.92.9",
8
+ "version": "2.92.11",
9
9
  "main": "build/meep.module.js",
10
10
  "module": "build/meep.module.js",
11
11
  "exports": {
@@ -1 +1 @@
1
- {"version":3,"file":"BinaryUint32BVH.d.ts","sourceRoot":"","sources":["../../../../../../src/core/bvh2/binary/2/BinaryUint32BVH.js"],"names":[],"mappings":"AAcA;;;GAGG;AACH,gCAFU,MAAM,CAEmB;AAEnC;;;;GAIG;AACH,mCAFU,MAAM,CAEsB;AACtC;;;GAGG;AACH,iCAFU,MAAM,CAEoB;AAiDpC;IACI;;;;OAIG;IACH,sBAAc;IAEd;;;;OAIG;IACH,gCAAe;IAEf;;;;OAIG;IACH,+BAAc;IAEd;;;;OAIG;IACH,4BAAwB;IAExB;;;;OAIG;IACH,0BAAsB;IA0CtB;;;OAGG;IACH,2BAOC;IAED,wBAEC;IAnDD;;;OAGG;IACH,oBAFa,MAAM,CAIlB;IAED,2BAEC;IAED,gCAEC;IAED,8BAEC;IAED;;;OAGG;IACH,uBAFa,MAAM,CAIlB;IAED,4BAEC;IAED,0BAEC;IAmBD;;;;OAIG;IACH,2BAHW,MAAM,GACJ,MAAM,CAalB;IAED,6BASC;IAED;;;OAGG;IACH,oBAFW,MAAM,QAchB;IAED;;;;;;;;;;OAUG;IACH,mBATW,MAAM,WACN,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,QAwBhB;IAED;;;;;OAKG;IACH,oBAJW,MAAM,eACN,MAAM,EAAE,GAAC,YAAY,sBACrB,MAAM,QAIhB;IAED;;;;OAIG;IACH,4BAHW,MAAM,GACJ,MAAM,CAQlB;IAED,qCAoBC;IAED;;;;;;;OAOG;IACH,yCAYC;IAED;;;;;;OAMG;IACH,kDAuBC;IAED,wBAUC;IAGD;;;OAGG;IACH,oBAFW,MAAM,EAAE,QAkElB;IAED;;;;;OAKG;IACH,sBAUC;IAED;;OAEG;IACH,cAsEC;CACJ"}
1
+ {"version":3,"file":"BinaryUint32BVH.d.ts","sourceRoot":"","sources":["../../../../../../src/core/bvh2/binary/2/BinaryUint32BVH.js"],"names":[],"mappings":"AAcA;;;GAGG;AACH,gCAFU,MAAM,CAEmB;AAEnC;;;;GAIG;AACH,mCAFU,MAAM,CAEsB;AACtC;;;GAGG;AACH,iCAFU,MAAM,CAEoB;AAiDpC;IACI;;;;OAIG;IACH,sBAAc;IAEd;;;;OAIG;IACH,gCAAe;IAEf;;;;OAIG;IACH,+BAAc;IAEd;;;;OAIG;IACH,4BAAwB;IAExB;;;;OAIG;IACH,0BAAsB;IA0CtB;;;OAGG;IACH,2BAOC;IAED,wBAEC;IAnDD;;;OAGG;IACH,oBAFa,MAAM,CAIlB;IAED,2BAEC;IAED,gCAEC;IAED,8BAEC;IAED;;;OAGG;IACH,uBAFa,MAAM,CAIlB;IAED,4BAEC;IAED,0BAEC;IAmBD;;;;OAIG;IACH,2BAHW,MAAM,GACJ,MAAM,CAalB;IAED,6BASC;IAED;;;OAGG;IACH,oBAFW,MAAM,QAgBhB;IAED;;;;;;;;;;OAUG;IACH,mBATW,MAAM,WACN,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,QA0BhB;IAED;;;;;OAKG;IACH,oBAJW,MAAM,eACN,MAAM,EAAE,GAAC,YAAY,sBACrB,MAAM,QAIhB;IAED;;;;OAIG;IACH,4BAHW,MAAM,GACJ,MAAM,CAQlB;IAED,qCAoBC;IAED;;;;;;;OAOG;IACH,yCAYC;IAED;;;;;;OAMG;IACH,kDAuBC;IAED,wBAUC;IAGD;;;OAGG;IACH,oBAFW,MAAM,EAAE,QAkElB;IAED;;;;;OAKG;IACH,sBAUC;IAED;;OAEG;IACH,cAsEC;CACJ"}
@@ -204,6 +204,8 @@ export class BinaryUint32BVH {
204
204
  * @param {number} count
205
205
  */
206
206
  setLeafCount(count) {
207
+ assert.isNonNegativeInteger(count, 'count');
208
+
207
209
  this.__node_count_leaf = count;
208
210
 
209
211
  const twoLeafLimit = ceilPowerOfTwo(count);
@@ -240,6 +242,8 @@ export class BinaryUint32BVH {
240
242
  assert.notNaN(y1, 'y1');
241
243
  assert.notNaN(z1, 'z1');
242
244
 
245
+ assert.isNonNegativeInteger(payload, 'payload');
246
+
243
247
  const address = index * BVH_LEAF_NODE_SIZE + this.__node_count_binary * BVH_BINARY_NODE_SIZE;
244
248
 
245
249
  aabb3_array_set(
@@ -34,9 +34,9 @@ export class NumericInterval {
34
34
  */
35
35
  multiplyScalar(value: number): void;
36
36
  /**
37
- * Performs inverse linear interpolation on a given input
38
- * @param {number} v
39
- * @returns {number}
37
+ * Compute normalized position of input within this interval, where result is 0 if input is equal to `min`, and 1 when input is equal to `max`
38
+ * @param {number} v value to be normalized
39
+ * @returns {number} value between 0..1 if input is within [min,max] range, otherwise result will be extrapolated proportionately outside the 0,1 region
40
40
  */
41
41
  normalizeValue(v: number): number;
42
42
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"NumericInterval.d.ts","sourceRoot":"","sources":["../../../../../src/core/math/interval/NumericInterval.js"],"names":[],"mappings":"AAWA;IACI;;;;;OAKG;IACH,kBAJW,MAAM,QACN,MAAM,EAwBhB;IAZG;;;OAGG;IACH,KAFU,MAAM,CAEF;IACd;;;OAGG;IACH,KAFU,MAAM,CAEF;IAEd,0DAA6B;IAIjC;;;;OAIG;IACH,SAHW,MAAM,OACN,MAAM,QAsBhB;IAED;;;OAGG;IACH,YAFW,eAAe,QAIzB;IAED;;;OAGG;IACH,sBAFW,MAAM,QAahB;IAED;;;;OAIG;IACH,kBAHW,MAAM,GACJ,MAAM,CAIlB;IAED;;;OAGG;IACH,UAFa,OAAO,CAInB;IAED;;;;OAIG;IACH,WAFa,OAAO,CAInB;IAED;;;OAGG;IACH,kBAFa,MAAM,CAIlB;IAED;;;;OAIG;IACH,gCAFa,MAAM,CAMlB;IAED,0BAEC;IAED;;;MAKC;IAED;;;OAGG;IACH,2CAGC;IAED;;;OAGG;IACH,6CAGC;IAED;;;;OAIG;IACH,cAHW,eAAe,GACb,OAAO,CAInB;IAED;;;OAGG;IACH,QAFa,MAAM,CAQlB;IAED;;;OAGG;IACH,mBAEC;IAGL;;;OAGG;IACH,4BAFU,OAAO,CAE0B;CAN1C;;iBAUS,eAAe;mBAKf,eAAe;;mBA5MN,+BAA+B"}
1
+ {"version":3,"file":"NumericInterval.d.ts","sourceRoot":"","sources":["../../../../../src/core/math/interval/NumericInterval.js"],"names":[],"mappings":"AAKA;IACI;;;;;OAKG;IACH,kBAJW,MAAM,QACN,MAAM,EAwBhB;IAZG;;;OAGG;IACH,KAFU,MAAM,CAEF;IACd;;;OAGG;IACH,KAFU,MAAM,CAEF;IAEd,0DAA6B;IAIjC;;;;OAIG;IACH,SAHW,MAAM,OACN,MAAM,QAsBhB;IAED;;;OAGG;IACH,YAFW,eAAe,QAIzB;IAED;;;OAGG;IACH,sBAFW,MAAM,QAahB;IAED;;;;OAIG;IACH,kBAHW,MAAM,GACJ,MAAM,CAIlB;IAED;;;OAGG;IACH,UAFa,OAAO,CAInB;IAED;;;;OAIG;IACH,WAFa,OAAO,CAInB;IAED;;;OAGG;IACH,kBAFa,MAAM,CAIlB;IAED;;;;OAIG;IACH,gCAFa,MAAM,CAMlB;IAED,0BAEC;IAED;;;MAKC;IAED;;;OAGG;IACH,2CAGC;IAED;;;OAGG;IACH,6CAGC;IAED;;;;OAIG;IACH,cAHW,eAAe,GACb,OAAO,CAInB;IAED;;;OAGG;IACH,QAFa,MAAM,CAQlB;IAED;;;OAGG;IACH,mBAEC;IAGL;;;OAGG;IACH,4BAFU,OAAO,CAE0B;CAN1C;;iBAUS,eAAe;mBAKf,eAAe;;mBA5MN,+BAA+B"}
@@ -1,13 +1,7 @@
1
- /**
2
- *
3
- * @param {number} min
4
- * @param {number} max
5
- * @constructor
6
- */
7
1
  import { assert } from "../../assert.js";
8
2
  import Signal from "../../events/signal/Signal.js";
9
- import { inverseLerp } from "../inverseLerp.js";
10
3
  import { computeHashFloat } from "../../primitives/numbers/computeHashFloat.js";
4
+ import { inverseLerp } from "../inverseLerp.js";
11
5
 
12
6
  export class NumericInterval {
13
7
  /**
@@ -23,7 +17,7 @@ export class NumericInterval {
23
17
  assert.isNumber(min, 'min');
24
18
  assert.isNumber(max, 'max');
25
19
 
26
- assert.ok(max >= min, `max=${max} must be >= than min=${min}`);
20
+ assert.greaterThanOrEqual(max, min, `max [${max}] must be >= than min[${min}]`);
27
21
 
28
22
  /**
29
23
  *
@@ -93,9 +87,9 @@ export class NumericInterval {
93
87
  }
94
88
 
95
89
  /**
96
- * Performs inverse linear interpolation on a given input
97
- * @param {number} v
98
- * @returns {number}
90
+ * Compute normalized position of input within this interval, where result is 0 if input is equal to `min`, and 1 when input is equal to `max`
91
+ * @param {number} v value to be normalized
92
+ * @returns {number} value between 0..1 if input is within [min,max] range, otherwise result will be extrapolated proportionately outside the 0,1 region
99
93
  */
100
94
  normalizeValue(v) {
101
95
  return inverseLerp(this.min, this.max, v);
@@ -123,7 +117,7 @@ export class NumericInterval {
123
117
  * @returns {number}
124
118
  */
125
119
  computeAverage() {
126
- return (this.min + this.max) / 2;
120
+ return (this.min + this.max) * 0.5;
127
121
  }
128
122
 
129
123
  /**
@@ -132,7 +126,7 @@ export class NumericInterval {
132
126
  * @returns {number}
133
127
  */
134
128
  sampleRandom(random) {
135
- assert.equal(typeof random, 'function', `random must be a function, instead was ${typeof random}`);
129
+ assert.isFunction(random, "random");
136
130
 
137
131
  return this.min + random() * (this.max - this.min);
138
132
  }
@@ -78,3 +78,12 @@ test("sampleRandom", () => {
78
78
  expect(sut.sampleRandom(() => 1)).toBe(7);
79
79
  expect(sut.sampleRandom(() => 0.5)).toBeCloseTo(2);
80
80
  });
81
+
82
+ test("computeAverage", () => {
83
+ expect(new NumericInterval(0, 0).computeAverage()).toBe(0);
84
+ expect(new NumericInterval(1, 1).computeAverage()).toBe(1);
85
+ expect(new NumericInterval(-1, -1).computeAverage()).toBe(-1);
86
+
87
+ expect(new NumericInterval(3, 7).computeAverage()).toBe(5);
88
+ expect(new NumericInterval(3.1, 7.1).computeAverage()).toBe(5.1);
89
+ });
@@ -1,6 +1,8 @@
1
1
  import { max3 } from "./max3.js";
2
2
 
3
3
  test("max3", () => {
4
+ expect(max3(0, 0, 0)).toBe(0);
5
+
4
6
  expect(max3(-1, -3, 1)).toBe(1);
5
7
 
6
8
  expect(max3(-3, -1, 1)).toBe(1);
@@ -1,6 +1,8 @@
1
1
  import { min3 } from "./min3.js";
2
2
 
3
3
  test("min3", () => {
4
+ expect(min3(0,0,0)).toBe(0);
5
+
4
6
  expect(min3(-1, -3, 1)).toBe(-3);
5
7
 
6
8
  expect(min3(-3, -1, 1)).toBe(-3);
@@ -1,7 +1,7 @@
1
- import { min2 } from "../min2.js";
2
- import { max2 } from "../max2.js";
3
1
  import { assert } from "../../assert.js";
4
- import { spline_bezier3 } from './spline_bezier3'
2
+ import { max2 } from "../max2.js";
3
+ import { min2 } from "../min2.js";
4
+ import { spline_bezier3 } from './spline_bezier3.js'
5
5
 
6
6
  /**
7
7
  * Compute bounds of a 3-rd degree bezier curve
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Perform cubic hermite interpolation
3
+ * @param {number} t normalized interpolation position (0..1)
4
+ * @param {number} p0 first value
5
+ * @param {number} p1 second value
6
+ * @param {number} m0 first tangent
7
+ * @param {number} m1 second tangent
8
+ * @return {number}
9
+ */
10
+ export function spline_hermite3(t: number, p0: number, p1: number, m0: number, m1: number): number;
11
+ //# sourceMappingURL=spline_hermite3.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spline_hermite3.d.ts","sourceRoot":"","sources":["../../../../../src/core/math/spline/spline_hermite3.js"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,mCAPW,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,GACL,MAAM,CAajB"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Perform cubic hermite interpolation
3
+ * @param {number} t normalized interpolation position (0..1)
4
+ * @param {number} p0 first value
5
+ * @param {number} p1 second value
6
+ * @param {number} m0 first tangent
7
+ * @param {number} m1 second tangent
8
+ * @return {number}
9
+ */
10
+ export function spline_hermite3(t, p0, p1, m0, m1) {
11
+
12
+ const t2 = t * t;
13
+ const t3 = t2 * t;
14
+
15
+ const a = 2 * t3 - 3 * t2 + 1;
16
+ const b = t3 - 2 * t2 + t;
17
+ const c = t3 - t2;
18
+ const d = -2 * t3 + 3 * t2;
19
+
20
+ return a * p0 + b * m0 + c * m1 + d * p1;
21
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Compute bounds of a 3-rd degree hermite curve
3
+ * Note that this is a 1d case solver
4
+ * Lower bound will be written into result[offset], upper bounds will be written into result[offset+result_stride]
5
+ * Solution is based on https://stackoverflow.com/questions/24809978/calculating-the-bounding-box-of-cubic-bezier-curve
6
+ * Differentiation of hermite polynomial is done in WolframAlpha
7
+ * 0 = 3 t^2 (m0 + m1 + 2 p0 - 2 p1) - 2 t (2 m0 + m1 + 3 p0 - 3 p1) + m0
8
+ * @param {number[]|Float32Array} result
9
+ * @param {number} result_offset offset into the result array
10
+ * @param {number} result_stride
11
+ * @param {number} p0
12
+ * @param {number} p1
13
+ * @param {number} m0
14
+ * @param {number} m1
15
+ */
16
+ export function spline_hermite3_bounds(result: number[] | Float32Array, result_offset: number, result_stride: number, p0: number, p1: number, m0: number, m1: number): void;
17
+ //# sourceMappingURL=spline_hermite3_bounds.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spline_hermite3_bounds.d.ts","sourceRoot":"","sources":["../../../../../src/core/math/spline/spline_hermite3_bounds.js"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;GAcG;AACH,+CARW,MAAM,EAAE,GAAC,YAAY,iBACrB,MAAM,iBACN,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,QA4EhB"}
@@ -0,0 +1,95 @@
1
+ import { assert } from "../../assert.js";
2
+ import { max2 } from "../max2.js";
3
+ import { min2 } from "../min2.js";
4
+ import { spline_hermite3 } from "./spline_hermite3.js";
5
+
6
+ /**
7
+ * Compute bounds of a 3-rd degree hermite curve
8
+ * Note that this is a 1d case solver
9
+ * Lower bound will be written into result[offset], upper bounds will be written into result[offset+result_stride]
10
+ * Solution is based on https://stackoverflow.com/questions/24809978/calculating-the-bounding-box-of-cubic-bezier-curve
11
+ * Differentiation of hermite polynomial is done in WolframAlpha
12
+ * 0 = 3 t^2 (m0 + m1 + 2 p0 - 2 p1) - 2 t (2 m0 + m1 + 3 p0 - 3 p1) + m0
13
+ * @param {number[]|Float32Array} result
14
+ * @param {number} result_offset offset into the result array
15
+ * @param {number} result_stride
16
+ * @param {number} p0
17
+ * @param {number} p1
18
+ * @param {number} m0
19
+ * @param {number} m1
20
+ */
21
+ export function spline_hermite3_bounds(
22
+ result,
23
+ result_offset,
24
+ result_stride,
25
+ p0, p1, m0, m1) {
26
+
27
+ assert.greaterThan(result_stride, 0, 'result_stride must be greater than 0');
28
+ assert.isInteger(result_stride, 'result_stride');
29
+
30
+ const a = 3 * (m0 + m1 + 2 * p0 - 2 * p1);
31
+ const b = -2 * (2 * m0 + m1 + 3 * p0 - 3 * p1);
32
+ const c = m0;
33
+
34
+ let min = min2(p0, p1);
35
+ let max = max2(p0, p1);
36
+
37
+ if (Math.abs(a) < 1e-12) {
38
+
39
+ if (Math.abs(b) >= 1e-12) {
40
+ const t = -c / b;
41
+
42
+ if (0 < t && t < 1) {
43
+ const value = spline_hermite3(t, p0, p1, m0, m1);
44
+
45
+ if (value < min) {
46
+ min = value;
47
+ }
48
+ if (value > max) {
49
+ max = value;
50
+ }
51
+
52
+ }
53
+
54
+ }
55
+
56
+ } else {
57
+
58
+ const b2ac = b * b - 4 * c * a;
59
+ const sqrtb2ac = Math.sqrt(b2ac);
60
+
61
+ if (b2ac >= 0) {
62
+
63
+ const t1 = (-b + sqrtb2ac) / (2 * a);
64
+
65
+ if (0 < t1 && t1 < 1) {
66
+ const value = spline_hermite3(t1, p0, p1, m0, m1);
67
+
68
+ if (value < min) {
69
+ min = value;
70
+ }
71
+ if (value > max) {
72
+ max = value;
73
+ }
74
+ }
75
+
76
+ const t2 = (-b - sqrtb2ac) / (2 * a);
77
+
78
+ if (0 < t2 && t2 < 1) {
79
+ const value = spline_hermite3(t2, p0, p1, m0, m1);
80
+
81
+ if (value < min) {
82
+ min = value;
83
+ }
84
+ if (value > max) {
85
+ max = value;
86
+ }
87
+ }
88
+
89
+ }
90
+
91
+ }
92
+
93
+ result[result_offset] = min;
94
+ result[result_offset + result_stride] = max;
95
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=spline_hermite3_bounds.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spline_hermite3_bounds.spec.d.ts","sourceRoot":"","sources":["../../../../../src/core/math/spline/spline_hermite3_bounds.spec.js"],"names":[],"mappings":""}
@@ -0,0 +1,37 @@
1
+ import { spline_hermite3_bounds } from "./spline_hermite3_bounds.js";
2
+
3
+ test("spline of 0 length", () => {
4
+ const bounds = [];
5
+
6
+ spline_hermite3_bounds(
7
+ bounds, 0, 1,
8
+ 0, 0, 0, 0
9
+ );
10
+
11
+ expect(bounds[0]).toBeCloseTo(0);
12
+ expect(bounds[1]).toBeCloseTo(0);
13
+ });
14
+
15
+ test("0-slope line", () => {
16
+ const bounds = [];
17
+
18
+ spline_hermite3_bounds(
19
+ bounds, 0, 1,
20
+ -2, 2, 0, 0
21
+ );
22
+
23
+ expect(bounds[0]).toBeCloseTo(-2);
24
+ expect(bounds[1]).toBeCloseTo(2);
25
+ });
26
+
27
+ test("overshooting control points", () => {
28
+ const bounds = [];
29
+
30
+ spline_hermite3_bounds(
31
+ bounds, 0, 1,
32
+ 0, 1, 100, 100
33
+ );
34
+
35
+ expect(bounds[0]).toBeLessThan(0);
36
+ expect(bounds[1]).toBeGreaterThan(1);
37
+ });
@@ -1 +1 @@
1
- {"version":3,"file":"AnimationCurve.d.ts","sourceRoot":"","sources":["../../../../../src/engine/animation/curve/AnimationCurve.js"],"names":[],"mappings":"AAyCA;;;GAGG;AACH;IA4EI;;;;OAIG;IACH,kBAHW,QAAQ,EAAE,GACR,cAAc,CAU1B;IAxFD;;;OAGG;IACH,eAFU,QAAQ,EAAE,CAEV;IAEV;;;;OAIG;IACH,SAHW,QAAQ,GACN,MAAM,CA4BlB;IAED;;;OAGG;IACH,cAFW,QAAQ,EAAE,QAQpB;IAED;;;;OAIG;IACH,YAHW,QAAQ,GACN,OAAO,CAYnB;IAED;;OAEG;IACH,cAEC;IAiBD;;;OAGG;IACH,qBAEC;IAGD;;;;OAIG;IACH,YAHW,MAAM,GACL,MAAM,CA+BjB;IAED;;;OAGG;IACH,qBAFW,MAAM,QAoBhB;IAED;;;;OAIG;IACH,sBAHW,MAAM,UACN,MAAM,QAWhB;IAED,0BAKC;IAED;;MAIC;IAED;;aAeC;CACJ;yBAtPwB,eAAe"}
1
+ {"version":3,"file":"AnimationCurve.d.ts","sourceRoot":"","sources":["../../../../../src/engine/animation/curve/AnimationCurve.js"],"names":[],"mappings":"AAmCA;;;GAGG;AACH;IA4EI;;;;OAIG;IACH,kBAHW,QAAQ,EAAE,GACR,cAAc,CAU1B;IAxFD;;;OAGG;IACH,eAFU,QAAQ,EAAE,CAEV;IAEV;;;;OAIG;IACH,SAHW,QAAQ,GACN,MAAM,CA4BlB;IAED;;;OAGG;IACH,cAFW,QAAQ,EAAE,QAQpB;IAED;;;;OAIG;IACH,YAHW,QAAQ,GACN,OAAO,CAYnB;IAED;;OAEG;IACH,cAEC;IAiBD;;;OAGG;IACH,qBAEC;IAGD;;;;OAIG;IACH,YAHW,MAAM,GACL,MAAM,CA+BjB;IAED;;;OAGG;IACH,qBAFW,MAAM,QAoBhB;IAED;;;;OAIG;IACH,sBAHW,MAAM,UACN,MAAM,QAWhB;IAED,0BAKC;IAED;;MAIC;IAED;;aAeC;CACJ;yBA/OwB,eAAe"}
@@ -1,32 +1,26 @@
1
1
  import { binarySearchHighIndex } from "../../../core/collection/array/binarySearchHighIndex.js";
2
2
  import { inverseLerp } from "../../../core/math/inverseLerp.js";
3
3
  import { lerp } from "../../../core/math/lerp.js";
4
+ import { spline_hermite3 } from "../../../core/math/spline/spline_hermite3.js";
4
5
  import { invokeObjectToJSON } from "../../../core/model/object/invokeObjectToJSON.js";
5
6
  import { Keyframe } from "./Keyframe.js";
6
7
 
7
8
  /**
8
9
  *
9
- * @param {number} t
10
+ * @param {number} t interpolation value, between 0 and 1
10
11
  * @param {Keyframe} keyframe0
11
12
  * @param {Keyframe} keyframe1
12
13
  * @return {number}
13
14
  */
14
15
  function evaluate(t, keyframe0, keyframe1) {
15
-
16
- const dt = keyframe1.time - keyframe0.time;
17
-
18
- const m0 = keyframe0.outTangent * dt;
19
- const m1 = keyframe1.inTangent * dt;
20
-
21
- const t2 = t * t;
22
- const t3 = t2 * t;
23
-
24
- const a = 2 * t3 - 3 * t2 + 1;
25
- const b = t3 - 2 * t2 + t;
26
- const c = t3 - t2;
27
- const d = -2 * t3 + 3 * t2;
28
-
29
- return a * keyframe0.value + b * m0 + c * m1 + d * keyframe1.value;
16
+ const time_distance = keyframe1.time - keyframe0.time;
17
+
18
+ return spline_hermite3(
19
+ t,
20
+ keyframe0.value, keyframe1.value,
21
+ keyframe0.outTangent * time_distance,
22
+ keyframe1.inTangent * time_distance
23
+ );
30
24
  }
31
25
 
32
26
  /**
@@ -113,6 +113,17 @@ test("smooth tangents on a middle frame", () => {
113
113
  expect(key.inTangent).toEqual(key.outTangent);
114
114
  });
115
115
 
116
+ test("extreme tangent interpolation", () => {
117
+
118
+
119
+ const curve = new AnimationCurve();
120
+
121
+ curve.add(Keyframe.from(0, 1, 0, -1));
122
+ curve.add(Keyframe.from(1, 2, 1, 0));
123
+
124
+ expect(curve.evaluate(0.5)).toBe(0.5);
125
+
126
+ });
116
127
 
117
128
  test("to/from JSON consistency", () => {
118
129
 
@@ -9,7 +9,7 @@ import { AnimationCurve } from "../AnimationCurve.js";
9
9
  import { build_curve_editor } from "../draw/build_curve_editor.js";
10
10
  import { build_plot_entity_from_array } from "../draw/build_plot_entity_from_array.js";
11
11
  import { Keyframe } from "../Keyframe.js";
12
- import { CURVE_EASE_OUT } from "../preset/CURVE_EASE_OUT.js";
12
+ import { CURVE_EASE_IN_OUT } from "../preset/CURVE_EASE_IN_OUT.js";
13
13
  import { downsample_float_array_curve_by_error } from "./downsample_float_array_curve_by_error.js";
14
14
  import { sample_animation_curve_to_float_array } from "./sample_animation_curve_to_float_array.js";
15
15
 
@@ -139,11 +139,22 @@ async function main(engine) {
139
139
  return curve;
140
140
  }
141
141
 
142
+ function sample_curve_5() {
143
+
144
+ const curve = new AnimationCurve();
145
+
146
+ curve.add(Keyframe.from(0, 1, 0, -1));
147
+ curve.add(Keyframe.from(10, 1, 1, 0));
148
+
149
+ return curve;
150
+ }
151
+
142
152
  // const curve = sample_curve_0();
143
153
 
144
154
  // curve.smoothAllTangents();
145
155
 
146
- const curve = CURVE_EASE_OUT;
156
+ // const curve = sample_curve_5();
157
+ const curve = CURVE_EASE_IN_OUT;
147
158
 
148
159
  const ecd = engine.entityManager.dataset;
149
160
 
@@ -1 +1 @@
1
- {"version":3,"file":"compute_curve_aabb.d.ts","sourceRoot":"","sources":["../../../../../src/engine/animation/curve/compute_curve_aabb.js"],"names":[],"mappings":"AAGA;;;;GAIG;AACH,4EAiBC"}
1
+ {"version":3,"file":"compute_curve_aabb.d.ts","sourceRoot":"","sources":["../../../../../src/engine/animation/curve/compute_curve_aabb.js"],"names":[],"mappings":"AAMA;;;;GAIG;AACH,4EAmCC"}
@@ -1,5 +1,8 @@
1
1
  import { max2 } from "../../../core/math/max2.js";
2
2
  import { min2 } from "../../../core/math/min2.js";
3
+ import { spline_hermite3_bounds } from "../../../core/math/spline/spline_hermite3_bounds.js";
4
+
5
+ const temp_bounds = new Float32Array(4);
3
6
 
4
7
  /**
5
8
  *
@@ -12,14 +15,32 @@ export function compute_curve_aabb(out, curve) {
12
15
  let y0 = Number.POSITIVE_INFINITY;
13
16
  let y1 = Number.NEGATIVE_INFINITY;
14
17
 
15
- for (let i = 0; i < curve.keys.length; i++) {
16
- const keyframe = curve.keys[i];
18
+ const keys = curve.keys;
19
+ const key_count = keys.length;
20
+
21
+ let previous = keys[0];
22
+ x0 = x1 = previous.time;
23
+ y0 = y1 = previous.value;
24
+
25
+
26
+ for (let i = 1; i < key_count; i++) {
27
+ const keyframe = keys[i];
28
+
29
+ const time_delta = keyframe.time - previous.time;
30
+
31
+ spline_hermite3_bounds(temp_bounds, 0, 1,
32
+ previous.value, keyframe.value,
33
+ previous.outTangent * time_delta,
34
+ keyframe.inTangent * time_delta
35
+ );
17
36
 
18
37
  x0 = min2(x0, keyframe.time)
19
38
  x1 = max2(x1, keyframe.time)
20
39
 
21
- y0 = min2(y0, keyframe.value);
22
- y1 = max2(y1, keyframe.value);
40
+ y0 = min2(y0, temp_bounds[0]);
41
+ y1 = max2(y1, temp_bounds[1]);
42
+
43
+ previous = keyframe;
23
44
  }
24
45
 
25
46
  out.set(x0, y0, x1, y1);
@@ -1 +1 @@
1
- {"version":3,"file":"build_plot_entity_from_array.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/animation/curve/draw/build_plot_entity_from_array.js"],"names":[],"mappings":"AAQA;;;;;;;;;;GAUG;AACH,2FATW,MAAM,EAAE,GAOP,MAAM,CAkCjB;mBAjDkB,wBAAwB"}
1
+ {"version":3,"file":"build_plot_entity_from_array.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/animation/curve/draw/build_plot_entity_from_array.js"],"names":[],"mappings":"AASA;;;;;;;;;;GAUG;AACH,2FATW,MAAM,EAAE,GAOP,MAAM,CAyCjB;mBAxDkB,wBAAwB"}
@@ -1,3 +1,4 @@
1
+ import { array_compute_min_max } from "../../../../core/collection/array/array_compute_min_max.js";
1
2
  import Vector2 from "../../../../core/geom/Vector2.js";
2
3
  import { CanvasView } from "../../../../view/elements/CanvasView.js";
3
4
  import Entity from "../../../ecs/Entity.js";
@@ -35,10 +36,17 @@ export function build_plot_entity_from_array({
35
36
  });
36
37
  const ctx = canvasView.context2d;
37
38
 
38
- canvas2d_plot_data_line({ ctx, data, width, height, margin });
39
+ canvas2d_plot_data_line({ ctx, data, width, height, margin, range_x: [0, 1], range_y: array_compute_min_max(data) });
39
40
 
40
41
  const text = `${data.length}`;
41
- canvas2d_draw_label({ ctx: ctx, text: text, x: margin.x, y: height - (20) });
42
+ canvas2d_draw_label({
43
+ ctx: ctx,
44
+ text: text,
45
+ x: margin.x,
46
+ y: height - (20),
47
+ fontSize: 20,
48
+ color: 'red'
49
+ });
42
50
 
43
51
  if (typeof label === "string" && label.length > 0) {
44
52
  canvas2d_draw_label({ ctx: ctx, text: label, x: width - margin.x - 50, y: 20 })
@@ -38,22 +38,22 @@ async function main(engine) {
38
38
  yaw: 3.123185307179593,
39
39
  });
40
40
  //
41
- // make_sample('data/models/samples/InterpolationTest.glb',[
42
- // 'Step Scale',
43
- // 'Linear Scale',
44
- // 'CubicSpline Scale',
45
- // 'Step Rotation',
46
- // 'CubicSpline Rotation',
47
- // 'Linear Rotation',
48
- // 'Step Translation',
49
- // 'CubicSpline Translation',
50
- // 'Linear Translation'
51
- // ],engine.entityManager.dataset);
52
- //
53
- make_sample('data/models/samples/BoxAnimated.glb',[
54
- 'animation_0'
41
+ make_sample('data/models/samples/InterpolationTest.glb',[
42
+ 'Step Scale',
43
+ 'Linear Scale',
44
+ 'CubicSpline Scale',
45
+ 'Step Rotation',
46
+ 'CubicSpline Rotation',
47
+ 'Linear Rotation',
48
+ 'Step Translation',
49
+ 'CubicSpline Translation',
50
+ 'Linear Translation'
55
51
  ],engine.entityManager.dataset);
56
52
 
53
+ // make_sample('data/models/samples/BoxAnimated.glb',[
54
+ // 'animation_0'
55
+ // ],engine.entityManager.dataset);
56
+
57
57
  // make_sample('data/models/samples/animatedbox1.gltf', [
58
58
  // 'All Animations'
59
59
  // ], engine.entityManager.dataset);
@@ -4,6 +4,9 @@
4
4
  * @param {string} text
5
5
  * @param {number} x
6
6
  * @param {number} y
7
+ * @param {string} [color] CSS color
8
+ * @param {number} [fontSize] in pixels
9
+ * @param {string} [outline] CSS color
7
10
  */
8
- export function canvas2d_draw_label({ ctx, text, x, y }: CanvasRenderingContext2D): void;
11
+ export function canvas2d_draw_label({ ctx, text, x, y, color, fontSize, outline }: CanvasRenderingContext2D): void;
9
12
  //# sourceMappingURL=canvas2d_draw_label.d.ts.map