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