@woosh/meep-engine 2.67.0 → 2.68.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 (50) hide show
  1. package/build/meep.cjs +0 -1
  2. package/build/meep.module.js +0 -1
  3. package/package.json +1 -1
  4. package/src/engine/graphics/ecs/mesh/Mesh.d.ts +0 -1
  5. package/src/engine/graphics/ecs/mesh-v2/ShadedGeometry.d.ts +0 -5
  6. package/src/engine/graphics/ecs/mesh-v2/ShadedGeometry.js +0 -1
  7. package/src/engine/graphics/material/optimization/prototypeMaterialOptimizer.js +16 -19
  8. package/src/engine/graphics/render/forward_plus/prototype/prototypeLightManager.js +46 -47
  9. package/src/core/bvh2/BVHTasks.js +0 -65
  10. package/src/core/bvh2/BinaryNode.d.ts +0 -13
  11. package/src/core/bvh2/BinaryNode.js +0 -1188
  12. package/src/core/bvh2/BinaryNode.spec.js +0 -309
  13. package/src/core/bvh2/LeafNode.d.ts +0 -7
  14. package/src/core/bvh2/LeafNode.js +0 -147
  15. package/src/core/bvh2/Node.d.ts +0 -9
  16. package/src/core/bvh2/Node.js +0 -196
  17. package/src/core/bvh2/NodeValidator.js +0 -197
  18. package/src/core/bvh2/StacklessTraverser.js +0 -154
  19. package/src/core/bvh2/StacklessTraverser.spec.js +0 -109
  20. package/src/core/bvh2/serialization/deserializeBinaryNode.js +0 -40
  21. package/src/core/bvh2/serialization/deserializeBinaryNodeFromBinaryBuffer.js +0 -90
  22. package/src/core/bvh2/serialization/serializeBinaryNode.js +0 -31
  23. package/src/core/bvh2/serialization/serializeBinaryNodeToBinaryBuffer.js +0 -86
  24. package/src/core/bvh2/transform/BottomUpOptimizingRebuilder.js +0 -144
  25. package/src/core/bvh2/transform/RotationOptimizer.js +0 -123
  26. package/src/core/bvh2/transform/RotationOptimizer.spec.js +0 -303
  27. package/src/core/bvh2/transform/tryRotateSingleNode.js +0 -260
  28. package/src/core/bvh2/traversal/BVHVisitor.js +0 -30
  29. package/src/core/bvh2/traversal/RaycastBVHVisitor.js +0 -66
  30. package/src/core/bvh2/traversal/ThreeClippingPlaneComputingBVHVisitor.js +0 -384
  31. package/src/core/bvh2/traversal/ThreeFrustumsIntersectionBVHVisitor.js +0 -52
  32. package/src/core/bvh2/traversal/bvh_traverse_pre_order_using_stack.js +0 -43
  33. package/src/core/bvh2/traversal/queryBinaryNode_ClippingPlanes.d.ts +0 -5
  34. package/src/core/bvh2/traversal/queryBinaryNode_ClippingPlanes.js +0 -66
  35. package/src/core/bvh2/traversal/queryBinaryNode_CollectData.js +0 -49
  36. package/src/core/bvh2/traversal/queryBinaryNode_CollectLeaves.js +0 -51
  37. package/src/core/bvh2/traversal/queryBinaryNode_FrustumIntersections.js +0 -77
  38. package/src/core/bvh2/traversal/queryBinaryNode_SphereIntersections.js +0 -63
  39. package/src/core/bvh2/traversal/traverseBinaryNodeUsingVisitor.js +0 -50
  40. package/src/core/bvh2/traversal/traverseBinaryNodeUsingVisitor_DepthFirst_PreOrder.js +0 -34
  41. package/src/core/bvh2/util/find_least_common_ancestor.js +0 -34
  42. package/src/core/bvh2/visual/convert_bvh_to_dot_format_string.js +0 -50
  43. package/src/core/geom/2d/bvh/BinaryNode2.js +0 -152
  44. package/src/core/geom/2d/bvh/LeafNode2.js +0 -11
  45. package/src/core/geom/2d/bvh/Node2.js +0 -51
  46. package/src/engine/ecs/terrain/tiles/FirstRayIntersectionTerrainBVHVisitor.js +0 -74
  47. package/src/engine/graphics/geometry/bvh/BVHFromGeometry.js +0 -72
  48. package/src/engine/graphics/geometry/bvh/buffered/BVHGeometryRaycaster.js +0 -240
  49. package/src/engine/graphics/geometry/bvh/buffered/IndexedTraingleBoundsComputer.js +0 -43
  50. package/src/engine/graphics/render/forward_plus/query/query_bvh_frustum_from_objects.js +0 -133
@@ -1,144 +0,0 @@
1
- import { BinaryNode } from "../BinaryNode.js";
2
- import { isLeaf } from "../LeafNode.js";
3
- import { surfaceAreaHeuristic } from "../sah/surfaceAreaHeuristic.js";
4
- import { aabb3_score_boxes_SAH } from "../../geom/3d/aabb/aabb3_score_boxes_SAH.js";
5
- import { aabb3_box_surface_area_2 } from "../../geom/3d/aabb/aabb3_box_surface_area_2.js";
6
-
7
- function BottomUpOptimizingRebuilder() {
8
- this.root = null;
9
- this.nodes = [];
10
- /**
11
- * @type {function(left:NodeDescription, right:NodeDescription):number} heuristic Cost function of pairing two nodes, lower value means better pairing
12
- */
13
- this.heuristic = aabb3_score_boxes_SAH;
14
- }
15
-
16
- /**
17
- *
18
- * @param {BinaryNode} root
19
- */
20
- BottomUpOptimizingRebuilder.prototype.init = function (root) {
21
- this.root = root;
22
- const nodes = this.nodes = [];
23
- const binaryNodePool = this.binaryNodePool = [];
24
-
25
- //first extract all leaf nodes
26
- root.traversePreOrderUsingStack(function (node) {
27
- if (isLeaf(node)) {
28
- nodes.push(node);
29
- } else if (node !== root) {
30
- //collect intermediate nodes for reuse
31
- binaryNodePool.push(node);
32
- }
33
- });
34
- };
35
- /**
36
- * Factory to allow reuse of existing node, avoiding garbage collection
37
- * @returns {BinaryNode}
38
- */
39
- BottomUpOptimizingRebuilder.prototype.makeBinaryNode = function () {
40
- if (this.binaryNodePool.length > 0) {
41
- return this.binaryNodePool.pop();
42
- } else {
43
- return new BinaryNode();
44
- }
45
- };
46
-
47
- /**
48
- *
49
- * @param {number} maxSteps
50
- * @returns {boolean} true when complete
51
- */
52
- BottomUpOptimizingRebuilder.prototype.compute = function (maxSteps) {
53
- const self = this;
54
- /**
55
- *
56
- * @type {Array.<NodeDescription>}
57
- */
58
- const nodes = this.nodes;
59
-
60
- let nodeCount = nodes.length;
61
-
62
- const heuristic = this.heuristic;
63
-
64
- let stepsRemaining = maxSteps;
65
-
66
-
67
- while (nodeCount > 2 && stepsRemaining-- >= 0) {
68
- let bestI = -1;
69
- let bestJ = -1;
70
- let bestCost = Number.POSITIVE_INFINITY;
71
- for (let i = 0; i < nodeCount - 1; i++) {
72
- const first = nodes[i];
73
- for (let j = i + 1; j < nodeCount; j++) {
74
- const second = nodes[j];
75
-
76
- const cost = heuristic(first, second);
77
-
78
- if (cost < bestCost) {
79
- bestCost = cost;
80
-
81
- bestI = i;
82
- bestJ = j;
83
- }
84
- }
85
- }
86
-
87
- const first = nodes[bestI];
88
- const second = nodes[bestJ];
89
-
90
- const binaryNode = self.makeBinaryNode();
91
- binaryNode.setChildren(first, second);
92
-
93
- //transplant new node in place of the second removed node
94
- nodes[bestI] = binaryNode;
95
- nodes.splice(bestJ, 1);
96
-
97
- nodeCount--;
98
- }
99
-
100
- const root = this.root;
101
-
102
- if (nodeCount === 2) {
103
- root.setChildren(nodes[0], nodes[1]);
104
- return true;
105
- } else if (nodeCount === 1) {
106
- root.left = nodes[0];
107
- root.left.parentNode = root;
108
- root.refit();
109
- return true;
110
- } else if (nodeCount === 0) {
111
- //no nodes, we're done
112
- return true;
113
- } else {
114
- //not done yet
115
- return false;
116
- }
117
- };
118
-
119
- const leafCounts = new Map();
120
-
121
- function leaves(node) {
122
- if (leafCounts.has(node)) {
123
- return leafCounts.get(node);
124
- } else {
125
- const count = countLeaves(node);
126
- leafCounts.set(node, count);
127
- return count;
128
- }
129
- }
130
-
131
- function sah(left, right) {
132
- const leftArea = aabb3_box_surface_area_2(left);
133
- const rightArea = aabb3_box_surface_area_2(right);
134
-
135
- const leftLeaves = leaves(left);
136
- const rightLeaves = leaves(right);
137
-
138
- const commonArea = aabb3_score_boxes_SAH(left, right);
139
-
140
- return surfaceAreaHeuristic(commonArea, leftArea, rightArea, leftLeaves, rightLeaves);
141
- }
142
-
143
-
144
- export { BottomUpOptimizingRebuilder };
@@ -1,123 +0,0 @@
1
- import { BinaryNode } from "../BinaryNode.js";
2
- import { isLeaf } from "../LeafNode.js";
3
- import { StacklessTraverser } from "../StacklessTraverser.js";
4
- import { tryRotateSingleNode } from "./tryRotateSingleNode.js";
5
-
6
-
7
- /**
8
- *
9
- * @type {(BinaryNode|LeafNode)[]}
10
- */
11
- const stack = [];
12
- let stackPointer = 0;
13
-
14
- /**
15
- * * @param {BinaryNode} node
16
- * @param {Map.<NodeDescription,int>} leafCounts
17
- */
18
- function getLeafCount(node, leafCounts) {
19
- if (isLeaf(node)) {
20
- return 1;
21
- }
22
-
23
- let result = 0;
24
-
25
- let n;
26
-
27
- const storedValue = leafCounts.get(node);
28
-
29
- if (storedValue !== undefined) {
30
- return storedValue;
31
- }
32
-
33
- const stackOffset = stackPointer;
34
-
35
- stack[stackPointer++] = node;
36
-
37
- while (stackPointer-- > stackOffset) {
38
-
39
- n = stack[stackPointer];
40
-
41
-
42
- const storedValue = leafCounts.get(node);
43
-
44
- if (storedValue !== undefined) {
45
- result += storedValue;
46
- continue;
47
- }
48
-
49
-
50
- if (n.isBinaryNode) {
51
-
52
- if (n.right !== null) {
53
- stack[stackPointer++] = n.right;
54
- }
55
-
56
- if (n.left !== null) {
57
- stack[stackPointer++] = n.left;
58
- }
59
-
60
- } else {
61
-
62
- result++;
63
- }
64
-
65
- }
66
-
67
- //drop the stack frame
68
- stackPointer = stackOffset;
69
-
70
- leafCounts.set(node, result);
71
-
72
- return result;
73
- }
74
-
75
- /**
76
- *
77
- * @param {BinaryNode} root
78
- * @param {int} maxIterations
79
- */
80
- export function optimize(root, maxIterations = 1000) {
81
- const traverser = new StacklessTraverser();
82
-
83
- traverser.init(root);
84
-
85
- let changeCounter = 0;
86
-
87
- const leafCounts = new Map();
88
-
89
- function visit(node) {
90
-
91
- if (isLeaf(node)) {
92
- //skip leaves
93
- return true;
94
- }
95
-
96
- const rotationType = tryRotateSingleNode(node, leafCounts);
97
- if (rotationType !== 0) {
98
- changeCounter++;
99
- }
100
- }
101
-
102
- let oldChangeCounter = changeCounter;
103
-
104
- let i;
105
- for (i = 0; i < maxIterations; i++) {
106
- const canAdvance = traverser.advance(visit);
107
- if (!canAdvance) {
108
- //check if we have made any rotations in this traversal pass
109
- if (oldChangeCounter === changeCounter) {
110
- //done, no changes
111
- break;
112
- } else {
113
- oldChangeCounter = changeCounter;
114
- }
115
-
116
- //re-initialize the traverser
117
- traverser.init(root);
118
- }
119
-
120
- }
121
-
122
- return changeCounter;
123
- }
@@ -1,303 +0,0 @@
1
- import { seededRandom } from "../../math/random/seededRandom.js";
2
- import { BinaryNode } from "../BinaryNode.js";
3
- import { isLeaf, LeafNode } from "../LeafNode.js";
4
- import { validateNode, validateTree } from "../NodeValidator.js";
5
- import { optimize } from "./RotationOptimizer.js";
6
-
7
- expect.extend({
8
- toBeValid(node) {
9
- const violations = [];
10
-
11
- function violationCallback(v) {
12
- violations.push(v);
13
- }
14
-
15
- let pass = true;
16
- if (isLeaf(node)) {
17
- pass = pass && validateNode(node, violationCallback);
18
- } else {
19
- pass = pass && validateTree(node, violationCallback);
20
- }
21
-
22
- if (!pass) {
23
- let message = violations.map((v) => v.toString()).join("\n");
24
-
25
- if (message.trim().length === 0) {
26
- message = `node is not valid`;
27
- }
28
-
29
- return {
30
- message: function () {
31
- return message
32
- },
33
- pass: false
34
- };
35
- }
36
-
37
- return {
38
- pass: true
39
- };
40
- },
41
- /**
42
- *
43
- * @param {BinaryNode} container
44
- * @param node
45
- */
46
- toContainNode(container, node) {
47
- let found = false;
48
- let message;
49
- container.traversePreOrderUsingStack(function (n) {
50
- if (n === node) {
51
- found = true;
52
- //stop traversal
53
- return false;
54
- }
55
- });
56
-
57
- if (!found) {
58
- message = `node is not contained within the tree`;
59
- }
60
-
61
- return {
62
- message,
63
- pass: found
64
- };
65
- }
66
- });
67
-
68
- /**
69
- *
70
- * @param {number} v0
71
- * @param {number} v1
72
- * @param {*} [value]
73
- * @returns {LeafNode}
74
- */
75
- function leaf(v0, v1, value) {
76
- const leafNode = new LeafNode(value, v0, v0, v0, v1, v1, v1);
77
- return leafNode;
78
- }
79
-
80
- /**
81
- *
82
- * @param {NodeDescription} left
83
- * @param {NodeDescription} right
84
- * @returns {BinaryNode}
85
- */
86
- function pair(left, right) {
87
- const node = new BinaryNode();
88
-
89
- if (left === null) {
90
- node.right = right;
91
- right.parentNode = node;
92
- node.refit();
93
- } else if (right === null) {
94
- node.left = left;
95
- left.parentNode = left;
96
- node.refit();
97
- } else {
98
- node.setChildren(left, right);
99
- }
100
- return node;
101
- }
102
-
103
-
104
- describe.skip("suite", () => {
105
-
106
-
107
- test("empty node", () => {
108
- const node = new BinaryNode();
109
- node.setInfiniteBounds();
110
-
111
- optimize(node, 100);
112
-
113
- expect(node.left).toBeNull();
114
- expect(node.right).toBeNull();
115
- });
116
-
117
- test("does nothing on optimal 2 child tree", () => {
118
- const a = leaf(0, 1, "hello");
119
- const b = leaf(2, 3, "goodbye");
120
-
121
- const root = pair(a, b);
122
-
123
- const optimized = optimize(root, 100);
124
- expect(optimized).toBe(0);
125
-
126
- //positions preserved
127
- expect(root.left.object).toEqual(a.object);
128
- expect(root.right.object).toEqual(b.object);
129
-
130
- //parent node is root
131
- expect(root.left.parentNode).toEqual(root);
132
- expect(root.right.parentNode).toEqual(root);
133
-
134
- expect(root).toBeValid();
135
- });
136
-
137
- test("does nothing on optimal depth 2 tree", () => {
138
- const a = leaf(-2, -1, "a");
139
- const b = leaf(-1, 0, "b");
140
- const c = leaf(0, 1, "c");
141
- const d = leaf(1, 2, "d");
142
-
143
- const n0 = pair(a, b);
144
- const n1 = pair(c, d);
145
-
146
- const root = pair(n0, n1);
147
-
148
- const optimized = optimize(root, 100);
149
- expect(optimized).toBe(0);
150
-
151
- expect(root.parentNode).toBeNull();
152
-
153
- expect(root.left).toBe(n0);
154
- expect(root.right).toBe(n1);
155
-
156
- expect(n0.left).toBe(a);
157
- expect(n0.right).toBe(b);
158
-
159
- expect(n1.left).toBe(c);
160
- expect(n1.right).toBe(d);
161
-
162
- expect(root).toBeValid();
163
- });
164
-
165
- test("produces a valid tree from left-leaning tree with 4 leaves", () => {
166
- const a = leaf(-2, -1, "a");
167
- const b = leaf(-1, 0, "b");
168
- const c = leaf(0, 1, "c");
169
- const d = leaf(1, 2, "d");
170
-
171
- const root = pair(
172
- pair(
173
- pair(c, d),
174
- b
175
- ),
176
- a
177
- );
178
-
179
- optimize(root, 100);
180
-
181
- expect(root).toBeValid();
182
-
183
- expect(root).toContainNode(a);
184
- expect(root).toContainNode(b);
185
- expect(root).toContainNode(c);
186
- expect(root).toContainNode(d);
187
- });
188
-
189
- test("produces a valid tree from right-leaning tree with 4 leaves", () => {
190
- const a = leaf(-2, -1, "a");
191
- const b = leaf(-1, 0, "b");
192
- const c = leaf(0, 1, "c");
193
- const d = leaf(1, 2, "d");
194
-
195
- const root = pair(
196
- a,
197
- pair(
198
- b,
199
- pair(c, d)
200
- )
201
- );
202
-
203
- optimize(root, 100);
204
-
205
- expect(root).toBeValid();
206
-
207
- expect(root).toContainNode(a);
208
- expect(root).toContainNode(b);
209
- expect(root).toContainNode(c);
210
- expect(root).toContainNode(d);
211
- });
212
-
213
- test("100 node random tree optimization does not degrade quality", () => {
214
- const random = seededRandom(42);
215
-
216
- const nodes = [];
217
-
218
- for (let i = 0; i < 100; i++) {
219
- const x0 = random() * 100;
220
- const y0 = random() * 100;
221
- const z0 = random() * 100;
222
-
223
- const x1 = x0 + random() * 5;
224
- const y1 = y0 + random() * 5;
225
- const z1 = z0 + random() * 5;
226
-
227
- nodes.push(new LeafNode(i, x0, y0, z0, x1, y1, z1));
228
- }
229
-
230
- while (nodes.length >= 2) {
231
- const left = nodes.pop();
232
- const right = nodes.pop();
233
- nodes.unshift(pair(left, right));
234
- }
235
-
236
- const root = nodes[0];
237
-
238
- const oldSAH = root.computeSAH();
239
-
240
- optimize(root, 100);
241
-
242
- expect(root).toBeValid();
243
-
244
- const newSAH = root.computeSAH();
245
-
246
- //at least not degraded
247
- expect(newSAH).toBeLessThanOrEqual(oldSAH);
248
- });
249
-
250
- test("case 0: 4 node tree optimization does not degrade quality", () => {
251
- const ll = new LeafNode("ll",
252
- 76.06244471671744,
253
- 7.73902752171125,
254
- 1.925105413576489,
255
- 94.49883157197291,
256
- 50.63123012084361,
257
- 76.75841101302467
258
- );
259
-
260
- const lr = new LeafNode("lr",
261
- 76.11310176957886,
262
- 58.65097077867176,
263
- 11.346076624795387,
264
- 97.55653706044541,
265
- 89.91247777413719,
266
- 90.73181902923352
267
- );
268
-
269
- const rl = new LeafNode("rl",
270
- 32.4771196630536,
271
- 0.9366270797727339,
272
- 1.378434756588831,
273
- 66.71670340545461,
274
- 99.32784918828929,
275
- 97.52435446605432
276
- );
277
-
278
- const rr = new LeafNode("rr",
279
- 1.124263022938976,
280
- 0.13232239543867763,
281
- 2.702786005283997,
282
- 31.51776058888572,
283
- 94.87720282424561,
284
- 101.03932220629758
285
- );
286
-
287
- const root = pair(pair(ll, lr), pair(rl, rr));
288
-
289
- expect(root).toBeValid();
290
-
291
- const oldSAH = root.computeSAH();
292
-
293
- optimize(root, 1000);
294
-
295
- expect(root).toBeValid();
296
-
297
- const newSAH = root.computeSAH();
298
-
299
- //at least not degraded
300
- expect(newSAH).toBeLessThanOrEqual(oldSAH);
301
- });
302
-
303
- })