@woosh/meep-engine 2.68.0 → 2.70.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.
- package/build/bundle-worker-image-decoder.js +1 -1
- package/build/bundle-worker-terrain.js +1 -1
- package/build/meep.cjs +1090 -1581
- package/build/meep.min.js +1 -1
- package/build/meep.module.js +1090 -1581
- package/package.json +1 -1
- package/src/core/__module.js +1 -0
- package/src/core/binary/BinaryBuffer.js +37 -31
- package/src/core/bvh2/binary/2/BinaryUint32BVH.js +76 -52
- package/src/core/bvh2/binary/2/BinaryUint32BVH.spec.js +5 -7
- package/src/core/bvh2/binary/2/bvh32_query_user_data_overlaps_clipping_volume.js +94 -0
- package/src/core/bvh2/binary/2/bvh32_query_user_data_ray.js +17 -18
- package/src/core/bvh2/bvh3/query/BVHQueryIntersectsFrustum.js +4 -2
- package/src/core/geom/3d/aabb/AABB3.js +14 -14
- package/src/core/geom/3d/aabb/aabb3_array_intersects_clipping_volume_array.js +30 -0
- package/src/core/geom/3d/aabb/aabb3_intersects_clipping_volume_array.js +51 -0
- package/src/core/geom/3d/cone/compute_bounding_cone_of_2_cones.js +3 -2
- package/src/core/geom/3d/frustum/{read_frustum_planes_to_array.js → read_three_planes_to_array.js} +5 -3
- package/src/core/geom/3d/morton/v3_morton_encode_bounded.js +34 -0
- package/src/core/geom/3d/morton/v3_morton_encode_transformed.js +2 -1
- package/src/core/geom/3d/quaternion/quat3_createFromAxisAngle.js +11 -0
- package/src/core/geom/3d/quaternion/quat_decode_from_uint32.js +53 -0
- package/src/core/geom/3d/quaternion/quat_encode_to_uint32.js +106 -0
- package/src/core/geom/3d/triangle/triangle_intersects_clipping_volume.js +51 -0
- package/src/core/geom/Quaternion.js +8 -142
- package/src/core/geom/Vector2.js +6 -7
- package/src/core/geom/Vector3.js +15 -82
- package/src/core/geom/vec3/v3_binary_equality_decode.js +44 -0
- package/src/core/geom/vec3/v3_binary_equality_encode.js +47 -0
- package/src/core/primitives/numbers/computeHashFloat.js +2 -2
- package/src/engine/ecs/terrain/ecs/TerrainSystem.js +2 -2
- package/src/engine/ecs/terrain/ecs/makeTerrainWorkerProxy.js +1 -1
- package/src/engine/ecs/terrain/tiles/TerrainTile.js +9 -46
- package/src/engine/ecs/transform/Transform.js +8 -9
- package/src/engine/ecs/transform/TransformSerializationAdapter.js +18 -7
- package/src/engine/graphics/ecs/mesh/Mesh.js +11 -11
- package/src/engine/graphics/geometry/buffered/query/GeometrySpatialQueryAccelerator.d.ts +2 -2
- package/src/engine/graphics/geometry/buffered/query/GeometrySpatialQueryAccelerator.js +79 -36
- package/src/engine/graphics/geometry/buffered/query/bvh32_geometry_overlap_clipping_volume.js +88 -0
- package/src/engine/graphics/geometry/buffered/query/bvh32_geometry_raycast.js +108 -0
- package/src/engine/graphics/geometry/bvh/buffered/bvh32_from_indexed_geometry.js +4 -30
- package/src/engine/graphics/geometry/bvh/buffered/bvh32_from_unindexed_geometry.js +30 -0
- package/src/engine/graphics/geometry/bvh/buffered/bvh32_set_leaf_from_triangle.js +41 -0
- package/src/engine/graphics/render/forward_plus/LightManager.js +2 -2
- package/src/engine/graphics/render/forward_plus/query/query_bvh_frustum_from_texture.js +2 -2
- package/src/engine/graphics/render/view/CameraView.js +8 -8
- package/src/core/bvh2/binary/BinaryBVH.js +0 -281
- package/src/core/bvh2/binary/IndexedBinaryBVH.js +0 -407
- package/src/core/bvh2/binary/IndexedBinaryBVH.spec.js +0 -27
- package/src/core/bvh2/binary/IndexedBinaryBVHVisitor.js +0 -11
- package/src/core/bvh2/binary/NodeType.js +0 -8
- package/src/core/bvh2/binary/RayLeafIntersectionVisitor.js +0 -59
- package/src/core/geom/3d/aabb/aabb3_array_intersects_frustum_array.js +0 -20
- package/src/core/geom/3d/aabb/aabb3_intersects_frustum_array.js +0 -35
- package/src/engine/graphics/geometry/buffered/query/ClippingPlaneContainmentComputingVisitor.js +0 -195
- package/src/engine/graphics/geometry/buffered/query/GeometryVisitor.js +0 -87
- package/src/engine/graphics/geometry/buffered/query/RaycastNearestHitComputingVisitor.js +0 -206
- package/src/engine/graphics/geometry/bvh/buffered/BinaryBVHFromBufferGeometry.js +0 -123
package/package.json
CHANGED
package/src/core/__module.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { assert } from "../assert.js";
|
|
6
6
|
import { array_copy } from "../collection/array/array_copy.js";
|
|
7
|
+
import { typed_array_copy } from "../collection/array/typed/typed_array_copy.js";
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
*
|
|
@@ -142,8 +143,7 @@ export class BinaryBuffer {
|
|
|
142
143
|
const newData = new Uint8Array(capacity);
|
|
143
144
|
|
|
144
145
|
//copy old data
|
|
145
|
-
|
|
146
|
-
newData.set(oldData.subarray(0, copyLength), 0);
|
|
146
|
+
typed_array_copy(oldData, newData);
|
|
147
147
|
|
|
148
148
|
this.data = newData.buffer;
|
|
149
149
|
this.__data_uint8 = newData;
|
|
@@ -152,15 +152,24 @@ export class BinaryBuffer {
|
|
|
152
152
|
this.capacity = capacity;
|
|
153
153
|
}
|
|
154
154
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
155
|
+
/**
|
|
156
|
+
*
|
|
157
|
+
* @param {number} min_capacity
|
|
158
|
+
*/
|
|
159
|
+
ensureCapacity(min_capacity) {
|
|
160
|
+
const existing_capacity = this.capacity;
|
|
161
|
+
|
|
162
|
+
if (existing_capacity >= min_capacity) {
|
|
163
|
+
return;
|
|
163
164
|
}
|
|
165
|
+
|
|
166
|
+
const new_capacity = Math.ceil(Math.max(
|
|
167
|
+
min_capacity,
|
|
168
|
+
existing_capacity * this.__growFactor,
|
|
169
|
+
existing_capacity + MIN_GROWTH_STEP
|
|
170
|
+
));
|
|
171
|
+
|
|
172
|
+
this.setCapacity(new_capacity);
|
|
164
173
|
}
|
|
165
174
|
|
|
166
175
|
readFloat32() {
|
|
@@ -825,16 +834,14 @@ export class BinaryBuffer {
|
|
|
825
834
|
//mark non-NULL
|
|
826
835
|
this.writeUint32(len);
|
|
827
836
|
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
let at = startPosition; // output position
|
|
831
|
-
|
|
832
|
-
let tlen = Math.max(32, len + (len >> 1) + 7); // 1.5x size
|
|
837
|
+
let cursor = this.position; // output position
|
|
833
838
|
|
|
834
|
-
|
|
839
|
+
const expected_byte_size = Math.max(32, len + (len >> 1) + 7); // 1.5x size
|
|
835
840
|
|
|
836
|
-
|
|
841
|
+
this.ensureCapacity(expected_byte_size + cursor);
|
|
837
842
|
|
|
843
|
+
let target = this.__data_uint8;
|
|
844
|
+
let capacity = this.capacity;
|
|
838
845
|
|
|
839
846
|
while (pos < len) {
|
|
840
847
|
let value = string.charCodeAt(pos++);
|
|
@@ -853,37 +860,36 @@ export class BinaryBuffer {
|
|
|
853
860
|
}
|
|
854
861
|
|
|
855
862
|
// expand the buffer if we couldn't write 4 bytes
|
|
856
|
-
if (
|
|
857
|
-
tlen += 8; // minimum extra
|
|
858
|
-
tlen *= (1.0 + (pos / len) * 2); // take 2x the remaining
|
|
859
|
-
tlen = (tlen >> 3) << 3; // 8 byte offset
|
|
863
|
+
if (cursor + 4 > capacity) {
|
|
860
864
|
|
|
861
|
-
this.ensureCapacity(
|
|
865
|
+
this.ensureCapacity(cursor + 4);
|
|
862
866
|
|
|
867
|
+
// rebind variables
|
|
868
|
+
capacity = this.capacity;
|
|
863
869
|
target = this.__data_uint8;
|
|
864
870
|
}
|
|
865
871
|
|
|
866
872
|
if ((value & 0xffffff80) === 0) { // 1-byte
|
|
867
|
-
target[
|
|
873
|
+
target[cursor++] = value; // ASCII
|
|
868
874
|
continue;
|
|
869
875
|
} else if ((value & 0xfffff800) === 0) { // 2-byte
|
|
870
|
-
target[
|
|
876
|
+
target[cursor++] = ((value >> 6) & 0x1f) | 0xc0;
|
|
871
877
|
} else if ((value & 0xffff0000) === 0) { // 3-byte
|
|
872
|
-
target[
|
|
873
|
-
target[
|
|
878
|
+
target[cursor++] = ((value >> 12) & 0x0f) | 0xe0;
|
|
879
|
+
target[cursor++] = ((value >> 6) & 0x3f) | 0x80;
|
|
874
880
|
} else if ((value & 0xffe00000) === 0) { // 4-byte
|
|
875
|
-
target[
|
|
876
|
-
target[
|
|
877
|
-
target[
|
|
881
|
+
target[cursor++] = ((value >> 18) & 0x07) | 0xf0;
|
|
882
|
+
target[cursor++] = ((value >> 12) & 0x3f) | 0x80;
|
|
883
|
+
target[cursor++] = ((value >> 6) & 0x3f) | 0x80;
|
|
878
884
|
} else {
|
|
879
885
|
// FIXME: do we care
|
|
880
886
|
continue;
|
|
881
887
|
}
|
|
882
888
|
|
|
883
|
-
target[
|
|
889
|
+
target[cursor++] = (value & 0x3f) | 0x80;
|
|
884
890
|
}
|
|
885
891
|
|
|
886
|
-
this.position =
|
|
892
|
+
this.position = cursor;
|
|
887
893
|
}
|
|
888
894
|
|
|
889
895
|
/**
|
|
@@ -2,10 +2,11 @@ import { assert } from "../../../assert.js";
|
|
|
2
2
|
import { ceilPowerOfTwo } from "../../../binary/operations/ceilPowerOfTwo.js";
|
|
3
3
|
import { array_copy } from "../../../collection/array/array_copy.js";
|
|
4
4
|
import { array_swap } from "../../../collection/array/array_swap.js";
|
|
5
|
+
import { SCRATCH_UINT32_TRAVERSAL_STACK } from "../../../collection/SCRATCH_UINT32_TRAVERSAL_STACK.js";
|
|
5
6
|
import { aabb3_array_combine } from "../../../geom/3d/aabb/aabb3_array_combine.js";
|
|
6
7
|
import { aabb3_array_set } from "../../../geom/3d/aabb/aabb3_array_set.js";
|
|
7
8
|
import { aabb3_compute_half_surface_area } from "../../../geom/3d/aabb/aabb3_compute_half_surface_area.js";
|
|
8
|
-
import {
|
|
9
|
+
import { v3_morton_encode_bounded } from "../../../geom/3d/morton/v3_morton_encode_bounded.js";
|
|
9
10
|
import { max2 } from "../../../math/max2.js";
|
|
10
11
|
import { max3 } from "../../../math/max3.js";
|
|
11
12
|
import { min2 } from "../../../math/min2.js";
|
|
@@ -54,10 +55,10 @@ function copy_box_zero_size(data, destination, source) {
|
|
|
54
55
|
* Assumes data will be normalized to 0...1 value range
|
|
55
56
|
* @param {Float32Array} data
|
|
56
57
|
* @param {number} address
|
|
57
|
-
* @param {number[]}
|
|
58
|
+
* @param {number[]} bounds
|
|
58
59
|
* @returns {number}
|
|
59
60
|
*/
|
|
60
|
-
function build_morton(data, address,
|
|
61
|
+
function build_morton(data, address, bounds) {
|
|
61
62
|
|
|
62
63
|
const x0 = data[address];
|
|
63
64
|
const y0 = data[address + 1];
|
|
@@ -66,17 +67,15 @@ function build_morton(data, address, matrix) {
|
|
|
66
67
|
const y1 = data[address + 4];
|
|
67
68
|
const z1 = data[address + 5];
|
|
68
69
|
|
|
69
|
-
const cx = (x0 + x1)
|
|
70
|
-
const cy = (y0 + y1)
|
|
71
|
-
const cz = (z0 + z1)
|
|
70
|
+
const cx = (x0 + x1) * 0.5;
|
|
71
|
+
const cy = (y0 + y1) * 0.5;
|
|
72
|
+
const cz = (z0 + z1) * 0.5;
|
|
72
73
|
|
|
73
|
-
return
|
|
74
|
-
// return v3_morton_encode_transformed(cx, cy, cz, matrix);
|
|
74
|
+
return v3_morton_encode_bounded(cx, cy, cz, bounds);
|
|
75
75
|
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
-
const
|
|
79
|
-
const stack = [];
|
|
78
|
+
const stack = SCRATCH_UINT32_TRAVERSAL_STACK;
|
|
80
79
|
|
|
81
80
|
export class BinaryUint32BVH {
|
|
82
81
|
/**
|
|
@@ -100,34 +99,41 @@ export class BinaryUint32BVH {
|
|
|
100
99
|
*/
|
|
101
100
|
__data_uint32;
|
|
102
101
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
*/
|
|
110
|
-
this.__node_count_binary = 0;
|
|
102
|
+
/**
|
|
103
|
+
*
|
|
104
|
+
* @type {number}
|
|
105
|
+
* @private
|
|
106
|
+
*/
|
|
107
|
+
__node_count_binary = 0;
|
|
111
108
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
109
|
+
/**
|
|
110
|
+
*
|
|
111
|
+
* @type {number}
|
|
112
|
+
* @private
|
|
113
|
+
*/
|
|
114
|
+
__node_count_leaf = 0;
|
|
118
115
|
|
|
116
|
+
constructor() {
|
|
119
117
|
this.data = new ArrayBuffer(320);
|
|
120
118
|
}
|
|
121
119
|
|
|
120
|
+
/**
|
|
121
|
+
* In bytes
|
|
122
|
+
* @returns {number}
|
|
123
|
+
*/
|
|
124
|
+
estimateByteSize() {
|
|
125
|
+
return this.data.byteLength + 248;
|
|
126
|
+
}
|
|
127
|
+
|
|
122
128
|
getTotalBoxCount() {
|
|
123
129
|
return this.__node_count_binary + this.__node_count_leaf;
|
|
124
130
|
}
|
|
125
131
|
|
|
126
|
-
|
|
132
|
+
get binary_node_count() {
|
|
127
133
|
return this.__node_count_binary;
|
|
128
134
|
}
|
|
129
135
|
|
|
130
|
-
|
|
136
|
+
get leaf_node_count() {
|
|
131
137
|
return this.__node_count_leaf;
|
|
132
138
|
}
|
|
133
139
|
|
|
@@ -149,10 +155,12 @@ export class BinaryUint32BVH {
|
|
|
149
155
|
|
|
150
156
|
/**
|
|
151
157
|
*
|
|
152
|
-
* @param {ArrayBuffer}
|
|
158
|
+
* @param {ArrayBuffer} buffer
|
|
153
159
|
*/
|
|
154
|
-
set data(
|
|
155
|
-
|
|
160
|
+
set data(buffer) {
|
|
161
|
+
assert.defined(buffer, 'buffer');
|
|
162
|
+
|
|
163
|
+
this.__data_buffer = buffer;
|
|
156
164
|
|
|
157
165
|
this.__data_float32 = new Float32Array(this.__data_buffer);
|
|
158
166
|
this.__data_uint32 = new Uint32Array(this.__data_buffer);
|
|
@@ -162,6 +170,24 @@ export class BinaryUint32BVH {
|
|
|
162
170
|
return this.__data_buffer;
|
|
163
171
|
}
|
|
164
172
|
|
|
173
|
+
/**
|
|
174
|
+
* Resolve index of the node to address where the node data starts, this is required to know where AABB is stored in memory
|
|
175
|
+
* @param {number} node_index
|
|
176
|
+
* @returns {number}
|
|
177
|
+
*/
|
|
178
|
+
getNodeAddress(node_index) {
|
|
179
|
+
const binary_node_count = this.__node_count_binary;
|
|
180
|
+
const leaf_node_index = node_index - binary_node_count;
|
|
181
|
+
|
|
182
|
+
if (leaf_node_index < 0) {
|
|
183
|
+
// binary node
|
|
184
|
+
return node_index * BVH_BINARY_NODE_SIZE;
|
|
185
|
+
} else {
|
|
186
|
+
// leaf node
|
|
187
|
+
return binary_node_count * BVH_BINARY_NODE_SIZE + leaf_node_index * BVH_LEAF_NODE_SIZE;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
165
191
|
initialize_structure() {
|
|
166
192
|
// compute memory requirements
|
|
167
193
|
const word_count = this.__node_count_binary * BVH_BINARY_NODE_SIZE + this.__node_count_leaf * BVH_LEAF_NODE_SIZE;
|
|
@@ -280,17 +306,15 @@ export class BinaryUint32BVH {
|
|
|
280
306
|
* @private
|
|
281
307
|
*/
|
|
282
308
|
__compute_bounds_area_of_3_boxes(a, b, c) {
|
|
283
|
-
this.
|
|
284
|
-
this.readBounds(b, scratch_box_0, 6);
|
|
285
|
-
this.readBounds(c, scratch_box_0, 12);
|
|
309
|
+
const float32 = this.__data_float32;
|
|
286
310
|
|
|
287
|
-
const x0 = min3(
|
|
288
|
-
const y0 = min3(
|
|
289
|
-
const z0 = min3(
|
|
311
|
+
const x0 = min3(float32[a + 0], float32[b + 0], float32[c + 0]);
|
|
312
|
+
const y0 = min3(float32[a + 1], float32[b + 1], float32[c + 1]);
|
|
313
|
+
const z0 = min3(float32[a + 2], float32[b + 2], float32[c + 2]);
|
|
290
314
|
|
|
291
|
-
const x1 = max3(
|
|
292
|
-
const y1 = max3(
|
|
293
|
-
const z1 = max3(
|
|
315
|
+
const x1 = max3(float32[a + 3], float32[b + 3], float32[c + 3]);
|
|
316
|
+
const y1 = max3(float32[a + 4], float32[b + 4], float32[c + 4]);
|
|
317
|
+
const z1 = max3(float32[a + 5], float32[b + 5], float32[c + 5]);
|
|
294
318
|
|
|
295
319
|
return aabb3_compute_half_surface_area(x0, y0, z0, x1, y1, z1);
|
|
296
320
|
}
|
|
@@ -342,9 +366,9 @@ export class BinaryUint32BVH {
|
|
|
342
366
|
|
|
343
367
|
/**
|
|
344
368
|
* Sort leaf nodes according to their morton codes
|
|
345
|
-
* @param {number[]}
|
|
369
|
+
* @param {number[]} bounds
|
|
346
370
|
*/
|
|
347
|
-
sort_morton(
|
|
371
|
+
sort_morton(bounds) {
|
|
348
372
|
|
|
349
373
|
const leaf_block_address = this.__node_count_binary * BVH_BINARY_NODE_SIZE;
|
|
350
374
|
|
|
@@ -374,15 +398,15 @@ export class BinaryUint32BVH {
|
|
|
374
398
|
|
|
375
399
|
const pivot_address = pivotIndex * BVH_LEAF_NODE_SIZE + leaf_block_address;
|
|
376
400
|
|
|
377
|
-
const pivot = build_morton(data, pivot_address,
|
|
401
|
+
const pivot = build_morton(data, pivot_address, bounds);
|
|
378
402
|
|
|
379
403
|
/* partition */
|
|
380
404
|
while (i <= j) {
|
|
381
|
-
while (build_morton(data, i * BVH_LEAF_NODE_SIZE + leaf_block_address,
|
|
405
|
+
while (build_morton(data, i * BVH_LEAF_NODE_SIZE + leaf_block_address, bounds) < pivot) {
|
|
382
406
|
i++;
|
|
383
407
|
}
|
|
384
408
|
|
|
385
|
-
while (build_morton(data, j * BVH_LEAF_NODE_SIZE + leaf_block_address,
|
|
409
|
+
while (build_morton(data, j * BVH_LEAF_NODE_SIZE + leaf_block_address, bounds) > pivot) {
|
|
386
410
|
j--;
|
|
387
411
|
}
|
|
388
412
|
|
|
@@ -452,22 +476,22 @@ export class BinaryUint32BVH {
|
|
|
452
476
|
|
|
453
477
|
// build bottom-most level, just above the leaves
|
|
454
478
|
for (i = 0; i < level_node_count; i++) {
|
|
455
|
-
const
|
|
456
|
-
const
|
|
479
|
+
const leaf_index_0 = i * 2;
|
|
480
|
+
const leaf_index_1 = leaf_index_0 + 1;
|
|
457
481
|
|
|
458
|
-
const
|
|
459
|
-
const
|
|
482
|
+
const leaf_offset_0 = leaf_node_block_address + leaf_index_0 * BVH_LEAF_NODE_SIZE;
|
|
483
|
+
const leaf_offset_1 = leaf_node_block_address + leaf_index_1 * BVH_LEAF_NODE_SIZE;
|
|
460
484
|
|
|
461
|
-
if (
|
|
485
|
+
if (leaf_index_1 < node_count_leaf) {
|
|
462
486
|
// both children nodes are valid
|
|
463
487
|
aabb3_array_combine(
|
|
464
488
|
float32, offset,
|
|
465
|
-
float32,
|
|
466
|
-
float32,
|
|
489
|
+
float32, leaf_offset_0,
|
|
490
|
+
float32, leaf_offset_1
|
|
467
491
|
);
|
|
468
|
-
} else if (
|
|
492
|
+
} else if (leaf_index_0 < node_count_leaf) {
|
|
469
493
|
// only left child node is valid
|
|
470
|
-
array_copy(float32,
|
|
494
|
+
array_copy(float32, leaf_offset_0, float32, offset, 6);
|
|
471
495
|
} else {
|
|
472
496
|
//initialize to 0-size box same position as previous node
|
|
473
497
|
copy_box_zero_size(this.__data_float32, offset, (offset - BVH_BINARY_NODE_SIZE));
|
|
@@ -19,7 +19,7 @@ test('0 leaf tree must have a no binary nodes', () => {
|
|
|
19
19
|
bvh.initialize_structure();
|
|
20
20
|
bvh.build();
|
|
21
21
|
|
|
22
|
-
expect(bvh.
|
|
22
|
+
expect(bvh.binary_node_count).toBe(0);
|
|
23
23
|
});
|
|
24
24
|
|
|
25
25
|
test('1 leaf tree must have a single binary node', () => {
|
|
@@ -29,7 +29,7 @@ test('1 leaf tree must have a single binary node', () => {
|
|
|
29
29
|
bvh.initialize_structure();
|
|
30
30
|
bvh.build();
|
|
31
31
|
|
|
32
|
-
expect(bvh.
|
|
32
|
+
expect(bvh.binary_node_count).toBe(1);
|
|
33
33
|
});
|
|
34
34
|
|
|
35
35
|
test('4 leaf tree must have a 3 binary nodes', () => {
|
|
@@ -39,7 +39,7 @@ test('4 leaf tree must have a 3 binary nodes', () => {
|
|
|
39
39
|
bvh.initialize_structure();
|
|
40
40
|
bvh.build();
|
|
41
41
|
|
|
42
|
-
expect(bvh.
|
|
42
|
+
expect(bvh.binary_node_count).toBe(3);
|
|
43
43
|
});
|
|
44
44
|
|
|
45
45
|
test('read/write 1 leaf', () => {
|
|
@@ -129,10 +129,8 @@ test('4 node sorted build', () => {
|
|
|
129
129
|
bvh.setLeafData(3, 13, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6);
|
|
130
130
|
|
|
131
131
|
bvh.sort_morton([
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
0, 0, 1, 0,
|
|
135
|
-
0, 0, 0, 1
|
|
132
|
+
0, 0, 0,
|
|
133
|
+
1, 1, 1
|
|
136
134
|
]);
|
|
137
135
|
bvh.build();
|
|
138
136
|
});
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { SCRATCH_UINT32_TRAVERSAL_STACK } from "../../../collection/SCRATCH_UINT32_TRAVERSAL_STACK.js";
|
|
2
|
+
import {
|
|
3
|
+
aabb3_array_intersects_clipping_volume_array
|
|
4
|
+
} from "../../../geom/3d/aabb/aabb3_array_intersects_clipping_volume_array.js";
|
|
5
|
+
|
|
6
|
+
const stack = SCRATCH_UINT32_TRAVERSAL_STACK;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
*
|
|
10
|
+
* @param {number[]} result
|
|
11
|
+
* @param {number} result_offset
|
|
12
|
+
* @param {BinaryUint32BVH} bvh
|
|
13
|
+
* @param {Float32Array|number[]} planes
|
|
14
|
+
* @param {number} planes_offset
|
|
15
|
+
* @param {number} plane_count
|
|
16
|
+
* @returns {number}
|
|
17
|
+
*/
|
|
18
|
+
export function bvh32_query_user_data_overlaps_clipping_volume(
|
|
19
|
+
result, result_offset,
|
|
20
|
+
bvh,
|
|
21
|
+
planes, planes_offset, plane_count
|
|
22
|
+
) {
|
|
23
|
+
let hit_count = 0;
|
|
24
|
+
|
|
25
|
+
const binary_node_count = bvh.binary_node_count;
|
|
26
|
+
|
|
27
|
+
if (binary_node_count <= 0) {
|
|
28
|
+
// this should not happen
|
|
29
|
+
return 0;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
*
|
|
34
|
+
* @type {number}
|
|
35
|
+
*/
|
|
36
|
+
const stack_top = stack.pointer++;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* After performing empirical tests, stack-based depth-first traversal turns out faster than using a queue
|
|
40
|
+
* @type {number}
|
|
41
|
+
*/
|
|
42
|
+
stack[stack_top] = 0;
|
|
43
|
+
|
|
44
|
+
const last_valid_index = binary_node_count + bvh.leaf_node_count;
|
|
45
|
+
|
|
46
|
+
const float32 = bvh.float32;
|
|
47
|
+
const uint32 = bvh.uint32;
|
|
48
|
+
|
|
49
|
+
do {
|
|
50
|
+
stack.pointer--;
|
|
51
|
+
|
|
52
|
+
// query_bvh_frustum_from_objects.iteration_count++;
|
|
53
|
+
const node_index = stack[stack.pointer];
|
|
54
|
+
|
|
55
|
+
const node_address = bvh.getNodeAddress(node_index);
|
|
56
|
+
|
|
57
|
+
if (!aabb3_array_intersects_clipping_volume_array(
|
|
58
|
+
float32, node_address,
|
|
59
|
+
planes, planes_offset, plane_count
|
|
60
|
+
)) {
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const is_intermediate_node = node_index < binary_node_count;
|
|
65
|
+
|
|
66
|
+
if (is_intermediate_node) {
|
|
67
|
+
// is intermediate node
|
|
68
|
+
|
|
69
|
+
const left_index = (node_index << 1) + 1;
|
|
70
|
+
const right_index = left_index + 1;
|
|
71
|
+
|
|
72
|
+
// left node ends up on top of the stack, which aligns with the desired access sequence
|
|
73
|
+
if (right_index < last_valid_index) {
|
|
74
|
+
stack[stack.pointer++] = right_index;
|
|
75
|
+
// micro-optimization, since we know that right node is valid and left appears before that, left is valid too
|
|
76
|
+
stack[stack.pointer++] = left_index;
|
|
77
|
+
} else if (left_index < last_valid_index) {
|
|
78
|
+
stack[stack.pointer++] = left_index;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
} else {
|
|
83
|
+
// leaf node
|
|
84
|
+
|
|
85
|
+
// write to output
|
|
86
|
+
result[result_offset + hit_count] = uint32[node_address + 6];
|
|
87
|
+
|
|
88
|
+
hit_count++;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
} while (stack.pointer > stack_top)
|
|
92
|
+
|
|
93
|
+
return hit_count;
|
|
94
|
+
}
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import { SCRATCH_UINT32_TRAVERSAL_STACK } from "../../../collection/SCRATCH_UINT32_TRAVERSAL_STACK.js";
|
|
2
2
|
import { aabb3_array_intersects_ray } from "../../../geom/3d/aabb/aabb3_array_intersects_ray.js";
|
|
3
|
-
import { BVH_BINARY_NODE_SIZE, BVH_LEAF_NODE_SIZE } from "./BinaryUint32BVH.js";
|
|
4
3
|
|
|
5
4
|
const stack = SCRATCH_UINT32_TRAVERSAL_STACK;
|
|
6
5
|
|
|
7
6
|
/**
|
|
8
7
|
*
|
|
9
|
-
* @param {BinaryUint32BVH} bvh
|
|
10
8
|
* @param {number[]} result
|
|
11
9
|
* @param {number} result_offset
|
|
10
|
+
* @param {BinaryUint32BVH} bvh
|
|
12
11
|
* @param {number} origin_x
|
|
13
12
|
* @param {number} origin_y
|
|
14
13
|
* @param {number} origin_z
|
|
@@ -18,14 +17,14 @@ const stack = SCRATCH_UINT32_TRAVERSAL_STACK;
|
|
|
18
17
|
* @returns {number}
|
|
19
18
|
*/
|
|
20
19
|
export function bvh32_query_user_data_ray(
|
|
21
|
-
bvh,
|
|
22
20
|
result, result_offset,
|
|
21
|
+
bvh,
|
|
23
22
|
origin_x, origin_y, origin_z,
|
|
24
23
|
direction_x, direction_y, direction_z
|
|
25
24
|
) {
|
|
26
25
|
let hit_count = 0;
|
|
27
26
|
|
|
28
|
-
const binary_node_count = bvh.
|
|
27
|
+
const binary_node_count = bvh.binary_node_count;
|
|
29
28
|
|
|
30
29
|
if (binary_node_count <= 0) {
|
|
31
30
|
// this should not happen
|
|
@@ -44,7 +43,7 @@ export function bvh32_query_user_data_ray(
|
|
|
44
43
|
*/
|
|
45
44
|
stack[stack_top] = 0;
|
|
46
45
|
|
|
47
|
-
const last_valid_index = binary_node_count + bvh.
|
|
46
|
+
const last_valid_index = binary_node_count + bvh.leaf_node_count;
|
|
48
47
|
|
|
49
48
|
const float32 = bvh.float32;
|
|
50
49
|
const uint32 = bvh.uint32;
|
|
@@ -55,17 +54,20 @@ export function bvh32_query_user_data_ray(
|
|
|
55
54
|
// query_bvh_frustum_from_objects.iteration_count++;
|
|
56
55
|
const node_index = stack[stack.pointer];
|
|
57
56
|
|
|
58
|
-
|
|
57
|
+
const node_address = bvh.getNodeAddress(node_index);
|
|
58
|
+
|
|
59
|
+
if (!aabb3_array_intersects_ray(
|
|
60
|
+
float32, node_address,
|
|
61
|
+
origin_x, origin_y, origin_z,
|
|
62
|
+
direction_x, direction_y, direction_z
|
|
63
|
+
)) {
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const is_intermediate_node = node_index < binary_node_count;
|
|
68
|
+
|
|
69
|
+
if (is_intermediate_node) {
|
|
59
70
|
// is intermediate node
|
|
60
|
-
const node_address = node_index * BVH_BINARY_NODE_SIZE;
|
|
61
|
-
|
|
62
|
-
if (!aabb3_array_intersects_ray(
|
|
63
|
-
float32, node_address,
|
|
64
|
-
origin_x, origin_y, origin_z,
|
|
65
|
-
direction_x, direction_y, direction_z
|
|
66
|
-
)) {
|
|
67
|
-
continue;
|
|
68
|
-
}
|
|
69
71
|
|
|
70
72
|
const left_index = (node_index << 1) + 1;
|
|
71
73
|
const right_index = left_index + 1;
|
|
@@ -82,9 +84,6 @@ export function bvh32_query_user_data_ray(
|
|
|
82
84
|
|
|
83
85
|
} else {
|
|
84
86
|
// leaf node
|
|
85
|
-
const leaf_index = node_index - binary_node_count;
|
|
86
|
-
|
|
87
|
-
const node_address = leaf_index * BVH_LEAF_NODE_SIZE + binary_node_count * BVH_BINARY_NODE_SIZE;
|
|
88
87
|
|
|
89
88
|
// write to output
|
|
90
89
|
result[result_offset + hit_count] = uint32[node_address + 6];
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
aabb3_array_intersects_clipping_volume_array
|
|
3
|
+
} from "../../../geom/3d/aabb/aabb3_array_intersects_clipping_volume_array.js";
|
|
2
4
|
import { BVHQuery } from "./BVHQuery.js";
|
|
3
5
|
|
|
4
6
|
const scratch_aabb = [];
|
|
@@ -29,6 +31,6 @@ export class BVHQueryIntersectsFrustum extends BVHQuery {
|
|
|
29
31
|
|
|
30
32
|
tree.node_get_aabb(node, scratch_aabb);
|
|
31
33
|
|
|
32
|
-
return
|
|
34
|
+
return aabb3_array_intersects_clipping_volume_array(scratch_aabb, 0, this.frustum, 0, 6);
|
|
33
35
|
}
|
|
34
36
|
}
|
|
@@ -3,20 +3,20 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
import {assert} from "../../../assert.js";
|
|
6
|
+
import { assert } from "../../../assert.js";
|
|
7
7
|
import computeMortonCode from "../morton/Morton.js";
|
|
8
|
-
import {aabb3_array_intersects_point} from "./aabb3_array_intersects_point.js";
|
|
9
|
-
import {aabb3_build_corners} from "./aabb3_build_corners.js";
|
|
10
|
-
import {aabb3_compute_distance_above_plane_max} from "./aabb3_compute_distance_above_plane_max.js";
|
|
11
|
-
import {aabb3_compute_plane_side} from "./aabb3_compute_plane_side.js";
|
|
12
|
-
import {aabb3_compute_surface_area} from "./aabb3_compute_surface_area.js";
|
|
13
|
-
import {
|
|
14
|
-
import {aabb3_intersects_frustum_degree} from "./aabb3_intersects_frustum_degree.js";
|
|
15
|
-
import {aabb3_intersects_line_segment} from "./aabb3_intersects_line_segment.js";
|
|
16
|
-
import {aabb3_intersects_ray} from "./aabb3_intersects_ray.js";
|
|
17
|
-
import {aabb3_matrix4_project} from "./aabb3_matrix4_project.js";
|
|
18
|
-
import {aabb3_signed_distance_sqr_to_point} from "./aabb3_signed_distance_sqr_to_point.js";
|
|
19
|
-
import {aabb3_signed_distance_to_aabb3} from "./aabb3_signed_distance_to_aabb3.js";
|
|
8
|
+
import { aabb3_array_intersects_point } from "./aabb3_array_intersects_point.js";
|
|
9
|
+
import { aabb3_build_corners } from "./aabb3_build_corners.js";
|
|
10
|
+
import { aabb3_compute_distance_above_plane_max } from "./aabb3_compute_distance_above_plane_max.js";
|
|
11
|
+
import { aabb3_compute_plane_side } from "./aabb3_compute_plane_side.js";
|
|
12
|
+
import { aabb3_compute_surface_area } from "./aabb3_compute_surface_area.js";
|
|
13
|
+
import { aabb3_intersects_clipping_volume_array } from "./aabb3_intersects_clipping_volume_array.js";
|
|
14
|
+
import { aabb3_intersects_frustum_degree } from "./aabb3_intersects_frustum_degree.js";
|
|
15
|
+
import { aabb3_intersects_line_segment } from "./aabb3_intersects_line_segment.js";
|
|
16
|
+
import { aabb3_intersects_ray } from "./aabb3_intersects_ray.js";
|
|
17
|
+
import { aabb3_matrix4_project } from "./aabb3_matrix4_project.js";
|
|
18
|
+
import { aabb3_signed_distance_sqr_to_point } from "./aabb3_signed_distance_sqr_to_point.js";
|
|
19
|
+
import { aabb3_signed_distance_to_aabb3 } from "./aabb3_signed_distance_to_aabb3.js";
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
22
|
* Axis-Aligned bounding box in 3D
|
|
@@ -850,7 +850,7 @@ export class AABB3 {
|
|
|
850
850
|
const y1 = this.y1;
|
|
851
851
|
const z1 = this.z1;
|
|
852
852
|
|
|
853
|
-
return
|
|
853
|
+
return aabb3_intersects_clipping_volume_array(x0, y0, z0, x1, y1, z1, frustum, 0, 6);
|
|
854
854
|
}
|
|
855
855
|
|
|
856
856
|
/**
|