@woosh/meep-engine 2.60.0 → 2.61.0

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 (65) hide show
  1. package/build/meep.cjs +20211 -20240
  2. package/build/meep.min.js +1 -1
  3. package/build/meep.module.js +20211 -20240
  4. package/package.json +1 -1
  5. package/src/core/binary/BitSet.js +1 -1
  6. package/src/core/geom/3d/sphere/harmonics/sh3_dering_optimize_positive.js +30 -182
  7. package/src/core/geom/3d/sphere/harmonics/sh3_dering_optimize_positive.spec.js +27 -1
  8. package/src/core/geom/ConicRay.js +16 -21
  9. package/src/core/geom/ConicRay.spec.js +24 -0
  10. package/src/core/geom/packing/miniball/Miniball.js +68 -117
  11. package/src/core/geom/packing/miniball/Miniball.spec.js +3 -3
  12. package/src/core/geom/packing/miniball/Subspan.js +47 -34
  13. package/src/core/geom/packing/miniball/miniball_compute_quality.js +64 -0
  14. package/src/core/math/bessel_3.js +1 -0
  15. package/src/core/math/random/randomBytes.js +2 -2
  16. package/src/core/math/sqr.js +8 -0
  17. package/src/core/model/node-graph/Connection.js +21 -23
  18. package/src/core/model/node-graph/DataType.js +16 -17
  19. package/src/core/model/node-graph/NodeGraph.js +49 -50
  20. package/src/core/model/node-graph/node/NodeDescription.js +42 -44
  21. package/src/core/model/node-graph/node/NodeInstance.js +59 -60
  22. package/src/core/model/node-graph/node/NodeInstancePortReference.js +27 -29
  23. package/src/core/model/node-graph/node/NodeRegistry.js +16 -18
  24. package/src/core/model/node-graph/node/Port.js +35 -37
  25. package/src/core/model/node-graph/node/parameter/NodeParameterDescription.js +27 -13
  26. package/src/core/path/computePathDirectory.spec.js +8 -0
  27. package/src/core/process/BaseProcess.d.ts +5 -0
  28. package/src/core/process/WatchDog.js +76 -75
  29. package/src/core/process/action/AsynchronousAction.js +24 -22
  30. package/src/core/process/executor/profile/Profile.js +34 -24
  31. package/src/core/process/executor/profile/TraceEvent.js +75 -75
  32. package/src/core/process/worker/OnDemandWorkerManager.js +27 -30
  33. package/src/core/process/worker/WorkerBuilder.js +149 -149
  34. package/src/core/process/worker/WorkerProxy.js +25 -21
  35. package/src/core/process/worker/extractTransferables.js +2 -2
  36. package/src/engine/Engine.js +58 -53
  37. package/src/engine/EngineConfiguration.d.ts +4 -4
  38. package/src/engine/ecs/EntityManager.js +517 -614
  39. package/src/engine/ecs/System.js +2 -2
  40. package/src/engine/ecs/transform/Transform.d.ts +7 -5
  41. package/src/engine/ecs/transform/Transform.js +30 -16
  42. package/src/engine/ecs/validateSystem.js +89 -0
  43. package/src/engine/graphics/GraphicsEngine.js +433 -483
  44. package/src/engine/graphics/camera/testClippingPlaneComputation.js +46 -48
  45. package/src/engine/graphics/ecs/camera/Camera.js +11 -11
  46. package/src/engine/graphics/ecs/decal/v2/FPDecalSystem.js +2 -2
  47. package/src/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.js +2 -2
  48. package/src/engine/graphics/ecs/mesh-v2/aggregate/SGMeshSystem.js +2 -2
  49. package/src/engine/graphics/ecs/path/tube/prototypeAnimatedPathMask.js +60 -62
  50. package/src/engine/graphics/ecs/water2/shader/testWaterShader.js +20 -22
  51. package/src/engine/graphics/geometry/instancing/InstancedMeshGroup.js +15 -4
  52. package/src/engine/graphics/particles/particular/engine/ParticularEngine.js +156 -180
  53. package/src/engine/graphics/particles/particular/engine/utils/volume/prototypeParticleVolume.js +69 -71
  54. package/src/engine/graphics/render/buffer/buffers/prototypeNormalFrameBuffer.js +51 -53
  55. package/src/engine/graphics/render/forward_plus/plugin/ptototypeFPPlugin.js +67 -69
  56. package/src/engine/graphics/render/visibility/hiz/prototypeHiZ.js +56 -58
  57. package/src/engine/graphics/shadows/testShadowMapRendering.js +30 -34
  58. package/src/engine/graphics/texture/sampler/resize/sampler2d_scale_down_lanczos.spec.js +22 -20
  59. package/src/engine/graphics/texture/sampler/resize/sampler2d_scale_down_linear.js +10 -13
  60. package/src/engine/graphics/texture/virtual/VirtualTexture.spec.js +1 -1
  61. package/src/engine/plugin/EnginePluginManager.d.ts +6 -1
  62. package/src/engine/ecs/components/ClingToHeightMap.js +0 -19
  63. package/src/engine/ecs/components/SynchronizePosition.js +0 -15
  64. package/src/engine/ecs/systems/ClingToHeightMapSystem.js +0 -170
  65. package/src/engine/ecs/systems/SynchronizePositionSystem.js +0 -43
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.60.0",
8
+ "version": "2.61.0",
9
9
  "main": "build/meep.module.js",
10
10
  "module": "build/meep.module.js",
11
11
  "exports": {
@@ -457,7 +457,7 @@ BitSet.prototype.get = function (bitIndex) {
457
457
  assert.isNonNegativeInteger(bitIndex, "bitIndex");
458
458
 
459
459
  if (bitIndex >= this.__length) {
460
- //bit is outside of the recorded region
460
+ //bit is outside the recorded region
461
461
  return false;
462
462
  }
463
463
 
@@ -1,18 +1,26 @@
1
- import { max2 } from "../../../../math/max2.js";
2
- import { mat3, vec3 } from "gl-matrix";
3
- import { array_copy } from "../../../../collection/array/array_copy.js";
4
- import { min2 } from "../../../../math/min2.js";
5
- import { assert } from "../../../../assert.js";
1
+ import {mat3, vec3} from "gl-matrix";
2
+ import {assert} from "../../../../assert.js";
3
+ import {array_copy} from "../../../../collection/array/array_copy.js";
4
+ import {min2} from "../../../../math/min2.js";
6
5
 
7
6
  /*
8
7
  @see https://github.com/Bestmaker602/olacziy/blob/212b64ea5f1856b390cdf7629801243f76a4466d/libs/ibl/src/CubemapSH.cpp
9
8
  */
10
9
 
10
+
11
+ const F_PI = 3.14159265358979323846264338327950288;
12
+ const F_SQRT1_2 = 0.707106781186547524400844362104849039;
13
+ const M_SQRT_3 = 1.7320508076;
14
+
15
+ const M_SQRT_PI = 1.7724538509;
16
+ const M_SQRT_5 = 2.2360679775;
17
+ const M_SQRT_15 = 3.8729833462;
18
+
11
19
  /**
12
20
  *
13
21
  * @param {number[]} M 5x5 matrix
14
22
  * @param {number[]} x vec5
15
- * @return {number[]}
23
+ * @return {number[]} vec5
16
24
  */
17
25
  function multiply_5d(M, x) {
18
26
  return [
@@ -24,51 +32,6 @@ function multiply_5d(M, x) {
24
32
  ];
25
33
  }
26
34
 
27
-
28
- /**
29
- * returns n! / d!
30
- * @param {number} n
31
- * @param {number} d
32
- * @return {number}
33
- */
34
- function factorial(n, d = 1) {
35
- let _d = max2(1, d);
36
- let _n = max2(1, n);
37
-
38
- let r = 1.0;
39
-
40
- if (_n === _d) {
41
- // intentionally left blank
42
- } else if (_n > _d) {
43
- for (; _n > _d; _n--) {
44
- r *= _n;
45
- }
46
- } else {
47
- for (; _d > _n; _d--) {
48
- r *= _d;
49
- }
50
- r = 1.0 / r;
51
- }
52
- return r;
53
- }
54
-
55
- const F_PI = 3.14159265358979323846264338327950288;
56
- const F_2_PI = 0.636619772367581343075535053490057448;
57
- const F_2_SQRTPI = 1.12837916709551257389615890312154517;
58
- const F_SQRT2 = 1.41421356237309504880168872420969808;
59
- const F_SQRT1_2 = 0.707106781186547524400844362104849039;
60
- const M_SQRT_3 = 1.7320508076;
61
-
62
- /**
63
- * SH scaling factors:
64
- * returns sqrt((2*l + 1) / 4*pi) * sqrt( (l-|m|)! / (l+|m|)! )
65
- */
66
- function Kml(m, l) {
67
- m = m < 0 ? -m : m; // abs() is not constexpr
68
- const K = (2 * l + 1) * factorial((l - m), (l + m));
69
- return Math.sqrt(K) * (F_2_SQRTPI * 0.25);
70
- }
71
-
72
35
  /**
73
36
  * compute Index of spherical harmonics coefficient
74
37
  * @param {number} m signed offset from zonal harmonic
@@ -79,127 +42,6 @@ function SHindex(m, l) {
79
42
  return l * (l + 1) + m;
80
43
  }
81
44
 
82
- /**
83
- *
84
- * @param {number[]} result
85
- * @param {number} result_offset
86
- * @param {number} numBands
87
- */
88
- function Ki(result, result_offset, numBands) {
89
- for (let l = 0; l < numBands; l++) {
90
- result[SHindex(0, l) + result_offset] = Kml(0, l);
91
- for (let m = 1; m <= l; m++) {
92
- result[SHindex(m, l) + result_offset] =
93
- result[SHindex(-m, l) + result_offset] = F_SQRT2 * Kml(m, l);
94
- }
95
- }
96
- }
97
-
98
- /**
99
- * < cos(theta) > SH coefficients pre-multiplied by 1 / K(0,l)
100
- * @param {number} l
101
- * @returns {number}
102
- */
103
- function computeTruncatedCosSh(l) {
104
- if (l === 0) {
105
- return F_PI;
106
- } else if (l === 1) {
107
- return 2 * F_PI / 3;
108
- } else if ((l & 1) !== 0) {
109
- return 0;
110
- }
111
-
112
- const l_2 = l / 2;
113
- const A0 = ((l_2 & 1) ? 1.0 : -1.0) / ((l + 2) * (l - 1));
114
- const A1 = factorial(l, l_2) / (factorial(l_2) * (1 << l));
115
- return 2 * F_PI * A0 * A1;
116
- }
117
-
118
- /*
119
- * Calculates non-normalized SH bases, i.e.:
120
- * m > 0, cos(m*phi) * P(m,l)
121
- * m < 0, sin(|m|*phi) * P(|m|,l)
122
- * m = 0, P(0,l)
123
- */
124
- function computeShBasis(SHb, result_offset, numBands, sx, sy, sz) {
125
-
126
- /*
127
- * TODO: all the Legendre computation below is identical for all faces, so it
128
- * might make sense to pre-compute it once. Also note that there is
129
- * a fair amount of symmetry within a face (which we could take advantage of
130
- * to reduce the pre-compute table).
131
- */
132
-
133
- /*
134
- * Below, we compute the associated Legendre polynomials using recursion.
135
- * see: http://mathworld.wolfram.com/AssociatedLegendrePolynomial.html
136
- *
137
- * Note [0]: sz == cos(theta) ==> we only need to compute P(sz)
138
- *
139
- * Note [1]: We in fact compute P(sz) / sin(theta)^|m|, by removing
140
- * the "sqrt(1 - sz*sz)" [i.e.: sin(theta)] factor from the recursion.
141
- * This is later corrected in the ( cos(m*phi), sin(m*phi) ) recursion.
142
- */
143
-
144
- // s = (x, y, z) = (sin(theta)*cos(phi), sin(theta)*sin(phi), cos(theta))
145
-
146
- // handle m=0 separately, since it produces only one coefficient
147
- let Pml_2 = 0;
148
- let Pml_1 = 1;
149
- SHb[result_offset + 0] = Pml_1;
150
- for (let l = 1; l < numBands; l++) {
151
- const Pml = ((2 * l - 1.0) * Pml_1 * sz - (l - 1.0) * Pml_2) / l;
152
- Pml_2 = Pml_1;
153
- Pml_1 = Pml;
154
- SHb[result_offset + SHindex(0, l)] = Pml;
155
- }
156
- let Pmm = 1;
157
- for (let m = 1; m < numBands; m++) {
158
- Pmm = (1.0 - 2 * m) * Pmm; // See [1], divide by sqrt(1 - sz*sz);
159
- Pml_2 = Pmm;
160
- Pml_1 = (2 * m + 1.0) * Pmm * sz;
161
- // l == m
162
- SHb[result_offset + SHindex(-m, m)] = Pml_2;
163
- SHb[result_offset + SHindex(m, m)] = Pml_2;
164
- if (m + 1 < numBands) {
165
- // l == m+1
166
- SHb[result_offset + SHindex(-m, m + 1)] = Pml_1;
167
- SHb[result_offset + SHindex(m, m + 1)] = Pml_1;
168
- for (let l = m + 2; l < numBands; l++) {
169
- const Pml = ((2 * l - 1.0) * Pml_1 * sz - (l + m - 1.0) * Pml_2) / (l - m);
170
- Pml_2 = Pml_1;
171
- Pml_1 = Pml;
172
- SHb[result_offset + SHindex(-m, l)] = Pml;
173
- SHb[result_offset + SHindex(m, l)] = Pml;
174
- }
175
- }
176
- }
177
-
178
- // At this point, SHb contains the associated Legendre polynomials divided
179
- // by sin(theta)^|m|. Below we compute the SH basis.
180
- //
181
- // ( cos(m*phi), sin(m*phi) ) recursion:
182
- // cos(m*phi + phi) == cos(m*phi)*cos(phi) - sin(m*phi)*sin(phi)
183
- // sin(m*phi + phi) == sin(m*phi)*cos(phi) + cos(m*phi)*sin(phi)
184
- // cos[m+1] == cos[m]*sx - sin[m]*sy
185
- // sin[m+1] == sin[m]*sx + cos[m]*sy
186
- //
187
- // Note that (d.x, d.y) == (cos(phi), sin(phi)) * sin(theta), so the
188
- // code below actually evaluates:
189
- // (cos((m*phi), sin(m*phi)) * sin(theta)^|m|
190
- let Cm = sx;
191
- let Sm = sy;
192
- for (let m = 1; m <= numBands; m++) {
193
- for (let l = m; l < numBands; l++) {
194
- SHb[result_offset + SHindex(-m, l)] *= Sm;
195
- SHb[result_offset + SHindex(m, l)] *= Cm;
196
- }
197
- const Cm1 = Cm * sx - Sm * sy;
198
- const Sm1 = Sm * sx + Cm * sy;
199
- Cm = Cm1;
200
- Sm = Sm1;
201
- }
202
- }
203
45
 
204
46
  /*
205
47
  * utilities to rotate very low order spherical harmonics (up to 3rd band)
@@ -247,10 +89,10 @@ function rotateShericalHarmonicBand1(band1, M) {
247
89
  /**
248
90
  * This projects a vec3 to SH2/k space (i.e. we premultiply by 1/k)
249
91
  * below can't be constexpr
250
- * @return {number[]} vec5
251
92
  * @param {number} x
252
93
  * @param {number} y
253
94
  * @param {number} z
95
+ * @return {number[]} vec5
254
96
  */
255
97
  function project_v3_to_sh(x, y, z) {
256
98
  return [
@@ -266,7 +108,7 @@ function project_v3_to_sh(x, y, z) {
266
108
  *
267
109
  * @param {number[]} band2 vec5
268
110
  * @param {number[]} M mat3
269
- * @return {*}
111
+ * @return {number[]} vec5
270
112
  */
271
113
  function rotateShericalHarmonicBand2(band2, M) {
272
114
  const n = F_SQRT1_2;
@@ -310,7 +152,7 @@ function rotateShericalHarmonicBand2(band2, M) {
310
152
  return result;
311
153
  }
312
154
 
313
- /*
155
+ /**
314
156
  * SH from environment with high dynamic range (or high frequencies -- high dynamic range creates
315
157
  * high frequencies) exhibit "ringing" and negative values when reconstructed.
316
158
  * To mitigate this, we need to low-pass the input image -- or equivalently window the SH by
@@ -321,7 +163,9 @@ function rotateShericalHarmonicBand2(band2, M) {
321
163
  * Deringing Spherical Harmonics
322
164
  * by Peter-Pike Sloan
323
165
  * https://www.ppsloan.org/publications/shdering.pdf
324
- *
166
+ * @param {number} w
167
+ * @param {number} l
168
+ * @returns {number}
325
169
  */
326
170
  function sincWindow(l, w) {
327
171
  if (l === 0) {
@@ -379,10 +223,6 @@ function shmin(input_sh3) {
379
223
  // See "Deringing Spherical Harmonics" by Peter-Pike Sloan
380
224
  // https://www.ppsloan.org/publications/shdering.pdf
381
225
 
382
- const M_SQRT_PI = 1.7724538509;
383
- const M_SQRT_3 = 1.7320508076;
384
- const M_SQRT_5 = 2.2360679775;
385
- const M_SQRT_15 = 3.8729833462;
386
226
  const A = [
387
227
  1.0 / (2.0 * M_SQRT_PI), // 0: 0 0
388
228
  -M_SQRT_3 / (2.0 * M_SQRT_PI), // 1: 1 -1
@@ -545,9 +385,13 @@ function windowing(f, cutoff, numBands) {
545
385
  * @param {number} input_offset
546
386
  * @param {number} numBands
547
387
  * @param {number} channel_count
548
- * @param {number} cutoff
388
+ * @param {number} [cutoff]
549
389
  */
550
- function windowSH(output, output_offset, input, input_offset, numBands, channel_count, cutoff) {
390
+ function windowSH(
391
+ output, output_offset,
392
+ input, input_offset,
393
+ numBands, channel_count, cutoff = 0
394
+ ) {
551
395
  assert.isNonNegativeInteger(channel_count, 'channel_count');
552
396
  assert.greaterThan(channel_count, 0, 'channel_count must be greater than 0');
553
397
 
@@ -575,13 +419,17 @@ function windowSH(output, output_offset, input, input_offset, numBands, channel_
575
419
  // find a cut-off band that works
576
420
  let l = numBands;
577
421
  let r = cutoff;
422
+
578
423
  for (let i = 0; i < 16 && l + 0.1 < r; i++) {
424
+
579
425
  const m = 0.5 * (l + r);
426
+
580
427
  if (shmin(windowing(SH, m, numBands)) < 0) {
581
428
  r = m;
582
429
  } else {
583
430
  l = m;
584
431
  }
432
+
585
433
  }
586
434
 
587
435
  // record minimum cutoff
@@ -1,6 +1,6 @@
1
1
  import { sh3_dering_optimize_positive } from "./sh3_dering_optimize_positive.js";
2
2
 
3
- test("de-ringing produces plausible numeric values", () => {
3
+ test("de-ringing produces plausible numeric values from 1", () => {
4
4
 
5
5
  const result = [];
6
6
 
@@ -25,3 +25,29 @@ test("de-ringing produces plausible numeric values", () => {
25
25
  }
26
26
 
27
27
  });
28
+
29
+ test("de-ringing produces plausible numeric values from -1", () => {
30
+
31
+ const result = [];
32
+
33
+ const harmonics = new Float32Array(9);
34
+
35
+ harmonics.fill(-1);
36
+
37
+ sh3_dering_optimize_positive(
38
+ result, 0,
39
+ harmonics,
40
+ 0,
41
+ 1
42
+ );
43
+
44
+ for (let i = 0; i < 9; i++) {
45
+
46
+ const element = result[i];
47
+
48
+ expect(element).not.toBeNaN();
49
+ expect(Number.isFinite(element)).toBe(true);
50
+
51
+ }
52
+
53
+ });
@@ -1,9 +1,9 @@
1
- import { assert } from "../assert.js";
1
+ import {assert} from "../assert.js";
2
+ import {computeHashIntegerArray} from "../collection/array/computeHashIntegerArray.js";
3
+ import {EPSILON} from "../math/EPSILON.js";
4
+ import {epsilonEquals} from "../math/epsilonEquals.js";
5
+ import {computeHashFloat} from "../primitives/numbers/computeHashFloat.js";
2
6
  import Vector3 from "./Vector3.js";
3
- import { computeHashIntegerArray } from "../collection/array/computeHashIntegerArray.js";
4
- import { computeHashFloat } from "../primitives/numbers/computeHashFloat.js";
5
- import { epsilonEquals } from "../math/epsilonEquals.js";
6
- import { EPSILON } from "../math/EPSILON.js";
7
7
 
8
8
 
9
9
  /**
@@ -11,24 +11,19 @@ import { EPSILON } from "../math/EPSILON.js";
11
11
  * Mainly used inside particle systems for pick a motion direction at spawn
12
12
  */
13
13
  export class ConicRay {
14
+
14
15
  /**
15
- *
16
- * @constructor
16
+ * Must be normalized
17
+ * @type {Vector3}
17
18
  */
18
- constructor() {
19
- /**
20
- * Must be normalized
21
- * @type {Vector3}
22
- */
23
- this.direction = new Vector3(0, 1, 0);
24
-
25
- /**
26
- * Semi-angle of the cone, that is the angle between the center axis and the edge of the cone
27
- * In radians
28
- * @type {number}
29
- */
30
- this.angle = 0;
31
- }
19
+ direction = new Vector3(0, 1, 0);
20
+
21
+ /**
22
+ * Half-angle of the cone, that is the angle between the center axis and the edge of the cone
23
+ * In radians
24
+ * @type {number}
25
+ */
26
+ angle = 0;
32
27
 
33
28
  toJSON() {
34
29
  return {
@@ -0,0 +1,24 @@
1
+ import {ConicRay} from "./ConicRay.js";
2
+ import Vector3 from "./Vector3.js";
3
+
4
+ test("constructor", () => {
5
+ const ray = new ConicRay();
6
+
7
+ expect(ray.angle).not.toBeNaN();
8
+ expect(typeof ray.angle).toBe("number");
9
+ expect(ray.direction).toBeDefined();
10
+ });
11
+
12
+ test("sampleRandomDirection", () => {
13
+
14
+ const ray = new ConicRay();
15
+
16
+ ray.angle = Math.PI * 0.25;
17
+
18
+ const r = new Vector3();
19
+
20
+ ray.sampleRandomDirection(() => 0, r);
21
+
22
+ expect(r.length()).toBeCloseTo(1);
23
+ expect(r.angleTo(ray.direction)).toBeLessThanOrEqual(ray.angle);
24
+ });