@woosh/meep-engine 2.79.0 → 2.80.1

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 (60) hide show
  1. package/build/meep.cjs +179 -199
  2. package/build/meep.min.js +1 -1
  3. package/build/meep.module.js +179 -199
  4. package/package.json +1 -1
  5. package/src/core/geom/2d/aabb/AABB2.js +6 -18
  6. package/src/core/geom/3d/SurfacePoint3.spec.js +1 -1
  7. package/src/core/geom/3d/{matrix → mat4}/m4_multiply.spec.js +3 -4
  8. package/src/core/geom/3d/{matrix → mat4}/m4_multiply_alphatensor.spec.js +3 -3
  9. package/src/core/geom/3d/morton/v3_morton_encode_transformed.spec.js +1 -1
  10. package/src/core/geom/3d/sphere/sphere_radius_sqr_from_v3_array_transformed.spec.js +1 -1
  11. package/src/core/geom/Vector3.js +2 -2
  12. package/src/core/geom/Vector3.spec.js +2 -2
  13. package/src/core/geom/packing/max-rect/{MaxRectangles.js → MaxRectanglesPacker.js} +25 -32
  14. package/src/core/geom/packing/max-rect/MaxRectanglesPacker.spec.js +60 -0
  15. package/src/core/geom/packing/max-rect/packMaxRectangles.js +19 -0
  16. package/src/core/graph/cluster_mesh_metis.js +3 -3
  17. package/src/core/graph/metis/metis.js +16 -1
  18. package/src/core/graph/metis/metis_options.js +32 -29
  19. package/src/core/math/bell_membership_function.js +1 -1
  20. package/src/core/math/computeIsoscelesTriangleApexAngle.js +2 -2
  21. package/src/core/math/computeIsoscelesTriangleApexAngle.spec.js +6 -0
  22. package/src/core/math/interval/overlap1D.js +7 -0
  23. package/src/core/math/noise/create_simplex_noise_2d.js +4 -0
  24. package/src/core/math/spline/computeCatmullRomSplineUniformDistance.js +3 -3
  25. package/src/core/math/spline/v3_computeCatmullRomSplineUniformDistance.js +42 -0
  26. package/src/core/math/statistics/computeStatisticalPartialMedian.js +7 -1
  27. package/src/core/math/statistics/computeStatisticalPercentile.js +12 -3
  28. package/src/core/math/statistics/computeStatisticalPercentile.spec.js +11 -0
  29. package/src/core/math/statistics/computeStatisticalStandardDeviation.js +12 -0
  30. package/src/core/math/statistics/{computeSampleStandardDeviation.js → computeStatisticalVariance.js} +4 -6
  31. package/src/core/math/statistics/computeStatisticalVariance.spec.js +10 -0
  32. package/src/core/model/node-graph/Connection.js +6 -5
  33. package/src/core/model/node-graph/Connection.spec.js +12 -0
  34. package/src/core/model/node-graph/DataType.spec.js +19 -0
  35. package/src/core/model/node-graph/node/NodeDescription.js +12 -10
  36. package/src/core/model/node-graph/node/NodeDescription.spec.js +52 -1
  37. package/src/core/model/node-graph/node/NodeInstancePortReference.spec.js +66 -0
  38. package/src/core/model/node-graph/util/graph_clone_by_node_subset.js +4 -7
  39. package/src/core/model/node-graph/util/graph_collect_connections_amongst_nodes.js +0 -2
  40. package/src/core/model/object/objectKeyByValue.js +3 -2
  41. package/src/engine/ecs/renderable/Renderable.js +1 -1
  42. package/src/engine/ecs/terrain/ecs/TerrainSystem.js +1 -1
  43. package/src/engine/ecs/terrain/tiles/TerrainTile.spec.js +2 -2
  44. package/src/engine/ecs/transform/Transform.js +3 -3
  45. package/src/engine/ecs/transform/Transform.spec.js +3 -3
  46. package/src/engine/graphics/ecs/path/entity/testEntityPath.js +16 -10
  47. package/src/engine/graphics/material/optimization/MaterialOptimizationContext.js +1 -1
  48. package/src/engine/graphics/texture/atlas/TextureAtlas.js +1 -1
  49. package/src/engine/graphics/texture/atlas/gpu/WebGLTextureAtlas.js +3 -3
  50. package/src/engine/graphics/three/expand_aabb_by_transformed_three_object.js +1 -1
  51. package/src/engine/graphics/three/expand_aabb_by_transformed_three_object.spec.js +2 -2
  52. package/src/engine/navigation/ecs/components/Path.js +5 -12
  53. package/src/engine/simulation/Ticker.js +40 -61
  54. package/src/core/geom/LineSegment.js +0 -207
  55. /package/src/core/geom/3d/{matrix → mat4}/MATRIX_4_IDENTITY.js +0 -0
  56. /package/src/core/geom/3d/{matrix → mat4}/MATRIX_4_IDENTITY.spec.js +0 -0
  57. /package/src/core/geom/3d/{matrix → mat4}/allocate_transform_m4.js +0 -0
  58. /package/src/core/geom/3d/{matrix → mat4}/m4_make_translation.js +0 -0
  59. /package/src/core/geom/3d/{matrix → mat4}/m4_multiply.js +0 -0
  60. /package/src/core/geom/3d/{matrix → mat4}/m4_multiply_alphatensor.js +0 -0
package/build/meep.cjs CHANGED
@@ -2222,7 +2222,7 @@ let Vector3$1 = class Vector3 {
2222
2222
 
2223
2223
  /**
2224
2224
  *
2225
- * @param {number[]} array
2225
+ * @param {number[]|Float32Array} array
2226
2226
  * @param {number} offset
2227
2227
  */
2228
2228
  readFromArray(array, offset = 0) {
@@ -2235,7 +2235,7 @@ let Vector3$1 = class Vector3 {
2235
2235
 
2236
2236
  /**
2237
2237
  *
2238
- * @param {number[]} array
2238
+ * @param {number[]|Float32Array} array
2239
2239
  * @param {number} offset
2240
2240
  */
2241
2241
  writeToArray(array, offset = 0) {
@@ -77621,10 +77621,11 @@ class ShadedGeometrySystem extends System {
77621
77621
  }
77622
77622
 
77623
77623
  /**
77624
- *
77624
+ * Given an object and a value, find the first property with matching value and returns name of that property
77625
+ * Useful for working with ENUM-like objects
77625
77626
  * @param {Object<T>} object
77626
77627
  * @param {T} value
77627
- * @returns {string|undefined}
77628
+ * @returns {string|undefined} name of the property, or undefined if property not found
77628
77629
  */
77629
77630
  function objectKeyByValue(object, value) {
77630
77631
  for (let i in object) {
@@ -79232,46 +79233,6 @@ Stats.Panel = function ( name, fg, bg ) {
79232
79233
 
79233
79234
  };
79234
79235
 
79235
- /**
79236
- *
79237
- * @param {number} ax0
79238
- * @param {number} ay0
79239
- * @param {number} ax1
79240
- * @param {number} ay1
79241
- * @param {number} bx0
79242
- * @param {number} by0
79243
- * @param {number} bx1
79244
- * @param {number} by1
79245
- * @param {AABB2} result
79246
- * @returns {boolean} true if overlap exists, false if no overlap
79247
- */
79248
- function aabb2_compute_overlap(
79249
- ax0, ay0, ax1, ay1,
79250
- bx0, by0, bx1, by1,
79251
- result
79252
- ) {
79253
-
79254
- const x0 = max2(ax0, bx0);
79255
- const x1 = min2(ax1, bx1);
79256
-
79257
- if (x0 >= x1) {
79258
- //no overlap
79259
- return false;
79260
- }
79261
-
79262
- const y0 = max2(ay0, by0);
79263
- const y1 = min2(ay1, by1);
79264
-
79265
- if (y0 >= y1) {
79266
- //no overlap
79267
- return false;
79268
- }
79269
-
79270
- result.set(x0, y0, x1, y1);
79271
-
79272
- return true;
79273
- }
79274
-
79275
79236
  /**
79276
79237
  *
79277
79238
  * Find intersection point between two line segments if they intersect at all
@@ -79356,6 +79317,46 @@ function line_segment_compute_line_segment_intersection_2d(
79356
79317
  return collision;
79357
79318
  }
79358
79319
 
79320
+ /**
79321
+ *
79322
+ * @param {number} ax0
79323
+ * @param {number} ay0
79324
+ * @param {number} ax1
79325
+ * @param {number} ay1
79326
+ * @param {number} bx0
79327
+ * @param {number} by0
79328
+ * @param {number} bx1
79329
+ * @param {number} by1
79330
+ * @param {AABB2} result
79331
+ * @returns {boolean} true if overlap exists, false if no overlap
79332
+ */
79333
+ function aabb2_compute_overlap(
79334
+ ax0, ay0, ax1, ay1,
79335
+ bx0, by0, bx1, by1,
79336
+ result
79337
+ ) {
79338
+
79339
+ const x0 = max2(ax0, bx0);
79340
+ const x1 = min2(ax1, bx1);
79341
+
79342
+ if (x0 >= x1) {
79343
+ //no overlap
79344
+ return false;
79345
+ }
79346
+
79347
+ const y0 = max2(ay0, by0);
79348
+ const y1 = min2(ay1, by1);
79349
+
79350
+ if (y0 >= y1) {
79351
+ //no overlap
79352
+ return false;
79353
+ }
79354
+
79355
+ result.set(x0, y0, x1, y1);
79356
+
79357
+ return true;
79358
+ }
79359
+
79359
79360
  /**
79360
79361
  * Created by Alex on 08/08/2016.
79361
79362
  * @copyright Alex Goldring 2016
@@ -79484,7 +79485,7 @@ class AABB2 {
79484
79485
  /**
79485
79486
  *
79486
79487
  * @param {AABB2} other
79487
- * @returns {number}
79488
+ * @returns {boolean}
79488
79489
  */
79489
79490
  overlapExists(other) {
79490
79491
  const ax0 = this.x0;
@@ -79511,6 +79512,7 @@ class AABB2 {
79511
79512
  _expandToFit(x0, y0, x1, y1) {
79512
79513
  this.x0 = min2(this.x0, x0);
79513
79514
  this.y0 = min2(this.y0, y0);
79515
+
79514
79516
  this.x1 = max2(this.x1, x1);
79515
79517
  this.y1 = max2(this.y1, y1);
79516
79518
  }
@@ -79521,21 +79523,8 @@ class AABB2 {
79521
79523
  * @param {number} y
79522
79524
  */
79523
79525
  _expandToFitPoint(x, y) {
79524
- if (x < this.x0) {
79525
- this.x0 = x;
79526
- }
79527
-
79528
- if (x > this.x1) {
79529
- this.x1 = x;
79530
- }
79531
-
79532
- if (y < this.y0) {
79533
- this.y0 = y;
79534
- }
79535
-
79536
- if (y > this.y1) {
79537
- this.y1 = y;
79538
- }
79526
+ // shortcut, use a 0-size box
79527
+ this._expandToFit(x, y, x, y);
79539
79528
  }
79540
79529
 
79541
79530
  /**
@@ -86069,7 +86058,7 @@ function computeStatisticalPartialMedian(values, start, end) {
86069
86058
 
86070
86059
  const range = end - start;
86071
86060
 
86072
- const position = (start + range) >> 1;
86061
+ const position = start + (range >> 1);
86073
86062
 
86074
86063
  return copy[position];
86075
86064
  }
@@ -95345,23 +95334,38 @@ class Clock {
95345
95334
  * Created by Alex on 06/05/2015.
95346
95335
  */
95347
95336
 
95337
+ /**
95338
+ * Simulation tick generator
95339
+ * Dispatches "tick" every animation frame or "maxDelay" time, whichever happens to be soonest
95340
+ * This is essentially the timing bus that all the simulation systems subscribe to for their step advancement
95341
+ */
95348
95342
  class Ticker {
95349
95343
  /**
95350
95344
  * @readonly
95351
95345
  * @type {Clock}
95352
95346
  */
95353
95347
  clock = new Clock();
95348
+
95354
95349
  /**
95355
95350
  * @private
95356
95351
  * @type {boolean}
95357
95352
  */
95358
- isRunning = false;
95353
+ #isRunning = false;
95354
+
95359
95355
 
95360
95356
  /**
95361
- *
95362
- * @type {SignalHandler[]}
95357
+ * Dispatches time delta in seconds since last tick
95358
+ * @readonly
95359
+ * @type {Signal<number>}
95363
95360
  */
95364
- callbacks = [];
95361
+ onTick = new Signal();
95362
+
95363
+ /**
95364
+ * @deprecated
95365
+ */
95366
+ get callbacks() {
95367
+ throw new Error('deprecated, use onTick signal instead');
95368
+ }
95365
95369
 
95366
95370
  /**
95367
95371
  *
@@ -95372,78 +95376,43 @@ class Ticker {
95372
95376
  }
95373
95377
 
95374
95378
  /**
95375
- *
95379
+ * @deprecated use onTick signal directly instead
95376
95380
  * @param {function} callback
95377
95381
  * @param {*} [thisArg]
95378
95382
  */
95379
95383
  subscribe(callback, thisArg) {
95380
- const handler = new SignalHandler(callback, thisArg);
95381
-
95382
- this.callbacks.push(handler);
95384
+ this.onTick.add(callback, thisArg);
95383
95385
  }
95384
95386
 
95385
95387
  /**
95386
- *
95388
+ * @deprecated use onTick signal directly instead
95387
95389
  * @param {function} callback
95388
95390
  * @param {*} [thisArg]
95389
95391
  */
95390
95392
  unsubscribe(callback, thisArg) {
95391
-
95392
- const callbacks = this.callbacks;
95393
- const n = callbacks.length;
95394
- for (let i = 0; i < n; i++) {
95395
- const cb = callbacks[i];
95396
-
95397
- if (cb.handle === callback) {
95398
- if (thisArg !== undefined) {
95399
- if (thisArg === cb.context) {
95400
- callbacks.splice(i, 1);
95401
- return;
95402
- }
95403
- } else {
95404
- callbacks.splice(i, 1);
95405
- return;
95406
- }
95407
- }
95408
- }
95409
-
95393
+ this.onTick.remove(callback, thisArg);
95410
95394
  }
95411
95395
 
95412
95396
  /**
95413
95397
  *
95414
- * @param {number} maxTimeout
95398
+ * @param {number} [maxTimeout]
95415
95399
  */
95416
95400
  start({ maxTimeout = 100 } = {}) {
95417
95401
 
95418
-
95419
- const self = this;
95420
95402
  let timeout = null;
95421
95403
  let animationFrame = null;
95422
95404
 
95423
- this.isRunning = true;
95424
-
95425
- function update() {
95426
- if (self.isRunning) {
95427
-
95428
- const delta = self.clock.getDelta();
95429
-
95430
- const callbacks = self.callbacks;
95405
+ this.#isRunning = true;
95431
95406
 
95432
- for (let i = 0; i < callbacks.length; i++) {
95433
- const callback = callbacks[i];
95434
-
95435
- try {
95436
- callback.handle.call(callback.context, delta);
95437
- } catch (e) {
95438
- }
95439
-
95440
- }
95407
+ const update = () => {
95408
+ if (!this.#isRunning) {
95409
+ return;
95441
95410
  }
95442
- }
95443
95411
 
95444
- function cycle() {
95445
- update();
95446
- }
95412
+ const delta = this.clock.getDelta();
95413
+
95414
+ this.onTick.send1(delta);
95415
+ };
95447
95416
 
95448
95417
  function timeoutCallback() {
95449
95418
  cancelAnimationFrame(animationFrame);
@@ -95459,22 +95428,22 @@ class Ticker {
95459
95428
 
95460
95429
  function animate() {
95461
95430
  animationFrame = requestAnimationFrame(animationFrameCallback);
95462
- cycle();
95431
+ update();
95463
95432
  timeout = setTimeout(timeoutCallback, maxTimeout);
95464
95433
  }
95465
95434
 
95466
- self.clock.getDelta(); //purge delta
95467
- self.clock.start();
95435
+ this.clock.getDelta(); //purge delta
95436
+ this.clock.start();
95468
95437
 
95469
95438
  requestAnimationFrame(animationFrameCallback);
95470
95439
  }
95471
95440
 
95472
95441
  pause() {
95473
- this.isRunning = false;
95442
+ this.#isRunning = false;
95474
95443
  }
95475
95444
 
95476
95445
  resume() {
95477
- this.isRunning = true;
95446
+ this.#isRunning = true;
95478
95447
  }
95479
95448
  }
95480
95449
 
@@ -106099,76 +106068,6 @@ class QuadTreeNode extends AABB2 {
106099
106068
 
106100
106069
  }
106101
106070
 
106102
- /**
106103
- * Remove all rectangles that are fully contained within others
106104
- * @param {QuadTreeNode} boxes
106105
- */
106106
- function removeRedundantBoxes(boxes) {
106107
- const removals = [];
106108
-
106109
-
106110
- let datum;
106111
-
106112
- /**
106113
- *
106114
- * @param {QuadTreeDatum} intersection
106115
- */
106116
- function visitDatumIntersection(intersection) {
106117
- if (datum === intersection) {
106118
- //skip self
106119
- return;
106120
- }
106121
-
106122
- const ax0 = intersection.x0;
106123
- const ay0 = intersection.y0;
106124
- const ax1 = intersection.x1;
106125
- const ay1 = intersection.y1;
106126
-
106127
- const bx0 = datum.x0;
106128
- const by0 = datum.y0;
106129
- const bx1 = datum.x1;
106130
- const by1 = datum.y1;
106131
-
106132
- //question is now whether it is containment
106133
- if (ax0 >= bx0 && ax1 <= bx1 && ay0 >= by0 && ay1 <= by1) {
106134
- //b contains a
106135
- removals.push(intersection);
106136
- } else if (bx0 >= ax0 && bx1 <= ax1 && by0 >= ay0 && by1 <= ay1) {
106137
- //a contains b
106138
- removals.push(datum);
106139
-
106140
- //scheduled removal of the datum, prevent further traversal
106141
- return false;
106142
- }
106143
- }
106144
-
106145
- /**
106146
- *
106147
- * @param {QuadTreeNode} node
106148
- */
106149
- function visitTreeNode(node) {
106150
- const data = node.data;
106151
- const dataCount = data.length;
106152
-
106153
- for (let i = 0; i < dataCount; i++) {
106154
- /**
106155
- *
106156
- * @type {QuadTreeDatum}
106157
- */
106158
- datum = data[i];
106159
-
106160
- node.traverseRectangleIntersections(datum.x0, datum.y0, datum.x1, datum.y1, visitDatumIntersection);
106161
- }
106162
- }
106163
-
106164
- boxes.traversePreOrder(visitTreeNode);
106165
-
106166
- for (let i = 0; i < removals.length; i++) {
106167
- const removal = removals[i];
106168
- removal.disconnect();
106169
- }
106170
- }
106171
-
106172
106071
  /**
106173
106072
  *
106174
106073
  * @param {number} containerWidth
@@ -106404,6 +106303,81 @@ function packOneBox(box, free) {
106404
106303
  return true;
106405
106304
  }
106406
106305
 
106306
+ /**
106307
+ * Remove all rectangles that are fully contained within others
106308
+ * @param {QuadTreeNode} boxes
106309
+ */
106310
+ function removeRedundantBoxes(boxes) {
106311
+ const removals = [];
106312
+
106313
+
106314
+ let datum;
106315
+
106316
+ /**
106317
+ *
106318
+ * @param {QuadTreeDatum} intersection
106319
+ */
106320
+ function visitDatumIntersection(intersection) {
106321
+ if (datum === intersection) {
106322
+ //skip self
106323
+ return;
106324
+ }
106325
+
106326
+ const ax0 = intersection.x0;
106327
+ const ay0 = intersection.y0;
106328
+ const ax1 = intersection.x1;
106329
+ const ay1 = intersection.y1;
106330
+
106331
+ const bx0 = datum.x0;
106332
+ const by0 = datum.y0;
106333
+ const bx1 = datum.x1;
106334
+ const by1 = datum.y1;
106335
+
106336
+ //question is now whether it is containment
106337
+ if (ax0 >= bx0 && ax1 <= bx1 && ay0 >= by0 && ay1 <= by1) {
106338
+ //b contains a
106339
+ removals.push(intersection);
106340
+ } else if (bx0 >= ax0 && bx1 <= ax1 && by0 >= ay0 && by1 <= ay1) {
106341
+ //a contains b
106342
+ removals.push(datum);
106343
+
106344
+ //scheduled removal of the datum, prevent further traversal
106345
+ return false;
106346
+ }
106347
+ }
106348
+
106349
+ /**
106350
+ *
106351
+ * @param {QuadTreeNode} node
106352
+ */
106353
+ function visitTreeNode(node) {
106354
+ const data = node.data;
106355
+ const dataCount = data.length;
106356
+
106357
+ for (let i = 0; i < dataCount; i++) {
106358
+ /**
106359
+ *
106360
+ * @type {QuadTreeDatum}
106361
+ */
106362
+ datum = data[i];
106363
+
106364
+ node.traverseRectangleIntersections(datum.x0, datum.y0, datum.x1, datum.y1, visitDatumIntersection);
106365
+ }
106366
+ }
106367
+
106368
+ boxes.traversePreOrder(visitTreeNode);
106369
+
106370
+ for (let i = 0; i < removals.length; i++) {
106371
+ const removal = removals[i];
106372
+ removal.disconnect();
106373
+ }
106374
+ }
106375
+
106376
+ /**
106377
+ * Packs rectangles into a finite area, packer is incremental and supports both insertions and removals of rectangles
106378
+ * Implementation of "max rectangles" packing algorithm.
106379
+ * Useful for packing texture atlases
106380
+ */
106407
106381
  class MaxRectanglesPacker {
106408
106382
  /**
106409
106383
  *
@@ -106418,6 +106392,8 @@ class MaxRectanglesPacker {
106418
106392
  * @type {QuadTreeNode}
106419
106393
  */
106420
106394
  this.free = new QuadTreeNode(0, 0, width, height);
106395
+
106396
+ // initialize a with a free space occupying the entire area
106421
106397
  this.free.add(null, 0, 0, width, height);
106422
106398
 
106423
106399
  /**
@@ -106492,7 +106468,8 @@ class MaxRectanglesPacker {
106492
106468
  }
106493
106469
 
106494
106470
  /**
106495
- *
106471
+ * Tests whether a rectangle of given dimensions can be packed into remaining space
106472
+ * Essentially, if this method succeeds - insertion will succeed as well, and if it fails - insertion will fail too
106496
106473
  * @param {number} w
106497
106474
  * @param {number} h
106498
106475
  * @return {boolean}
@@ -106576,9 +106553,10 @@ class MaxRectanglesPacker {
106576
106553
  }
106577
106554
 
106578
106555
  /**
106579
- * Resize the packer canvas
106556
+ * Resize the packer canvas, may trigger repacking if new dimensions are smaller than the existing ones
106580
106557
  * @param {number} width
106581
106558
  * @param {number} height
106559
+ * @returns {boolean} false if packing fails after resize, true otherwise
106582
106560
  */
106583
106561
  resize(width, height) {
106584
106562
 
@@ -106591,18 +106569,20 @@ class MaxRectanglesPacker {
106591
106569
 
106592
106570
  if (oldWidth > width || oldHeight > height) {
106593
106571
  //canvas was made smaller in at least one dimension, re-pack is required
106594
- this.repack();
106595
- } else {
106596
- //canvas was enlarged, we can simply add new free areas
106597
- if (width > oldWidth) {
106598
- this.free.insertDatum(new QuadTreeDatum(oldWidth, 0, width, height));
106599
- }
106600
- if (height > oldHeight) {
106601
- this.free.insertDatum(new QuadTreeDatum(0, oldHeight, width, height));
106602
- }
106572
+ return this.repack();
106573
+ }
106574
+
106575
+ //canvas was enlarged, we can simply add new free areas
106576
+ if (width > oldWidth) {
106577
+ this.free.insertDatum(new QuadTreeDatum(oldWidth, 0, width, height));
106578
+ }
106579
+ if (height > oldHeight) {
106580
+ this.free.insertDatum(new QuadTreeDatum(0, oldHeight, width, height));
106603
106581
  }
106604
106582
 
106605
106583
  // assert.ok(this.validate());
106584
+
106585
+ return true;
106606
106586
  }
106607
106587
 
106608
106588
  validate() {