@woosh/meep-engine 2.68.0 → 2.69.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 (40) hide show
  1. package/build/bundle-worker-terrain.js +1 -1
  2. package/build/meep.cjs +698 -1269
  3. package/build/meep.min.js +1 -1
  4. package/build/meep.module.js +698 -1269
  5. package/package.json +1 -1
  6. package/src/core/bvh2/binary/2/BinaryUint32BVH.js +55 -28
  7. package/src/core/bvh2/binary/2/BinaryUint32BVH.spec.js +3 -3
  8. package/src/core/bvh2/binary/2/bvh32_query_user_data_overlaps_clipping_volume.js +94 -0
  9. package/src/core/bvh2/binary/2/bvh32_query_user_data_ray.js +17 -18
  10. package/src/core/bvh2/bvh3/query/BVHQueryIntersectsFrustum.js +4 -2
  11. package/src/core/geom/3d/aabb/AABB3.js +14 -14
  12. package/src/core/geom/3d/aabb/aabb3_array_intersects_clipping_volume_array.js +30 -0
  13. package/src/core/geom/3d/aabb/aabb3_intersects_clipping_volume_array.js +51 -0
  14. package/src/core/geom/3d/frustum/{read_frustum_planes_to_array.js → read_three_planes_to_array.js} +5 -3
  15. package/src/core/geom/3d/triangle/triangle_intersects_clipping_volume.js +51 -0
  16. package/src/engine/ecs/terrain/ecs/TerrainSystem.js +2 -2
  17. package/src/engine/ecs/terrain/ecs/makeTerrainWorkerProxy.js +1 -1
  18. package/src/engine/ecs/terrain/tiles/TerrainTile.js +9 -46
  19. package/src/engine/graphics/geometry/buffered/query/GeometrySpatialQueryAccelerator.d.ts +2 -2
  20. package/src/engine/graphics/geometry/buffered/query/GeometrySpatialQueryAccelerator.js +79 -36
  21. package/src/engine/graphics/geometry/buffered/query/bvh32_geometry_overlap_clipping_volume.js +88 -0
  22. package/src/engine/graphics/geometry/buffered/query/bvh32_geometry_raycast.js +108 -0
  23. package/src/engine/graphics/geometry/bvh/buffered/bvh32_from_indexed_geometry.js +4 -30
  24. package/src/engine/graphics/geometry/bvh/buffered/bvh32_from_unindexed_geometry.js +30 -0
  25. package/src/engine/graphics/geometry/bvh/buffered/bvh32_set_leaf_from_triangle.js +41 -0
  26. package/src/engine/graphics/render/forward_plus/LightManager.js +2 -2
  27. package/src/engine/graphics/render/forward_plus/query/query_bvh_frustum_from_texture.js +2 -2
  28. package/src/engine/graphics/render/view/CameraView.js +8 -8
  29. package/src/core/bvh2/binary/BinaryBVH.js +0 -281
  30. package/src/core/bvh2/binary/IndexedBinaryBVH.js +0 -407
  31. package/src/core/bvh2/binary/IndexedBinaryBVH.spec.js +0 -27
  32. package/src/core/bvh2/binary/IndexedBinaryBVHVisitor.js +0 -11
  33. package/src/core/bvh2/binary/NodeType.js +0 -8
  34. package/src/core/bvh2/binary/RayLeafIntersectionVisitor.js +0 -59
  35. package/src/core/geom/3d/aabb/aabb3_array_intersects_frustum_array.js +0 -20
  36. package/src/core/geom/3d/aabb/aabb3_intersects_frustum_array.js +0 -35
  37. package/src/engine/graphics/geometry/buffered/query/ClippingPlaneContainmentComputingVisitor.js +0 -195
  38. package/src/engine/graphics/geometry/buffered/query/GeometryVisitor.js +0 -87
  39. package/src/engine/graphics/geometry/buffered/query/RaycastNearestHitComputingVisitor.js +0 -206
  40. package/src/engine/graphics/geometry/bvh/buffered/BinaryBVHFromBufferGeometry.js +0 -123
package/build/meep.cjs CHANGED
@@ -56894,34 +56894,41 @@ class BinaryUint32BVH {
56894
56894
  */
56895
56895
  __data_uint32;
56896
56896
 
56897
- constructor() {
56898
-
56899
- /**
56900
- *
56901
- * @type {number}
56902
- * @private
56903
- */
56904
- this.__node_count_binary = 0;
56897
+ /**
56898
+ *
56899
+ * @type {number}
56900
+ * @private
56901
+ */
56902
+ __node_count_binary = 0;
56905
56903
 
56906
- /**
56907
- *
56908
- * @type {number}
56909
- * @private
56910
- */
56911
- this.__node_count_leaf = 0;
56904
+ /**
56905
+ *
56906
+ * @type {number}
56907
+ * @private
56908
+ */
56909
+ __node_count_leaf = 0;
56912
56910
 
56911
+ constructor() {
56913
56912
  this.data = new ArrayBuffer(320);
56914
56913
  }
56915
56914
 
56915
+ /**
56916
+ * In bytes
56917
+ * @returns {number}
56918
+ */
56919
+ estimateByteSize() {
56920
+ return this.data.byteLength + 248;
56921
+ }
56922
+
56916
56923
  getTotalBoxCount() {
56917
56924
  return this.__node_count_binary + this.__node_count_leaf;
56918
56925
  }
56919
56926
 
56920
- getBinaryNodeCount() {
56927
+ get binary_node_count() {
56921
56928
  return this.__node_count_binary;
56922
56929
  }
56923
56930
 
56924
- getLeafNodeCount() {
56931
+ get leaf_node_count() {
56925
56932
  return this.__node_count_leaf;
56926
56933
  }
56927
56934
 
@@ -56943,10 +56950,12 @@ class BinaryUint32BVH {
56943
56950
 
56944
56951
  /**
56945
56952
  *
56946
- * @param {ArrayBuffer} v
56953
+ * @param {ArrayBuffer} buffer
56947
56954
  */
56948
- set data(v) {
56949
- this.__data_buffer = v;
56955
+ set data(buffer) {
56956
+ assert.defined(buffer, 'buffer');
56957
+
56958
+ this.__data_buffer = buffer;
56950
56959
 
56951
56960
  this.__data_float32 = new Float32Array(this.__data_buffer);
56952
56961
  this.__data_uint32 = new Uint32Array(this.__data_buffer);
@@ -56956,6 +56965,24 @@ class BinaryUint32BVH {
56956
56965
  return this.__data_buffer;
56957
56966
  }
56958
56967
 
56968
+ /**
56969
+ * Resolve index of the node to address where the node data starts, this is required to know where AABB is stored in memory
56970
+ * @param {number} node_index
56971
+ * @returns {number}
56972
+ */
56973
+ getNodeAddress(node_index) {
56974
+ const binary_node_count = this.__node_count_binary;
56975
+ const leaf_node_index = node_index - binary_node_count;
56976
+
56977
+ if (leaf_node_index < 0) {
56978
+ // binary node
56979
+ return node_index * BVH_BINARY_NODE_SIZE;
56980
+ } else {
56981
+ // leaf node
56982
+ return binary_node_count * BVH_BINARY_NODE_SIZE + leaf_node_index * BVH_LEAF_NODE_SIZE;
56983
+ }
56984
+ }
56985
+
56959
56986
  initialize_structure() {
56960
56987
  // compute memory requirements
56961
56988
  const word_count = this.__node_count_binary * BVH_BINARY_NODE_SIZE + this.__node_count_leaf * BVH_LEAF_NODE_SIZE;
@@ -57246,22 +57273,22 @@ class BinaryUint32BVH {
57246
57273
 
57247
57274
  // build bottom-most level, just above the leaves
57248
57275
  for (i = 0; i < level_node_count; i++) {
57249
- const leafIndex0 = i * 2;
57250
- const leafIndex1 = leafIndex0 + 1;
57276
+ const leaf_index_0 = i * 2;
57277
+ const leaf_index_1 = leaf_index_0 + 1;
57251
57278
 
57252
- const leafOffset0 = leaf_node_block_address + leafIndex0 * BVH_LEAF_NODE_SIZE;
57253
- const leafOffset1 = leaf_node_block_address + leafIndex1 * BVH_LEAF_NODE_SIZE;
57279
+ const leaf_offset_0 = leaf_node_block_address + leaf_index_0 * BVH_LEAF_NODE_SIZE;
57280
+ const leaf_offset_1 = leaf_node_block_address + leaf_index_1 * BVH_LEAF_NODE_SIZE;
57254
57281
 
57255
- if (leafIndex1 < node_count_leaf) {
57282
+ if (leaf_index_1 < node_count_leaf) {
57256
57283
  // both children nodes are valid
57257
57284
  aabb3_array_combine(
57258
57285
  float32, offset,
57259
- float32, leafOffset0,
57260
- float32, leafOffset1
57286
+ float32, leaf_offset_0,
57287
+ float32, leaf_offset_1
57261
57288
  );
57262
- } else if (leafIndex0 < node_count_leaf) {
57289
+ } else if (leaf_index_0 < node_count_leaf) {
57263
57290
  // only left child node is valid
57264
- array_copy(float32, leafOffset0, float32, offset, 6);
57291
+ array_copy(float32, leaf_offset_0, float32, offset, 6);
57265
57292
  } else {
57266
57293
  //initialize to 0-size box same position as previous node
57267
57294
  copy_box_zero_size(this.__data_float32, offset, (offset - BVH_BINARY_NODE_SIZE));
@@ -57301,127 +57328,6 @@ class BinaryUint32BVH {
57301
57328
 
57302
57329
  //
57303
57330
 
57304
- /**
57305
- *
57306
- * @param {ArrayLike<number>|number[]|Float32Array} aabb bounding box, order: x0,y0,z0,x1,y1,z1
57307
- * @param {number} aabb_offset
57308
- * @param {number} origin_x
57309
- * @param {number} origin_y
57310
- * @param {number} origin_z
57311
- * @param {number} direction_x
57312
- * @param {number} direction_y
57313
- * @param {number} direction_z
57314
- */
57315
- function aabb3_array_intersects_ray(
57316
- aabb, aabb_offset,
57317
- origin_x, origin_y, origin_z,
57318
- direction_x, direction_y, direction_z
57319
- ) {
57320
- return aabb3_intersects_ray(
57321
- aabb[aabb_offset], aabb[aabb_offset+1], aabb[aabb_offset+2],
57322
- aabb[aabb_offset+3], aabb[aabb_offset+4], aabb[aabb_offset+5],
57323
- origin_x, origin_y, origin_z,
57324
- direction_x, direction_y, direction_z
57325
- );
57326
- }
57327
-
57328
- const stack$7 = SCRATCH_UINT32_TRAVERSAL_STACK;
57329
-
57330
- /**
57331
- *
57332
- * @param {BinaryUint32BVH} bvh
57333
- * @param {number[]} result
57334
- * @param {number} result_offset
57335
- * @param {number} origin_x
57336
- * @param {number} origin_y
57337
- * @param {number} origin_z
57338
- * @param {number} direction_x
57339
- * @param {number} direction_y
57340
- * @param {number} direction_z
57341
- * @returns {number}
57342
- */
57343
- function bvh32_query_user_data_ray(
57344
- bvh,
57345
- result, result_offset,
57346
- origin_x, origin_y, origin_z,
57347
- direction_x, direction_y, direction_z
57348
- ) {
57349
- let hit_count = 0;
57350
-
57351
- const binary_node_count = bvh.getBinaryNodeCount();
57352
-
57353
- if (binary_node_count <= 0) {
57354
- // this should not happen
57355
- return 0;
57356
- }
57357
-
57358
- /**
57359
- *
57360
- * @type {number}
57361
- */
57362
- const stack_top = stack$7.pointer++;
57363
-
57364
- /**
57365
- * After performing empirical tests, stack-based depth-first traversal turns out faster than using a queue
57366
- * @type {number}
57367
- */
57368
- stack$7[stack_top] = 0;
57369
-
57370
- const last_valid_index = binary_node_count + bvh.getLeafNodeCount();
57371
-
57372
- const float32 = bvh.float32;
57373
- const uint32 = bvh.uint32;
57374
-
57375
- do {
57376
- stack$7.pointer--;
57377
-
57378
- // query_bvh_frustum_from_objects.iteration_count++;
57379
- const node_index = stack$7[stack$7.pointer];
57380
-
57381
- if (node_index < binary_node_count) {
57382
- // is intermediate node
57383
- const node_address = node_index * BVH_BINARY_NODE_SIZE;
57384
-
57385
- if (!aabb3_array_intersects_ray(
57386
- float32, node_address,
57387
- origin_x, origin_y, origin_z,
57388
- direction_x, direction_y, direction_z
57389
- )) {
57390
- continue;
57391
- }
57392
-
57393
- const left_index = (node_index << 1) + 1;
57394
- const right_index = left_index + 1;
57395
-
57396
- // left node ends up on top of the stack, which aligns with the desired access sequence
57397
- if (right_index < last_valid_index) {
57398
- stack$7[stack$7.pointer++] = right_index;
57399
- // micro-optimization, since we know that right node is valid and left appears before that, left is valid too
57400
- stack$7[stack$7.pointer++] = left_index;
57401
- } else if (left_index < last_valid_index) {
57402
- stack$7[stack$7.pointer++] = left_index;
57403
- }
57404
-
57405
-
57406
- } else {
57407
- // leaf node
57408
- const leaf_index = node_index - binary_node_count;
57409
-
57410
- const node_address = leaf_index * BVH_LEAF_NODE_SIZE + binary_node_count * BVH_BINARY_NODE_SIZE;
57411
-
57412
- // write to output
57413
- result[result_offset + hit_count] = uint32[node_address + 6];
57414
-
57415
- hit_count++;
57416
- }
57417
-
57418
- } while (stack$7.pointer > stack_top)
57419
-
57420
- return hit_count;
57421
- }
57422
-
57423
- //
57424
-
57425
57331
  /**
57426
57332
  *
57427
57333
  * @param {ArrayLike<number>|number[]|AABB3} aabb
@@ -57600,23 +57506,37 @@ function aabb3_compute_plane_side(
57600
57506
  }
57601
57507
 
57602
57508
  /**
57603
- *
57509
+ * Tests whether AABB intersects a clipping volume defined by a set of planes
57510
+ * Mainly useful for frustum checks
57604
57511
  * @param {number} x0
57605
57512
  * @param {number} y0
57606
57513
  * @param {number} z0
57607
57514
  * @param {number} x1
57608
57515
  * @param {number} y1
57609
57516
  * @param {number} z1
57610
- * @param {ArrayLike<number>|number[]|Float32Array|Float64Array} frustum
57517
+ * @param {ArrayLike<number>|number[]|Float32Array|Float64Array} planes
57518
+ * @param {number} planes_offset
57519
+ * @param {number} plane_count
57611
57520
  * @return {boolean}
57612
57521
  */
57613
- function aabb3_intersects_frustum_array(x0, y0, z0, x1, y1, z1, frustum) {
57614
- for (let i = 0; i < 24; i += 4) {
57522
+ function aabb3_intersects_clipping_volume_array(
57523
+ x0, y0, z0,
57524
+ x1, y1, z1,
57525
+ planes, planes_offset, plane_count
57526
+ ) {
57527
+
57528
+ assert.isNonNegativeInteger(planes_offset, 'frustum_offset');
57529
+
57530
+ const limit = plane_count * 4;
57615
57531
 
57616
- const plane_x = frustum[i];
57617
- const plane_y = frustum[i + 1];
57618
- const plane_z = frustum[i + 2];
57619
- const plane_w = frustum[i + 3];
57532
+ for (let i = 0; i < limit; i += 4) {
57533
+
57534
+ const offset = planes_offset + i;
57535
+
57536
+ const plane_x = planes[offset];
57537
+ const plane_y = planes[offset + 1];
57538
+ const plane_z = planes[offset + 2];
57539
+ const plane_w = planes[offset + 3];
57620
57540
 
57621
57541
  const plane_distance = aabb3_compute_distance_above_plane_max(
57622
57542
  plane_x, plane_y, plane_z, plane_w,
@@ -57631,6 +57551,7 @@ function aabb3_intersects_frustum_array(x0, y0, z0, x1, y1, z1, frustum) {
57631
57551
  }
57632
57552
 
57633
57553
  return true;
57554
+
57634
57555
  }
57635
57556
 
57636
57557
  //
@@ -58710,7 +58631,7 @@ class AABB3 {
58710
58631
  const y1 = this.y1;
58711
58632
  const z1 = this.z1;
58712
58633
 
58713
- return aabb3_intersects_frustum_array(x0, y0, z0, x1, y1, z1, frustum);
58634
+ return aabb3_intersects_clipping_volume_array(x0, y0, z0, x1, y1, z1, frustum, 0, 6);
58714
58635
  }
58715
58636
 
58716
58637
  /**
@@ -58845,6 +58766,127 @@ function ray3_array_compose(output, origin_x, origin_y, origin_z, direction_x, d
58845
58766
  output[5] = direction_z;
58846
58767
  }
58847
58768
 
58769
+ //
58770
+
58771
+ /**
58772
+ *
58773
+ * @param {ArrayLike<number>|number[]|Float32Array} aabb bounding box, order: x0,y0,z0,x1,y1,z1
58774
+ * @param {number} aabb_offset
58775
+ * @param {number} origin_x
58776
+ * @param {number} origin_y
58777
+ * @param {number} origin_z
58778
+ * @param {number} direction_x
58779
+ * @param {number} direction_y
58780
+ * @param {number} direction_z
58781
+ */
58782
+ function aabb3_array_intersects_ray(
58783
+ aabb, aabb_offset,
58784
+ origin_x, origin_y, origin_z,
58785
+ direction_x, direction_y, direction_z
58786
+ ) {
58787
+ return aabb3_intersects_ray(
58788
+ aabb[aabb_offset], aabb[aabb_offset+1], aabb[aabb_offset+2],
58789
+ aabb[aabb_offset+3], aabb[aabb_offset+4], aabb[aabb_offset+5],
58790
+ origin_x, origin_y, origin_z,
58791
+ direction_x, direction_y, direction_z
58792
+ );
58793
+ }
58794
+
58795
+ const stack$7 = SCRATCH_UINT32_TRAVERSAL_STACK;
58796
+
58797
+ /**
58798
+ *
58799
+ * @param {number[]} result
58800
+ * @param {number} result_offset
58801
+ * @param {BinaryUint32BVH} bvh
58802
+ * @param {number} origin_x
58803
+ * @param {number} origin_y
58804
+ * @param {number} origin_z
58805
+ * @param {number} direction_x
58806
+ * @param {number} direction_y
58807
+ * @param {number} direction_z
58808
+ * @returns {number}
58809
+ */
58810
+ function bvh32_query_user_data_ray(
58811
+ result, result_offset,
58812
+ bvh,
58813
+ origin_x, origin_y, origin_z,
58814
+ direction_x, direction_y, direction_z
58815
+ ) {
58816
+ let hit_count = 0;
58817
+
58818
+ const binary_node_count = bvh.binary_node_count;
58819
+
58820
+ if (binary_node_count <= 0) {
58821
+ // this should not happen
58822
+ return 0;
58823
+ }
58824
+
58825
+ /**
58826
+ *
58827
+ * @type {number}
58828
+ */
58829
+ const stack_top = stack$7.pointer++;
58830
+
58831
+ /**
58832
+ * After performing empirical tests, stack-based depth-first traversal turns out faster than using a queue
58833
+ * @type {number}
58834
+ */
58835
+ stack$7[stack_top] = 0;
58836
+
58837
+ const last_valid_index = binary_node_count + bvh.leaf_node_count;
58838
+
58839
+ const float32 = bvh.float32;
58840
+ const uint32 = bvh.uint32;
58841
+
58842
+ do {
58843
+ stack$7.pointer--;
58844
+
58845
+ // query_bvh_frustum_from_objects.iteration_count++;
58846
+ const node_index = stack$7[stack$7.pointer];
58847
+
58848
+ const node_address = bvh.getNodeAddress(node_index);
58849
+
58850
+ if (!aabb3_array_intersects_ray(
58851
+ float32, node_address,
58852
+ origin_x, origin_y, origin_z,
58853
+ direction_x, direction_y, direction_z
58854
+ )) {
58855
+ continue;
58856
+ }
58857
+
58858
+ const is_intermediate_node = node_index < binary_node_count;
58859
+
58860
+ if (is_intermediate_node) {
58861
+ // is intermediate node
58862
+
58863
+ const left_index = (node_index << 1) + 1;
58864
+ const right_index = left_index + 1;
58865
+
58866
+ // left node ends up on top of the stack, which aligns with the desired access sequence
58867
+ if (right_index < last_valid_index) {
58868
+ stack$7[stack$7.pointer++] = right_index;
58869
+ // micro-optimization, since we know that right node is valid and left appears before that, left is valid too
58870
+ stack$7[stack$7.pointer++] = left_index;
58871
+ } else if (left_index < last_valid_index) {
58872
+ stack$7[stack$7.pointer++] = left_index;
58873
+ }
58874
+
58875
+
58876
+ } else {
58877
+ // leaf node
58878
+
58879
+ // write to output
58880
+ result[result_offset + hit_count] = uint32[node_address + 6];
58881
+
58882
+ hit_count++;
58883
+ }
58884
+
58885
+ } while (stack$7.pointer > stack_top)
58886
+
58887
+ return hit_count;
58888
+ }
58889
+
58848
58890
  /**
58849
58891
  * NOTE: adapted from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteIntrRay3Triangle3.h
58850
58892
  * @source https://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm (Möller and Trumbore, « Fast, Minimum Storage Ray-Triangle Intersection », Journal of Graphics Tools, vol. 2,‎ 1997, p. 21–28)
@@ -59002,6 +59044,110 @@ function computeTriangleRayIntersection(
59002
59044
  return true;
59003
59045
  }
59004
59046
 
59047
+ const scratch_array$4 = [];
59048
+ const scratch_hit = new SurfacePoint3();
59049
+
59050
+ /**
59051
+ *
59052
+ * @param {SurfacePoint3} result
59053
+ * @param {BinaryUint32BVH} bvh
59054
+ * @param {number[]|ArrayLike<number>} vertices
59055
+ * @param {number} vertex_offset Unless you're using an interleaved buffer of some kind, this will be 0
59056
+ * @param {number} vertex_stride Unless you're using an interleaved buffer, this should be 3
59057
+ * @param {number[]|ArrayLike<number>|undefined} indices if this is set to undefined - implicit indexing will be used
59058
+ * @param {number} originX
59059
+ * @param {number} originY
59060
+ * @param {number} originZ
59061
+ * @param {number} directionX
59062
+ * @param {number} directionY
59063
+ * @param {number} directionZ
59064
+ * @returns {boolean}
59065
+ */
59066
+ function bvh32_geometry_raycast(
59067
+ result,
59068
+ bvh,
59069
+ vertices, vertex_offset, vertex_stride,
59070
+ indices,
59071
+ originX, originY, originZ,
59072
+ directionX, directionY, directionZ
59073
+ ) {
59074
+ let hit_found = false;
59075
+
59076
+ const hit_count = bvh32_query_user_data_ray(
59077
+ scratch_array$4, 0,
59078
+ bvh,
59079
+ originX, originY, originZ,
59080
+ directionX, directionY, directionZ
59081
+ );
59082
+
59083
+ let best_distance = Infinity;
59084
+
59085
+ let a, b, c;
59086
+
59087
+ for (let i = 0; i < hit_count; i++) {
59088
+ const triangle_index = scratch_array$4[i];
59089
+
59090
+ const index3 = triangle_index * 3;
59091
+
59092
+ if (indices !== undefined) {
59093
+ assert.lessThan(index3 + 2, indices.length, 'triangle index overflow, possibly geometry changed but tree was not rebuilt?');
59094
+
59095
+ a = indices[index3];
59096
+ b = indices[index3 + 1];
59097
+ c = indices[index3 + 2];
59098
+ } else {
59099
+ // implicit indices
59100
+ a = index3;
59101
+ b = index3 + 1;
59102
+ c = index3 + 2;
59103
+ }
59104
+
59105
+ const a_address = a * vertex_stride + vertex_offset;
59106
+ const b_address = b * vertex_stride + vertex_offset;
59107
+ const c_address = c * vertex_stride + vertex_offset;
59108
+
59109
+ assert.lessThan(a_address + 2, vertices.length, 'a-vertex overflow');
59110
+ assert.lessThan(b_address + 2, vertices.length, 'b-vertex overflow');
59111
+ assert.lessThan(c_address + 2, vertices.length, 'c-vertex overflow');
59112
+
59113
+ const ax = vertices[a_address];
59114
+ const ay = vertices[a_address + 1];
59115
+ const az = vertices[a_address + 2];
59116
+
59117
+ const bx = vertices[b_address];
59118
+ const by = vertices[b_address + 1];
59119
+ const bz = vertices[b_address + 2];
59120
+
59121
+ const cx = vertices[c_address];
59122
+ const cy = vertices[c_address + 1];
59123
+ const cz = vertices[c_address + 2];
59124
+
59125
+ const triangle_hit_found = computeTriangleRayIntersection(
59126
+ scratch_hit,
59127
+ originX, originY, originZ,
59128
+ directionX, directionY, directionZ,
59129
+ ax, ay, az,
59130
+ bx, by, bz,
59131
+ cx, cy, cz
59132
+ );
59133
+
59134
+ if (!triangle_hit_found) {
59135
+ continue;
59136
+ }
59137
+
59138
+ hit_found = true;
59139
+
59140
+ const distance_sqr = scratch_hit.position._distanceSqrTo(originX, originY, originZ);
59141
+
59142
+ if (distance_sqr < best_distance) {
59143
+ best_distance = distance_sqr;
59144
+ result.copy(scratch_hit);
59145
+ }
59146
+ }
59147
+
59148
+ return hit_found;
59149
+ }
59150
+
59005
59151
  /**
59006
59152
  * Created by Alex on 28/01/2017.
59007
59153
  */
@@ -59083,9 +59229,6 @@ var ThreeFactory = {
59083
59229
  const EMPTY_GEOMETRY = new BufferGeometry();
59084
59230
  const DEFAULT_MATERIAL = new MeshBasicMaterial();
59085
59231
 
59086
- const scratch_array$3 = [];
59087
- const scratch_hit = new SurfacePoint3();
59088
-
59089
59232
  const ray_tmp = [];
59090
59233
  const m4_tmp = [];
59091
59234
 
@@ -59241,52 +59384,19 @@ class TerrainTile {
59241
59384
  const _directionY = ray_tmp[4];
59242
59385
  const _directionZ = ray_tmp[5];
59243
59386
 
59244
- const hit_count = bvh32_query_user_data_ray(
59245
- this.bvh,
59246
- scratch_array$3, 0,
59247
- _originX, _originY, _originZ,
59248
- _directionX, _directionY, _directionZ
59249
- );
59250
-
59251
- let best_distance = Infinity;
59252
- let hit_found = false;
59253
-
59254
59387
  const geometry = this.geometry;
59255
59388
 
59256
59389
  const geometryIndices = geometry.getIndex().array;
59257
59390
  const geometryPositions = geometry.getAttribute('position').array;
59258
59391
 
59259
- for (let i = 0; i < hit_count; i++) {
59260
- const triangle_index = scratch_array$3[i];
59261
-
59262
- const index3 = triangle_index * 3;
59263
-
59264
- const a = geometryIndices[index3] * 3;
59265
- const b = geometryIndices[index3 + 1] * 3;
59266
- const c = geometryIndices[index3 + 2] * 3;
59267
-
59268
- const triangle_hit_found = computeTriangleRayIntersection(
59269
- scratch_hit,
59270
- _originX, _originY, _originZ,
59271
- _directionX, _directionY, _directionZ,
59272
- geometryPositions[a], geometryPositions[a + 1], geometryPositions[a + 2],
59273
- geometryPositions[b], geometryPositions[b + 1], geometryPositions[b + 2],
59274
- geometryPositions[c], geometryPositions[c + 1], geometryPositions[c + 2],
59275
- );
59276
-
59277
- if (!triangle_hit_found) {
59278
- continue;
59279
- }
59280
-
59281
- hit_found = true;
59282
-
59283
- const distance_sqr = scratch_hit.position._distanceSqrTo(_originX, _originY, _originZ);
59284
-
59285
- if (distance_sqr < best_distance) {
59286
- best_distance = distance_sqr;
59287
- result.copy(scratch_hit);
59288
- }
59289
- }
59392
+ let hit_found = bvh32_geometry_raycast(
59393
+ result,
59394
+ this.bvh,
59395
+ geometryPositions, 0, 3,
59396
+ geometryIndices,
59397
+ _originX, _originY, _originZ,
59398
+ _directionX, _directionY, _directionZ
59399
+ );
59290
59400
 
59291
59401
  if (hit_found) {
59292
59402
  result.applyMatrix4(m4);
@@ -59708,7 +59818,7 @@ class TerrainTile {
59708
59818
  *
59709
59819
  * @type {number[]}
59710
59820
  */
59711
- const scratch_array$2 = [];
59821
+ const scratch_array$3 = [];
59712
59822
  const scratch_contact = new SurfacePoint3();
59713
59823
 
59714
59824
  class TerrainTileManager {
@@ -60284,7 +60394,7 @@ class TerrainTileManager {
60284
60394
  const hit_count = bvh_query_leaves_ray(
60285
60395
  this.bvh,
60286
60396
  this.bvh.root,
60287
- scratch_array$2, 0,
60397
+ scratch_array$3, 0,
60288
60398
  originX, originY, originZ,
60289
60399
  directionX, directionY, directionZ
60290
60400
  );
@@ -60293,7 +60403,7 @@ class TerrainTileManager {
60293
60403
  let hit_found = false;
60294
60404
 
60295
60405
  for (let i = 0; i < hit_count; i++) {
60296
- const node_id = scratch_array$2[i];
60406
+ const node_id = scratch_array$3[i];
60297
60407
 
60298
60408
  const tile_index = this.bvh.node_get_user_data(node_id);
60299
60409
 
@@ -65201,7 +65311,7 @@ function makeTerrainWorkerProxy() {
65201
65311
  resolve({
65202
65312
  geometry: geometry,
65203
65313
  bvh: {
65204
- leaf_count: bvh.getLeafNodeCount(),
65314
+ leaf_count: bvh.leaf_node_count,
65205
65315
  data: bvh.data
65206
65316
  }
65207
65317
  });
@@ -67185,598 +67295,283 @@ function aabb3_from_threejs_geometry(result, geometry) {
67185
67295
  aabb3_from_min_max(result, min, max);
67186
67296
  }
67187
67297
 
67188
- class IndexedBinaryBVHVisitor {
67189
- /**
67190
- *
67191
- * @param {number} address
67192
- * @param {NodeType} type
67193
- * @returns {boolean}
67194
- */
67195
- visit(address, type) {
67196
-
67197
- }
67198
- }
67199
-
67200
67298
  /**
67201
67299
  *
67202
- * @enum {number}
67300
+ * @param {Plane[]} planes
67301
+ * @param {ArrayLike<number>|number[]|Float32Array|Float64Array} array
67203
67302
  */
67204
- const NodeType = {
67205
- LEAF: 0,
67206
- BINARY: 1
67207
- };
67208
-
67209
- class RayLeafIntersectionVisitor extends IndexedBinaryBVHVisitor {
67210
- constructor() {
67211
- super();
67212
- this.callback = noop;
67213
- this.callbackThisArg = null;
67214
-
67215
- this.originX = 0;
67216
- this.originY = 0;
67217
- this.originZ = 0;
67303
+ function read_three_planes_to_array(planes, array) {
67304
+ const plane_count = planes.length;
67218
67305
 
67219
- this.directionX = 0;
67220
- this.directionY = 0;
67221
- this.directionZ = 0;
67306
+ assert.greaterThanOrEqual(array.length, plane_count * 4, 'target array is too small');
67222
67307
 
67223
- /**
67224
- *
67225
- * @type {IndexedBinaryBVH}
67226
- */
67227
- this.root = null;
67228
- }
67229
-
67230
- visit(address, type) {
67231
- const root = this.root;
67232
-
67233
- const data = root.data;
67234
- const binaryNodeCount = root.binaryNodeCount;
67235
-
67236
- const x0 = data[address];
67237
- const y0 = data[address + 1];
67238
- const z0 = data[address + 2];
67239
- const x1 = data[address + 3];
67240
- const y1 = data[address + 4];
67241
- const z1 = data[address + 5];
67242
-
67243
- const intersectionFound = aabb3_intersects_ray(x0, y0, z0, x1, y1, z1,
67244
- this.originX, this.originY, this.originZ,
67245
- this.directionX, this.directionY, this.directionZ
67246
- );
67308
+ for (let i = 0; i < plane_count; i++) {
67309
+ const plane = planes[i];
67247
67310
 
67248
- if (!intersectionFound) {
67249
- return false;
67250
- }
67311
+ const offset = i * 4;
67251
67312
 
67252
- if (type === NodeType.LEAF) {
67253
- const value = address / 6 - binaryNodeCount;
67313
+ const normal = plane.normal;
67254
67314
 
67255
- this.callback.call(this.callbackThisArg, value, address, type);
67315
+ array[offset] = normal.x;
67316
+ array[offset + 1] = normal.y;
67317
+ array[offset + 2] = normal.z;
67256
67318
 
67257
- return false;
67258
- } else {
67259
- return true;
67260
- }
67319
+ array[offset + 3] = plane.constant;
67261
67320
  }
67262
67321
  }
67263
67322
 
67264
- /**
67265
- * Created by Alex on 29/05/2016.
67266
- */
67267
-
67268
-
67269
67323
  /**
67270
67324
  *
67271
- * @type {Float32Array|number[]}
67325
+ * @param {BinaryUint32BVH} bvh
67326
+ * @param {number} triangle_index
67327
+ * @param {number[]|Float32Array} vertices
67328
+ * @param {number} a_index
67329
+ * @param {number} b_index
67330
+ * @param {number} c_index
67272
67331
  */
67273
- const scratch_aabb_0 = new Float32Array(6);
67274
-
67275
-
67276
- class IndexedBinaryBVH {
67277
- /**
67278
- *
67279
- * @constructor
67280
- */
67281
- constructor() {
67282
- /**
67283
- *
67284
- * @type {number}
67285
- */
67286
- this.leafNodeCount = 0;
67287
-
67288
- /**
67289
- *
67290
- * @type {number}
67291
- */
67292
- this.binaryNodeCount = 0;
67293
-
67294
- /**
67295
- * Total number of boxes contained in the tree, some might be unused
67296
- * @type {number}
67297
- */
67298
- this.boxCount = 0;
67299
-
67300
- /**
67301
- *
67302
- * @type {Float32Array|number[]}
67303
- */
67304
- this.data = new Float32Array(16);
67305
- }
67306
-
67307
- /**
67308
- *
67309
- * @returns {number}
67310
- */
67311
- estimateByteSize(){
67312
- return this.data.buffer.byteLength + 248;
67313
- }
67314
-
67315
- /**
67316
- *
67317
- * @param {int} leafCount
67318
- */
67319
- initialize(leafCount) {
67320
-
67321
- const twoLog = Math.log(leafCount) / Math.log(2);
67322
-
67323
- const twoLeafLimit = Math.pow(2, Math.ceil(twoLog));
67324
- const binaryNodeCount = twoLeafLimit - 1;
67325
-
67326
- this.leafNodeCount = leafCount;
67327
-
67328
- this.binaryNodeCount = binaryNodeCount;
67329
-
67330
- this.boxCount = this.leafNodeCount + this.binaryNodeCount;
67331
-
67332
- // possibly resize the storage
67333
- const storage_size = this.boxCount * 6;
67334
-
67335
- if (this.data.length < storage_size) {
67336
- this.data = new Float32Array(storage_size);
67337
- } else {
67338
- this.data.fill(0);
67339
- }
67340
- }
67341
-
67342
- unsortedBuiltIntermediate() {
67343
- const data = this.data;
67344
-
67345
- const nodeCount = this.binaryNodeCount;
67346
-
67347
- const leafNodesOffset = this.binaryNodeCount * 6;
67348
-
67349
- let level = Math.floor(Math.log(nodeCount) / Math.log(2));
67350
-
67351
- let i, offset, levelNodeCount;
67352
- //NOTE: building first level separately allows to avoid some switching logic needed to determine what is the type of lower level node
67353
- //build one level above leaf nodes
67354
- levelNodeCount = Math.pow(2, level);
67355
- offset = (levelNodeCount - 1) * 6;
67356
-
67357
- let parentIndex, childIndex0, childIndex1;
67358
-
67359
- for (i = 0; i < levelNodeCount; i++) {
67360
- const leafIndex0 = i * 2;
67361
- const leafIndex1 = leafIndex0 + 1;
67362
-
67363
- const leafOffset0 = leafNodesOffset + leafIndex0 * 6;
67364
- const leafOffset1 = leafNodesOffset + leafIndex1 * 6;
67365
-
67366
- if (leafIndex1 < this.leafNodeCount) {
67367
- binaryNodeRefit(data, offset, leafOffset0, leafOffset1);
67368
- } else if (leafIndex0 < this.leafNodeCount) {
67369
- copyBox(leafOffset0, offset, data);
67370
- } else {
67371
- //initialize to 0-size box same position as previous node
67372
- copyBoxZeroSize(offset - 6, offset, data);
67373
- }
67374
-
67375
- offset += 6;
67376
- }
67377
-
67378
- level--;
67379
-
67380
- //build intermediate nodes
67381
- for (; level >= 0; level--) {
67382
- levelNodeCount = Math.pow(2, level);
67383
- parentIndex = (levelNodeCount - 1);
67384
-
67385
- for (i = 0; i < levelNodeCount; i++) {
67386
-
67387
- childIndex0 = (parentIndex << 1) + 1;
67388
- childIndex1 = childIndex0 + 1;
67389
-
67390
- binaryNodeRefit(data, parentIndex * 6, childIndex0 * 6, childIndex1 * 6);
67391
-
67392
- parentIndex++;
67393
- }
67394
- }
67395
-
67396
- //set bounds of the bvh
67397
- array_copy(data, 0, scratch_aabb_0, 0, 6);
67398
-
67399
- this.x0 = scratch_aabb_0[0];
67400
- this.y0 = scratch_aabb_0[1];
67401
- this.z0 = scratch_aabb_0[2];
67402
- this.x1 = scratch_aabb_0[3];
67403
- this.y1 = scratch_aabb_0[4];
67404
- this.z1 = scratch_aabb_0[5];
67405
- }
67406
-
67407
- /**
67408
- * Sets bounds of a given leaf
67409
- * NOTE: to build tree, must call {@link #unsortedBuiltIntermediate} after all leaves are set
67410
- * @param {number} leaf_index
67411
- * @param {number} x0
67412
- * @param {number} y0
67413
- * @param {number} z0
67414
- * @param {number} x1
67415
- * @param {number} y1
67416
- * @param {number} z1
67417
- */
67418
- writeLeaf(leaf_index, x0, y0, z0, x1, y1, z1) {
67419
- const offset = this.binaryNodeCount * 6 + leaf_index * 6;
67420
- writeBox(this.data, offset, x0, y0, z0, x1, y1, z1);
67421
- }
67422
-
67423
- /**
67424
- * @template T
67425
- * @deprecated use {@link #writeLeaf} instead followed by {@link #unsortedBuiltIntermediate}
67426
- * @param {function(index:number,offset:number,data:T, writeBox:function):void} visitor
67427
- */
67428
- setLeafs(visitor) {
67429
- let offset = this.binaryNodeCount * 6;
67430
-
67431
- const data = this.data;
67332
+ function bvh32_set_leaf_from_triangle(bvh, triangle_index, vertices, a_index, b_index, c_index) {
67333
+ const a = a_index * 3;
67334
+ const b = b_index * 3;
67335
+ const c = c_index * 3;
67432
67336
 
67433
- let i = 0;
67434
- const l = this.leafNodeCount;
67435
- for (; i < l; i++) {
67436
- visitor(i, offset, data, writeBox);
67337
+ // read actual positions of each vertex
67338
+ const aX = vertices[a];
67339
+ const aY = vertices[a + 1];
67340
+ const aZ = vertices[a + 2];
67437
67341
 
67438
- offset += 6;
67439
- }
67440
- this.unsortedBuiltIntermediate();
67441
- }
67342
+ const bX = vertices[b];
67343
+ const bY = vertices[b + 1];
67344
+ const bZ = vertices[b + 2];
67442
67345
 
67443
- /**
67444
- *
67445
- * @param {IndexedBinaryBVHVisitor} visitor
67446
- * @param {Number} startIndex
67447
- */
67448
- traversePreOrderStack(visitor, startIndex) {
67346
+ const cX = vertices[c];
67347
+ const cY = vertices[c + 1];
67348
+ const cZ = vertices[c + 2];
67449
67349
 
67450
- const stackOffset = stackPointer;
67350
+ // compute bounds of the triangle
67351
+ const x0 = min3(aX, bX, cX);
67352
+ const y0 = min3(aY, bY, cY);
67353
+ const z0 = min3(aZ, bZ, cZ);
67451
67354
 
67452
- stack$6[stackPointer++] = startIndex;
67355
+ const x1 = max3(aX, bX, cX);
67356
+ const y1 = max3(aY, bY, cY);
67357
+ const z1 = max3(aZ, bZ, cZ);
67453
67358
 
67454
- const nodeThreshold = this.binaryNodeCount * 6;
67455
- const endAddress = this.boxCount * 6;
67456
-
67457
- while (stackPointer-- > stackOffset) {
67458
-
67459
- const index = stack$6[stackPointer];
67460
-
67461
- const address = index * 6;
67359
+ bvh.setLeafData(triangle_index, triangle_index, x0, y0, z0, x1, y1, z1);
67360
+ }
67361
+
67362
+ /**
67363
+ *
67364
+ * @param {BinaryUint32BVH} bvh
67365
+ * @param {Float32Array} vertices
67366
+ * @param {Uint32Array} indices
67367
+ */
67368
+ function bvh32_from_indexed_geometry(bvh, vertices, indices) {
67462
67369
 
67463
- const split = visitor.visit(address, NodeType.BINARY);
67464
- if (split) {
67370
+ const triangle_count = indices.length / 3;
67465
67371
 
67466
- const leftIndex = (index << 1) + 1;
67467
- const rightIndex = leftIndex + 1;
67372
+ bvh.setLeafCount(triangle_count);
67373
+ bvh.initialize_structure();
67468
67374
 
67469
- const leftAddress = leftIndex * 6;
67470
- const rightAddress = rightIndex * 6;
67375
+ for (let i = 0; i < triangle_count; i++) {
67471
67376
 
67472
- //right
67473
- if (rightAddress < endAddress) {
67474
- if (rightAddress < nodeThreshold) {
67475
- stack$6[stackPointer++] = rightIndex;
67476
- } else {
67477
- visitor.visit(rightAddress, NodeType.LEAF);
67478
- }
67479
- }
67377
+ const index3 = i * 3;
67480
67378
 
67481
- //left
67482
- if (leftAddress < endAddress) {
67483
- if (leftAddress < nodeThreshold) {
67484
- stack$6[stackPointer++] = leftIndex;
67485
- } else {
67486
- visitor.visit(leftAddress, NodeType.LEAF);
67487
- }
67488
- }
67489
- }
67490
- }
67379
+ // read triangle vertex indices
67380
+ const iA = indices[index3];
67381
+ const iB = indices[index3 + 1];
67382
+ const iC = indices[index3 + 2];
67491
67383
 
67492
- //drop stack
67493
- stackPointer = stackOffset;
67384
+ bvh32_set_leaf_from_triangle(bvh, i, vertices, iA, iB, iC);
67494
67385
  }
67495
67386
 
67496
- /**
67497
- *
67498
- * @param {function} visitor
67499
- * @param {number} index
67500
- * @param {number} type
67501
- */
67502
- traversePreOrder(visitor, index, type) {
67503
- const address = index * 6;
67504
- const carryOn = visitor(address, type);
67505
- const nodeThreshold = this.binaryNodeCount * 6;
67506
- const endAddress = this.boxCount * 6;
67507
-
67508
- if (carryOn !== false) {
67387
+ // finalize build
67388
+ // bvh.sort_morton(MATRIX_4_IDENTITY);
67389
+ bvh.build();
67390
+ }
67391
+
67392
+ /**
67393
+ *
67394
+ * @param {BinaryUint32BVH} bvh
67395
+ * @param {Float32Array} vertices
67396
+ */
67397
+ function bvh32_from_unindexed_geometry(bvh, vertices) {
67509
67398
 
67510
- const leftIndex = (index << 1) + 1;
67511
- const rightIndex = leftIndex + 1;
67399
+ const triangle_count = indices.length / 3;
67512
67400
 
67513
- const leftAddress = leftIndex * 6;
67514
- const rightAddress = rightIndex * 6;
67515
- //left
67516
- if (leftAddress < endAddress) {
67517
- if (leftAddress < nodeThreshold) {
67518
- this.traversePreOrder(visitor, leftIndex, NodeType.BINARY);
67519
- } else {
67520
- visitor(leftAddress, NodeType.LEAF);
67521
- }
67522
- }
67523
- //right
67524
- if (rightAddress < endAddress) {
67525
- if (rightAddress < nodeThreshold) {
67526
- this.traversePreOrder(visitor, rightIndex, NodeType.BINARY);
67527
- } else {
67528
- visitor(rightAddress, NodeType.LEAF);
67529
- }
67530
- }
67531
- }
67532
- }
67401
+ bvh.setLeafCount(triangle_count);
67402
+ bvh.initialize_structure();
67533
67403
 
67534
- /**
67535
- * @deprecated use a visitor object instead
67536
- * @param {number} startX
67537
- * @param {number} startY
67538
- * @param {number} startZ
67539
- * @param {number} directionX
67540
- * @param {number} directionY
67541
- * @param {number} directionZ
67542
- * @param {function} visitor
67543
- * @param {*} [thisArg]
67544
- */
67545
- traverseRayLeafIntersections(startX, startY, startZ, directionX, directionY, directionZ, visitor, thisArg) {
67546
- rayLeafIntersectionVisitor.originX = startX;
67547
- rayLeafIntersectionVisitor.originY = startY;
67548
- rayLeafIntersectionVisitor.originZ = startZ;
67404
+ for (let i = 0; i < triangle_count; i++) {
67549
67405
 
67550
- rayLeafIntersectionVisitor.directionX = directionX;
67551
- rayLeafIntersectionVisitor.directionY = directionY;
67552
- rayLeafIntersectionVisitor.directionZ = directionZ;
67406
+ const index3 = i * 3;
67553
67407
 
67554
- rayLeafIntersectionVisitor.root = this;
67555
- rayLeafIntersectionVisitor.callback = visitor;
67556
- rayLeafIntersectionVisitor.callbackThisArg = thisArg;
67408
+ // generate triangle vertex indices
67409
+ const iA = index3;
67410
+ const iB = index3 + 1;
67411
+ const iC = index3 + 2;
67557
67412
 
67558
- this.traversePreOrderStack(rayLeafIntersectionVisitor, 0);
67413
+ bvh32_set_leaf_from_triangle(bvh, i, vertices, iA, iB, iC);
67559
67414
  }
67560
- }
67561
67415
 
67416
+ // finalize build
67417
+ // bvh.sort_morton(MATRIX_4_IDENTITY);
67418
+ bvh.build();
67419
+ }
67420
+
67562
67421
  /**
67563
67422
  *
67564
- * @param {number[]|Float32Array} source
67565
- * @param {number} source_address_0
67566
- * @param {number} source_address_1
67567
- * @param {number[]|Float32Array} destination
67568
- * @param {number} destination_offset
67423
+ * @param {THREE.InterleavedBufferAttribute|THREE.BufferAttribute} source_attribute
67424
+ * @returns {THREE.BufferAttribute}
67569
67425
  */
67570
- function contain_box_array(source, source_address_0, source_address_1, destination, destination_offset) {
67571
-
67572
- const ax0 = source[source_address_0];
67573
- const ay0 = source[source_address_0 + 1];
67574
- const az0 = source[source_address_0 + 2];
67575
- const ax1 = source[source_address_0 + 3];
67576
- const ay1 = source[source_address_0 + 4];
67577
- const az1 = source[source_address_0 + 5];
67578
-
67579
- const bx0 = source[source_address_1];
67580
- const by0 = source[source_address_1 + 1];
67581
- const bz0 = source[source_address_1 + 2];
67582
- const bx1 = source[source_address_1 + 3];
67583
- const by1 = source[source_address_1 + 4];
67584
- const bz1 = source[source_address_1 + 5];
67585
-
67586
- const x0 = min2(ax0, bx0);
67587
- const y0 = min2(ay0, by0);
67588
- const z0 = min2(az0, bz0);
67426
+ function deinterleaveBufferAttribute(source_attribute) {
67427
+ if (source_attribute.isInterleavedBufferAttribute !== true && source_attribute.isBufferAttribute) {
67428
+ return source_attribute;
67429
+ }
67589
67430
 
67590
- const x1 = max2(ax1, bx1);
67591
- const y1 = max2(ay1, by1);
67592
- const z1 = max2(az1, bz1);
67431
+ const source_data = source_attribute.data;
67432
+ const source_data_array = source_data.array;
67433
+ const stride = source_data.stride;
67593
67434
 
67594
- destination[destination_offset] = x0;
67595
- destination[destination_offset + 1] = y0;
67596
- destination[destination_offset + 2] = z0;
67597
- destination[destination_offset + 3] = x1;
67598
- destination[destination_offset + 4] = y1;
67599
- destination[destination_offset + 5] = z1;
67600
- }
67435
+ const item_count = source_attribute.count;
67436
+ const itemSize = source_attribute.itemSize;
67437
+ const array_size = item_count * itemSize;
67601
67438
 
67602
- /**
67603
- *
67604
- * @param {Float32Array} array
67605
- * @param {number} address
67606
- * @param {number} x0
67607
- * @param {number} y0
67608
- * @param {number} z0
67609
- * @param {number} x1
67610
- * @param {number} y1
67611
- * @param {number} z1
67612
- */
67613
- function writeBox(array, address, x0, y0, z0, x1, y1, z1) {
67614
- array[address] = x0;
67615
- array[address + 1] = y0;
67616
- array[address + 2] = z0;
67617
- array[address + 3] = x1;
67618
- array[address + 4] = y1;
67619
- array[address + 5] = z1;
67620
- }
67439
+ const offset = source_attribute.offset;
67621
67440
 
67622
- /**
67623
- *
67624
- * @param {number} from
67625
- * @param {number} to
67626
- * @param {Float32Array} array
67627
- */
67628
- function copyBox(from, to, array) {
67629
- array_copy(array, from, array, to, 6);
67630
- }
67441
+ const destination_array = new source_data_array.constructor(array_size);
67631
67442
 
67632
- /**
67633
- *
67634
- * @param {number} from
67635
- * @param {number} to
67636
- * @param {Float32Array|number[]} array
67637
- */
67638
- function copyBoxZeroSize(from, to, array) {
67639
- array_copy(array, from, scratch_aabb_0, 0, 3);
67443
+ const attribute = new BufferAttribute(destination_array, itemSize);
67640
67444
 
67641
- scratch_aabb_0[3] = scratch_aabb_0[0];
67642
- scratch_aabb_0[4] = scratch_aabb_0[1];
67643
- scratch_aabb_0[5] = scratch_aabb_0[2];
67445
+ attribute.normalized = source_attribute.normalized;
67446
+ attribute.name = source_attribute.name;
67644
67447
 
67645
- array_copy(scratch_aabb_0, 0, array, to, 6);
67646
- }
67448
+ let i = 0, j = 0;
67449
+ // copy data
67450
+ for (; i < item_count; i++) {
67451
+ for (j = 0; j < itemSize; j++) {
67452
+ destination_array[i * itemSize + j] = source_data_array[i * stride + offset + j];
67453
+ }
67454
+ }
67647
67455
 
67456
+ return attribute;
67457
+ }
67458
+
67648
67459
  /**
67649
67460
  *
67650
- * @param {Float32Array} array
67651
- * @param {number} binaryNode
67652
- * @param {number} childNode0
67653
- * @param {number} childNode1
67461
+ * @param {Float32Array|number[]} aabb
67462
+ * @param {number} aabb_offset
67463
+ * @param {Float32Array|number[]} planes
67464
+ * @param {number} planes_offset
67465
+ * @param {number} plane_count
67466
+ * @return {boolean}
67654
67467
  */
67655
- function binaryNodeRefit(array, binaryNode, childNode0, childNode1) {
67656
- contain_box_array(array, childNode0, childNode1, array, binaryNode);
67657
- }
67658
-
67468
+ function aabb3_array_intersects_clipping_volume_array(
67469
+ aabb, aabb_offset,
67470
+ planes, planes_offset, plane_count
67471
+ ) {
67659
67472
 
67660
- const stack$6 = [];
67661
- let stackPointer = 0;
67473
+ const x0 = aabb[aabb_offset + 0];
67474
+ const y0 = aabb[aabb_offset + 1];
67475
+ const z0 = aabb[aabb_offset + 2];
67476
+ const x1 = aabb[aabb_offset + 3];
67477
+ const y1 = aabb[aabb_offset + 4];
67478
+ const z1 = aabb[aabb_offset + 5];
67662
67479
 
67663
- const rayLeafIntersectionVisitor = new RayLeafIntersectionVisitor();
67480
+ return aabb3_intersects_clipping_volume_array(
67481
+ x0, y0, z0,
67482
+ x1, y1, z1,
67483
+ planes, planes_offset, plane_count
67484
+ );
67485
+ }
67664
67486
 
67665
- /**
67666
- * Created by Alex on 29/05/2016.
67667
- */
67487
+ const stack$6 = SCRATCH_UINT32_TRAVERSAL_STACK;
67668
67488
 
67669
67489
  /**
67670
67490
  *
67671
- * @param {Float32Array|Float64Array|Array.<Number>} vertices
67672
- * @param {Uint8Array|Uint16Array|Uint32Array|Array.<Number>} indices
67673
- * @returns {IndexedBinaryBVH}
67491
+ * @param {number[]} result
67492
+ * @param {number} result_offset
67493
+ * @param {BinaryUint32BVH} bvh
67494
+ * @param {Float32Array|number[]} planes
67495
+ * @param {number} planes_offset
67496
+ * @param {number} plane_count
67497
+ * @returns {number}
67674
67498
  */
67675
- function buildUnsorted(vertices, indices) {
67676
- //
67677
- const numNodes = indices.length / 3;
67678
-
67679
- const tree = new IndexedBinaryBVH();
67680
- tree.initialize(numNodes);
67681
-
67682
- for (let i = 0; i < numNodes; i++) {
67683
-
67684
- const index3 = i * 3;
67685
-
67686
- // read triangle vertex indices
67687
- const iA = indices[index3];
67688
- const iB = indices[index3 + 1];
67689
- const iC = indices[index3 + 2];
67690
-
67691
- const a = iA * 3;
67692
- const b = iB * 3;
67693
- const c = iC * 3;
67694
-
67695
- // read actual positions of each vertex
67696
- const aX = vertices[a];
67697
- const aY = vertices[a + 1];
67698
- const aZ = vertices[a + 2];
67699
-
67700
- const bX = vertices[b];
67701
- const bY = vertices[b + 1];
67702
- const bZ = vertices[b + 2];
67499
+ function bvh32_query_user_data_overlaps_clipping_volume(
67500
+ result, result_offset,
67501
+ bvh,
67502
+ planes, planes_offset, plane_count
67503
+ ) {
67504
+ let hit_count = 0;
67703
67505
 
67704
- const cX = vertices[c];
67705
- const cY = vertices[c + 1];
67706
- const cZ = vertices[c + 2];
67506
+ const binary_node_count = bvh.binary_node_count;
67707
67507
 
67708
- // compute bounds of the triangle
67709
- const x0 = min3(aX, bX, cX);
67710
- const y0 = min3(aY, bY, cY);
67711
- const z0 = min3(aZ, bZ, cZ);
67508
+ if (binary_node_count <= 0) {
67509
+ // this should not happen
67510
+ return 0;
67511
+ }
67712
67512
 
67713
- const x1 = max3(aX, bX, cX);
67714
- const y1 = max3(aY, bY, cY);
67715
- const z1 = max3(aZ, bZ, cZ);
67513
+ /**
67514
+ *
67515
+ * @type {number}
67516
+ */
67517
+ const stack_top = stack$6.pointer++;
67716
67518
 
67717
- tree.writeLeaf(i, x0, y0, z0, x1, y1, z1);
67718
- }
67519
+ /**
67520
+ * After performing empirical tests, stack-based depth-first traversal turns out faster than using a queue
67521
+ * @type {number}
67522
+ */
67523
+ stack$6[stack_top] = 0;
67719
67524
 
67720
- // finalize build
67721
- tree.unsortedBuiltIntermediate();
67525
+ const last_valid_index = binary_node_count + bvh.leaf_node_count;
67722
67526
 
67723
- return tree;
67724
- }
67527
+ const float32 = bvh.float32;
67528
+ const uint32 = bvh.uint32;
67725
67529
 
67726
- /**
67727
- *
67728
- * @param {Float32Array|Float64Array|Array.<Number>} vertices
67729
- * @returns {IndexedBinaryBVH}
67730
- */
67731
- function buildUnsortedUnindexed(vertices) {
67732
- //
67733
- const numNodes = vertices.length / 9;
67530
+ do {
67531
+ stack$6.pointer--;
67734
67532
 
67735
- const tree = new IndexedBinaryBVH();
67736
- tree.initialize(numNodes);
67533
+ // query_bvh_frustum_from_objects.iteration_count++;
67534
+ const node_index = stack$6[stack$6.pointer];
67737
67535
 
67738
- for (let i = 0; i < numNodes; i++) {
67536
+ const node_address = bvh.getNodeAddress(node_index);
67739
67537
 
67740
- const index3 = i * 3;
67538
+ if (!aabb3_array_intersects_clipping_volume_array(
67539
+ float32, node_address,
67540
+ planes, planes_offset, plane_count
67541
+ )) {
67542
+ continue;
67543
+ }
67741
67544
 
67742
- // read triangle vertex indices
67743
- const iA = index3;
67744
- const iB = index3 + 1;
67745
- const iC = index3 + 2;
67545
+ const is_intermediate_node = node_index < binary_node_count;
67746
67546
 
67747
- const a = iA * 3;
67748
- const b = iB * 3;
67749
- const c = iC * 3;
67547
+ if (is_intermediate_node) {
67548
+ // is intermediate node
67750
67549
 
67751
- // read actual positions of each vertex
67752
- const aX = vertices[a];
67753
- const aY = vertices[a + 1];
67754
- const aZ = vertices[a + 2];
67550
+ const left_index = (node_index << 1) + 1;
67551
+ const right_index = left_index + 1;
67755
67552
 
67756
- const bX = vertices[b];
67757
- const bY = vertices[b + 1];
67758
- const bZ = vertices[b + 2];
67553
+ // left node ends up on top of the stack, which aligns with the desired access sequence
67554
+ if (right_index < last_valid_index) {
67555
+ stack$6[stack$6.pointer++] = right_index;
67556
+ // micro-optimization, since we know that right node is valid and left appears before that, left is valid too
67557
+ stack$6[stack$6.pointer++] = left_index;
67558
+ } else if (left_index < last_valid_index) {
67559
+ stack$6[stack$6.pointer++] = left_index;
67560
+ }
67759
67561
 
67760
- const cX = vertices[c];
67761
- const cY = vertices[c + 1];
67762
- const cZ = vertices[c + 2];
67763
67562
 
67764
- // compute bounds of the triangle
67765
- const x0 = min3(aX, bX, cX);
67766
- const y0 = min3(aY, bY, cY);
67767
- const z0 = min3(aZ, bZ, cZ);
67563
+ } else {
67564
+ // leaf node
67768
67565
 
67769
- const x1 = max3(aX, bX, cX);
67770
- const y1 = max3(aY, bY, cY);
67771
- const z1 = max3(aZ, bZ, cZ);
67566
+ // write to output
67567
+ result[result_offset + hit_count] = uint32[node_address + 6];
67772
67568
 
67773
- tree.writeLeaf(i, x0, y0, z0, x1, y1, z1);
67774
- }
67569
+ hit_count++;
67570
+ }
67775
67571
 
67776
- // finalize build
67777
- tree.unsortedBuiltIntermediate();
67572
+ } while (stack$6.pointer > stack_top)
67778
67573
 
67779
- return tree;
67574
+ return hit_count;
67780
67575
  }
67781
67576
 
67782
67577
  /**
@@ -67813,526 +67608,145 @@ function computeTrianglePlaneSide(
67813
67608
  return result;
67814
67609
  }
67815
67610
 
67816
- class GeometrySpatialAcceleratorVisitor extends IndexedBinaryBVHVisitor {
67817
- constructor() {
67818
- super();
67819
-
67820
-
67821
- /**
67822
- * @protected
67823
- * @type {THREE.BufferGeometry}
67824
- */
67825
- this.__geometry = null;
67826
-
67827
- /**
67828
- *
67829
- * @type {number[]}
67830
- * @protected
67831
- */
67832
- this.__buffer_indices = null;
67833
-
67834
- /**
67835
- *
67836
- * @type {number[]}
67837
- * @protected
67838
- */
67839
- this.__buffer_vertices = null;
67840
-
67841
- /**
67842
- *
67843
- * @type {number}
67844
- * @protected
67845
- */
67846
- this.__buffer_vertex_stride = 3;
67847
-
67848
- /**
67849
- *
67850
- * @type {number}
67851
- * @protected
67852
- */
67853
- this.__buffer_position_offset = 0;
67854
-
67855
- /**
67856
- * @protected
67857
- * @type {IndexedBinaryBVH}
67858
- */
67859
- this.__root = null;
67860
- }
67861
-
67862
- /**
67863
- * @param {IndexedBinaryBVH} root
67864
- */
67865
- setRoot(root) {
67866
- this.__root = root;
67867
- }
67868
-
67869
-
67870
- /**
67871
- * @param {THREE.BufferGeometry} geometry
67872
- */
67873
- setGeometry(geometry) {
67874
- this.geometry = geometry;
67875
-
67876
- const index_attribute = geometry.getIndex();
67877
-
67878
- if (index_attribute) {
67879
- this.__buffer_indices = index_attribute.array;
67880
- } else {
67881
- // no index attribute
67882
- this.__buffer_indices = null;
67883
- }
67884
-
67885
- const position_attribute = geometry.getAttribute('position');
67886
-
67887
- if (position_attribute.isInterleavedBufferAttribute) {
67888
- const data = position_attribute.data;
67889
-
67890
- this.__buffer_vertices = data.array;
67891
- this.__buffer_vertex_stride = data.stride;
67892
- this.__buffer_position_offset = position_attribute.offset;
67893
- } else {
67894
- this.__buffer_vertices = position_attribute.array;
67895
- this.__buffer_vertex_stride = 3;
67896
- this.__buffer_position_offset = 0;
67897
- }
67898
- }
67899
-
67900
- }
67901
-
67902
- class ClippingPlaneContainmentComputingVisitor extends GeometrySpatialAcceleratorVisitor {
67903
- constructor() {
67904
- super();
67905
-
67906
- /**
67907
- * @private
67908
- * @type {Plane[]}
67909
- */
67910
- this.planes = [];
67911
-
67912
- /**
67913
- *
67914
- * @private
67915
- * @type {number}
67916
- */
67917
- this.plane_count = 0;
67918
-
67919
- this.__hit_count_in = 0;
67920
- this.__hit_count_out = 0;
67921
- this.__hit_count_intersect = 0;
67922
- }
67923
-
67924
- reset() {
67925
- this.__hit_count_in = 0;
67926
- this.__hit_count_intersect = 0;
67927
- this.__hit_count_out = 0;
67928
- }
67929
-
67930
- /**
67931
- *
67932
- * @returns {number}
67933
- */
67934
- getContainment() {
67935
- if (this.__hit_count_out === 0) {
67936
- if (this.__hit_count_intersect > 0) {
67937
- return 0;
67938
- } else {
67939
- // fully in
67940
- return 1;
67941
- }
67942
- } else {
67943
- if (this.__hit_count_intersect > 0 || this.__hit_count_in > 0) {
67944
- return 0;
67945
- } else {
67946
- // fully out
67947
- return -1;
67948
- }
67949
- }
67950
- }
67951
-
67952
- /**
67953
- * @param {Plane[]} planes
67954
- */
67955
- setPlanes(planes) {
67956
- this.planes = planes;
67957
- this.plane_count = planes.length;
67958
- }
67959
-
67960
-
67961
- visit(address, type) {
67962
- const root = this.__root;
67963
-
67964
- const data = root.data;
67965
- const binaryNodeCount = root.binaryNodeCount;
67966
-
67967
- const planes = this.planes;
67968
- const plane_count = this.plane_count;
67969
-
67970
- let intersect_flag = false;
67971
- if (type === NodeType.LEAF) {
67972
- // check triangle intersection
67973
-
67974
- const index = address / 6 - binaryNodeCount;
67975
-
67976
- const index3 = index * 3;
67977
-
67978
- const indices = this.__buffer_indices;
67979
-
67980
- const a = indices[index3];
67981
- const b = indices[index3 + 1];
67982
- const c = indices[index3 + 2];
67983
-
67984
- const vertices = this.__buffer_vertices;
67985
-
67986
- const stride = this.__buffer_vertex_stride;
67987
- const offset = this.__buffer_position_offset;
67988
-
67989
- const a_address = a * stride + offset;
67990
- const b_address = b * stride + offset;
67991
- const c_address = c * stride + offset;
67992
-
67993
- const ax = vertices[a_address];
67994
- const ay = vertices[a_address + 1];
67995
- const az = vertices[a_address + 2];
67996
-
67997
- const bx = vertices[b_address];
67998
- const by = vertices[b_address + 1];
67999
- const bz = vertices[b_address + 2];
68000
-
68001
- const cx = vertices[c_address];
68002
- const cy = vertices[c_address + 1];
68003
- const cz = vertices[c_address + 2];
68004
-
68005
- for (let i = 0; i < plane_count; i++) {
68006
- const plane = planes[i];
68007
-
68008
- const plane_normal_x = plane.normal.x;
68009
- const plane_normal_y = plane.normal.y;
68010
- const plane_normal_z = plane.normal.z;
68011
- const plane_constant = plane.constant;
68012
-
68013
- const side = computeTrianglePlaneSide(
68014
- plane_normal_x,
68015
- plane_normal_y,
68016
- plane_normal_z,
68017
- plane_constant,
68018
- ax, ay, az,
68019
- bx, by, bz,
68020
- cx, cy, cz
68021
- );
68022
-
68023
- if (side === -3) {
68024
- // fully outside
68025
- this.__hit_count_out++;
68026
- return false;
68027
- } else if (side < 3) {
68028
- intersect_flag = true;
68029
- }
68030
- }
68031
-
68032
- if (intersect_flag) {
68033
- this.__hit_count_intersect++;
68034
- } else {
68035
- this.__hit_count_in++;
68036
- }
68037
-
68038
- return false;
68039
- } else {
68040
- // this is an intermediate node (binary node)
68041
-
68042
- // check AABB intersection
68043
-
68044
-
68045
- const x0 = data[address];
68046
- const y0 = data[address + 1];
68047
- const z0 = data[address + 2];
68048
- const x1 = data[address + 3];
68049
- const y1 = data[address + 4];
68050
- const z1 = data[address + 5];
68051
-
68052
-
68053
- for (let i = 0; i < plane_count; i++) {
68054
- const plane = planes[i];
68055
-
68056
- const plane_normal_x = plane.normal.x;
68057
- const plane_normal_y = plane.normal.y;
68058
- const plane_normal_z = plane.normal.z;
68059
- const plane_constant = plane.constant;
68060
-
68061
- const side = aabb3_compute_plane_side(
68062
- plane_normal_x,
68063
- plane_normal_y,
68064
- plane_normal_z,
68065
- plane_constant,
68066
-
68067
- x0, y0, z0,
68068
- x1, y1, z1
68069
- );
68070
-
68071
- if (side === -2) {
68072
- this.__hit_count_out++;
68073
-
68074
- return false;
68075
- } else if (side === 0) {
68076
- intersect_flag = true;
68077
- }
68078
- }
68079
-
68080
- if (intersect_flag) {
68081
- return true;
68082
- } else {
68083
- // no need to traverse further down, the whole node is in
68084
- this.__hit_count_in++;
68085
- return false;
68086
- }
68087
- }
68088
-
68089
-
68090
- }
68091
- }
68092
-
68093
- class RaycastNearestHitComputingVisitor extends GeometrySpatialAcceleratorVisitor {
68094
- constructor() {
68095
- super();
68096
-
68097
-
68098
- /**
68099
- *
68100
- * @type {number}
68101
- * @private
68102
- */
68103
- this.__nearest_distance = Number.POSITIVE_INFINITY;
68104
-
68105
- /**
68106
- * @readonly
68107
- * @type {SurfacePoint3}
68108
- * @private
68109
- */
68110
- this.__nearest_hit = new SurfacePoint3();
68111
-
68112
- /**
68113
- * @readonly
68114
- * @type {SurfacePoint3}
68115
- * @private
68116
- */
68117
- this.__temp_hit = new SurfacePoint3();
68118
-
68119
- /**
68120
- *
68121
- * @type {boolean}
68122
- * @private
68123
- */
68124
- this.__hit_found = false;
67611
+ /**
67612
+ * @param {number[]|Float32Array} planes
67613
+ * @param {number} planes_offset
67614
+ * @param {number} plane_count
67615
+ * @param {number} ax
67616
+ * @param {number} ay
67617
+ * @param {number} az
67618
+ * @param {number} bx
67619
+ * @param {number} by
67620
+ * @param {number} bz
67621
+ * @param {number} cx
67622
+ * @param {number} cy
67623
+ * @param {number} cz
67624
+ * @returns {boolean}
67625
+ */
67626
+ function triangle_intersects_clipping_volume(
67627
+ planes, planes_offset, plane_count,
67628
+ ax, ay, az,
67629
+ bx, by, bz,
67630
+ cx, cy, cz
67631
+ ) {
68125
67632
 
68126
- /**
68127
- * @readonly
68128
- * @type {Vector3}
68129
- * @private
68130
- */
68131
- this.__ray_origin = new Vector3$1();
67633
+ for (let j = 0; j < plane_count; j++) {
68132
67634
 
68133
- /**
68134
- * @readonly
68135
- * @type {Vector3}
68136
- * @private
68137
- */
68138
- this.__ray_direction = new Vector3$1();
68139
- }
67635
+ const plane_address = planes_offset + j * 4;
68140
67636
 
68141
- /**
68142
- *
68143
- * @param {number} origin_x
68144
- * @param {number} origin_y
68145
- * @param {number} origin_z
68146
- * @param {number} direction_x
68147
- * @param {number} direction_y
68148
- * @param {number} direction_z
68149
- */
68150
- setRay(origin_x, origin_y, origin_z, direction_x, direction_y, direction_z) {
68151
- this.__ray_origin.set(
68152
- origin_x,
68153
- origin_y,
68154
- origin_z
68155
- );
67637
+ const plane_normal_x = planes[plane_address];
67638
+ const plane_normal_y = planes[plane_address + 1];
67639
+ const plane_normal_z = planes[plane_address + 2];
67640
+ const plane_constant = planes[plane_address + 3];
68156
67641
 
68157
- this.__ray_direction.set(
68158
- direction_x,
68159
- direction_y,
68160
- direction_z
67642
+ const side = computeTrianglePlaneSide(
67643
+ plane_normal_x,
67644
+ plane_normal_y,
67645
+ plane_normal_z,
67646
+ plane_constant,
67647
+ ax, ay, az,
67648
+ bx, by, bz,
67649
+ cx, cy, cz
68161
67650
  );
68162
- }
68163
-
68164
- reset() {
68165
- this.__nearest_distance = Number.POSITIVE_INFINITY;
68166
- this.__hit_found = false;
68167
- }
68168
-
68169
- getNearestHit() {
68170
- return this.__nearest_hit;
68171
- }
68172
-
68173
- isHitFound() {
68174
- return this.__hit_found;
68175
- }
68176
-
68177
-
68178
- visit(address, type) {
68179
- const root = this.__root;
68180
-
68181
- const data = root.data;
68182
- const binaryNodeCount = root.binaryNodeCount;
68183
-
68184
- const rayOrigin = this.__ray_origin;
68185
- const rayDirection = this.__ray_direction;
68186
-
68187
- if (type === NodeType.LEAF) {
68188
- // do triangle test
68189
-
68190
- const index = address / 6 - binaryNodeCount;
68191
-
68192
- const index3 = index * 3;
68193
-
68194
- const indices = this.__buffer_indices;
68195
-
68196
- let a, b, c;
68197
-
68198
- if (indices !== null) {
68199
- assert.lessThan(index3 + 2, indices.length, 'triangle index overflow, possibly geometry changed but tree was not rebuilt?');
68200
-
68201
- a = indices[index3];
68202
- b = indices[index3 + 1];
68203
- c = indices[index3 + 2];
68204
- } else {
68205
- // implicit indices
68206
- a = index3;
68207
- b = index3 + 1;
68208
- c = index3 + 2;
68209
- }
68210
-
68211
- const vertices = this.__buffer_vertices;
68212
-
68213
- const stride = this.__buffer_vertex_stride;
68214
- const offset = this.__buffer_position_offset;
68215
-
68216
- const a_address = a * stride + offset;
68217
- const b_address = b * stride + offset;
68218
- const c_address = c * stride + offset;
68219
-
68220
- assert.lessThan(a_address + 2, vertices.length, 'a-vertex overflow');
68221
- assert.lessThan(b_address + 2, vertices.length, 'b-vertex overflow');
68222
- assert.lessThan(c_address + 2, vertices.length, 'c-vertex overflow');
68223
-
68224
- const ax = vertices[a_address];
68225
- const ay = vertices[a_address + 1];
68226
- const az = vertices[a_address + 2];
68227
-
68228
- const bx = vertices[b_address];
68229
- const by = vertices[b_address + 1];
68230
- const bz = vertices[b_address + 2];
68231
-
68232
- const cx = vertices[c_address];
68233
- const cy = vertices[c_address + 1];
68234
- const cz = vertices[c_address + 2];
68235
-
68236
- const temp_hit = this.__temp_hit;
68237
-
68238
- if (computeTriangleRayIntersection(
68239
- temp_hit,
68240
- rayOrigin.x,
68241
- rayOrigin.y,
68242
- rayOrigin.z,
68243
- rayDirection.x,
68244
- rayDirection.y,
68245
- rayDirection.z,
68246
- ax, ay, az,
68247
- bx, by, bz,
68248
- cx, cy, cz
68249
- )) {
68250
- const d = temp_hit.position.distanceSqrTo(rayOrigin);
68251
-
68252
- if (d < this.__nearest_distance) {
68253
- this.__nearest_hit.copy(temp_hit);
68254
- this.__nearest_hit.index = index;
68255
-
68256
- this.__nearest_distance = d;
68257
-
68258
- this.__hit_found = true;
68259
- }
68260
-
68261
- }
68262
67651
 
67652
+ if (side === -3) {
67653
+ // fully outside
68263
67654
  return false;
68264
-
68265
- } else {
68266
- // do AABB test
68267
-
68268
- const x0 = data[address];
68269
- const y0 = data[address + 1];
68270
- const z0 = data[address + 2];
68271
- const x1 = data[address + 3];
68272
- const y1 = data[address + 4];
68273
- const z1 = data[address + 5];
68274
-
68275
- return aabb3_intersects_ray(
68276
- x0, y0, z0,
68277
- x1, y1, z1,
68278
-
68279
- rayOrigin.x,
68280
- rayOrigin.y,
68281
- rayOrigin.z,
68282
-
68283
- rayDirection.x,
68284
- rayDirection.y,
68285
- rayDirection.z
68286
- );
68287
-
68288
67655
  }
68289
67656
  }
67657
+
67658
+ return true;
68290
67659
  }
68291
67660
 
67661
+ const scratch_array$2 = [];
67662
+
68292
67663
  /**
68293
67664
  *
68294
- * @param {THREE.InterleavedBufferAttribute|THREE.BufferAttribute} source_attribute
68295
- * @returns {THREE.BufferAttribute}
67665
+ * @param {BinaryUint32BVH} bvh
67666
+ * @param {number[]|ArrayLike<number>} vertices
67667
+ * @param {number} vertex_offset Unless you're using an interleaved buffer of some kind, this will be 0
67668
+ * @param {number} vertex_stride Unless you're using an interleaved buffer, this should be 3
67669
+ * @param {number[]|ArrayLike<number>|undefined} indices if this is set to undefined - implicit indexing will be used
67670
+ * @param {number[]|Float32Array} planes
67671
+ * @param {number} planes_offset
67672
+ * @param {number} plane_count
67673
+ * @returns {boolean}
68296
67674
  */
68297
- function deinterleaveBufferAttribute(source_attribute) {
68298
- if (source_attribute.isInterleavedBufferAttribute !== true && source_attribute.isBufferAttribute) {
68299
- return source_attribute;
68300
- }
68301
-
68302
- const source_data = source_attribute.data;
68303
- const source_data_array = source_data.array;
68304
- const stride = source_data.stride;
67675
+ function bvh32_geometry_overlap_clipping_volume(
67676
+ bvh,
67677
+ vertices, vertex_offset, vertex_stride,
67678
+ indices,
67679
+ planes, planes_offset, plane_count
67680
+ ) {
68305
67681
 
68306
- const item_count = source_attribute.count;
68307
- const itemSize = source_attribute.itemSize;
68308
- const array_size = item_count * itemSize;
67682
+ const hit_count = bvh32_query_user_data_overlaps_clipping_volume(
67683
+ scratch_array$2, 0,
67684
+ bvh,
67685
+ planes, planes_offset, plane_count
67686
+ );
68309
67687
 
68310
- const offset = source_attribute.offset;
67688
+ let a, b, c;
68311
67689
 
68312
- const destination_array = new source_data_array.constructor(array_size);
67690
+ for (let i = 0; i < hit_count; i++) {
67691
+ const triangle_index = scratch_array$2[i];
68313
67692
 
68314
- const attribute = new BufferAttribute(destination_array, itemSize);
67693
+ const index3 = triangle_index * 3;
68315
67694
 
68316
- attribute.normalized = source_attribute.normalized;
68317
- attribute.name = source_attribute.name;
67695
+ if (indices !== undefined) {
67696
+ assert.lessThan(index3 + 2, indices.length, 'triangle index overflow, possibly geometry changed but tree was not rebuilt?');
68318
67697
 
68319
- let i = 0, j = 0;
68320
- // copy data
68321
- for (; i < item_count; i++) {
68322
- for (j = 0; j < itemSize; j++) {
68323
- destination_array[i * itemSize + j] = source_data_array[i * stride + offset + j];
67698
+ a = indices[index3];
67699
+ b = indices[index3 + 1];
67700
+ c = indices[index3 + 2];
67701
+ } else {
67702
+ // implicit indices
67703
+ a = index3;
67704
+ b = index3 + 1;
67705
+ c = index3 + 2;
67706
+ }
67707
+
67708
+ const a_address = a * vertex_stride + vertex_offset;
67709
+ const b_address = b * vertex_stride + vertex_offset;
67710
+ const c_address = c * vertex_stride + vertex_offset;
67711
+
67712
+ assert.lessThan(a_address + 2, vertices.length, 'a-vertex overflow');
67713
+ assert.lessThan(b_address + 2, vertices.length, 'b-vertex overflow');
67714
+ assert.lessThan(c_address + 2, vertices.length, 'c-vertex overflow');
67715
+
67716
+ const ax = vertices[a_address];
67717
+ const ay = vertices[a_address + 1];
67718
+ const az = vertices[a_address + 2];
67719
+
67720
+ const bx = vertices[b_address];
67721
+ const by = vertices[b_address + 1];
67722
+ const bz = vertices[b_address + 2];
67723
+
67724
+ const cx = vertices[c_address];
67725
+ const cy = vertices[c_address + 1];
67726
+ const cz = vertices[c_address + 2];
67727
+
67728
+ if (triangle_intersects_clipping_volume(
67729
+ planes, planes_offset, plane_count,
67730
+ ax, ay, az,
67731
+ bx, by, bz,
67732
+ cx, cy, cz
67733
+ )) {
67734
+ return true;
68324
67735
  }
67736
+
68325
67737
  }
68326
67738
 
68327
- return attribute;
67739
+ return false;
68328
67740
  }
68329
67741
 
67742
+ const scratch_planes = [];
67743
+
68330
67744
  class GeometrySpatialQueryAccelerator {
68331
67745
  constructor(cache_size = 100 * 1024 * 1024) {
68332
67746
 
68333
67747
  /**
68334
67748
  *
68335
- * @type {Cache<THREE.BufferGeometry, IndexedBinaryBVH>}
67749
+ * @type {Cache<THREE.BufferGeometry, BinaryUint32BVH>}
68336
67750
  */
68337
67751
  this.cache = new Cache({
68338
67752
  maxWeight: cache_size,
@@ -68344,15 +67758,13 @@ class GeometrySpatialQueryAccelerator {
68344
67758
  },
68345
67759
  /**
68346
67760
  *
68347
- * @param {IndexedBinaryBVH} tree
67761
+ * @param {BinaryUint32BVH} tree
68348
67762
  */
68349
67763
  valueWeigher(tree) {
68350
67764
  return tree.estimateByteSize();
68351
67765
  }
68352
67766
  });
68353
67767
 
68354
- this.__visitor_clip = new ClippingPlaneContainmentComputingVisitor();
68355
- this.__visitor_raycast = new RaycastNearestHitComputingVisitor();
68356
67768
  }
68357
67769
 
68358
67770
  /**
@@ -68375,23 +67787,46 @@ class GeometrySpatialQueryAccelerator {
68375
67787
  *
68376
67788
  * @param {THREE.BufferGeometry} geometry
68377
67789
  * @param {Plane[]} planes
68378
- * @returns {number} -1,0,1. -1 means fully outside, 0 means partially inside, 1 means fully inside
67790
+ * @returns {boolean} true means some overlap exists, false otherwise
68379
67791
  */
68380
67792
  queryContainmentViaClippingPlanes(geometry, planes) {
68381
67793
  assert.notNull(geometry, 'geometry');
68382
67794
  assert.defined(geometry, 'geometry');
68383
67795
 
67796
+
68384
67797
  const bvh = this.__acquireBVH(geometry);
68385
67798
 
68386
- this.__visitor_clip.reset();
67799
+ read_three_planes_to_array(planes, scratch_planes);
67800
+
67801
+ const geometryIndices = geometry.getIndex()?.array;
67802
+ const position_attribute = geometry.getAttribute('position');
67803
+
67804
+ let position_data;
67805
+ let stride = 3;
67806
+ let position_data_offset = 0;
67807
+
67808
+ if (position_attribute.isInterleavedBufferAttribute) {
67809
+
67810
+ position_data = position_attribute.data.array;
68387
67811
 
68388
- this.__visitor_clip.setGeometry(geometry);
68389
- this.__visitor_clip.setPlanes(planes);
68390
- this.__visitor_clip.setRoot(bvh);
67812
+ stride = position_attribute.data.stride;
67813
+ position_data_offset = position_attribute.offset;
68391
67814
 
68392
- bvh.traversePreOrderStack(this.__visitor_clip, 0);
67815
+ } else {
68393
67816
 
68394
- return this.__visitor_clip.getContainment();
67817
+ position_data = position_attribute.array;
67818
+
67819
+ stride = 3;
67820
+ position_data_offset = 0;
67821
+
67822
+ }
67823
+
67824
+ return bvh32_geometry_overlap_clipping_volume(
67825
+ bvh,
67826
+ position_data, position_data_offset, stride,
67827
+ geometryIndices,
67828
+ scratch_planes, 0, planes.length
67829
+ );
68395
67830
  }
68396
67831
 
68397
67832
  /**
@@ -68441,11 +67876,33 @@ class GeometrySpatialQueryAccelerator {
68441
67876
  return false;
68442
67877
  }
68443
67878
 
68444
- this.__visitor_raycast.reset();
67879
+ const geometryIndices = geometry.getIndex()?.array;
67880
+ const position_attribute = geometry.getAttribute('position');
67881
+
67882
+ let position_data;
67883
+ let stride = 3;
67884
+ let position_data_offset = 0;
67885
+
67886
+ if (position_attribute.isInterleavedBufferAttribute) {
67887
+
67888
+ position_data = position_attribute.data.array;
67889
+
67890
+ stride = position_attribute.data.stride;
67891
+ position_data_offset = position_attribute.offset;
67892
+
67893
+ } else {
67894
+
67895
+ position_data = position_attribute.array;
67896
+
67897
+ stride = 3;
67898
+ position_data_offset = 0;
67899
+
67900
+ }
68445
67901
 
68446
- this.__visitor_raycast.setGeometry(geometry);
68447
- this.__visitor_raycast.setRoot(bvh);
68448
- this.__visitor_raycast.setRay(
67902
+ return bvh32_geometry_raycast(
67903
+ destination, bvh,
67904
+ position_data, position_data_offset, stride,
67905
+ geometryIndices,
68449
67906
  ray_origin_x,
68450
67907
  ray_origin_y,
68451
67908
  ray_origin_z,
@@ -68454,16 +67911,6 @@ class GeometrySpatialQueryAccelerator {
68454
67911
  ray_direction_z
68455
67912
  );
68456
67913
 
68457
- bvh.traversePreOrderStack(this.__visitor_raycast, 0);
68458
-
68459
- if (this.__visitor_raycast.isHitFound()) {
68460
-
68461
- destination.copy(this.__visitor_raycast.getNearestHit());
68462
-
68463
- return true;
68464
- } else {
68465
- return false;
68466
- }
68467
67914
  }
68468
67915
 
68469
67916
  /**
@@ -68491,7 +67938,7 @@ class GeometrySpatialQueryAccelerator {
68491
67938
  /**
68492
67939
  * @private
68493
67940
  * @param {THREE.BufferGeometry} geometry
68494
- * @returns {IndexedBinaryBVH}
67941
+ * @returns {BinaryUint32BVH}
68495
67942
  */
68496
67943
  __acquireBVH(geometry) {
68497
67944
  assert.notNull(geometry, 'geometry');
@@ -68513,7 +67960,7 @@ class GeometrySpatialQueryAccelerator {
68513
67960
  /**
68514
67961
  * @private
68515
67962
  * @param {THREE.BufferGeometry} geometry
68516
- * @returns {IndexedBinaryBVH}
67963
+ * @returns {BinaryUint32BVH}
68517
67964
  */
68518
67965
  __buildBVH(geometry) {
68519
67966
  const position_attribute = geometry.getAttribute('position');
@@ -68522,14 +67969,19 @@ class GeometrySpatialQueryAccelerator {
68522
67969
  const de_interleaved_position_attribute = deinterleaveBufferAttribute(position_attribute);
68523
67970
  const vertices = de_interleaved_position_attribute.array;
68524
67971
 
67972
+ const bvh = new BinaryUint32BVH();
67973
+
68525
67974
  if (index_attribute === undefined || index_attribute === null) {
68526
- return buildUnsortedUnindexed(vertices);
68527
- }
67975
+ bvh32_from_unindexed_geometry(bvh, vertices);
67976
+ } else {
68528
67977
 
68529
- const de_interleaved_index_attribute = deinterleaveBufferAttribute(index_attribute);
68530
- const indices = de_interleaved_index_attribute.array;
67978
+ const de_interleaved_index_attribute = deinterleaveBufferAttribute(index_attribute);
67979
+ const indices = de_interleaved_index_attribute.array;
68531
67980
 
68532
- return buildUnsorted(vertices, indices);
67981
+ bvh32_from_indexed_geometry(bvh, vertices, indices);
67982
+ }
67983
+
67984
+ return bvh;
68533
67985
  }
68534
67986
 
68535
67987
  }
@@ -69348,29 +68800,6 @@ function bvh_query_user_data_overlaps_frustum(
69348
68800
  return result_cursor - result_offset;
69349
68801
  }
69350
68802
 
69351
- /**
69352
- *
69353
- * @param {Plane[]} planes
69354
- * @param {ArrayLike<number>|number[]|Float32Array|Float64Array} array
69355
- */
69356
- function read_frustum_planes_to_array(planes, array) {
69357
- assert.greaterThanOrEqual(array.length, 24, 'target array is too small');
69358
-
69359
- for (let i = 0; i < 6; i++) {
69360
- const plane = planes[i];
69361
-
69362
- const offset = i * 4;
69363
-
69364
- const normal = plane.normal;
69365
-
69366
- array[offset] = normal.x;
69367
- array[offset + 1] = normal.y;
69368
- array[offset + 2] = normal.z;
69369
-
69370
- array[offset + 3] = plane.constant;
69371
- }
69372
- }
69373
-
69374
68803
  /**
69375
68804
  * @template CTX
69376
68805
  * @template Asset
@@ -71961,7 +71390,7 @@ class TerrainSystem extends System {
71961
71390
 
71962
71391
  for (let i = 0; i < frustums.length; i++) {
71963
71392
 
71964
- read_frustum_planes_to_array(frustums[i].planes, frustum);
71393
+ read_three_planes_to_array(frustums[i].planes, frustum);
71965
71394
 
71966
71395
  found_tiles += bvh_query_user_data_overlaps_frustum(tiles, tile_count, tileManager.bvh, frustum);
71967
71396
  }
@@ -91558,7 +90987,7 @@ class CameraView {
91558
90987
  frustum_from_camera(camera, scratch_frustum, false);
91559
90988
 
91560
90989
  // update view definition
91561
- read_frustum_planes_to_array(scratch_frustum.planes, this.frustum);
90990
+ read_three_planes_to_array(scratch_frustum.planes, this.frustum);
91562
90991
 
91563
90992
  // read projection matrix
91564
90993
  // TODO
@@ -111244,7 +110673,7 @@ function query_bvh_frustum_from_texture(
111244
110673
  ) {
111245
110674
  let result = 0;
111246
110675
 
111247
- const binary_node_count = bvh.getBinaryNodeCount();
110676
+ const binary_node_count = bvh.binary_node_count;
111248
110677
 
111249
110678
  if (binary_node_count <= 0) {
111250
110679
  // this should not happen
@@ -111263,7 +110692,7 @@ function query_bvh_frustum_from_texture(
111263
110692
  */
111264
110693
  stack[stack_top] = 0;
111265
110694
 
111266
- const last_valid_index = binary_node_count + bvh.getLeafNodeCount();
110695
+ const last_valid_index = binary_node_count + bvh.leaf_node_count;
111267
110696
 
111268
110697
  const float32 = bvh.float32;
111269
110698
  const uint32 = bvh.uint32;
@@ -112819,7 +112248,7 @@ class LightManager {
112819
112248
 
112820
112249
  const nodes = [];
112821
112250
 
112822
- read_frustum_planes_to_array(this.__view_frustum.planes, scratch_frustum_planes);
112251
+ read_three_planes_to_array(this.__view_frustum.planes, scratch_frustum_planes);
112823
112252
 
112824
112253
  /*
112825
112254
  Search is done in 2 phases: