@woosh/meep-engine 2.34.32 → 2.34.36

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/core/assert.js +11 -0
  2. package/core/binary/BitSet.js +5 -0
  3. package/core/bvh2/BinaryNode.js +210 -74
  4. package/core/bvh2/Node.d.ts +3 -0
  5. package/core/bvh2/aabb3/AABB3.js +50 -4
  6. package/core/bvh2/aabb3/AABB3Math.js +1 -1
  7. package/core/bvh2/aabb3/aabb3_from_v3_array.js +34 -0
  8. package/core/bvh2/aabb3/aabb3_from_v3_array_transformed.js +39 -0
  9. package/core/bvh2/aabb3/aabb3_intersects_frustum_degree.js +46 -0
  10. package/core/bvh2/transform/RotationOptimizer.js +2 -262
  11. package/core/bvh2/transform/tryRotateSingleNode.js +259 -0
  12. package/core/bvh2/traversal/ThreeFrustumsIntersectionBVHVisitor.js +16 -35
  13. package/core/bvh2/traversal/queryBinaryNode_FrustumIntersections.js +52 -0
  14. package/core/collection/list/List.js +0 -34
  15. package/core/events/signal/Signal.js +1 -1
  16. package/core/geom/3d/aabb/aabb3_matrix4_project.js +2 -3
  17. package/core/geom/Quaternion.d.ts +2 -0
  18. package/engine/Engine.js +5 -0
  19. package/engine/asset/loaders/ArrayBufferLoader.js +7 -0
  20. package/engine/asset/loaders/image/ImageRGBADataLoader.js +11 -6
  21. package/engine/development/performance/AbstractMetric.js +4 -0
  22. package/engine/development/performance/RingBufferMetric.js +4 -0
  23. package/engine/ecs/EntityBuilder.js +12 -5
  24. package/engine/ecs/EntityComponentDataset.js +26 -6
  25. package/engine/ecs/attachment/AttachmentSystem.js +1 -1
  26. package/engine/ecs/attachment/TransformAttachmentBinding.js +0 -1
  27. package/engine/ecs/foliage/FoliageVisibilitySetBuilder.js +1 -31
  28. package/engine/ecs/foliage/InstancedFoliage.js +81 -152
  29. package/engine/ecs/foliage/ViewState.js +190 -0
  30. package/engine/ecs/foliage/ecs/Foliage2System.js +80 -12
  31. package/engine/ecs/foliage/ecs/InstancedMeshComponent.js +30 -0
  32. package/engine/ecs/foliage/ecs/InstancedMeshLayer.js +16 -0
  33. package/engine/ecs/foliage/ecs/InstancedMeshUtils.js +2 -2
  34. package/engine/ecs/parent/EntityNode.js +31 -49
  35. package/engine/ecs/sockets/AttachmentSockets.js +11 -1
  36. package/engine/ecs/transform-attachment/TransformAttachment.js +88 -0
  37. package/engine/ecs/transform-attachment/TransformAttachmentSystem.js +59 -0
  38. package/engine/graphics/GraphicsEngine.js +23 -2
  39. package/engine/graphics/ecs/light/binding/three/ThreeLightBinding.js +2 -19
  40. package/engine/graphics/ecs/mesh/updateNodeByTransformAndBBB.js +21 -21
  41. package/engine/graphics/ecs/mesh-v2/ShadedGeometry.js +9 -1
  42. package/engine/graphics/ecs/mesh-v2/ShadedGeometryFlags.js +4 -1
  43. package/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.js +3 -0
  44. package/engine/graphics/ecs/mesh-v2/sample/load_gltf.js +40 -8
  45. package/engine/graphics/ecs/mesh-v2/three_object_to_entity_composition.js +3 -3
  46. package/engine/graphics/geometry/instancing/InstancedMeshGroup.js +17 -11
  47. package/engine/graphics/micron/build/buildMicronGeometryFromBufferGeometry.js +1 -34
  48. package/engine/graphics/micron/build/fill_patch_geometry_data.js +19 -6
  49. package/engine/graphics/micron/format/MicronGeometry.js +21 -0
  50. package/engine/graphics/micron/plugin/MicronRenderPlugin.js +0 -3
  51. package/engine/graphics/micron/prototypeVirtualGeometry.js +69 -1
  52. package/engine/graphics/render/layers/RenderLayer.js +22 -85
  53. package/engine/graphics/render/visibility/VisibilityComputer.js +23 -103
  54. package/engine/sound/ecs/emitter/SoundEmitterSystem.js +1 -1
  55. package/package.json +1 -1
  56. package/samples/terrain/editor.js +0 -1
@@ -1,8 +1,7 @@
1
- import { boxSurfaceArea2 as computeArea, scoreBoxesSAH as computeAreaFor2 } from "../aabb3/AABB3Math.js";
2
1
  import { BinaryNode } from "../BinaryNode.js";
3
2
  import { isLeaf } from "../LeafNode.js";
4
- import { surfaceAreaHeuristic as sah } from "../sah/surfaceAreaHeuristic.js";
5
3
  import { StacklessTraverser } from "../StacklessTraverser.js";
4
+ import { tryRotateSingleNode } from "./tryRotateSingleNode.js";
6
5
 
7
6
 
8
7
  /**
@@ -73,266 +72,12 @@ function getLeafCount(node, leafCounts) {
73
72
  return result;
74
73
  }
75
74
 
76
- /**
77
- *
78
- * @param {Node} node
79
- * @param {BinaryNode} parent
80
- */
81
- function setParent(node, parent) {
82
- node.parentNode = parent;
83
- }
84
-
85
- /**
86
- * Based on paper "Fast, Effective BVH Updates for Animated Scenes" Kopta et. al. (url: http://www.cs.utah.edu/~thiago/papers/rotations.pdf)
87
- * @param {BinaryNode} node
88
- * @param {Map.<NodeDescription,int>} leafCounts
89
- * @returns {int} value from 0 to 6, 0 means no rotation has taken place
90
- */
91
- function tryRotateSingleNode(node, leafCounts) {
92
-
93
-
94
- const left = node.left;
95
- const right = node.right;
96
-
97
- if (left === null || right === null) {
98
- return 0;
99
- }
100
-
101
- let bestRotation = 0;
102
-
103
-
104
- const nodeArea = computeArea(node);
105
- const leftArea = computeArea(left);
106
- const rightArea = computeArea(right);
107
-
108
- const leftLeaves = left.leafNodeCount;
109
- const rightLeaves = right.leafNodeCount;
110
-
111
-
112
- let bestCost = sah(
113
- nodeArea,
114
- leftArea,
115
- rightArea,
116
- leftLeaves,
117
- rightLeaves
118
- );
119
-
120
- let candidateCost;
121
-
122
- let leftLeftArea,
123
- leftRightArea,
124
- rightLeftArea,
125
- rightRightArea;
126
-
127
- let leftLeft,
128
- leftRight,
129
- rightLeft,
130
- rightRight;
131
-
132
- let leftLeftLeaves,
133
- leftRightLeaves,
134
- rightLeftLeaves,
135
- rightRightLeaves;
136
-
137
- let considerLeft = !isLeaf(left);
138
-
139
- if (considerLeft) {
140
- leftLeft = left.left;
141
- leftRight = left.right;
142
-
143
- considerLeft = (leftLeft !== null && leftRight !== null);
144
- if (considerLeft) {
145
-
146
- leftLeftArea = computeArea(leftLeft);
147
- leftRightArea = computeArea(leftRight);
148
-
149
- leftLeftLeaves = leftLeft.leafNodeCount;
150
- leftRightLeaves = leftRight.leafNodeCount;
151
-
152
- // (1) N N //
153
- // / \ / \ //
154
- // L R -----> L LL //
155
- // / \ / \ //
156
- // LL LR R LR //
157
- candidateCost = sah(nodeArea, computeAreaFor2(right, leftRight), leftLeftArea, rightLeaves + leftRightLeaves, leftLeftLeaves);
158
-
159
- if (candidateCost < bestCost) {
160
- bestRotation = 1;
161
- bestCost = candidateCost;
162
- }
163
-
164
- // (2) N N //
165
- // / \ / \ //
166
- // L R -----> L LR //
167
- // / \ / \ //
168
- // LL LR LL R //
169
- candidateCost = sah(nodeArea, computeAreaFor2(leftLeft, right), leftRightArea, leftLeftLeaves + rightLeaves, leftRightLeaves);
170
-
171
-
172
- if (candidateCost < bestCost) {
173
- bestRotation = 2;
174
- bestCost = candidateCost;
175
- }
176
- }
177
- }
178
- if (!isLeaf(right)) {
179
- rightLeft = right.left;
180
- rightRight = right.right;
181
- if (rightLeft !== null && rightRight !== null) {
182
-
183
- rightLeftArea = computeArea(rightLeft);
184
- rightRightArea = computeArea(rightRight);
185
-
186
- rightLeftLeaves = rightLeft.leafNodeCount;
187
- rightRightLeaves = rightRight.leafNodeCount;
188
-
189
- // (3) N N //
190
- // / \ / \ //
191
- // L R -----> RL R //
192
- // / \ / \ //
193
- // RL RR L RR //
194
- candidateCost = sah(nodeArea, rightLeftArea, computeAreaFor2(left, rightRight), rightLeftLeaves, leftLeaves + rightRightLeaves);
195
-
196
- if (candidateCost < bestCost) {
197
- bestRotation = 3;
198
- bestCost = candidateCost;
199
- }
200
-
201
- // (4) N N //
202
- // / \ / \ //
203
- // L R -----> RR R //
204
- // / \ / \ //
205
- // RL RR RL L //
206
- candidateCost = sah(nodeArea, rightRightArea, computeAreaFor2(rightLeft, left), rightRightLeaves, rightLeftLeaves + leftLeaves);
207
-
208
-
209
- if (candidateCost < bestCost) {
210
- bestRotation = 4;
211
- bestCost = candidateCost;
212
- }
213
-
214
- if (considerLeft) {
215
- //both child nodes are not leaf
216
-
217
- // (5) N N //
218
- // / \ / \ //
219
- // L R -----> L R //
220
- // / \ / \ / \ / \ //
221
- // LL LR RL RR LL RL LR RR //
222
- candidateCost = sah(
223
- nodeArea,
224
- computeAreaFor2(leftLeft, rightLeft),
225
- computeAreaFor2(leftRight, rightRight),
226
- leftLeftLeaves + rightLeftLeaves,
227
- leftRightLeaves + rightRightLeaves
228
- );
229
-
230
-
231
- if (candidateCost < bestCost) {
232
- bestRotation = 5;
233
- bestCost = candidateCost;
234
- }
235
-
236
- // (6) N N //
237
- // / \ / \ //
238
- // L R -----> L R //
239
- // / \ / \ / \ / \ //
240
- // LL LR RL RR LL RR RL LR //
241
- candidateCost = sah(
242
- nodeArea,
243
- computeAreaFor2(leftLeft, rightRight),
244
- computeAreaFor2(rightLeft, leftRight),
245
- leftLeftLeaves + rightRightLeaves,
246
- rightLeftLeaves + leftRightLeaves
247
- );
248
-
249
- if (candidateCost < bestCost) {
250
- bestRotation = 6;
251
- }
252
- }
253
- }
254
- }
255
-
256
- switch (bestRotation) {
257
- case 0:
258
- //no rotation
259
- break;
260
- case 1:
261
- node.right = leftLeft;
262
- setParent(leftLeft, node);
263
- left.left = right;
264
- setParent(right, left);
265
-
266
- left.refit();
267
- //update leaf count
268
- node.left.updateLeafNodeCount();
269
- break;
270
- case 2:
271
- node.right = leftRight;
272
- setParent(leftRight, node);
273
- left.right = right;
274
- setParent(right, left);
275
-
276
- left.refit();
277
- //update leaf count
278
- node.left.updateLeafNodeCount();
279
- break;
280
- case 3:
281
- node.left = rightLeft;
282
- setParent(rightLeft, node);
283
- right.left = left;
284
- setParent(left, right);
285
-
286
- right.refit();
287
- //update leaf count
288
- node.right.updateLeafNodeCount();
289
- break;
290
- case 4:
291
- node.left = rightRight;
292
- setParent(rightRight, node);
293
- right.right = left;
294
- setParent(left, right);
295
-
296
- right.refit();
297
- //update leaf count
298
- node.right.updateLeafNodeCount();
299
- break;
300
- case 5:
301
- left.right = rightLeft;
302
- setParent(rightLeft, left);
303
- right.left = leftRight;
304
- setParent(leftRight, right);
305
-
306
- left.refit();
307
- right.refit();
308
-
309
- //update leaf count
310
- node.left.updateLeafNodeCount();
311
- node.right.updateLeafNodeCount();
312
- break;
313
- case 6:
314
- left.right = rightRight;
315
- setParent(rightRight, left);
316
- right.right = leftRight;
317
- setParent(leftRight, right);
318
-
319
- left.refit();
320
- right.refit();
321
- //update leaf count
322
- node.left.updateLeafNodeCount();
323
- node.right.updateLeafNodeCount();
324
- break;
325
- }
326
-
327
- return bestRotation;
328
- }
329
-
330
75
  /**
331
76
  *
332
77
  * @param {BinaryNode} root
333
78
  * @param {int} maxIterations
334
79
  */
335
- function optimize(root, maxIterations = 1000) {
80
+ export function optimize(root, maxIterations = 1000) {
336
81
  const traverser = new StacklessTraverser();
337
82
 
338
83
  traverser.init(root);
@@ -376,8 +121,3 @@ function optimize(root, maxIterations = 1000) {
376
121
 
377
122
  return changeCounter;
378
123
  }
379
-
380
- export {
381
- optimize,
382
- tryRotateSingleNode
383
- };
@@ -0,0 +1,259 @@
1
+ import { boxSurfaceArea2 as computeArea, scoreBoxesSAH as computeAreaFor2 } from "../aabb3/AABB3Math.js";
2
+ import { surfaceAreaHeuristic as sah } from "../sah/surfaceAreaHeuristic.js";
3
+ import { isLeaf } from "../LeafNode.js";
4
+
5
+ /**
6
+ *
7
+ * @param {Node} node
8
+ * @param {BinaryNode} parent
9
+ */
10
+ function setParent(node, parent) {
11
+ node.parentNode = parent;
12
+ }
13
+
14
+ /**
15
+ * Based on paper "Fast, Effective BVH Updates for Animated Scenes" Kopta et. al. (url: http://www.cs.utah.edu/~thiago/papers/rotations.pdf)
16
+ * @param {BinaryNode} node
17
+ * @returns {int} value from 0 to 6, 0 means no rotation has taken place
18
+ */
19
+ export function tryRotateSingleNode(node) {
20
+
21
+ const left = node.left;
22
+ const right = node.right;
23
+
24
+ if (left === null || right === null) {
25
+ return 0;
26
+ }
27
+
28
+ /*
29
+ First we compute best rotation to apply, enumerated by 0-6
30
+ */
31
+
32
+ let bestRotation = 0;
33
+
34
+
35
+ const nodeArea = computeArea(node);
36
+ const leftArea = computeArea(left);
37
+ const rightArea = computeArea(right);
38
+
39
+ const leftLeaves = left.leafNodeCount;
40
+ const rightLeaves = right.leafNodeCount;
41
+
42
+
43
+ let bestCost = sah(
44
+ nodeArea,
45
+ leftArea,
46
+ rightArea,
47
+ leftLeaves,
48
+ rightLeaves
49
+ );
50
+
51
+ let candidateCost;
52
+
53
+ let leftLeftArea,
54
+ leftRightArea,
55
+ rightLeftArea,
56
+ rightRightArea;
57
+
58
+ let leftLeft,
59
+ leftRight,
60
+ rightLeft,
61
+ rightRight;
62
+
63
+ let leftLeftLeaves,
64
+ leftRightLeaves,
65
+ rightLeftLeaves,
66
+ rightRightLeaves;
67
+
68
+ let considerLeft = !isLeaf(left);
69
+
70
+ if (considerLeft) {
71
+ leftLeft = left.left;
72
+ leftRight = left.right;
73
+
74
+ considerLeft = (leftLeft !== null && leftRight !== null);
75
+ if (considerLeft) {
76
+
77
+ leftLeftArea = computeArea(leftLeft);
78
+ leftRightArea = computeArea(leftRight);
79
+
80
+ leftLeftLeaves = leftLeft.leafNodeCount;
81
+ leftRightLeaves = leftRight.leafNodeCount;
82
+
83
+ // (1) N N //
84
+ // / \ / \ //
85
+ // L R -----> L LL //
86
+ // / \ / \ //
87
+ // LL LR R LR //
88
+ candidateCost = sah(nodeArea, computeAreaFor2(right, leftRight), leftLeftArea, rightLeaves + leftRightLeaves, leftLeftLeaves);
89
+
90
+ if (candidateCost < bestCost) {
91
+ bestRotation = 1;
92
+ bestCost = candidateCost;
93
+ }
94
+
95
+ // (2) N N //
96
+ // / \ / \ //
97
+ // L R -----> L LR //
98
+ // / \ / \ //
99
+ // LL LR LL R //
100
+ candidateCost = sah(nodeArea, computeAreaFor2(leftLeft, right), leftRightArea, leftLeftLeaves + rightLeaves, leftRightLeaves);
101
+
102
+
103
+ if (candidateCost < bestCost) {
104
+ bestRotation = 2;
105
+ bestCost = candidateCost;
106
+ }
107
+ }
108
+ }
109
+ if (!isLeaf(right)) {
110
+ rightLeft = right.left;
111
+ rightRight = right.right;
112
+ if (rightLeft !== null && rightRight !== null) {
113
+
114
+ rightLeftArea = computeArea(rightLeft);
115
+ rightRightArea = computeArea(rightRight);
116
+
117
+ rightLeftLeaves = rightLeft.leafNodeCount;
118
+ rightRightLeaves = rightRight.leafNodeCount;
119
+
120
+ // (3) N N //
121
+ // / \ / \ //
122
+ // L R -----> RL R //
123
+ // / \ / \ //
124
+ // RL RR L RR //
125
+ candidateCost = sah(nodeArea, rightLeftArea, computeAreaFor2(left, rightRight), rightLeftLeaves, leftLeaves + rightRightLeaves);
126
+
127
+ if (candidateCost < bestCost) {
128
+ bestRotation = 3;
129
+ bestCost = candidateCost;
130
+ }
131
+
132
+ // (4) N N //
133
+ // / \ / \ //
134
+ // L R -----> RR R //
135
+ // / \ / \ //
136
+ // RL RR RL L //
137
+ candidateCost = sah(nodeArea, rightRightArea, computeAreaFor2(rightLeft, left), rightRightLeaves, rightLeftLeaves + leftLeaves);
138
+
139
+
140
+ if (candidateCost < bestCost) {
141
+ bestRotation = 4;
142
+ bestCost = candidateCost;
143
+ }
144
+
145
+ if (considerLeft) {
146
+ //both child nodes are not leaf
147
+
148
+ // (5) N N //
149
+ // / \ / \ //
150
+ // L R -----> L R //
151
+ // / \ / \ / \ / \ //
152
+ // LL LR RL RR LL RL LR RR //
153
+ candidateCost = sah(
154
+ nodeArea,
155
+ computeAreaFor2(leftLeft, rightLeft),
156
+ computeAreaFor2(leftRight, rightRight),
157
+ leftLeftLeaves + rightLeftLeaves,
158
+ leftRightLeaves + rightRightLeaves
159
+ );
160
+
161
+
162
+ if (candidateCost < bestCost) {
163
+ bestRotation = 5;
164
+ bestCost = candidateCost;
165
+ }
166
+
167
+ // (6) N N //
168
+ // / \ / \ //
169
+ // L R -----> L R //
170
+ // / \ / \ / \ / \ //
171
+ // LL LR RL RR LL RR RL LR //
172
+ candidateCost = sah(
173
+ nodeArea,
174
+ computeAreaFor2(leftLeft, rightRight),
175
+ computeAreaFor2(rightLeft, leftRight),
176
+ leftLeftLeaves + rightRightLeaves,
177
+ rightLeftLeaves + leftRightLeaves
178
+ );
179
+
180
+ if (candidateCost < bestCost) {
181
+ bestRotation = 6;
182
+ }
183
+ }
184
+ }
185
+ }
186
+
187
+ switch (bestRotation) {
188
+ case 0:
189
+ //no rotation
190
+ break;
191
+ case 1:
192
+ node.right = leftLeft;
193
+ setParent(leftLeft, node);
194
+ left.left = right;
195
+ setParent(right, left);
196
+
197
+ left.refit();
198
+ //update leaf count
199
+ node.left.updateLeafNodeCount();
200
+ break;
201
+ case 2:
202
+ node.right = leftRight;
203
+ setParent(leftRight, node);
204
+ left.right = right;
205
+ setParent(right, left);
206
+
207
+ left.refit();
208
+ //update leaf count
209
+ node.left.updateLeafNodeCount();
210
+ break;
211
+ case 3:
212
+ node.left = rightLeft;
213
+ setParent(rightLeft, node);
214
+ right.left = left;
215
+ setParent(left, right);
216
+
217
+ right.refit();
218
+ //update leaf count
219
+ node.right.updateLeafNodeCount();
220
+ break;
221
+ case 4:
222
+ node.left = rightRight;
223
+ setParent(rightRight, node);
224
+ right.right = left;
225
+ setParent(left, right);
226
+
227
+ right.refit();
228
+ //update leaf count
229
+ node.right.updateLeafNodeCount();
230
+ break;
231
+ case 5:
232
+ left.right = rightLeft;
233
+ setParent(rightLeft, left);
234
+ right.left = leftRight;
235
+ setParent(leftRight, right);
236
+
237
+ left.refit();
238
+ right.refit();
239
+
240
+ //update leaf count
241
+ node.left.updateLeafNodeCount();
242
+ node.right.updateLeafNodeCount();
243
+ break;
244
+ case 6:
245
+ left.right = rightRight;
246
+ setParent(rightRight, left);
247
+ right.right = leftRight;
248
+ setParent(leftRight, right);
249
+
250
+ left.refit();
251
+ right.refit();
252
+ //update leaf count
253
+ node.left.updateLeafNodeCount();
254
+ node.right.updateLeafNodeCount();
255
+ break;
256
+ }
257
+
258
+ return bestRotation;
259
+ }
@@ -6,13 +6,11 @@ export class ThreeFrustumsIntersectionBVHVisitor extends BVHVisitor {
6
6
  super();
7
7
 
8
8
  /**
9
- * Collection of THREE.js Frustums
9
+ * [plane_x, plane_y, plane_z, constant] collection, defining a frustum
10
10
  * @private
11
- * @type {Frustum[]}
11
+ * @type {ArrayLike<number>|number[]}
12
12
  */
13
- this.frustums = [];
14
-
15
- this.frustumCount = 0;
13
+ this.frustum = [];
16
14
 
17
15
  /**
18
16
  *
@@ -23,49 +21,32 @@ export class ThreeFrustumsIntersectionBVHVisitor extends BVHVisitor {
23
21
 
24
22
  /**
25
23
  *
26
- * @param {Frustum[]} frustums
24
+ * @param {ArrayLike<number>|number[]|Float32Array} frustum
27
25
  */
28
- setFrustums(frustums) {
29
- this.frustums = frustums;
30
- this.frustumCount = frustums.length;
26
+ setFrustum(frustum) {
27
+ this.frustum = frustum;
31
28
  }
32
29
 
33
30
  visitLeaf(node) {
34
31
 
35
- const n = this.frustumCount;
36
-
37
- for (let i = 0; i < n; i++) {
32
+ const degree = node.intersectFrustumDegree_array(this.frustum);
38
33
 
39
- const degree = node.intersectFrustumDegree(this.frustums[i]);
40
-
41
- if (degree !== 0) {
42
- this.collector.visitLeaf(node);
43
- return;
44
- }
34
+ if (degree !== 0) {
35
+ // at least partially visible
36
+ this.collector.visitLeaf(node);
45
37
  }
46
-
47
38
  }
48
39
 
49
40
  visitBinary(node) {
50
- let flag = false;
51
-
52
- const n = this.frustumCount;
53
-
54
- for (let i = 0; i < n; i++) {
55
-
56
- const degree = node.intersectFrustumDegree(this.frustums[i]);
57
41
 
58
- if (degree === 2) {
59
- //completely inside
60
- traverseBinaryNodeUsingVisitor(node, this.collector);
61
- return false;
62
- } else if (degree === 1) {
63
- //partially inside, continue traversal
64
- flag = true;
65
- }
42
+ const degree = node.intersectFrustumDegree_array(this.frustum);
66
43
 
44
+ if (degree === 2) {
45
+ //completely inside, do fast traversal
46
+ traverseBinaryNodeUsingVisitor(node, this.collector);
47
+ return false;
67
48
  }
68
49
 
69
- return flag;
50
+ return degree === 1;
70
51
  }
71
52
  }
@@ -0,0 +1,52 @@
1
+ /**
2
+ *
3
+ * @type {(BinaryNode|LeafNode)[]}
4
+ */
5
+ const stack = [];
6
+
7
+
8
+ /**
9
+ * @template T
10
+ * @param {T[]} destination
11
+ * @param {number} destinationOffset
12
+ * @param {BinaryNode<T>} root
13
+ * @param {ArrayLike<number>|number[]|Float32Array} frustum
14
+ * @returns {number} Number of results
15
+ */
16
+ export function queryBinaryNode_FrustumIntersections_Data(destination, destinationOffset, root, frustum) {
17
+ let n;
18
+ let i = 0;
19
+ let stackPointer = 1;
20
+
21
+ stack[0] = root;
22
+
23
+ while (stackPointer > 0) {
24
+ stackPointer--;
25
+
26
+ n = stack[stackPointer];
27
+
28
+ if (!n.intersectFrustum_array(frustum)) {
29
+ continue;
30
+ }
31
+
32
+ if (n.isBinaryNode) {
33
+
34
+ if (n.right !== null) {
35
+ stack[stackPointer++] = n.right;
36
+ }
37
+
38
+ if (n.left !== null) {
39
+ stack[stackPointer++] = n.left;
40
+ }
41
+
42
+ } else {
43
+
44
+ destination[destinationOffset + i] = n.object;
45
+
46
+ i++;
47
+ }
48
+
49
+ }
50
+
51
+ return i;
52
+ }