@woosh/meep-engine 2.78.1 → 2.80.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 (56) hide show
  1. package/build/meep.cjs +235 -233
  2. package/build/meep.min.js +1 -1
  3. package/build/meep.module.js +235 -233
  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/Quaternion.js +1 -1
  12. package/src/core/geom/Vector3.js +2 -2
  13. package/src/core/geom/Vector3.spec.js +2 -2
  14. package/src/core/geom/packing/max-rect/{MaxRectangles.js → MaxRectanglesPacker.js} +25 -32
  15. package/src/core/geom/packing/max-rect/MaxRectanglesPacker.spec.js +60 -0
  16. package/src/core/geom/packing/max-rect/packMaxRectangles.js +19 -0
  17. package/src/core/geom/vec3/v3_angle_between.js +15 -4
  18. package/src/core/geom/vec3/{v3_computeOffsetVector.js → v3_displace_in_direction.js} +11 -2
  19. package/src/core/graph/cluster_mesh_metis.js +3 -3
  20. package/src/core/graph/metis/metis.js +16 -1
  21. package/src/core/graph/metis/metis_options.js +32 -29
  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/model/node-graph/node/NodeDescription.js +12 -10
  27. package/src/core/model/node-graph/node/NodeDescription.spec.js +14 -1
  28. package/src/core/model/object/objectKeyByValue.js +3 -2
  29. package/src/engine/ecs/ik/OneBoneSurfaceAlignmentSolver.js +2 -2
  30. package/src/engine/ecs/ik/TwoBoneInverseKinematicsSolver.js +2 -2
  31. package/src/engine/ecs/renderable/Renderable.js +1 -1
  32. package/src/engine/ecs/terrain/ecs/TerrainSystem.js +1 -1
  33. package/src/engine/ecs/terrain/tiles/TerrainTile.spec.js +2 -2
  34. package/src/engine/ecs/transform/Transform.js +3 -3
  35. package/src/engine/ecs/transform/Transform.spec.js +3 -3
  36. package/src/engine/ecs/transform-attachment/TransformAttachment.js +2 -1
  37. package/src/engine/ecs/transform-attachment/TransformAttachmentSystem.js +45 -33
  38. package/src/engine/graphics/ecs/path/entity/testEntityPath.js +16 -10
  39. package/src/engine/graphics/material/optimization/MaterialOptimizationContext.js +1 -1
  40. package/src/engine/graphics/texture/atlas/TextureAtlas.js +1 -1
  41. package/src/engine/graphics/texture/atlas/gpu/WebGLTextureAtlas.js +3 -3
  42. package/src/engine/graphics/three/expand_aabb_by_transformed_three_object.js +1 -1
  43. package/src/engine/graphics/three/expand_aabb_by_transformed_three_object.spec.js +2 -2
  44. package/src/engine/navigation/ecs/components/Path.js +5 -12
  45. package/src/engine/simulation/Ticker.js +40 -61
  46. package/src/core/geom/LineSegment.js +0 -207
  47. package/src/core/primitives/strings/prefixTree/PrefixTree.js +0 -225
  48. package/src/core/primitives/strings/prefixTree/PrefixTree.spec.js +0 -39
  49. package/src/core/primitives/strings/prefixTree/PrefixTreeLeaf.js +0 -25
  50. package/src/core/primitives/strings/prefixTree/PrefixTreeNode.js +0 -16
  51. /package/src/core/geom/3d/{matrix → mat4}/MATRIX_4_IDENTITY.js +0 -0
  52. /package/src/core/geom/3d/{matrix → mat4}/MATRIX_4_IDENTITY.spec.js +0 -0
  53. /package/src/core/geom/3d/{matrix → mat4}/allocate_transform_m4.js +0 -0
  54. /package/src/core/geom/3d/{matrix → mat4}/m4_make_translation.js +0 -0
  55. /package/src/core/geom/3d/{matrix → mat4}/m4_multiply.js +0 -0
  56. /package/src/core/geom/3d/{matrix → mat4}/m4_multiply_alphatensor.js +0 -0
@@ -1,27 +1,42 @@
1
1
  /**
2
2
  * Created by Alex on 06/05/2015.
3
3
  */
4
- import Clock from '../Clock.js';
5
- import { SignalHandler } from "../../core/events/signal/SignalHandler.js";
6
4
  import { assert } from "../../core/assert.js";
5
+ import Signal from "../../core/events/signal/Signal.js";
6
+ import Clock from '../Clock.js';
7
7
 
8
+ /**
9
+ * Simulation tick generator
10
+ * Dispatches "tick" every animation frame or "maxDelay" time, whichever happens to be soonest
11
+ * This is essentially the timing bus that all the simulation systems subscribe to for their step advancement
12
+ */
8
13
  class Ticker {
9
14
  /**
10
15
  * @readonly
11
16
  * @type {Clock}
12
17
  */
13
18
  clock = new Clock();
19
+
14
20
  /**
15
21
  * @private
16
22
  * @type {boolean}
17
23
  */
18
- isRunning = false;
24
+ #isRunning = false;
25
+
19
26
 
20
27
  /**
21
- *
22
- * @type {SignalHandler[]}
28
+ * Dispatches time delta in seconds since last tick
29
+ * @readonly
30
+ * @type {Signal<number>}
23
31
  */
24
- callbacks = [];
32
+ onTick = new Signal();
33
+
34
+ /**
35
+ * @deprecated
36
+ */
37
+ get callbacks() {
38
+ throw new Error('deprecated, use onTick signal instead');
39
+ }
25
40
 
26
41
  /**
27
42
  *
@@ -32,80 +47,44 @@ class Ticker {
32
47
  }
33
48
 
34
49
  /**
35
- *
50
+ * @deprecated use onTick signal directly instead
36
51
  * @param {function} callback
37
52
  * @param {*} [thisArg]
38
53
  */
39
54
  subscribe(callback, thisArg) {
40
- const handler = new SignalHandler(callback, thisArg);
41
-
42
- this.callbacks.push(handler);
55
+ this.onTick.add(callback, thisArg);
43
56
  }
44
57
 
45
58
  /**
46
- *
59
+ * @deprecated use onTick signal directly instead
47
60
  * @param {function} callback
48
61
  * @param {*} [thisArg]
49
62
  */
50
63
  unsubscribe(callback, thisArg) {
51
- assert.isFunction(callback, 'callback');
52
-
53
- const callbacks = this.callbacks;
54
- const n = callbacks.length;
55
- for (let i = 0; i < n; i++) {
56
- const cb = callbacks[i];
57
-
58
- if (cb.handle === callback) {
59
- if (thisArg !== undefined) {
60
- if (thisArg === cb.context) {
61
- callbacks.splice(i, 1);
62
- return;
63
- }
64
- } else {
65
- callbacks.splice(i, 1);
66
- return;
67
- }
68
- }
69
- }
70
-
64
+ this.onTick.remove(callback, thisArg);
71
65
  }
72
66
 
73
67
  /**
74
68
  *
75
- * @param {number} maxTimeout
69
+ * @param {number} [maxTimeout]
76
70
  */
77
71
  start({ maxTimeout = 100 } = {}) {
78
- assert.typeOf(maxTimeout, 'number', 'maxTimeout');
72
+ assert.isNumber(maxTimeout, 'maxTimeout');
73
+ assert.greaterThan(maxTimeout, 0);
79
74
 
80
-
81
- const self = this;
82
75
  let timeout = null;
83
76
  let animationFrame = null;
84
77
 
85
- this.isRunning = true;
86
-
87
- function update() {
88
- if (self.isRunning) {
89
-
90
- const delta = self.clock.getDelta();
78
+ this.#isRunning = true;
91
79
 
92
- const callbacks = self.callbacks;
93
-
94
- for (let i = 0; i < callbacks.length; i++) {
95
- const callback = callbacks[i];
96
-
97
- try {
98
- callback.handle.call(callback.context, delta);
99
- } catch (e) {
100
- console.error('Error in ticker subscription:', e);
101
- }
102
-
103
- }
80
+ const update = () => {
81
+ if (!this.#isRunning) {
82
+ return;
104
83
  }
105
- }
106
84
 
107
- function cycle() {
108
- update();
85
+ const delta = this.clock.getDelta();
86
+
87
+ this.onTick.send1(delta);
109
88
  }
110
89
 
111
90
  function timeoutCallback() {
@@ -122,22 +101,22 @@ class Ticker {
122
101
 
123
102
  function animate() {
124
103
  animationFrame = requestAnimationFrame(animationFrameCallback);
125
- cycle();
104
+ update();
126
105
  timeout = setTimeout(timeoutCallback, maxTimeout);
127
106
  }
128
107
 
129
- self.clock.getDelta(); //purge delta
130
- self.clock.start();
108
+ this.clock.getDelta(); //purge delta
109
+ this.clock.start();
131
110
 
132
111
  requestAnimationFrame(animationFrameCallback);
133
112
  }
134
113
 
135
114
  pause() {
136
- this.isRunning = false;
115
+ this.#isRunning = false;
137
116
  }
138
117
 
139
118
  resume() {
140
- this.isRunning = true;
119
+ this.#isRunning = true;
141
120
  }
142
121
  }
143
122
 
@@ -1,207 +0,0 @@
1
- /**
2
- * Created by Alex on 18/03/14.
3
- */
4
- import Vector3 from "./Vector3.js";
5
- import { clamp01 } from "../math/clamp01.js";
6
-
7
-
8
- const SMALL_NUM = 1e-9;
9
- /**
10
- * @param {Vector3} first
11
- * @param {Vector3} second
12
- * @constructor
13
- */
14
- const LineSegment = function (first, second) {
15
- this.p0 = first || null;
16
- this.p1 = second || null;
17
-
18
- };
19
-
20
- LineSegment.prototype.closestPointToPointParameter = function (point, clampToLine) {
21
-
22
-
23
- const startP = point.clone().sub(this.p0);
24
- const startEnd = this.p1.clone().sub(this.p0);
25
-
26
- const startEnd2 = startEnd.dot(startEnd);
27
- const startEnd_startP = startEnd.dot(startP);
28
-
29
- let t = startEnd_startP / startEnd2;
30
-
31
- if (clampToLine) {
32
-
33
- t = clamp01(t);
34
-
35
- }
36
-
37
- return t;
38
-
39
- };
40
-
41
- LineSegment.prototype.closestPointToPoint = function (point) {
42
-
43
- const t = this.closestPointToPointParameter(point, true);
44
-
45
- const result = this.p1.clone().sub(this.p0);
46
- return result.scale(t).add(this.p0);
47
-
48
- };
49
- /**
50
- * @param {Vector3} p
51
- * @returns {number}
52
- */
53
- LineSegment.prototype.distanceToPoint = function (p) {
54
- const closestPointToPoint = this.closestPointToPoint(p);
55
- return closestPointToPoint.sub(p).length();
56
- };
57
- /**
58
- * @param {LineSegment} other
59
- * @returns {number}
60
- */
61
- LineSegment.prototype.distanceToSegment = function (other) {
62
- const u = this.p1.clone().sub(this.p0);
63
- const v = other.p1.clone().sub(other.p0);
64
- const w = this.p0.clone().sub(other.p0);
65
- const a = u.dot(u); // always >= 0
66
- const b = u.dot(v);
67
- const c = v.dot(v); // always >= 0
68
- let d = u.dot(w);
69
- const e = v.dot(w);
70
- const D = a * c - b * b; // always >= 0
71
- let sc, sN, sD = D; // sc = sN / sD, default sD = D >= 0
72
- let tc, tN, tD = D; // tc = tN / tD, default tD = D >= 0
73
-
74
- // compute the line parameters of the two closest points
75
- if (D < SMALL_NUM) { // the lines are almost parallel
76
- sN = 0.0; // force using point P0 on segment S1
77
- sD = 1.0; // to prevent possible division by 0.0 later
78
- tN = e;
79
- tD = c;
80
- } else { // get the closest points on the infinite lines
81
- sN = (b * e - c * d);
82
- tN = (a * e - b * d);
83
- if (sN < 0.0) { // sc < 0 => the s=0 edge is visible
84
- sN = 0.0;
85
- tN = e;
86
- tD = c;
87
- } else if (sN > sD) { // sc > 1 => the s=1 edge is visible
88
- sN = sD;
89
- tN = e + b;
90
- tD = c;
91
- }
92
- }
93
-
94
- if (tN < 0.0) { // tc < 0 => the t=0 edge is visible
95
- tN = 0.0;
96
- // recompute sc for this edge
97
- if (-d < 0.0)
98
- sN = 0.0;
99
- else if (-d > a)
100
- sN = sD;
101
- else {
102
- sN = -d;
103
- sD = a;
104
- }
105
- } else if (tN > tD) { // tc > 1 => the t=1 edge is visible
106
- tN = tD;
107
- // recompute sc for this edge
108
- if ((-d + b) < 0.0)
109
- sN = 0;
110
- else if ((-d + b) > a)
111
- sN = sD;
112
- else {
113
- sN = (-d + b);
114
- sD = a;
115
- }
116
- }
117
- // finally do the division to get sc and tc
118
- sc = (Math.abs(sN) < SMALL_NUM ? 0.0 : sN / sD);
119
- tc = (Math.abs(tN) < SMALL_NUM ? 0.0 : tN / tD);
120
-
121
- // get the difference of the two closest points
122
- const dP = w.clone().add(
123
- u.clone().scale(sc).sub(
124
- v.clone().scale(tc)
125
- )
126
- ); // = S1(sc) - S2(tc)
127
-
128
- return dP.length(); // return the closest distance
129
- };
130
- LineSegment.prototype.clone = function () {
131
- return new LineSegment(this.p0, this.p1);
132
- };
133
- LineSegment.prototype.midPoint = function () {
134
- return this.p1.lerp(this.p0, 0.5);
135
- };
136
- LineSegment.prototype.shrinkByScalar = function (scalar) {
137
- const length = this.length();
138
- const newScale = (length - scalar) / length;
139
- const halfScaleDelta = (1 - newScale) / 2;
140
- //find mid point
141
- let midPoint = this.midPoint();
142
- //pull edges towards the midpoint
143
- const newP0 = this.p0.clone().lerp(this.p1, halfScaleDelta);
144
- const newP1 = this.p1.clone().lerp(this.p0, halfScaleDelta);
145
- this.p0 = newP0;
146
- this.p1 = newP1;
147
- //new length should now be equal to oldLength - scalar;
148
- return this;
149
- };
150
- LineSegment.prototype.length = function () {
151
- return this.p0.distanceTo(this.p1);
152
- };
153
- LineSegment.prototype.translate = function (vector) {
154
- this.p0.add(vector);
155
- this.p1.add(vector);
156
- };
157
-
158
-
159
- /**
160
- *
161
- * @param {Vector3} a0
162
- * @param {Vector3} a1
163
- * @param {Vector3} b0
164
- * @param {Vector3} b1
165
- * @param {Vector3} result
166
- * @returns {boolean}
167
- */
168
- LineSegment.intersectionPoint = (function () {
169
- const cross_da_db = new Vector3();
170
- const cross_dc_db = new Vector3();
171
- const dc = new Vector3();
172
- const da = new Vector3();
173
- const db = new Vector3();
174
-
175
- /**
176
- *
177
- * @param {Vector3} a0
178
- * @param {Vector3} a1
179
- * @param {Vector3} b0
180
- * @param {Vector3} b1
181
- * @param {Vector3} result
182
- * @returns {boolean}
183
- */
184
- function intersectionPoint(a0, a1, b0, b1, result) {
185
- da.copy(a1).sub(a0);
186
- db.copy(b1).sub(b0);
187
- dc.copy(b0).sub(a0);
188
-
189
- cross_da_db.copy(da).cross(db);
190
- if (dc.dot(cross_da_db) !== 0.0) {
191
- // lines are not coplanar
192
- return false;
193
- }
194
-
195
- cross_dc_db.copy(dc).cross(db);
196
- const s = cross_dc_db.dot(cross_da_db) / cross_da_db.lengthSqr();
197
- result.copy(da).multiplyScalar(s).add(a0);
198
- if (s >= 0.0 && s <= 1.0) {
199
- return true;
200
- }
201
-
202
- return false;
203
- }
204
-
205
- return intersectionPoint;
206
- })();
207
- export default LineSegment;
@@ -1,225 +0,0 @@
1
- import { PrefixTreeLeaf } from "./PrefixTreeLeaf.js";
2
- import { PrefixTreeNode } from "./PrefixTreeNode.js";
3
-
4
- export class PrefixTree extends PrefixTreeNode {
5
- constructor() {
6
- super();
7
-
8
- /**
9
- *
10
- * @type {string}
11
- */
12
- this.character = "";
13
-
14
- /**
15
- *
16
- * @type {PrefixTreeNode[]}
17
- */
18
- this.children = [];
19
- }
20
-
21
- /**
22
- *
23
- * @param {PrefixTreeNode} node
24
- */
25
- addChild(node) {
26
- node.depth = this.depth + 1;
27
- node.parent = this;
28
-
29
- this.children.push(node);
30
- }
31
-
32
- /**
33
- *
34
- * @param {string} character
35
- * @return {PrefixTree|undefined}
36
- */
37
- findChildByCharacter(character) {
38
- const n = this.children.length;
39
-
40
- for (let i = 0; i < n; i++) {
41
- const child = this.children[i];
42
-
43
- if (!child.isPrefixTree) {
44
- continue;
45
- }
46
-
47
- if (child.character === character) {
48
- return child;
49
- }
50
- }
51
- }
52
-
53
- /**
54
- *
55
- * @param {string} word
56
- * @returns {PrefixTreeLeaf|undefined}
57
- */
58
- findLeafByWord(word) {
59
-
60
- const n = this.children.length;
61
-
62
- for (let i = 0; i < n; i++) {
63
- const child = this.children[i];
64
-
65
- if (!child.isPrefixTreeLeaf) {
66
- continue;
67
- }
68
-
69
- if (child.word === word) {
70
- return child;
71
- }
72
- }
73
- }
74
-
75
- /**
76
- *
77
- * @param {string[]} result
78
- */
79
- collectValues(result) {
80
- const children = this.children;
81
- const n = children.length;
82
-
83
- for (let i = 0; i < n; i++) {
84
- const node = children[i];
85
-
86
- if (node.isPrefixTree) {
87
- node.collectValue(result);
88
- } else {
89
- const values = node.values;
90
- const valueCount = values.length;
91
-
92
- for (let j = 0; j < valueCount; j++) {
93
- const value = values[j];
94
-
95
- result.push(value);
96
- }
97
- }
98
- }
99
- }
100
-
101
- /**
102
- *
103
- * @param {string[]} result
104
- * @param {string} prefix
105
- */
106
- findValuesByPrefix(result, prefix) {
107
- const l = prefix.length;
108
-
109
- let n = this;
110
-
111
- for (let i = 0; i < l; i++) {
112
-
113
- const character = prefix.charAt(i);
114
- n = n.findChildByCharacter(character)
115
-
116
- if (n === undefined) {
117
- return;
118
- }
119
- }
120
-
121
-
122
- }
123
-
124
- /**
125
- *
126
- * @param {string} text
127
- * @param {RegExp} splitExpression
128
- * @param {boolean} stripSpecial
129
- * @param {boolean} stripPunctuation
130
- * @param {boolean} forceLowerCase
131
- * @param {*} value
132
- */
133
- insertText({ text, splitExpression = /\s/, stripSpecial = true, stripPunctuation = true, forceLowerCase = true, value }) {
134
- const strings = text.split(splitExpression);
135
-
136
- const words = [];
137
-
138
- const n = strings.length;
139
-
140
- let i;
141
-
142
- for (i = 0; i < n; i++) {
143
- const input = strings[i];
144
-
145
- let output = input;
146
-
147
- if (stripSpecial) {
148
- output = output.replace(/[\n\t\r]/g, '');
149
- }
150
-
151
- if (stripPunctuation) {
152
- output = output.replace(/[\,\.\!\?\-\+\[\]\(\)\=\"\']/g, '');
153
- }
154
-
155
- if (forceLowerCase) {
156
- output = output.toLocaleLowerCase();
157
- }
158
-
159
- if (output.length === 0) {
160
- continue;
161
- }
162
-
163
- if (words.indexOf(output) !== -1) {
164
- //skip, already recorded
165
- continue;
166
- }
167
-
168
- words.push(output);
169
- }
170
-
171
- const wordCount = words.length;
172
-
173
- for (i = 0; i < wordCount; i++) {
174
-
175
- const word = words[i];
176
-
177
- this.insertWord(word, value);
178
- }
179
- }
180
-
181
- /**
182
- *
183
- * @param {string} word
184
- * @param {*} value
185
- */
186
- insertWord(word, value) {
187
- const n = word.length;
188
-
189
- if (n <= this.depth) {
190
- //last letter
191
- let leaf = this.findLeafByWord(word);
192
-
193
- if (leaf === undefined) {
194
- leaf = new PrefixTreeLeaf();
195
-
196
- leaf.word = word;
197
-
198
- this.addChild(leaf);
199
- }
200
-
201
- leaf.values.push(value);
202
-
203
- } else {
204
-
205
- const char = word.charAt(this.depth);
206
-
207
- let child = this.findChildByCharacter(char);
208
-
209
- if (child === undefined) {
210
- child = new PrefixTree();
211
- child.character = char;
212
-
213
- this.addChild(child);
214
- }
215
-
216
- child.insertWord(word, value);
217
- }
218
- }
219
- }
220
-
221
- /**
222
- * @readonly
223
- * @type {boolean}
224
- */
225
- PrefixTree.prototype.isPrefixTree = true;
@@ -1,39 +0,0 @@
1
- import { PrefixTree } from "./PrefixTree.js";
2
-
3
- test('inset one letter', () => {
4
- const t = new PrefixTree();
5
-
6
- t.insertWord('a');
7
-
8
- const child = t.findChildByCharacter('a');
9
-
10
- expect(child.character).toBe('a');
11
- expect(child.children[0].word).toBe('a');
12
- expect(child.children[0].values.length).toBe(1);
13
- });
14
-
15
- test('insert one letter twice', () => {
16
-
17
- const t = new PrefixTree();
18
-
19
- t.insertWord('a');
20
- t.insertWord('a');
21
-
22
- const child = t.findChildByCharacter('a');
23
-
24
- expect(child.character).toBe('a');
25
- expect(child.children[0].word).toBe('a');
26
- expect(child.children[0].values.length).toBe(2);
27
- });
28
-
29
-
30
- test('complex', () => {
31
-
32
- const t = new PrefixTree();
33
-
34
- "cat sat on a mat. Horse smoked a camel. Bear snored, slithered and slobbered".split(/\s/).forEach(word => {
35
- t.insertWord(word);
36
- });
37
-
38
- console.log("");
39
- });
@@ -1,25 +0,0 @@
1
- import { PrefixTreeNode } from "./PrefixTreeNode.js";
2
-
3
- export class PrefixTreeLeaf extends PrefixTreeNode {
4
- constructor() {
5
- super();
6
-
7
- /**
8
- * Values associated with the word
9
- * @type {Array}
10
- */
11
- this.values = [];
12
-
13
- /**
14
- * Actual word
15
- * @type {string}
16
- */
17
- this.word = "";
18
- }
19
- }
20
-
21
- /**
22
- * @readonly
23
- * @type {boolean}
24
- */
25
- PrefixTreeLeaf.prototype.isPrefixTreeLeaf = true;
@@ -1,16 +0,0 @@
1
- export class PrefixTreeNode {
2
- constructor() {
3
-
4
- /**
5
- *
6
- * @type {number}
7
- */
8
- this.depth = 0;
9
-
10
- /**
11
- *
12
- * @type {PrefixTree|null}
13
- */
14
- this.parent = null;
15
- }
16
- }