@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.
- package/core/assert.js +11 -0
- package/core/binary/BitSet.js +5 -0
- package/core/bvh2/BinaryNode.js +210 -74
- package/core/bvh2/Node.d.ts +3 -0
- package/core/bvh2/aabb3/AABB3.js +50 -4
- package/core/bvh2/aabb3/AABB3Math.js +1 -1
- package/core/bvh2/aabb3/aabb3_from_v3_array.js +34 -0
- package/core/bvh2/aabb3/aabb3_from_v3_array_transformed.js +39 -0
- package/core/bvh2/aabb3/aabb3_intersects_frustum_degree.js +46 -0
- package/core/bvh2/transform/RotationOptimizer.js +2 -262
- package/core/bvh2/transform/tryRotateSingleNode.js +259 -0
- package/core/bvh2/traversal/ThreeFrustumsIntersectionBVHVisitor.js +16 -35
- package/core/bvh2/traversal/queryBinaryNode_FrustumIntersections.js +52 -0
- package/core/collection/list/List.js +0 -34
- package/core/events/signal/Signal.js +1 -1
- package/core/geom/3d/aabb/aabb3_matrix4_project.js +2 -3
- package/core/geom/Quaternion.d.ts +2 -0
- package/engine/Engine.js +5 -0
- package/engine/asset/loaders/ArrayBufferLoader.js +7 -0
- package/engine/asset/loaders/image/ImageRGBADataLoader.js +11 -6
- package/engine/development/performance/AbstractMetric.js +4 -0
- package/engine/development/performance/RingBufferMetric.js +4 -0
- package/engine/ecs/EntityBuilder.js +12 -5
- package/engine/ecs/EntityComponentDataset.js +26 -6
- package/engine/ecs/attachment/AttachmentSystem.js +1 -1
- package/engine/ecs/attachment/TransformAttachmentBinding.js +0 -1
- package/engine/ecs/foliage/FoliageVisibilitySetBuilder.js +1 -31
- package/engine/ecs/foliage/InstancedFoliage.js +81 -152
- package/engine/ecs/foliage/ViewState.js +190 -0
- package/engine/ecs/foliage/ecs/Foliage2System.js +80 -12
- package/engine/ecs/foliage/ecs/InstancedMeshComponent.js +30 -0
- package/engine/ecs/foliage/ecs/InstancedMeshLayer.js +16 -0
- package/engine/ecs/foliage/ecs/InstancedMeshUtils.js +2 -2
- package/engine/ecs/parent/EntityNode.js +31 -49
- package/engine/ecs/sockets/AttachmentSockets.js +11 -1
- package/engine/ecs/transform-attachment/TransformAttachment.js +88 -0
- package/engine/ecs/transform-attachment/TransformAttachmentSystem.js +59 -0
- package/engine/graphics/GraphicsEngine.js +23 -2
- package/engine/graphics/ecs/light/binding/three/ThreeLightBinding.js +2 -19
- package/engine/graphics/ecs/mesh/updateNodeByTransformAndBBB.js +21 -21
- package/engine/graphics/ecs/mesh-v2/ShadedGeometry.js +9 -1
- package/engine/graphics/ecs/mesh-v2/ShadedGeometryFlags.js +4 -1
- package/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.js +3 -0
- package/engine/graphics/ecs/mesh-v2/sample/load_gltf.js +40 -8
- package/engine/graphics/ecs/mesh-v2/three_object_to_entity_composition.js +3 -3
- package/engine/graphics/geometry/instancing/InstancedMeshGroup.js +17 -11
- package/engine/graphics/micron/build/buildMicronGeometryFromBufferGeometry.js +1 -34
- package/engine/graphics/micron/build/fill_patch_geometry_data.js +19 -6
- package/engine/graphics/micron/format/MicronGeometry.js +21 -0
- package/engine/graphics/micron/plugin/MicronRenderPlugin.js +0 -3
- package/engine/graphics/micron/prototypeVirtualGeometry.js +69 -1
- package/engine/graphics/render/layers/RenderLayer.js +22 -85
- package/engine/graphics/render/visibility/VisibilityComputer.js +23 -103
- package/engine/sound/ecs/emitter/SoundEmitterSystem.js +1 -1
- package/package.json +1 -1
- package/samples/terrain/editor.js +0 -1
package/core/assert.js
CHANGED
|
@@ -316,6 +316,17 @@ assert.defined = function (value, name = "value") {
|
|
|
316
316
|
|
|
317
317
|
};
|
|
318
318
|
|
|
319
|
+
/**
|
|
320
|
+
*
|
|
321
|
+
* @param {*} value
|
|
322
|
+
* @param {String} [name]
|
|
323
|
+
*/
|
|
324
|
+
assert.isNull = function (value, name){
|
|
325
|
+
if (value !== null) {
|
|
326
|
+
throw new Error(`${name} is NOT null`);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
319
330
|
/**
|
|
320
331
|
*
|
|
321
332
|
* @param {*} value
|
package/core/binary/BitSet.js
CHANGED
|
@@ -533,6 +533,11 @@ BitSet.prototype.shift = function (distance, start_index, end_index) {
|
|
|
533
533
|
* Sets all of the bits in this BitSet to false.
|
|
534
534
|
*/
|
|
535
535
|
BitSet.prototype.reset = function () {
|
|
536
|
+
if (this.__length <= 0) {
|
|
537
|
+
// no action required
|
|
538
|
+
return;
|
|
539
|
+
}
|
|
540
|
+
|
|
536
541
|
this.__data_uint32.fill(0, 0, Math.ceil(this.__length / 32));
|
|
537
542
|
this.__length = 0;
|
|
538
543
|
};
|
package/core/bvh2/BinaryNode.js
CHANGED
|
@@ -8,7 +8,7 @@ import { arrayQuickSort } from "../collection/array/arrayQuickSort.js";
|
|
|
8
8
|
import { max2 } from "../math/max2.js";
|
|
9
9
|
import { min2 } from "../math/min2.js";
|
|
10
10
|
import { computeSampleStandardDeviation } from "../math/statistics/computeSampleStandardDeviation.js";
|
|
11
|
-
import { aabb3_intersect_aabb3, boxSurfaceArea2 } from "./aabb3/AABB3Math.js";
|
|
11
|
+
import { _boxSurfaceArea2, aabb3_intersect_aabb3, boxSurfaceArea2 } from "./aabb3/AABB3Math.js";
|
|
12
12
|
import { isLeaf, LeafNode } from "./LeafNode.js";
|
|
13
13
|
import { Node } from "./Node.js";
|
|
14
14
|
import { surfaceAreaHeuristic } from "./sah/surfaceAreaHeuristic.js";
|
|
@@ -141,11 +141,133 @@ BinaryNode.prototype.setChildren = function (left, right) {
|
|
|
141
141
|
|
|
142
142
|
/**
|
|
143
143
|
*
|
|
144
|
+
* @param {Node} child
|
|
145
|
+
*/
|
|
146
|
+
BinaryNode.prototype.setChildLeft = function (child) {
|
|
147
|
+
assert.isNull(this.left, 'left');
|
|
148
|
+
|
|
149
|
+
this.left = child;
|
|
150
|
+
|
|
151
|
+
this.updateLeafNodeCount();
|
|
152
|
+
|
|
153
|
+
this.refit();
|
|
154
|
+
|
|
155
|
+
child.parentNode = this;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
*
|
|
160
|
+
* @param {Node} child
|
|
161
|
+
*/
|
|
162
|
+
BinaryNode.prototype.setChildRight = function (child) {
|
|
163
|
+
assert.isNull(this.right, 'right');
|
|
164
|
+
|
|
165
|
+
this.right = child;
|
|
166
|
+
|
|
167
|
+
this.updateLeafNodeCount();
|
|
168
|
+
|
|
169
|
+
this.refit();
|
|
170
|
+
|
|
171
|
+
child.parentNode = this;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* @see "Dynamic BVH" by Erin Catto / Blizzard
|
|
176
|
+
* @param {AABB3} node
|
|
177
|
+
* @param {AABB3} addition
|
|
178
|
+
* @returns {number}
|
|
179
|
+
*/
|
|
180
|
+
function inclusion_surface_area_heuristic(node, addition) {
|
|
181
|
+
const x0 = min2(node.x0, addition.x0);
|
|
182
|
+
const y0 = min2(node.y0, addition.y0);
|
|
183
|
+
const z0 = min2(node.z0, addition.z0);
|
|
184
|
+
|
|
185
|
+
const x1 = max2(node.x1, addition.x1);
|
|
186
|
+
const y1 = max2(node.y1, addition.y1);
|
|
187
|
+
const z1 = max2(node.z1, addition.z1);
|
|
188
|
+
|
|
189
|
+
return _boxSurfaceArea2(x0, y0, z0, x1, y1, z1) - boxSurfaceArea2(node);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
*
|
|
194
|
+
* @param {BinaryNode|LeafNode} node
|
|
195
|
+
* @param {AABB3} addition
|
|
196
|
+
*/
|
|
197
|
+
function inclusion_cost_lower_bound(node, addition) {
|
|
198
|
+
let n = node;
|
|
199
|
+
let r = boxSurfaceArea2(addition);
|
|
200
|
+
|
|
201
|
+
while (n !== null) {
|
|
202
|
+
|
|
203
|
+
r += n.costForInclusion(addition);
|
|
204
|
+
|
|
205
|
+
n = n.parentNode;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
return r;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* For incremental insertion, a sibling needs to be found, newly inserted node will be parented together with this sibling
|
|
144
213
|
* @param {AABB3} box
|
|
145
|
-
* @returns {
|
|
214
|
+
* @returns {BinaryNode|LeafNode}
|
|
215
|
+
*/
|
|
216
|
+
BinaryNode.prototype.__insertion_findSiblingFor = function (box) {
|
|
217
|
+
|
|
218
|
+
const open_set = [this];
|
|
219
|
+
let cursor = 1;
|
|
220
|
+
|
|
221
|
+
let best_cost = Infinity;
|
|
222
|
+
let best_node = this;
|
|
223
|
+
|
|
224
|
+
while (cursor > 0) {
|
|
225
|
+
const node = open_set[--cursor];
|
|
226
|
+
|
|
227
|
+
const cost = inclusion_surface_area_heuristic(node, box);
|
|
228
|
+
|
|
229
|
+
if (cost < best_cost) {
|
|
230
|
+
best_cost = cost;
|
|
231
|
+
best_node = node;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
if (node.isBinaryNode) {
|
|
235
|
+
|
|
236
|
+
if (node.isProtected()) {
|
|
237
|
+
continue;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// consider pushing children into the queue
|
|
241
|
+
|
|
242
|
+
// compute lower bound for cost
|
|
243
|
+
const c_low = inclusion_cost_lower_bound(node, box);
|
|
244
|
+
|
|
245
|
+
if (c_low < best_cost) {
|
|
246
|
+
// worth-while to explore children
|
|
247
|
+
if (node.left !== null) {
|
|
248
|
+
open_set[cursor++] = node.left;
|
|
249
|
+
}
|
|
250
|
+
if (node.right !== null) {
|
|
251
|
+
open_set[cursor++] = node.right
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
return best_node;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
*
|
|
264
|
+
* @param {AABB3} box
|
|
265
|
+
* @returns {Node|BinaryNode|LeafNode}
|
|
146
266
|
*/
|
|
147
267
|
BinaryNode.prototype.findParentFor = function (box) {
|
|
148
268
|
let n = this;
|
|
269
|
+
let aCost = 0;
|
|
270
|
+
let bCost = 0;
|
|
149
271
|
|
|
150
272
|
for (; ;) {
|
|
151
273
|
|
|
@@ -181,8 +303,8 @@ BinaryNode.prototype.findParentFor = function (box) {
|
|
|
181
303
|
}
|
|
182
304
|
}
|
|
183
305
|
|
|
184
|
-
|
|
185
|
-
|
|
306
|
+
aCost = a.costForInclusion(box);
|
|
307
|
+
bCost = b.costForInclusion(box);
|
|
186
308
|
|
|
187
309
|
if (aCost === bCost) {
|
|
188
310
|
|
|
@@ -196,9 +318,9 @@ BinaryNode.prototype.findParentFor = function (box) {
|
|
|
196
318
|
|
|
197
319
|
}
|
|
198
320
|
|
|
199
|
-
//change costs to be
|
|
200
|
-
aCost = a.
|
|
201
|
-
bCost = b.
|
|
321
|
+
//change costs to be based on balance
|
|
322
|
+
aCost = a.leafNodeCount / boxSurfaceArea2(a);
|
|
323
|
+
bCost = b.leafNodeCount / boxSurfaceArea2(b);
|
|
202
324
|
}
|
|
203
325
|
|
|
204
326
|
if (aCost === bCost) {
|
|
@@ -419,11 +541,12 @@ BinaryNode.prototype.bubbleRefit = function () {
|
|
|
419
541
|
n = n.parentNode;
|
|
420
542
|
|
|
421
543
|
if (n === null) {
|
|
544
|
+
// hit the root
|
|
422
545
|
return;
|
|
423
546
|
}
|
|
424
547
|
|
|
425
|
-
//check if this node violates bounds of the parent
|
|
426
548
|
|
|
549
|
+
//check if this node violates bounds of the parent
|
|
427
550
|
let flag = false;
|
|
428
551
|
|
|
429
552
|
if (_x0 < n.x0) {
|
|
@@ -518,26 +641,29 @@ function countLeaves(node) {
|
|
|
518
641
|
}
|
|
519
642
|
|
|
520
643
|
/**
|
|
521
|
-
*
|
|
644
|
+
* @deprecated Incorrect usage of SAH
|
|
522
645
|
* @return {number}
|
|
523
646
|
*/
|
|
524
647
|
BinaryNode.prototype.computeSAH = function () {
|
|
525
648
|
let leftLeaves, rightLeaves, leftArea, rightArea;
|
|
526
649
|
|
|
527
|
-
|
|
650
|
+
const left = this.left;
|
|
651
|
+
|
|
652
|
+
if (left === null) {
|
|
528
653
|
leftArea = 0;
|
|
529
654
|
leftLeaves = 0;
|
|
530
655
|
} else {
|
|
531
|
-
leftArea = boxSurfaceArea2(
|
|
532
|
-
leftLeaves =
|
|
656
|
+
leftArea = boxSurfaceArea2(left);
|
|
657
|
+
leftLeaves = left.leafNodeCount;
|
|
533
658
|
}
|
|
534
659
|
|
|
535
|
-
|
|
660
|
+
const right = this.right;
|
|
661
|
+
if (right === null) {
|
|
536
662
|
rightArea = 0;
|
|
537
663
|
rightLeaves = 0;
|
|
538
664
|
} else {
|
|
539
|
-
rightArea = boxSurfaceArea2(
|
|
540
|
-
rightLeaves =
|
|
665
|
+
rightArea = boxSurfaceArea2(right);
|
|
666
|
+
rightLeaves = right.leafNodeCount;
|
|
541
667
|
}
|
|
542
668
|
|
|
543
669
|
const thisArea = boxSurfaceArea2(this);
|
|
@@ -546,37 +672,37 @@ BinaryNode.prototype.computeSAH = function () {
|
|
|
546
672
|
};
|
|
547
673
|
|
|
548
674
|
BinaryNode.prototype.updateLeafNodeCount = function () {
|
|
549
|
-
let
|
|
675
|
+
let node = this;
|
|
550
676
|
|
|
551
|
-
|
|
677
|
+
while (node !== null) {
|
|
678
|
+
let n = 0;
|
|
552
679
|
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
680
|
+
const right = node.right;
|
|
681
|
+
|
|
682
|
+
if (right !== null) {
|
|
683
|
+
if (right.isLeafNode) {
|
|
684
|
+
n++;
|
|
685
|
+
} else {
|
|
686
|
+
n += right.leafNodeCount;
|
|
687
|
+
}
|
|
558
688
|
}
|
|
559
|
-
}
|
|
560
689
|
|
|
561
|
-
|
|
690
|
+
const left = this.left;
|
|
562
691
|
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
692
|
+
if (left !== null) {
|
|
693
|
+
if (left.isLeafNode) {
|
|
694
|
+
n++;
|
|
695
|
+
} else {
|
|
696
|
+
n += left.leafNodeCount;
|
|
697
|
+
}
|
|
568
698
|
}
|
|
569
|
-
}
|
|
570
699
|
|
|
571
|
-
|
|
700
|
+
node.leafNodeCount = n;
|
|
572
701
|
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
if (parentNode !== null) {
|
|
577
|
-
// bubble up
|
|
578
|
-
parentNode.updateLeafNodeCount();
|
|
702
|
+
// propagate update up the tree
|
|
703
|
+
node = node.parentNode;
|
|
579
704
|
}
|
|
705
|
+
|
|
580
706
|
}
|
|
581
707
|
|
|
582
708
|
|
|
@@ -1024,19 +1150,18 @@ BinaryNode.prototype.computeBalanceFactor = function () {
|
|
|
1024
1150
|
};
|
|
1025
1151
|
|
|
1026
1152
|
/**
|
|
1027
|
-
*
|
|
1153
|
+
* @template T
|
|
1028
1154
|
* @param {number} x0
|
|
1029
1155
|
* @param {number} y0
|
|
1030
1156
|
* @param {number} z0
|
|
1031
1157
|
* @param {number} x1
|
|
1032
1158
|
* @param {number} y1
|
|
1033
1159
|
* @param {number} z1
|
|
1034
|
-
* @param {
|
|
1160
|
+
* @param {T} value
|
|
1035
1161
|
* @returns {LeafNode}
|
|
1036
1162
|
*/
|
|
1037
1163
|
BinaryNode.prototype.insert = function (x0, y0, z0, x1, y1, z1, value) {
|
|
1038
|
-
const leaf = new LeafNode(value);
|
|
1039
|
-
leaf.setBounds(x0, y0, z0, x1, y1, z1);
|
|
1164
|
+
const leaf = new LeafNode(value, x0, y0, z0, x1, y1, z1);
|
|
1040
1165
|
this.insertNode(leaf);
|
|
1041
1166
|
return leaf;
|
|
1042
1167
|
};
|
|
@@ -1065,6 +1190,8 @@ function transplantNewCommonParent(node, child) {
|
|
|
1065
1190
|
|
|
1066
1191
|
parent.bubbleExpandToFit(bNode);
|
|
1067
1192
|
|
|
1193
|
+
parent.updateLeafNodeCount();
|
|
1194
|
+
|
|
1068
1195
|
return bNode;
|
|
1069
1196
|
}
|
|
1070
1197
|
|
|
@@ -1073,51 +1200,60 @@ function transplantNewCommonParent(node, child) {
|
|
|
1073
1200
|
* @param {Node|BinaryNode|LeafNode} child
|
|
1074
1201
|
*/
|
|
1075
1202
|
BinaryNode.prototype.insertNode = function (child) {
|
|
1076
|
-
|
|
1077
|
-
assert.
|
|
1078
|
-
assert.
|
|
1203
|
+
|
|
1204
|
+
assert.notNull(child, "child");
|
|
1205
|
+
assert.defined(child, "child");
|
|
1206
|
+
assert.isInstanceOf(child, Node, 'child', "Node");
|
|
1079
1207
|
assert.equal(child.parentNode, null, "parentNode must be null, otherwise Node still belongs to another tree");
|
|
1080
1208
|
|
|
1081
|
-
const
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
child
|
|
1091
|
-
node.bubbleExpandToFit(child);
|
|
1092
|
-
} else if (node.right === null) {
|
|
1093
|
-
node.right = child;
|
|
1094
|
-
child.parentNode = node;
|
|
1095
|
-
node.bubbleExpandToFit(child);
|
|
1209
|
+
const sibling = this.__insertion_findSiblingFor(child);
|
|
1210
|
+
|
|
1211
|
+
const sibling_parent = sibling.parentNode;
|
|
1212
|
+
if (sibling_parent === null) {
|
|
1213
|
+
// root node
|
|
1214
|
+
|
|
1215
|
+
if (sibling.left === null) {
|
|
1216
|
+
sibling.setChildLeft(child);
|
|
1217
|
+
} else if (sibling.right === null) {
|
|
1218
|
+
sibling.setChildRight(child);
|
|
1096
1219
|
} else {
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
bNode.parentNode = node;
|
|
1103
|
-
node.bubbleExpandToFit(bNode);
|
|
1220
|
+
const parent = new BinaryNode();
|
|
1221
|
+
|
|
1222
|
+
parent.setChildren(sibling.right, child);
|
|
1223
|
+
sibling.right = parent;
|
|
1224
|
+
parent.parentNode = sibling;
|
|
1104
1225
|
}
|
|
1105
1226
|
|
|
1106
|
-
node.updateLeafNodeCount();
|
|
1107
1227
|
} else {
|
|
1108
|
-
//need to do transplanting and introduce a new common parent
|
|
1109
|
-
bNode = transplantNewCommonParent(node, child);
|
|
1110
1228
|
|
|
1111
|
-
|
|
1112
|
-
}
|
|
1229
|
+
// non-root
|
|
1113
1230
|
|
|
1114
|
-
|
|
1231
|
+
if (sibling_parent.left === sibling && sibling_parent.right === null) {
|
|
1232
|
+
|
|
1233
|
+
// right node is free, take it
|
|
1234
|
+
sibling_parent.setChildRight(child);
|
|
1235
|
+
|
|
1236
|
+
} else if (sibling_parent.right === sibling && sibling_parent.left === null) {
|
|
1237
|
+
|
|
1238
|
+
// left node is free, take it
|
|
1239
|
+
sibling_parent.setChildLeft(child);
|
|
1240
|
+
|
|
1241
|
+
} else {
|
|
1242
|
+
|
|
1243
|
+
transplantNewCommonParent(sibling, child)
|
|
1244
|
+
|
|
1245
|
+
}
|
|
1246
|
+
|
|
1247
|
+
sibling_parent.bubbleRefit();
|
|
1248
|
+
|
|
1249
|
+
}
|
|
1250
|
+
}
|
|
1115
1251
|
|
|
1116
1252
|
/**
|
|
1117
|
-
*
|
|
1253
|
+
* @param {boolean} deep
|
|
1118
1254
|
* @returns {BinaryNode}
|
|
1119
1255
|
*/
|
|
1120
|
-
BinaryNode.prototype.clone = function (deep) {
|
|
1256
|
+
BinaryNode.prototype.clone = function (deep = false) {
|
|
1121
1257
|
const clone = new BinaryNode();
|
|
1122
1258
|
|
|
1123
1259
|
clone.x0 = this.x0;
|
package/core/bvh2/Node.d.ts
CHANGED
package/core/bvh2/aabb3/AABB3.js
CHANGED
|
@@ -6,9 +6,10 @@
|
|
|
6
6
|
import { aabb3_computeDistanceAbovePlane } from "../../geom/3d/aabb/aabb3_computeDistanceAbovePlane.js";
|
|
7
7
|
import { computeAABB3PlaneSide } from "../../geom/3d/aabb/computeAABB3PlaneSide.js";
|
|
8
8
|
import computeMortonCode from "../../geom/3d/morton/Morton.js";
|
|
9
|
-
import {
|
|
9
|
+
import { boxSurfaceArea, intersectRay, intersectSegment } from "./AABB3Math.js";
|
|
10
10
|
import { aabb3_build_corners } from "../../geom/3d/aabb/aabb3_build_corners.js";
|
|
11
11
|
import { assert } from "../../assert.js";
|
|
12
|
+
import { aabb3_intersects_frustum_degree } from "./aabb3_intersects_frustum_degree.js";
|
|
12
13
|
|
|
13
14
|
|
|
14
15
|
/**
|
|
@@ -81,7 +82,7 @@ AABB3.prototype.computeMortonCode = function () {
|
|
|
81
82
|
* @returns {number}
|
|
82
83
|
*/
|
|
83
84
|
AABB3.prototype.computeSurfaceArea = function () {
|
|
84
|
-
return
|
|
85
|
+
return boxSurfaceArea(this.x0, this.y0, this.z0, this.x1, this.y1, this.z1);
|
|
85
86
|
};
|
|
86
87
|
|
|
87
88
|
/**
|
|
@@ -296,7 +297,8 @@ AABB3.prototype.costForInclusion = function (other) {
|
|
|
296
297
|
};
|
|
297
298
|
|
|
298
299
|
/**
|
|
299
|
-
*
|
|
300
|
+
* Surface area delta when including a given AABB
|
|
301
|
+
* 0 means that including a given AABB would not cause any change to total surface area
|
|
300
302
|
* @param {number} x0
|
|
301
303
|
* @param {number} y0
|
|
302
304
|
* @param {number} z0
|
|
@@ -834,7 +836,7 @@ AABB3.prototype.intersectFrustumDegree = function (frustum) {
|
|
|
834
836
|
|
|
835
837
|
let i = 0;
|
|
836
838
|
let result = 2;
|
|
837
|
-
for (
|
|
839
|
+
for (; i < 6; i++) {
|
|
838
840
|
|
|
839
841
|
const plane = planes[i];
|
|
840
842
|
|
|
@@ -848,6 +850,16 @@ AABB3.prototype.intersectFrustumDegree = function (frustum) {
|
|
|
848
850
|
}
|
|
849
851
|
return result;
|
|
850
852
|
};
|
|
853
|
+
/**
|
|
854
|
+
*
|
|
855
|
+
* @param {number[]} frustum
|
|
856
|
+
* @returns {number}
|
|
857
|
+
*/
|
|
858
|
+
AABB3.prototype.intersectFrustumDegree_array = function (frustum) {
|
|
859
|
+
return aabb3_intersects_frustum_degree(
|
|
860
|
+
this.x0, this.y0, this.z0, this.x1, this.y1, this.z1, frustum
|
|
861
|
+
);
|
|
862
|
+
};
|
|
851
863
|
|
|
852
864
|
/**
|
|
853
865
|
*
|
|
@@ -866,6 +878,40 @@ AABB3.prototype.intersectFrustum = function intersectFrustum(frustum) {
|
|
|
866
878
|
return true;
|
|
867
879
|
};
|
|
868
880
|
|
|
881
|
+
/**
|
|
882
|
+
*
|
|
883
|
+
* @param {ArrayLike<number>|number[]|Float32Array}frustum
|
|
884
|
+
* @returns {boolean}
|
|
885
|
+
*/
|
|
886
|
+
AABB3.prototype.intersectFrustum_array = function intersectFrustum(frustum) {
|
|
887
|
+
const x0 = this.x0;
|
|
888
|
+
const y0 = this.y0;
|
|
889
|
+
const z0 = this.z0;
|
|
890
|
+
const x1 = this.x1;
|
|
891
|
+
const y1 = this.y1;
|
|
892
|
+
const z1 = this.z1;
|
|
893
|
+
|
|
894
|
+
for (let i = 0; i < 24; i += 4) {
|
|
895
|
+
|
|
896
|
+
const p_nx = frustum[i];
|
|
897
|
+
const p_ny = frustum[i + 1];
|
|
898
|
+
const p_nz = frustum[i + 2];
|
|
899
|
+
const p_c = frustum[i + 3];
|
|
900
|
+
|
|
901
|
+
if (aabb3_computeDistanceAbovePlane(
|
|
902
|
+
p_nx, p_ny, p_nz, p_c,
|
|
903
|
+
x0, y0, z0,
|
|
904
|
+
x1, y1, z1
|
|
905
|
+
) < 0) {
|
|
906
|
+
// below plane, i.e. outside of the frustum
|
|
907
|
+
return false;
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
}
|
|
911
|
+
return true;
|
|
912
|
+
};
|
|
913
|
+
|
|
914
|
+
|
|
869
915
|
/**
|
|
870
916
|
*
|
|
871
917
|
* @param {number} v
|
|
@@ -540,7 +540,7 @@ function boxSurfaceArea(x0, y0, z0, x1, y1, z1) {
|
|
|
540
540
|
const dx = x1 - x0;
|
|
541
541
|
const dy = y1 - y0;
|
|
542
542
|
const dz = z1 - z0;
|
|
543
|
-
return (
|
|
543
|
+
return (dy * (dx + dz) + dz * dx) * 2; //2 of each side
|
|
544
544
|
}
|
|
545
545
|
|
|
546
546
|
/**
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { min2 } from "../../math/min2.js";
|
|
2
|
+
import { max2 } from "../../math/max2.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
*
|
|
6
|
+
* @param {AABB3} result
|
|
7
|
+
* @param {number[]|ArrayLike<number>} input
|
|
8
|
+
* @param {number} input_length
|
|
9
|
+
*/
|
|
10
|
+
export function aabb3_from_v3_array(result, input, input_length) {
|
|
11
|
+
let x0 = Infinity;
|
|
12
|
+
let y0 = Infinity;
|
|
13
|
+
let z0 = Infinity;
|
|
14
|
+
|
|
15
|
+
let x1 = -Infinity;
|
|
16
|
+
let y1 = -Infinity;
|
|
17
|
+
let z1 = -Infinity;
|
|
18
|
+
|
|
19
|
+
for (let i = 0; i < input_length; i += 3) {
|
|
20
|
+
const x = input[i];
|
|
21
|
+
const y = input[i + 1];
|
|
22
|
+
const z = input[i + 2];
|
|
23
|
+
|
|
24
|
+
x0 = min2(x, x0);
|
|
25
|
+
y0 = min2(y, y0);
|
|
26
|
+
z0 = min2(z, z0);
|
|
27
|
+
|
|
28
|
+
x1 = max2(x, x1);
|
|
29
|
+
y1 = max2(y, y1);
|
|
30
|
+
z1 = max2(z, z1);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
result.setBounds(x0, y0, z0, x1, y1, z1);
|
|
34
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { min2 } from "../../math/min2.js";
|
|
2
|
+
import { max2 } from "../../math/max2.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
*
|
|
6
|
+
* @param {AABB3} result
|
|
7
|
+
* @param {number[]|ArrayLike<number>} input
|
|
8
|
+
* @param {number} input_length
|
|
9
|
+
* @param {ArrayLike<number>|number[]|Float32Array} e 4x4 transformation matrix
|
|
10
|
+
*/
|
|
11
|
+
export function aabb3_from_v3_array_transformed(result, input, input_length, e) {
|
|
12
|
+
let x0 = Infinity;
|
|
13
|
+
let y0 = Infinity;
|
|
14
|
+
let z0 = Infinity;
|
|
15
|
+
|
|
16
|
+
let x1 = -Infinity;
|
|
17
|
+
let y1 = -Infinity;
|
|
18
|
+
let z1 = -Infinity;
|
|
19
|
+
|
|
20
|
+
for (let i = 0; i < input_length; i += 3) {
|
|
21
|
+
const x = input[i];
|
|
22
|
+
const y = input[i + 1];
|
|
23
|
+
const z = input[i + 2];
|
|
24
|
+
|
|
25
|
+
const _x = e[0] * x + e[4] * y + e[8] * z + e[12];
|
|
26
|
+
const _y = e[1] * x + e[5] * y + e[9] * z + e[13];
|
|
27
|
+
const _z = e[2] * x + e[6] * y + e[10] * z + e[14];
|
|
28
|
+
|
|
29
|
+
x0 = min2(_x, x0);
|
|
30
|
+
y0 = min2(_y, y0);
|
|
31
|
+
z0 = min2(_z, z0);
|
|
32
|
+
|
|
33
|
+
x1 = max2(_x, x1);
|
|
34
|
+
y1 = max2(_y, y1);
|
|
35
|
+
z1 = max2(_z, z1);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
result.setBounds(x0, y0, z0, x1, y1, z1);
|
|
39
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
//
|
|
2
|
+
|
|
3
|
+
import { computeAABB3PlaneSide } from "../../geom/3d/aabb/computeAABB3PlaneSide.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
*
|
|
7
|
+
* @param {number} x0
|
|
8
|
+
* @param {number} y0
|
|
9
|
+
* @param {number} z0
|
|
10
|
+
* @param {number} x1
|
|
11
|
+
* @param {number} y1
|
|
12
|
+
* @param {number} z1
|
|
13
|
+
* @param {number[]} frustum
|
|
14
|
+
* @return {number}
|
|
15
|
+
*/
|
|
16
|
+
export function aabb3_intersects_frustum_degree(
|
|
17
|
+
x0, y0, z0,
|
|
18
|
+
x1, y1, z1,
|
|
19
|
+
frustum
|
|
20
|
+
) {
|
|
21
|
+
|
|
22
|
+
let i = 0;
|
|
23
|
+
let result = 2;
|
|
24
|
+
|
|
25
|
+
for (; i < 24; i += 4) {
|
|
26
|
+
|
|
27
|
+
const p_nx = frustum[i];
|
|
28
|
+
const p_ny = frustum[i + 1];
|
|
29
|
+
const p_nz = frustum[i + 2];
|
|
30
|
+
const p_c = frustum[i + 3];
|
|
31
|
+
|
|
32
|
+
const plane_side = computeAABB3PlaneSide(
|
|
33
|
+
p_nx, p_ny, p_nz, p_c,
|
|
34
|
+
x0, y0, z0, x1, y1, z1
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
if (plane_side < 0) {
|
|
38
|
+
// completely outside
|
|
39
|
+
return 0;
|
|
40
|
+
} else if (plane_side === 0) {
|
|
41
|
+
result = 1;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return result;
|
|
46
|
+
}
|