@woosh/meep-engine 2.68.0 → 2.70.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/build/bundle-worker-image-decoder.js +1 -1
  2. package/build/bundle-worker-terrain.js +1 -1
  3. package/build/meep.cjs +1090 -1581
  4. package/build/meep.min.js +1 -1
  5. package/build/meep.module.js +1090 -1581
  6. package/package.json +1 -1
  7. package/src/core/__module.js +1 -0
  8. package/src/core/binary/BinaryBuffer.js +37 -31
  9. package/src/core/bvh2/binary/2/BinaryUint32BVH.js +76 -52
  10. package/src/core/bvh2/binary/2/BinaryUint32BVH.spec.js +5 -7
  11. package/src/core/bvh2/binary/2/bvh32_query_user_data_overlaps_clipping_volume.js +94 -0
  12. package/src/core/bvh2/binary/2/bvh32_query_user_data_ray.js +17 -18
  13. package/src/core/bvh2/bvh3/query/BVHQueryIntersectsFrustum.js +4 -2
  14. package/src/core/geom/3d/aabb/AABB3.js +14 -14
  15. package/src/core/geom/3d/aabb/aabb3_array_intersects_clipping_volume_array.js +30 -0
  16. package/src/core/geom/3d/aabb/aabb3_intersects_clipping_volume_array.js +51 -0
  17. package/src/core/geom/3d/cone/compute_bounding_cone_of_2_cones.js +3 -2
  18. package/src/core/geom/3d/frustum/{read_frustum_planes_to_array.js → read_three_planes_to_array.js} +5 -3
  19. package/src/core/geom/3d/morton/v3_morton_encode_bounded.js +34 -0
  20. package/src/core/geom/3d/morton/v3_morton_encode_transformed.js +2 -1
  21. package/src/core/geom/3d/quaternion/quat3_createFromAxisAngle.js +11 -0
  22. package/src/core/geom/3d/quaternion/quat_decode_from_uint32.js +53 -0
  23. package/src/core/geom/3d/quaternion/quat_encode_to_uint32.js +106 -0
  24. package/src/core/geom/3d/triangle/triangle_intersects_clipping_volume.js +51 -0
  25. package/src/core/geom/Quaternion.js +8 -142
  26. package/src/core/geom/Vector2.js +6 -7
  27. package/src/core/geom/Vector3.js +15 -82
  28. package/src/core/geom/vec3/v3_binary_equality_decode.js +44 -0
  29. package/src/core/geom/vec3/v3_binary_equality_encode.js +47 -0
  30. package/src/core/primitives/numbers/computeHashFloat.js +2 -2
  31. package/src/engine/ecs/terrain/ecs/TerrainSystem.js +2 -2
  32. package/src/engine/ecs/terrain/ecs/makeTerrainWorkerProxy.js +1 -1
  33. package/src/engine/ecs/terrain/tiles/TerrainTile.js +9 -46
  34. package/src/engine/ecs/transform/Transform.js +8 -9
  35. package/src/engine/ecs/transform/TransformSerializationAdapter.js +18 -7
  36. package/src/engine/graphics/ecs/mesh/Mesh.js +11 -11
  37. package/src/engine/graphics/geometry/buffered/query/GeometrySpatialQueryAccelerator.d.ts +2 -2
  38. package/src/engine/graphics/geometry/buffered/query/GeometrySpatialQueryAccelerator.js +79 -36
  39. package/src/engine/graphics/geometry/buffered/query/bvh32_geometry_overlap_clipping_volume.js +88 -0
  40. package/src/engine/graphics/geometry/buffered/query/bvh32_geometry_raycast.js +108 -0
  41. package/src/engine/graphics/geometry/bvh/buffered/bvh32_from_indexed_geometry.js +4 -30
  42. package/src/engine/graphics/geometry/bvh/buffered/bvh32_from_unindexed_geometry.js +30 -0
  43. package/src/engine/graphics/geometry/bvh/buffered/bvh32_set_leaf_from_triangle.js +41 -0
  44. package/src/engine/graphics/render/forward_plus/LightManager.js +2 -2
  45. package/src/engine/graphics/render/forward_plus/query/query_bvh_frustum_from_texture.js +2 -2
  46. package/src/engine/graphics/render/view/CameraView.js +8 -8
  47. package/src/core/bvh2/binary/BinaryBVH.js +0 -281
  48. package/src/core/bvh2/binary/IndexedBinaryBVH.js +0 -407
  49. package/src/core/bvh2/binary/IndexedBinaryBVH.spec.js +0 -27
  50. package/src/core/bvh2/binary/IndexedBinaryBVHVisitor.js +0 -11
  51. package/src/core/bvh2/binary/NodeType.js +0 -8
  52. package/src/core/bvh2/binary/RayLeafIntersectionVisitor.js +0 -59
  53. package/src/core/geom/3d/aabb/aabb3_array_intersects_frustum_array.js +0 -20
  54. package/src/core/geom/3d/aabb/aabb3_intersects_frustum_array.js +0 -35
  55. package/src/engine/graphics/geometry/buffered/query/ClippingPlaneContainmentComputingVisitor.js +0 -195
  56. package/src/engine/graphics/geometry/buffered/query/GeometryVisitor.js +0 -87
  57. package/src/engine/graphics/geometry/buffered/query/RaycastNearestHitComputingVisitor.js +0 -206
  58. package/src/engine/graphics/geometry/bvh/buffered/BinaryBVHFromBufferGeometry.js +0 -123
package/build/meep.cjs CHANGED
@@ -1764,6 +1764,27 @@ function clamp$1(value, min, max) {
1764
1764
  }
1765
1765
  }
1766
1766
 
1767
+ /**
1768
+ * Very small value, used for comparison when compensation for rounding error is required
1769
+ * @type {number}
1770
+ */
1771
+ const EPSILON = 0.000001;
1772
+
1773
+ /**
1774
+ * Comparison of two numbers with a given tolerance
1775
+ * @param {number} a
1776
+ * @param {number} b
1777
+ * @param {number} tolerance
1778
+ * @returns {boolean}
1779
+ */
1780
+ function epsilonEquals(a, b, tolerance) {
1781
+ assert.isNumber(a, 'a');
1782
+ assert.isNumber(b, 'b');
1783
+ assert.isNumber(tolerance, 'tolerance');
1784
+
1785
+ return Math.abs(a - b) <= tolerance;
1786
+ }
1787
+
1767
1788
  /**
1768
1789
  * Linear interpolation between two values controlled by a given fraction
1769
1790
  * @param {number} a
@@ -1775,13 +1796,191 @@ function lerp$1(a, b, fraction) {
1775
1796
  return (b - a) * fraction + a;
1776
1797
  }
1777
1798
 
1799
+ /**
1800
+ * Returns lowest value out of 2 supplied
1801
+ * @param {number} a
1802
+ * @param {number} b
1803
+ * @returns {number}
1804
+ */
1805
+ function min2(a, b) {
1806
+ return a < b ? a : b;
1807
+ }
1808
+
1778
1809
  /**
1779
1810
  *
1780
1811
  * @param {number} v
1781
- * @returns {number} +1 if v>0, 0 if v == 0, -1 if v<0
1812
+ * @returns {number}
1782
1813
  */
1783
- function sign$1(v) {
1784
- return v > 0 ? 1 : (v < 0 ? -1 : 0);
1814
+ function computeHashFloat(v) {
1815
+ //we break the number up into fractional and whole parts
1816
+ const whole = v | 0;
1817
+
1818
+ const fraction = v - whole;
1819
+
1820
+ //fractional part is scaled up into int32 range, this inexact method, as it will produce 0 hash for values below a certain threshold
1821
+ const fractionHash = fraction * 1367130550;
1822
+
1823
+ //take XOR of both parts
1824
+ return fractionHash ^ whole;
1825
+ }
1826
+
1827
+ const K = Math.SQRT1_2 / 511;
1828
+
1829
+ /**
1830
+ * Based on GDC talk from Bungie on destiny, compressing quaternions for animation
1831
+ * @param {number[]} output
1832
+ * @param {number} output_offset
1833
+ * @param {number} value
1834
+ */
1835
+ function quat_decode_from_uint32(output, output_offset, value) {
1836
+ //read components
1837
+ const max = value & 0x3;
1838
+
1839
+ const iv0 = (value >> 2) & 0x3FF;
1840
+ const iv1 = (value >> 12) & 0x3FF;
1841
+ const iv2 = (value >> 22) & 0x3FF;
1842
+
1843
+ //scale components back to quaternion range
1844
+ const v0 = iv0 * K - Math.SQRT1_2;
1845
+ const v1 = iv1 * K - Math.SQRT1_2;
1846
+ const v2 = iv2 * K - Math.SQRT1_2;
1847
+
1848
+ //restore dropped component using quaternion identity: x^2 + y^2 + z^2 + w^2 = 1
1849
+ const dropped_2 = 1 - v0 * v0 - v1 * v1 - v2 * v2;
1850
+ const dropped = Math.sqrt(dropped_2);
1851
+
1852
+ let x, y, z, w;
1853
+ if (max === 0) {
1854
+ x = dropped;
1855
+ y = v0;
1856
+ z = v1;
1857
+ w = v2;
1858
+ } else if (max === 1) {
1859
+ x = v0;
1860
+ y = dropped;
1861
+ z = v1;
1862
+ w = v2;
1863
+ } else if (max === 2) {
1864
+ x = v0;
1865
+ y = v1;
1866
+ z = dropped;
1867
+ w = v2;
1868
+ } else {
1869
+ x = v0;
1870
+ y = v1;
1871
+ z = v2;
1872
+ w = dropped;
1873
+ }
1874
+
1875
+ output[output_offset] = x;
1876
+ output[output_offset + 1] = y;
1877
+ output[output_offset + 2] = z;
1878
+ output[output_offset + 3] = w;
1879
+ }
1880
+
1881
+ /**
1882
+ * Based on GDC talk from Bungie on destiny, compressing quaternions for animation
1883
+ * @param {number} x
1884
+ * @param {number} y
1885
+ * @param {number} z
1886
+ * @param {number} w
1887
+ * @returns {number}
1888
+ */
1889
+ function quat_encode_to_uint32(x, y, z, w) {
1890
+
1891
+ const absX = Math.abs(x);
1892
+ const absY = Math.abs(y);
1893
+ const absZ = Math.abs(z);
1894
+ const absW = Math.abs(w);
1895
+
1896
+ let max = 0;
1897
+
1898
+ //pick max component
1899
+ if (absY > absX) {
1900
+ if (absY > absZ) {
1901
+ if (absY > absW) {
1902
+ //absY is max
1903
+ max = 1;
1904
+ } else {
1905
+ //absW is max
1906
+ max = 3;
1907
+ }
1908
+ } else if (absZ > absW) {
1909
+ //absZ is max
1910
+ max = 2;
1911
+ } else {
1912
+ //absW is max
1913
+ max = 3;
1914
+ }
1915
+ } else if (absX > absZ) {
1916
+ if (absX > absW) {
1917
+ max = 0;
1918
+ } else {
1919
+ max = 3;
1920
+ }
1921
+ } else if (absZ > absW) {
1922
+ max = 2;
1923
+ } else {
1924
+ max = 3;
1925
+ }
1926
+
1927
+ let v0, v1, v2, dropped;
1928
+
1929
+ //max will be dropped
1930
+ if (max === 0) {
1931
+ //dropping x
1932
+ v0 = y;
1933
+ v1 = z;
1934
+ v2 = w;
1935
+
1936
+ dropped = x;
1937
+ } else if (max === 1) {
1938
+ //dropping y
1939
+ v0 = x;
1940
+ v1 = z;
1941
+ v2 = w;
1942
+
1943
+ dropped = y;
1944
+ } else if (max === 2) {
1945
+ //dropping z
1946
+ v0 = x;
1947
+ v1 = y;
1948
+ v2 = w;
1949
+
1950
+ dropped = z;
1951
+ } else {
1952
+ //dropping w
1953
+ v0 = x;
1954
+ v1 = y;
1955
+ v2 = z;
1956
+
1957
+ dropped = w;
1958
+ }
1959
+
1960
+ if (dropped < 0) {
1961
+ //reconstructing dropped value is only possible if it is positive, so we invert the quaternion to make dropped value positive
1962
+ v0 = -v0;
1963
+ v1 = -v1;
1964
+ v2 = -v2;
1965
+ }
1966
+
1967
+ const l = Math.sqrt(x * x + y * y + z * z + w * w);
1968
+ const m = 511 / (l * Math.SQRT1_2);
1969
+
1970
+ //re-normalize the remaining components to 10 bit UINT value
1971
+ const oV0 = Math.round(v0 * m + 511);
1972
+ const oV1 = Math.round(v1 * m + 511);
1973
+ const oV2 = Math.round(v2 * m + 511);
1974
+
1975
+ assert.ok(oV0 <= 1023 && oV0 >= 0, `expected 0 <= ov0 <= 1023, instead was '${oV0}'`);
1976
+ assert.ok(oV1 <= 1023 && oV1 >= 0, `expected 0 <= ov1 <= 1023, instead was '${oV1}'`);
1977
+ assert.ok(oV2 <= 1023 && oV2 >= 0, `expected 0 <= ov2 <= 1023, instead was '${oV2}'`);
1978
+
1979
+
1980
+ return (max & 0x3)
1981
+ | ((oV0 & 0x3FF) << 2)
1982
+ | ((oV1 & 0x3FF) << 12)
1983
+ | ((oV2 & 0x3FF) << 22);
1785
1984
  }
1786
1985
 
1787
1986
  /**
@@ -1800,13 +1999,11 @@ function v3_dot(x0, y0, z0, x1, y1, z1) {
1800
1999
 
1801
2000
  /**
1802
2001
  *
1803
- * @param {number} x
1804
- * @param {number} y
1805
- * @param {number} z
1806
- * @return {number}
2002
+ * @param {number} v
2003
+ * @returns {number} +1 if v>0, 0 if v == 0, -1 if v<0
1807
2004
  */
1808
- function v3_length_sqr(x, y, z) {
1809
- return x * x + y * y + z * z;
2005
+ function sign$1(v) {
2006
+ return v > 0 ? 1 : (v < 0 ? -1 : 0);
1810
2007
  }
1811
2008
 
1812
2009
  /**
@@ -1862,6 +2059,110 @@ function v3_angle_cos_between(x0, y0, z0, x1, y1, z1){
1862
2059
  return clamp$1(d / l, -1, 1);
1863
2060
  }
1864
2061
 
2062
+ /**
2063
+ *
2064
+ * @param {BinaryBuffer} buffer
2065
+ * @param {number[]} result
2066
+ * @param {number} result_offset
2067
+ */
2068
+ function v3_binary_equality_decode(buffer, result, result_offset) {
2069
+ const header = buffer.readUint8();
2070
+
2071
+ let x = 0;
2072
+ let y = 0;
2073
+ let z = 0;
2074
+
2075
+ if ((header & 7) === 7) {
2076
+ //all scale components are the same
2077
+ x = buffer.readFloat32();
2078
+ y = x;
2079
+ z = x;
2080
+ } else if ((header & 1) === 1) {
2081
+ //X and Y are the same, Z is different
2082
+ x = buffer.readFloat32();
2083
+ y = x;
2084
+ z = buffer.readFloat32();
2085
+ } else if ((header & 2) === 2) {
2086
+ //Y and Z are the same, X is different
2087
+ x = buffer.readFloat32();
2088
+ y = buffer.readFloat32();
2089
+ z = y;
2090
+ } else if ((header & 4) === 4) {
2091
+ //X and Z are the same, Y is different
2092
+ x = buffer.readFloat32();
2093
+ y = buffer.readFloat32();
2094
+ z = x;
2095
+ } else {
2096
+ //scale components are different
2097
+ x = buffer.readFloat32();
2098
+ y = buffer.readFloat32();
2099
+ z = buffer.readFloat32();
2100
+ }
2101
+
2102
+ result[result_offset] = x;
2103
+ result[result_offset + 1] = y;
2104
+ result[result_offset + 2] = z;
2105
+ }
2106
+
2107
+ /**
2108
+ *
2109
+ * @param {BinaryBuffer} buffer
2110
+ * @param {number} x
2111
+ * @param {number} y
2112
+ * @param {number} z
2113
+ */
2114
+ function v3_binary_equality_encode(buffer, x, y, z){
2115
+
2116
+ let header = 0;
2117
+
2118
+ if (x === y) {
2119
+ header |= 1;
2120
+ }
2121
+
2122
+ if (y === z) {
2123
+ header |= 2;
2124
+ }
2125
+
2126
+ if (x === z) {
2127
+ header |= 4;
2128
+ }
2129
+
2130
+ buffer.writeUint8(header);
2131
+
2132
+ if ((header & 7) === 7) {
2133
+ //all components are the same
2134
+ buffer.writeFloat32(x);
2135
+ } else if (header === 1) {
2136
+ //X and Y are the same, Z is different
2137
+ buffer.writeFloat32(x);
2138
+ buffer.writeFloat32(z);
2139
+ } else if (header === 2) {
2140
+ //Y and Z are the same, X is different
2141
+ buffer.writeFloat32(x);
2142
+ buffer.writeFloat32(y);
2143
+ } else if (header === 4) {
2144
+ //X and Z are the same, Y is different
2145
+ buffer.writeFloat32(x);
2146
+ buffer.writeFloat32(y);
2147
+ } else {
2148
+ //scale components are different
2149
+ buffer.writeFloat32(x);
2150
+ buffer.writeFloat32(y);
2151
+ buffer.writeFloat32(z);
2152
+ }
2153
+ }
2154
+
2155
+ /**
2156
+ *
2157
+ * @param {number} x
2158
+ * @param {number} y
2159
+ * @param {number} z
2160
+ * @return {number}
2161
+ */
2162
+ function v3_length_sqr(x, y, z) {
2163
+ return x * x + y * y + z * z;
2164
+ }
2165
+
1865
2166
  /**
1866
2167
  *
1867
2168
  * @param {Vector3} result
@@ -1933,45 +2234,6 @@ function v3_slerp(
1933
2234
  result.set(x, y, z);
1934
2235
  }
1935
2236
 
1936
- /**
1937
- *
1938
- * @param {number} v
1939
- * @returns {number}
1940
- */
1941
- function computeHashFloat(v) {
1942
- //we break the number up into fractional and whole parts
1943
- const fraction = v % 1;
1944
-
1945
- const whole = v | 0;
1946
-
1947
- //fractional part is scaled up into int32 range, this inexact method, as it will produce 0 hash for values below a certain threshold
1948
- const fractionHash = fraction * 1367130550;
1949
-
1950
- //take XOR of both parts
1951
- return fractionHash ^ whole;
1952
- }
1953
-
1954
- /**
1955
- * Comparison of two numbers with a given tolerance
1956
- * @param {number} a
1957
- * @param {number} b
1958
- * @param {number} tolerance
1959
- * @returns {boolean}
1960
- */
1961
- function epsilonEquals(a, b, tolerance) {
1962
- assert.isNumber(a, 'a');
1963
- assert.isNumber(b, 'b');
1964
- assert.isNumber(tolerance, 'tolerance');
1965
-
1966
- return Math.abs(a - b) <= tolerance;
1967
- }
1968
-
1969
- /**
1970
- * Very small value, used for comparison when compensation for rounding error is required
1971
- * @type {number}
1972
- */
1973
- const EPSILON = 0.000001;
1974
-
1975
2237
  /**
1976
2238
  * @author Alex Goldring
1977
2239
  * @copyright Alex Goldring 2015
@@ -2816,100 +3078,31 @@ let Vector3$1 = class Vector3 {
2816
3078
  /**
2817
3079
  *
2818
3080
  * @param {BinaryBuffer} buffer
3081
+ * @deprecated use dedicated method directly instead
2819
3082
  */
2820
3083
  toBinaryBufferFloat32_EqualityEncoded(buffer) {
2821
3084
  const x = this.x;
2822
3085
  const y = this.y;
2823
3086
  const z = this.z;
2824
3087
 
2825
- let header = 0;
2826
-
2827
- if (x === y) {
2828
- header |= 1;
2829
- }
2830
-
2831
- if (y === z) {
2832
- header |= 2;
2833
- }
2834
-
2835
- if (x === z) {
2836
- header |= 4;
2837
- }
2838
-
2839
- buffer.writeUint8(header);
2840
-
2841
- if ((header & 7) === 7) {
2842
- //all components are the same
2843
- buffer.writeFloat32(x);
2844
- } else if (header === 1) {
2845
- //X and Y are the same, Z is different
2846
- buffer.writeFloat32(x);
2847
- buffer.writeFloat32(z);
2848
- } else if (header === 2) {
2849
- //Y and Z are the same, X is different
2850
- buffer.writeFloat32(x);
2851
- buffer.writeFloat32(y);
2852
- } else if (header === 4) {
2853
- //X and Z are the same, Y is different
2854
- buffer.writeFloat32(x);
2855
- buffer.writeFloat32(y);
2856
- } else {
2857
- //scale components are different
2858
- buffer.writeFloat32(x);
2859
- buffer.writeFloat32(y);
2860
- buffer.writeFloat32(z);
2861
- }
3088
+ v3_binary_equality_encode(buffer, x, y, z);
2862
3089
  }
2863
3090
 
2864
3091
  /**
2865
3092
  * Uses an extra byte for a header. Only writes unique components. Useful for things like scale where all components usually have the same value
2866
3093
  * @param {BinaryBuffer} buffer
3094
+ * @deprecated use dedicated method directly instead
2867
3095
  */
2868
3096
  fromBinaryBufferFloat32_EqualityEncoded(buffer) {
2869
- const header = buffer.readUint8();
2870
-
2871
- let x = 0;
2872
- let y = 0;
2873
- let z = 0;
2874
-
2875
- if ((header & 7) === 7) {
2876
- //all scale components are the same
2877
- x = buffer.readFloat32();
2878
- y = x;
2879
- z = x;
2880
- } else if ((header & 1) === 1) {
2881
- //X and Y are the same, Z is different
2882
- x = buffer.readFloat32();
2883
- y = x;
2884
- z = buffer.readFloat32();
2885
- } else if ((header & 2) === 2) {
2886
- //Y and Z are the same, X is different
2887
- x = buffer.readFloat32();
2888
- y = buffer.readFloat32();
2889
- z = y;
2890
- } else if ((header & 4) === 4) {
2891
- //X and Z are the same, Y is different
2892
- x = buffer.readFloat32();
2893
- y = buffer.readFloat32();
2894
- z = x;
2895
- } else {
2896
- //scale components are different
2897
- x = buffer.readFloat32();
2898
- y = buffer.readFloat32();
2899
- z = buffer.readFloat32();
2900
- }
2901
-
2902
- this.set(x, y, z);
3097
+ v3_binary_equality_decode(buffer, this, 0);
2903
3098
  }
2904
3099
 
2905
3100
  hash() {
2906
- let hash = computeHashFloat(this.x);
2907
-
2908
- hash = ((hash << 5) - hash) + computeHashFloat(this.y);
2909
-
2910
- hash = ((hash << 5) - hash) + computeHashFloat(this.z);
3101
+ const x = computeHashFloat(this.x);
3102
+ const y = computeHashFloat(this.y);
3103
+ const z = computeHashFloat(this.z);
2911
3104
 
2912
- return hash;
3105
+ return x ^ (y << 1) ^ (z << 2);
2913
3106
  }
2914
3107
 
2915
3108
 
@@ -3067,16 +3260,6 @@ Vector3$1.typeName = "Vector3";
3067
3260
  */
3068
3261
  Vector3$1._dot = v3_dot;
3069
3262
 
3070
- /**
3071
- * Returns lowest value out of 2 supplied
3072
- * @param {number} a
3073
- * @param {number} b
3074
- * @returns {number}
3075
- */
3076
- function min2(a, b) {
3077
- return a < b ? a : b;
3078
- }
3079
-
3080
3263
  /**
3081
3264
  * Created by Alex on 10/03/14.
3082
3265
  */
@@ -3086,18 +3269,6 @@ const forward = new Vector3$1();
3086
3269
  const up = new Vector3$1();
3087
3270
  const right = new Vector3$1();
3088
3271
 
3089
- /**
3090
- * just in case you need that function also
3091
- * @param {Vector3} axis
3092
- * @param {number} angle
3093
- * @param {Quaternion} result
3094
- */
3095
- function quat3_createFromAxisAngle(axis, angle, result) {
3096
- const halfAngle = angle * .5;
3097
- const s = Math.sin(halfAngle);
3098
- result.set(axis.x * s, axis.y * s, axis.z * s, Math.cos(halfAngle));
3099
- }
3100
-
3101
3272
  let Quaternion$1 = class Quaternion {
3102
3273
  /**
3103
3274
  *
@@ -4520,31 +4691,7 @@ let Quaternion$1 = class Quaternion {
4520
4691
  * @param {number} value
4521
4692
  */
4522
4693
  decodeFromUint32(value) {
4523
- //read components
4524
- const max = value & 0x3;
4525
-
4526
- const iv0 = (value >> 2) & 0x3FF;
4527
- const iv1 = (value >> 12) & 0x3FF;
4528
- const iv2 = (value >> 22) & 0x3FF;
4529
-
4530
- //scale components back to quaternion range
4531
- const v0 = (iv0 / 511 - 1) * K_CONST;
4532
- const v1 = (iv1 / 511 - 1) * K_CONST;
4533
- const v2 = (iv2 / 511 - 1) * K_CONST;
4534
-
4535
- //restore dropped component using quaternion identity: x^2 + y^2 + z^2 + w^2 = 1
4536
- const dropped_2 = 1 - v0 * v0 - v1 * v1 - v2 * v2;
4537
- const dropped = Math.sqrt(dropped_2);
4538
-
4539
- if (max === 0) {
4540
- this.set(dropped, v0, v1, v2);
4541
- } else if (max === 1) {
4542
- this.set(v0, dropped, v1, v2);
4543
- } else if (max === 2) {
4544
- this.set(v0, v1, dropped, v2);
4545
- } else {
4546
- this.set(v0, v1, v2, dropped);
4547
- }
4694
+ quat_decode_from_uint32(this, 0, value);
4548
4695
  }
4549
4696
 
4550
4697
  /**
@@ -4552,107 +4699,7 @@ let Quaternion$1 = class Quaternion {
4552
4699
  * @returns {number}
4553
4700
  */
4554
4701
  encodeToUint32() {
4555
- const x = this.x;
4556
- const y = this.y;
4557
- const z = this.z;
4558
- const w = this.w;
4559
-
4560
- const absX = Math.abs(x);
4561
- const absY = Math.abs(y);
4562
- const absZ = Math.abs(z);
4563
- const absW = Math.abs(w);
4564
-
4565
- let max = 0;
4566
-
4567
- //pick max component
4568
- if (absY > absX) {
4569
- if (absY > absZ) {
4570
- if (absY > absW) {
4571
- //absY is max
4572
- max = 1;
4573
- } else {
4574
- //absW is max
4575
- max = 3;
4576
- }
4577
- } else if (absZ > absW) {
4578
- //absZ is max
4579
- max = 2;
4580
- } else {
4581
- //absW is max
4582
- max = 3;
4583
- }
4584
- } else if (absX > absZ) {
4585
- if (absX > absW) {
4586
- max = 0;
4587
- } else {
4588
- max = 3;
4589
- }
4590
- } else if (absZ > absW) {
4591
- max = 2;
4592
- } else {
4593
- max = 3;
4594
- }
4595
-
4596
- let v0, v1, v2, dropped;
4597
-
4598
- //max will be dropped
4599
- if (max === 0) {
4600
- //dropping x
4601
- v0 = y;
4602
- v1 = z;
4603
- v2 = w;
4604
-
4605
- dropped = x;
4606
- } else if (max === 1) {
4607
- //dropping y
4608
- v0 = x;
4609
- v1 = z;
4610
- v2 = w;
4611
-
4612
- dropped = y;
4613
- } else if (max === 2) {
4614
- //dropping z
4615
- v0 = x;
4616
- v1 = y;
4617
- v2 = w;
4618
-
4619
- dropped = z;
4620
- } else {
4621
- //dropping w
4622
- v0 = x;
4623
- v1 = y;
4624
- v2 = z;
4625
-
4626
- dropped = w;
4627
- }
4628
-
4629
- if (dropped < 0) {
4630
- //reconstructing dropped value is only possible if it is positive, so we invert the quaternion to make dropped value positive
4631
- v0 = -v0;
4632
- v1 = -v1;
4633
- v2 = -v2;
4634
- }
4635
-
4636
- const l = Math.sqrt(x * x + y * y + z * z + w * w);
4637
- const m = 1 / (l * K_CONST);
4638
-
4639
- //re-normalize the remaining components to 10 bit UINT value
4640
- const oV0 = Math.round((v0 * m + 1) * 511);
4641
- const oV1 = Math.round((v1 * m + 1) * 511);
4642
- const oV2 = Math.round((v2 * m + 1) * 511);
4643
-
4644
- assert.ok(oV0 <= 1023 && oV0 >= 0, `expected 0 <= ov0 <= 1023, instead was '${oV0}'`);
4645
- assert.ok(oV1 <= 1023 && oV1 >= 0, `expected 0 <= ov1 <= 1023, instead was '${oV1}'`);
4646
- assert.ok(oV2 <= 1023 && oV2 >= 0, `expected 0 <= ov2 <= 1023, instead was '${oV2}'`);
4647
-
4648
-
4649
- const result = (max & 0x3)
4650
- | ((oV0 & 0x3FF) << 2)
4651
- | ((oV1 & 0x3FF) << 12)
4652
- | ((oV2 & 0x3FF) << 22)
4653
- ;
4654
-
4655
- return result;
4702
+ return quat_encode_to_uint32(this.x, this.y, this.z, this.w);
4656
4703
  }
4657
4704
 
4658
4705
  /**
@@ -4839,13 +4886,7 @@ Quaternion$1.identity = Object.freeze(new Quaternion$1(0, 0, 0, 1));
4839
4886
  const axis = new Vector3$1();
4840
4887
 
4841
4888
 
4842
- const tempvec3 = new Vector3$1();
4843
-
4844
- /**
4845
- * Used in UINT32 packing
4846
- * @type {number}
4847
- */
4848
- const K_CONST = 0.70710678118; // 1/sqrt(2)
4889
+ const tempvec3 = new Vector3$1();
4849
4890
 
4850
4891
  /**
4851
4892
  * @readonly
@@ -5112,8 +5153,7 @@ class Transform {
5112
5153
  * @returns {boolean}
5113
5154
  */
5114
5155
  equals(other) {
5115
- return other.isTransform
5116
- && this.position.equals(other.position)
5156
+ return this.position.equals(other.position)
5117
5157
  && this.rotation.equals(other.rotation)
5118
5158
  && this.scale.equals(other.scale);
5119
5159
  }
@@ -48947,11 +48987,7 @@ class Vector2 {
48947
48987
  const x = computeHashFloat(this.x);
48948
48988
  const y = computeHashFloat(this.y);
48949
48989
 
48950
- let hash = ((x << 5) - x) + y;
48951
-
48952
- hash |= 0; //convert to 32bit int
48953
-
48954
- return hash;
48990
+ return ((x << 5) - x) + y;
48955
48991
  }
48956
48992
 
48957
48993
  /**
@@ -48962,8 +48998,11 @@ class Vector2 {
48962
48998
  const sin = Math.sin(angle);
48963
48999
  const cos = Math.cos(angle);
48964
49000
 
48965
- const x = this.x * cos - this.y * sin;
48966
- const y = this.x * sin + this.y * cos;
49001
+ const _x = this.x;
49002
+ const _y = this.y;
49003
+
49004
+ const x = _x * cos - _y * sin;
49005
+ const y = _x * sin + _y * cos;
48967
49006
 
48968
49007
  this.set(x, y);
48969
49008
  }
@@ -56786,6 +56825,39 @@ function mortonEncode_magicbits(x, y, z) {
56786
56825
  return x_bits | y_bits | z_bits;
56787
56826
  }
56788
56827
 
56828
+ /**
56829
+ * @param {number} x
56830
+ * @param {number} y
56831
+ * @param {number} z
56832
+ * @param {number[]} bounds
56833
+ * @returns {number}
56834
+ */
56835
+ function v3_morton_encode_bounded(x, y, z, bounds) {
56836
+
56837
+ const bounds_x0 = bounds[0];
56838
+ const bounds_y0 = bounds[1];
56839
+ const bounds_z0 = bounds[2];
56840
+
56841
+ const bounds_x1 = bounds[3];
56842
+ const bounds_y1 = bounds[4];
56843
+ const bounds_z1 = bounds[5];
56844
+
56845
+ const bounds_span_x = bounds_x1 - bounds_x0;
56846
+ const bounds_span_y = bounds_y1 - bounds_y0;
56847
+ const bounds_span_z = bounds_z1 - bounds_z0;
56848
+
56849
+ // scale to 10 bits
56850
+ const ndc_x = 1023 * (x - bounds_x0) / bounds_span_x;
56851
+ const ndc_y = 1023 * (y - bounds_y0) / bounds_span_y;
56852
+ const ndc_z = 1023 * (z - bounds_z0) / bounds_span_z;
56853
+
56854
+ return mortonEncode_magicbits(
56855
+ Math.round(ndc_x),
56856
+ Math.round(ndc_y),
56857
+ Math.round(ndc_z)
56858
+ );
56859
+ }
56860
+
56789
56861
  /**
56790
56862
  * Returns highest value out of 3 supplied
56791
56863
  * @param {number} a
@@ -56848,10 +56920,10 @@ function copy_box_zero_size(data, destination, source) {
56848
56920
  * Assumes data will be normalized to 0...1 value range
56849
56921
  * @param {Float32Array} data
56850
56922
  * @param {number} address
56851
- * @param {number[]} matrix
56923
+ * @param {number[]} bounds
56852
56924
  * @returns {number}
56853
56925
  */
56854
- function build_morton(data, address, matrix) {
56926
+ function build_morton(data, address, bounds) {
56855
56927
 
56856
56928
  const x0 = data[address];
56857
56929
  const y0 = data[address + 1];
@@ -56860,17 +56932,15 @@ function build_morton(data, address, matrix) {
56860
56932
  const y1 = data[address + 4];
56861
56933
  const z1 = data[address + 5];
56862
56934
 
56863
- const cx = (x0 + x1) / 2;
56864
- const cy = (y0 + y1) / 2;
56865
- const cz = (z0 + z1) / 2;
56935
+ const cx = (x0 + x1) * 0.5;
56936
+ const cy = (y0 + y1) * 0.5;
56937
+ const cz = (z0 + z1) * 0.5;
56866
56938
 
56867
- return mortonEncode_magicbits(cx, cy, cz);
56868
- // return v3_morton_encode_transformed(cx, cy, cz, matrix);
56939
+ return v3_morton_encode_bounded(cx, cy, cz, bounds);
56869
56940
 
56870
56941
  }
56871
56942
 
56872
- const scratch_box_0 = new Float32Array(18);
56873
- const stack$8 = [];
56943
+ const stack$8 = SCRATCH_UINT32_TRAVERSAL_STACK;
56874
56944
 
56875
56945
  class BinaryUint32BVH {
56876
56946
  /**
@@ -56894,34 +56964,41 @@ class BinaryUint32BVH {
56894
56964
  */
56895
56965
  __data_uint32;
56896
56966
 
56897
- constructor() {
56898
-
56899
- /**
56900
- *
56901
- * @type {number}
56902
- * @private
56903
- */
56904
- this.__node_count_binary = 0;
56967
+ /**
56968
+ *
56969
+ * @type {number}
56970
+ * @private
56971
+ */
56972
+ __node_count_binary = 0;
56905
56973
 
56906
- /**
56907
- *
56908
- * @type {number}
56909
- * @private
56910
- */
56911
- this.__node_count_leaf = 0;
56974
+ /**
56975
+ *
56976
+ * @type {number}
56977
+ * @private
56978
+ */
56979
+ __node_count_leaf = 0;
56912
56980
 
56981
+ constructor() {
56913
56982
  this.data = new ArrayBuffer(320);
56914
56983
  }
56915
56984
 
56985
+ /**
56986
+ * In bytes
56987
+ * @returns {number}
56988
+ */
56989
+ estimateByteSize() {
56990
+ return this.data.byteLength + 248;
56991
+ }
56992
+
56916
56993
  getTotalBoxCount() {
56917
56994
  return this.__node_count_binary + this.__node_count_leaf;
56918
56995
  }
56919
56996
 
56920
- getBinaryNodeCount() {
56997
+ get binary_node_count() {
56921
56998
  return this.__node_count_binary;
56922
56999
  }
56923
57000
 
56924
- getLeafNodeCount() {
57001
+ get leaf_node_count() {
56925
57002
  return this.__node_count_leaf;
56926
57003
  }
56927
57004
 
@@ -56943,10 +57020,12 @@ class BinaryUint32BVH {
56943
57020
 
56944
57021
  /**
56945
57022
  *
56946
- * @param {ArrayBuffer} v
57023
+ * @param {ArrayBuffer} buffer
56947
57024
  */
56948
- set data(v) {
56949
- this.__data_buffer = v;
57025
+ set data(buffer) {
57026
+ assert.defined(buffer, 'buffer');
57027
+
57028
+ this.__data_buffer = buffer;
56950
57029
 
56951
57030
  this.__data_float32 = new Float32Array(this.__data_buffer);
56952
57031
  this.__data_uint32 = new Uint32Array(this.__data_buffer);
@@ -56956,6 +57035,24 @@ class BinaryUint32BVH {
56956
57035
  return this.__data_buffer;
56957
57036
  }
56958
57037
 
57038
+ /**
57039
+ * Resolve index of the node to address where the node data starts, this is required to know where AABB is stored in memory
57040
+ * @param {number} node_index
57041
+ * @returns {number}
57042
+ */
57043
+ getNodeAddress(node_index) {
57044
+ const binary_node_count = this.__node_count_binary;
57045
+ const leaf_node_index = node_index - binary_node_count;
57046
+
57047
+ if (leaf_node_index < 0) {
57048
+ // binary node
57049
+ return node_index * BVH_BINARY_NODE_SIZE;
57050
+ } else {
57051
+ // leaf node
57052
+ return binary_node_count * BVH_BINARY_NODE_SIZE + leaf_node_index * BVH_LEAF_NODE_SIZE;
57053
+ }
57054
+ }
57055
+
56959
57056
  initialize_structure() {
56960
57057
  // compute memory requirements
56961
57058
  const word_count = this.__node_count_binary * BVH_BINARY_NODE_SIZE + this.__node_count_leaf * BVH_LEAF_NODE_SIZE;
@@ -57074,17 +57171,15 @@ class BinaryUint32BVH {
57074
57171
  * @private
57075
57172
  */
57076
57173
  __compute_bounds_area_of_3_boxes(a, b, c) {
57077
- this.readBounds(a, scratch_box_0, 0);
57078
- this.readBounds(b, scratch_box_0, 6);
57079
- this.readBounds(c, scratch_box_0, 12);
57174
+ const float32 = this.__data_float32;
57080
57175
 
57081
- const x0 = min3(scratch_box_0[0], scratch_box_0[6], scratch_box_0[12]);
57082
- const y0 = min3(scratch_box_0[1], scratch_box_0[7], scratch_box_0[13]);
57083
- const z0 = min3(scratch_box_0[2], scratch_box_0[8], scratch_box_0[14]);
57176
+ const x0 = min3(float32[a + 0], float32[b + 0], float32[c + 0]);
57177
+ const y0 = min3(float32[a + 1], float32[b + 1], float32[c + 1]);
57178
+ const z0 = min3(float32[a + 2], float32[b + 2], float32[c + 2]);
57084
57179
 
57085
- const x1 = max3(scratch_box_0[3], scratch_box_0[9], scratch_box_0[15]);
57086
- const y1 = max3(scratch_box_0[4], scratch_box_0[10], scratch_box_0[16]);
57087
- const z1 = max3(scratch_box_0[5], scratch_box_0[11], scratch_box_0[17]);
57180
+ const x1 = max3(float32[a + 3], float32[b + 3], float32[c + 3]);
57181
+ const y1 = max3(float32[a + 4], float32[b + 4], float32[c + 4]);
57182
+ const z1 = max3(float32[a + 5], float32[b + 5], float32[c + 5]);
57088
57183
 
57089
57184
  return aabb3_compute_half_surface_area(x0, y0, z0, x1, y1, z1);
57090
57185
  }
@@ -57136,9 +57231,9 @@ class BinaryUint32BVH {
57136
57231
 
57137
57232
  /**
57138
57233
  * Sort leaf nodes according to their morton codes
57139
- * @param {number[]} projection
57234
+ * @param {number[]} bounds
57140
57235
  */
57141
- sort_morton(projection) {
57236
+ sort_morton(bounds) {
57142
57237
 
57143
57238
  const leaf_block_address = this.__node_count_binary * BVH_BINARY_NODE_SIZE;
57144
57239
 
@@ -57168,15 +57263,15 @@ class BinaryUint32BVH {
57168
57263
 
57169
57264
  const pivot_address = pivotIndex * BVH_LEAF_NODE_SIZE + leaf_block_address;
57170
57265
 
57171
- const pivot = build_morton(data, pivot_address);
57266
+ const pivot = build_morton(data, pivot_address, bounds);
57172
57267
 
57173
57268
  /* partition */
57174
57269
  while (i <= j) {
57175
- while (build_morton(data, i * BVH_LEAF_NODE_SIZE + leaf_block_address) < pivot) {
57270
+ while (build_morton(data, i * BVH_LEAF_NODE_SIZE + leaf_block_address, bounds) < pivot) {
57176
57271
  i++;
57177
57272
  }
57178
57273
 
57179
- while (build_morton(data, j * BVH_LEAF_NODE_SIZE + leaf_block_address) > pivot) {
57274
+ while (build_morton(data, j * BVH_LEAF_NODE_SIZE + leaf_block_address, bounds) > pivot) {
57180
57275
  j--;
57181
57276
  }
57182
57277
 
@@ -57246,22 +57341,22 @@ class BinaryUint32BVH {
57246
57341
 
57247
57342
  // build bottom-most level, just above the leaves
57248
57343
  for (i = 0; i < level_node_count; i++) {
57249
- const leafIndex0 = i * 2;
57250
- const leafIndex1 = leafIndex0 + 1;
57344
+ const leaf_index_0 = i * 2;
57345
+ const leaf_index_1 = leaf_index_0 + 1;
57251
57346
 
57252
- const leafOffset0 = leaf_node_block_address + leafIndex0 * BVH_LEAF_NODE_SIZE;
57253
- const leafOffset1 = leaf_node_block_address + leafIndex1 * BVH_LEAF_NODE_SIZE;
57347
+ const leaf_offset_0 = leaf_node_block_address + leaf_index_0 * BVH_LEAF_NODE_SIZE;
57348
+ const leaf_offset_1 = leaf_node_block_address + leaf_index_1 * BVH_LEAF_NODE_SIZE;
57254
57349
 
57255
- if (leafIndex1 < node_count_leaf) {
57350
+ if (leaf_index_1 < node_count_leaf) {
57256
57351
  // both children nodes are valid
57257
57352
  aabb3_array_combine(
57258
57353
  float32, offset,
57259
- float32, leafOffset0,
57260
- float32, leafOffset1
57354
+ float32, leaf_offset_0,
57355
+ float32, leaf_offset_1
57261
57356
  );
57262
- } else if (leafIndex0 < node_count_leaf) {
57357
+ } else if (leaf_index_0 < node_count_leaf) {
57263
57358
  // only left child node is valid
57264
- array_copy(float32, leafOffset0, float32, offset, 6);
57359
+ array_copy(float32, leaf_offset_0, float32, offset, 6);
57265
57360
  } else {
57266
57361
  //initialize to 0-size box same position as previous node
57267
57362
  copy_box_zero_size(this.__data_float32, offset, (offset - BVH_BINARY_NODE_SIZE));
@@ -57301,127 +57396,6 @@ class BinaryUint32BVH {
57301
57396
 
57302
57397
  //
57303
57398
 
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
57399
  /**
57426
57400
  *
57427
57401
  * @param {ArrayLike<number>|number[]|AABB3} aabb
@@ -57600,23 +57574,37 @@ function aabb3_compute_plane_side(
57600
57574
  }
57601
57575
 
57602
57576
  /**
57603
- *
57577
+ * Tests whether AABB intersects a clipping volume defined by a set of planes
57578
+ * Mainly useful for frustum checks
57604
57579
  * @param {number} x0
57605
57580
  * @param {number} y0
57606
57581
  * @param {number} z0
57607
57582
  * @param {number} x1
57608
57583
  * @param {number} y1
57609
57584
  * @param {number} z1
57610
- * @param {ArrayLike<number>|number[]|Float32Array|Float64Array} frustum
57585
+ * @param {ArrayLike<number>|number[]|Float32Array|Float64Array} planes
57586
+ * @param {number} planes_offset
57587
+ * @param {number} plane_count
57611
57588
  * @return {boolean}
57612
57589
  */
57613
- function aabb3_intersects_frustum_array(x0, y0, z0, x1, y1, z1, frustum) {
57614
- for (let i = 0; i < 24; i += 4) {
57590
+ function aabb3_intersects_clipping_volume_array(
57591
+ x0, y0, z0,
57592
+ x1, y1, z1,
57593
+ planes, planes_offset, plane_count
57594
+ ) {
57595
+
57596
+ assert.isNonNegativeInteger(planes_offset, 'frustum_offset');
57597
+
57598
+ const limit = plane_count * 4;
57599
+
57600
+ for (let i = 0; i < limit; i += 4) {
57601
+
57602
+ const offset = planes_offset + i;
57615
57603
 
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];
57604
+ const plane_x = planes[offset];
57605
+ const plane_y = planes[offset + 1];
57606
+ const plane_z = planes[offset + 2];
57607
+ const plane_w = planes[offset + 3];
57620
57608
 
57621
57609
  const plane_distance = aabb3_compute_distance_above_plane_max(
57622
57610
  plane_x, plane_y, plane_z, plane_w,
@@ -57631,6 +57619,7 @@ function aabb3_intersects_frustum_array(x0, y0, z0, x1, y1, z1, frustum) {
57631
57619
  }
57632
57620
 
57633
57621
  return true;
57622
+
57634
57623
  }
57635
57624
 
57636
57625
  //
@@ -58710,7 +58699,7 @@ class AABB3 {
58710
58699
  const y1 = this.y1;
58711
58700
  const z1 = this.z1;
58712
58701
 
58713
- return aabb3_intersects_frustum_array(x0, y0, z0, x1, y1, z1, frustum);
58702
+ return aabb3_intersects_clipping_volume_array(x0, y0, z0, x1, y1, z1, frustum, 0, 6);
58714
58703
  }
58715
58704
 
58716
58705
  /**
@@ -58845,6 +58834,127 @@ function ray3_array_compose(output, origin_x, origin_y, origin_z, direction_x, d
58845
58834
  output[5] = direction_z;
58846
58835
  }
58847
58836
 
58837
+ //
58838
+
58839
+ /**
58840
+ *
58841
+ * @param {ArrayLike<number>|number[]|Float32Array} aabb bounding box, order: x0,y0,z0,x1,y1,z1
58842
+ * @param {number} aabb_offset
58843
+ * @param {number} origin_x
58844
+ * @param {number} origin_y
58845
+ * @param {number} origin_z
58846
+ * @param {number} direction_x
58847
+ * @param {number} direction_y
58848
+ * @param {number} direction_z
58849
+ */
58850
+ function aabb3_array_intersects_ray(
58851
+ aabb, aabb_offset,
58852
+ origin_x, origin_y, origin_z,
58853
+ direction_x, direction_y, direction_z
58854
+ ) {
58855
+ return aabb3_intersects_ray(
58856
+ aabb[aabb_offset], aabb[aabb_offset+1], aabb[aabb_offset+2],
58857
+ aabb[aabb_offset+3], aabb[aabb_offset+4], aabb[aabb_offset+5],
58858
+ origin_x, origin_y, origin_z,
58859
+ direction_x, direction_y, direction_z
58860
+ );
58861
+ }
58862
+
58863
+ const stack$7 = SCRATCH_UINT32_TRAVERSAL_STACK;
58864
+
58865
+ /**
58866
+ *
58867
+ * @param {number[]} result
58868
+ * @param {number} result_offset
58869
+ * @param {BinaryUint32BVH} bvh
58870
+ * @param {number} origin_x
58871
+ * @param {number} origin_y
58872
+ * @param {number} origin_z
58873
+ * @param {number} direction_x
58874
+ * @param {number} direction_y
58875
+ * @param {number} direction_z
58876
+ * @returns {number}
58877
+ */
58878
+ function bvh32_query_user_data_ray(
58879
+ result, result_offset,
58880
+ bvh,
58881
+ origin_x, origin_y, origin_z,
58882
+ direction_x, direction_y, direction_z
58883
+ ) {
58884
+ let hit_count = 0;
58885
+
58886
+ const binary_node_count = bvh.binary_node_count;
58887
+
58888
+ if (binary_node_count <= 0) {
58889
+ // this should not happen
58890
+ return 0;
58891
+ }
58892
+
58893
+ /**
58894
+ *
58895
+ * @type {number}
58896
+ */
58897
+ const stack_top = stack$7.pointer++;
58898
+
58899
+ /**
58900
+ * After performing empirical tests, stack-based depth-first traversal turns out faster than using a queue
58901
+ * @type {number}
58902
+ */
58903
+ stack$7[stack_top] = 0;
58904
+
58905
+ const last_valid_index = binary_node_count + bvh.leaf_node_count;
58906
+
58907
+ const float32 = bvh.float32;
58908
+ const uint32 = bvh.uint32;
58909
+
58910
+ do {
58911
+ stack$7.pointer--;
58912
+
58913
+ // query_bvh_frustum_from_objects.iteration_count++;
58914
+ const node_index = stack$7[stack$7.pointer];
58915
+
58916
+ const node_address = bvh.getNodeAddress(node_index);
58917
+
58918
+ if (!aabb3_array_intersects_ray(
58919
+ float32, node_address,
58920
+ origin_x, origin_y, origin_z,
58921
+ direction_x, direction_y, direction_z
58922
+ )) {
58923
+ continue;
58924
+ }
58925
+
58926
+ const is_intermediate_node = node_index < binary_node_count;
58927
+
58928
+ if (is_intermediate_node) {
58929
+ // is intermediate node
58930
+
58931
+ const left_index = (node_index << 1) + 1;
58932
+ const right_index = left_index + 1;
58933
+
58934
+ // left node ends up on top of the stack, which aligns with the desired access sequence
58935
+ if (right_index < last_valid_index) {
58936
+ stack$7[stack$7.pointer++] = right_index;
58937
+ // micro-optimization, since we know that right node is valid and left appears before that, left is valid too
58938
+ stack$7[stack$7.pointer++] = left_index;
58939
+ } else if (left_index < last_valid_index) {
58940
+ stack$7[stack$7.pointer++] = left_index;
58941
+ }
58942
+
58943
+
58944
+ } else {
58945
+ // leaf node
58946
+
58947
+ // write to output
58948
+ result[result_offset + hit_count] = uint32[node_address + 6];
58949
+
58950
+ hit_count++;
58951
+ }
58952
+
58953
+ } while (stack$7.pointer > stack_top)
58954
+
58955
+ return hit_count;
58956
+ }
58957
+
58848
58958
  /**
58849
58959
  * NOTE: adapted from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteIntrRay3Triangle3.h
58850
58960
  * @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 +59112,110 @@ function computeTriangleRayIntersection(
59002
59112
  return true;
59003
59113
  }
59004
59114
 
59115
+ const scratch_array$4 = [];
59116
+ const scratch_hit = new SurfacePoint3();
59117
+
59118
+ /**
59119
+ *
59120
+ * @param {SurfacePoint3} result
59121
+ * @param {BinaryUint32BVH} bvh
59122
+ * @param {number[]|ArrayLike<number>} vertices
59123
+ * @param {number} vertex_offset Unless you're using an interleaved buffer of some kind, this will be 0
59124
+ * @param {number} vertex_stride Unless you're using an interleaved buffer, this should be 3
59125
+ * @param {number[]|ArrayLike<number>|undefined} indices if this is set to undefined - implicit indexing will be used
59126
+ * @param {number} originX
59127
+ * @param {number} originY
59128
+ * @param {number} originZ
59129
+ * @param {number} directionX
59130
+ * @param {number} directionY
59131
+ * @param {number} directionZ
59132
+ * @returns {boolean}
59133
+ */
59134
+ function bvh32_geometry_raycast(
59135
+ result,
59136
+ bvh,
59137
+ vertices, vertex_offset, vertex_stride,
59138
+ indices,
59139
+ originX, originY, originZ,
59140
+ directionX, directionY, directionZ
59141
+ ) {
59142
+ let hit_found = false;
59143
+
59144
+ const hit_count = bvh32_query_user_data_ray(
59145
+ scratch_array$4, 0,
59146
+ bvh,
59147
+ originX, originY, originZ,
59148
+ directionX, directionY, directionZ
59149
+ );
59150
+
59151
+ let best_distance = Infinity;
59152
+
59153
+ let a, b, c;
59154
+
59155
+ for (let i = 0; i < hit_count; i++) {
59156
+ const triangle_index = scratch_array$4[i];
59157
+
59158
+ const index3 = triangle_index * 3;
59159
+
59160
+ if (indices !== undefined) {
59161
+ assert.lessThan(index3 + 2, indices.length, 'triangle index overflow, possibly geometry changed but tree was not rebuilt?');
59162
+
59163
+ a = indices[index3];
59164
+ b = indices[index3 + 1];
59165
+ c = indices[index3 + 2];
59166
+ } else {
59167
+ // implicit indices
59168
+ a = index3;
59169
+ b = index3 + 1;
59170
+ c = index3 + 2;
59171
+ }
59172
+
59173
+ const a_address = a * vertex_stride + vertex_offset;
59174
+ const b_address = b * vertex_stride + vertex_offset;
59175
+ const c_address = c * vertex_stride + vertex_offset;
59176
+
59177
+ assert.lessThan(a_address + 2, vertices.length, 'a-vertex overflow');
59178
+ assert.lessThan(b_address + 2, vertices.length, 'b-vertex overflow');
59179
+ assert.lessThan(c_address + 2, vertices.length, 'c-vertex overflow');
59180
+
59181
+ const ax = vertices[a_address];
59182
+ const ay = vertices[a_address + 1];
59183
+ const az = vertices[a_address + 2];
59184
+
59185
+ const bx = vertices[b_address];
59186
+ const by = vertices[b_address + 1];
59187
+ const bz = vertices[b_address + 2];
59188
+
59189
+ const cx = vertices[c_address];
59190
+ const cy = vertices[c_address + 1];
59191
+ const cz = vertices[c_address + 2];
59192
+
59193
+ const triangle_hit_found = computeTriangleRayIntersection(
59194
+ scratch_hit,
59195
+ originX, originY, originZ,
59196
+ directionX, directionY, directionZ,
59197
+ ax, ay, az,
59198
+ bx, by, bz,
59199
+ cx, cy, cz
59200
+ );
59201
+
59202
+ if (!triangle_hit_found) {
59203
+ continue;
59204
+ }
59205
+
59206
+ hit_found = true;
59207
+
59208
+ const distance_sqr = scratch_hit.position._distanceSqrTo(originX, originY, originZ);
59209
+
59210
+ if (distance_sqr < best_distance) {
59211
+ best_distance = distance_sqr;
59212
+ result.copy(scratch_hit);
59213
+ }
59214
+ }
59215
+
59216
+ return hit_found;
59217
+ }
59218
+
59005
59219
  /**
59006
59220
  * Created by Alex on 28/01/2017.
59007
59221
  */
@@ -59083,9 +59297,6 @@ var ThreeFactory = {
59083
59297
  const EMPTY_GEOMETRY = new BufferGeometry();
59084
59298
  const DEFAULT_MATERIAL = new MeshBasicMaterial();
59085
59299
 
59086
- const scratch_array$3 = [];
59087
- const scratch_hit = new SurfacePoint3();
59088
-
59089
59300
  const ray_tmp = [];
59090
59301
  const m4_tmp = [];
59091
59302
 
@@ -59241,52 +59452,19 @@ class TerrainTile {
59241
59452
  const _directionY = ray_tmp[4];
59242
59453
  const _directionZ = ray_tmp[5];
59243
59454
 
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
59455
  const geometry = this.geometry;
59255
59456
 
59256
59457
  const geometryIndices = geometry.getIndex().array;
59257
59458
  const geometryPositions = geometry.getAttribute('position').array;
59258
59459
 
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
- }
59460
+ let hit_found = bvh32_geometry_raycast(
59461
+ result,
59462
+ this.bvh,
59463
+ geometryPositions, 0, 3,
59464
+ geometryIndices,
59465
+ _originX, _originY, _originZ,
59466
+ _directionX, _directionY, _directionZ
59467
+ );
59290
59468
 
59291
59469
  if (hit_found) {
59292
59470
  result.applyMatrix4(m4);
@@ -59708,7 +59886,7 @@ class TerrainTile {
59708
59886
  *
59709
59887
  * @type {number[]}
59710
59888
  */
59711
- const scratch_array$2 = [];
59889
+ const scratch_array$3 = [];
59712
59890
  const scratch_contact = new SurfacePoint3();
59713
59891
 
59714
59892
  class TerrainTileManager {
@@ -60284,7 +60462,7 @@ class TerrainTileManager {
60284
60462
  const hit_count = bvh_query_leaves_ray(
60285
60463
  this.bvh,
60286
60464
  this.bvh.root,
60287
- scratch_array$2, 0,
60465
+ scratch_array$3, 0,
60288
60466
  originX, originY, originZ,
60289
60467
  directionX, directionY, directionZ
60290
60468
  );
@@ -60293,7 +60471,7 @@ class TerrainTileManager {
60293
60471
  let hit_found = false;
60294
60472
 
60295
60473
  for (let i = 0; i < hit_count; i++) {
60296
- const node_id = scratch_array$2[i];
60474
+ const node_id = scratch_array$3[i];
60297
60475
 
60298
60476
  const tile_index = this.bvh.node_get_user_data(node_id);
60299
60477
 
@@ -65201,7 +65379,7 @@ function makeTerrainWorkerProxy() {
65201
65379
  resolve({
65202
65380
  geometry: geometry,
65203
65381
  bvh: {
65204
- leaf_count: bvh.getLeafNodeCount(),
65382
+ leaf_count: bvh.leaf_node_count,
65205
65383
  data: bvh.data
65206
65384
  }
65207
65385
  });
@@ -67185,598 +67363,283 @@ function aabb3_from_threejs_geometry(result, geometry) {
67185
67363
  aabb3_from_min_max(result, min, max);
67186
67364
  }
67187
67365
 
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
67366
  /**
67201
67367
  *
67202
- * @enum {number}
67368
+ * @param {Plane[]} planes
67369
+ * @param {ArrayLike<number>|number[]|Float32Array|Float64Array} array
67203
67370
  */
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;
67371
+ function read_three_planes_to_array(planes, array) {
67372
+ const plane_count = planes.length;
67218
67373
 
67219
- this.directionX = 0;
67220
- this.directionY = 0;
67221
- this.directionZ = 0;
67374
+ assert.greaterThanOrEqual(array.length, plane_count * 4, 'target array is too small');
67222
67375
 
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
- );
67376
+ for (let i = 0; i < plane_count; i++) {
67377
+ const plane = planes[i];
67247
67378
 
67248
- if (!intersectionFound) {
67249
- return false;
67250
- }
67379
+ const offset = i * 4;
67251
67380
 
67252
- if (type === NodeType.LEAF) {
67253
- const value = address / 6 - binaryNodeCount;
67381
+ const normal = plane.normal;
67254
67382
 
67255
- this.callback.call(this.callbackThisArg, value, address, type);
67383
+ array[offset] = normal.x;
67384
+ array[offset + 1] = normal.y;
67385
+ array[offset + 2] = normal.z;
67256
67386
 
67257
- return false;
67258
- } else {
67259
- return true;
67260
- }
67387
+ array[offset + 3] = plane.constant;
67261
67388
  }
67262
67389
  }
67263
67390
 
67264
- /**
67265
- * Created by Alex on 29/05/2016.
67266
- */
67267
-
67268
-
67269
67391
  /**
67270
67392
  *
67271
- * @type {Float32Array|number[]}
67393
+ * @param {BinaryUint32BVH} bvh
67394
+ * @param {number} triangle_index
67395
+ * @param {number[]|Float32Array} vertices
67396
+ * @param {number} a_index
67397
+ * @param {number} b_index
67398
+ * @param {number} c_index
67272
67399
  */
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;
67400
+ function bvh32_set_leaf_from_triangle(bvh, triangle_index, vertices, a_index, b_index, c_index) {
67401
+ const a = a_index * 3;
67402
+ const b = b_index * 3;
67403
+ const c = c_index * 3;
67432
67404
 
67433
- let i = 0;
67434
- const l = this.leafNodeCount;
67435
- for (; i < l; i++) {
67436
- visitor(i, offset, data, writeBox);
67405
+ // read actual positions of each vertex
67406
+ const aX = vertices[a];
67407
+ const aY = vertices[a + 1];
67408
+ const aZ = vertices[a + 2];
67437
67409
 
67438
- offset += 6;
67439
- }
67440
- this.unsortedBuiltIntermediate();
67441
- }
67410
+ const bX = vertices[b];
67411
+ const bY = vertices[b + 1];
67412
+ const bZ = vertices[b + 2];
67442
67413
 
67443
- /**
67444
- *
67445
- * @param {IndexedBinaryBVHVisitor} visitor
67446
- * @param {Number} startIndex
67447
- */
67448
- traversePreOrderStack(visitor, startIndex) {
67414
+ const cX = vertices[c];
67415
+ const cY = vertices[c + 1];
67416
+ const cZ = vertices[c + 2];
67449
67417
 
67450
- const stackOffset = stackPointer;
67418
+ // compute bounds of the triangle
67419
+ const x0 = min3(aX, bX, cX);
67420
+ const y0 = min3(aY, bY, cY);
67421
+ const z0 = min3(aZ, bZ, cZ);
67451
67422
 
67452
- stack$6[stackPointer++] = startIndex;
67423
+ const x1 = max3(aX, bX, cX);
67424
+ const y1 = max3(aY, bY, cY);
67425
+ const z1 = max3(aZ, bZ, cZ);
67453
67426
 
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;
67427
+ bvh.setLeafData(triangle_index, triangle_index, x0, y0, z0, x1, y1, z1);
67428
+ }
67429
+
67430
+ /**
67431
+ *
67432
+ * @param {BinaryUint32BVH} bvh
67433
+ * @param {Float32Array} vertices
67434
+ * @param {Uint32Array} indices
67435
+ */
67436
+ function bvh32_from_indexed_geometry(bvh, vertices, indices) {
67462
67437
 
67463
- const split = visitor.visit(address, NodeType.BINARY);
67464
- if (split) {
67438
+ const triangle_count = indices.length / 3;
67465
67439
 
67466
- const leftIndex = (index << 1) + 1;
67467
- const rightIndex = leftIndex + 1;
67440
+ bvh.setLeafCount(triangle_count);
67441
+ bvh.initialize_structure();
67468
67442
 
67469
- const leftAddress = leftIndex * 6;
67470
- const rightAddress = rightIndex * 6;
67443
+ for (let i = 0; i < triangle_count; i++) {
67471
67444
 
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
- }
67445
+ const index3 = i * 3;
67480
67446
 
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
- }
67447
+ // read triangle vertex indices
67448
+ const iA = indices[index3];
67449
+ const iB = indices[index3 + 1];
67450
+ const iC = indices[index3 + 2];
67491
67451
 
67492
- //drop stack
67493
- stackPointer = stackOffset;
67452
+ bvh32_set_leaf_from_triangle(bvh, i, vertices, iA, iB, iC);
67494
67453
  }
67495
67454
 
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) {
67455
+ // finalize build
67456
+ // bvh.sort_morton(MATRIX_4_IDENTITY);
67457
+ bvh.build();
67458
+ }
67459
+
67460
+ /**
67461
+ *
67462
+ * @param {BinaryUint32BVH} bvh
67463
+ * @param {Float32Array} vertices
67464
+ */
67465
+ function bvh32_from_unindexed_geometry(bvh, vertices) {
67509
67466
 
67510
- const leftIndex = (index << 1) + 1;
67511
- const rightIndex = leftIndex + 1;
67467
+ const triangle_count = indices.length / 3;
67512
67468
 
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
- }
67469
+ bvh.setLeafCount(triangle_count);
67470
+ bvh.initialize_structure();
67533
67471
 
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;
67472
+ for (let i = 0; i < triangle_count; i++) {
67549
67473
 
67550
- rayLeafIntersectionVisitor.directionX = directionX;
67551
- rayLeafIntersectionVisitor.directionY = directionY;
67552
- rayLeafIntersectionVisitor.directionZ = directionZ;
67474
+ const index3 = i * 3;
67553
67475
 
67554
- rayLeafIntersectionVisitor.root = this;
67555
- rayLeafIntersectionVisitor.callback = visitor;
67556
- rayLeafIntersectionVisitor.callbackThisArg = thisArg;
67476
+ // generate triangle vertex indices
67477
+ const iA = index3;
67478
+ const iB = index3 + 1;
67479
+ const iC = index3 + 2;
67557
67480
 
67558
- this.traversePreOrderStack(rayLeafIntersectionVisitor, 0);
67481
+ bvh32_set_leaf_from_triangle(bvh, i, vertices, iA, iB, iC);
67559
67482
  }
67560
- }
67561
67483
 
67484
+ // finalize build
67485
+ // bvh.sort_morton(MATRIX_4_IDENTITY);
67486
+ bvh.build();
67487
+ }
67488
+
67562
67489
  /**
67563
67490
  *
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
67491
+ * @param {THREE.InterleavedBufferAttribute|THREE.BufferAttribute} source_attribute
67492
+ * @returns {THREE.BufferAttribute}
67569
67493
  */
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);
67494
+ function deinterleaveBufferAttribute(source_attribute) {
67495
+ if (source_attribute.isInterleavedBufferAttribute !== true && source_attribute.isBufferAttribute) {
67496
+ return source_attribute;
67497
+ }
67589
67498
 
67590
- const x1 = max2(ax1, bx1);
67591
- const y1 = max2(ay1, by1);
67592
- const z1 = max2(az1, bz1);
67499
+ const source_data = source_attribute.data;
67500
+ const source_data_array = source_data.array;
67501
+ const stride = source_data.stride;
67593
67502
 
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
- }
67503
+ const item_count = source_attribute.count;
67504
+ const itemSize = source_attribute.itemSize;
67505
+ const array_size = item_count * itemSize;
67601
67506
 
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
- }
67507
+ const offset = source_attribute.offset;
67621
67508
 
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
- }
67509
+ const destination_array = new source_data_array.constructor(array_size);
67631
67510
 
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);
67511
+ const attribute = new BufferAttribute(destination_array, itemSize);
67640
67512
 
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];
67513
+ attribute.normalized = source_attribute.normalized;
67514
+ attribute.name = source_attribute.name;
67644
67515
 
67645
- array_copy(scratch_aabb_0, 0, array, to, 6);
67646
- }
67516
+ let i = 0, j = 0;
67517
+ // copy data
67518
+ for (; i < item_count; i++) {
67519
+ for (j = 0; j < itemSize; j++) {
67520
+ destination_array[i * itemSize + j] = source_data_array[i * stride + offset + j];
67521
+ }
67522
+ }
67647
67523
 
67524
+ return attribute;
67525
+ }
67526
+
67648
67527
  /**
67649
67528
  *
67650
- * @param {Float32Array} array
67651
- * @param {number} binaryNode
67652
- * @param {number} childNode0
67653
- * @param {number} childNode1
67529
+ * @param {Float32Array|number[]} aabb
67530
+ * @param {number} aabb_offset
67531
+ * @param {Float32Array|number[]} planes
67532
+ * @param {number} planes_offset
67533
+ * @param {number} plane_count
67534
+ * @return {boolean}
67654
67535
  */
67655
- function binaryNodeRefit(array, binaryNode, childNode0, childNode1) {
67656
- contain_box_array(array, childNode0, childNode1, array, binaryNode);
67657
- }
67658
-
67536
+ function aabb3_array_intersects_clipping_volume_array(
67537
+ aabb, aabb_offset,
67538
+ planes, planes_offset, plane_count
67539
+ ) {
67659
67540
 
67660
- const stack$6 = [];
67661
- let stackPointer = 0;
67541
+ const x0 = aabb[aabb_offset + 0];
67542
+ const y0 = aabb[aabb_offset + 1];
67543
+ const z0 = aabb[aabb_offset + 2];
67544
+ const x1 = aabb[aabb_offset + 3];
67545
+ const y1 = aabb[aabb_offset + 4];
67546
+ const z1 = aabb[aabb_offset + 5];
67662
67547
 
67663
- const rayLeafIntersectionVisitor = new RayLeafIntersectionVisitor();
67548
+ return aabb3_intersects_clipping_volume_array(
67549
+ x0, y0, z0,
67550
+ x1, y1, z1,
67551
+ planes, planes_offset, plane_count
67552
+ );
67553
+ }
67664
67554
 
67665
- /**
67666
- * Created by Alex on 29/05/2016.
67667
- */
67555
+ const stack$6 = SCRATCH_UINT32_TRAVERSAL_STACK;
67668
67556
 
67669
67557
  /**
67670
67558
  *
67671
- * @param {Float32Array|Float64Array|Array.<Number>} vertices
67672
- * @param {Uint8Array|Uint16Array|Uint32Array|Array.<Number>} indices
67673
- * @returns {IndexedBinaryBVH}
67559
+ * @param {number[]} result
67560
+ * @param {number} result_offset
67561
+ * @param {BinaryUint32BVH} bvh
67562
+ * @param {Float32Array|number[]} planes
67563
+ * @param {number} planes_offset
67564
+ * @param {number} plane_count
67565
+ * @returns {number}
67674
67566
  */
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];
67567
+ function bvh32_query_user_data_overlaps_clipping_volume(
67568
+ result, result_offset,
67569
+ bvh,
67570
+ planes, planes_offset, plane_count
67571
+ ) {
67572
+ let hit_count = 0;
67703
67573
 
67704
- const cX = vertices[c];
67705
- const cY = vertices[c + 1];
67706
- const cZ = vertices[c + 2];
67574
+ const binary_node_count = bvh.binary_node_count;
67707
67575
 
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);
67576
+ if (binary_node_count <= 0) {
67577
+ // this should not happen
67578
+ return 0;
67579
+ }
67712
67580
 
67713
- const x1 = max3(aX, bX, cX);
67714
- const y1 = max3(aY, bY, cY);
67715
- const z1 = max3(aZ, bZ, cZ);
67581
+ /**
67582
+ *
67583
+ * @type {number}
67584
+ */
67585
+ const stack_top = stack$6.pointer++;
67716
67586
 
67717
- tree.writeLeaf(i, x0, y0, z0, x1, y1, z1);
67718
- }
67587
+ /**
67588
+ * After performing empirical tests, stack-based depth-first traversal turns out faster than using a queue
67589
+ * @type {number}
67590
+ */
67591
+ stack$6[stack_top] = 0;
67719
67592
 
67720
- // finalize build
67721
- tree.unsortedBuiltIntermediate();
67593
+ const last_valid_index = binary_node_count + bvh.leaf_node_count;
67722
67594
 
67723
- return tree;
67724
- }
67595
+ const float32 = bvh.float32;
67596
+ const uint32 = bvh.uint32;
67725
67597
 
67726
- /**
67727
- *
67728
- * @param {Float32Array|Float64Array|Array.<Number>} vertices
67729
- * @returns {IndexedBinaryBVH}
67730
- */
67731
- function buildUnsortedUnindexed(vertices) {
67732
- //
67733
- const numNodes = vertices.length / 9;
67598
+ do {
67599
+ stack$6.pointer--;
67734
67600
 
67735
- const tree = new IndexedBinaryBVH();
67736
- tree.initialize(numNodes);
67601
+ // query_bvh_frustum_from_objects.iteration_count++;
67602
+ const node_index = stack$6[stack$6.pointer];
67737
67603
 
67738
- for (let i = 0; i < numNodes; i++) {
67604
+ const node_address = bvh.getNodeAddress(node_index);
67739
67605
 
67740
- const index3 = i * 3;
67606
+ if (!aabb3_array_intersects_clipping_volume_array(
67607
+ float32, node_address,
67608
+ planes, planes_offset, plane_count
67609
+ )) {
67610
+ continue;
67611
+ }
67741
67612
 
67742
- // read triangle vertex indices
67743
- const iA = index3;
67744
- const iB = index3 + 1;
67745
- const iC = index3 + 2;
67613
+ const is_intermediate_node = node_index < binary_node_count;
67746
67614
 
67747
- const a = iA * 3;
67748
- const b = iB * 3;
67749
- const c = iC * 3;
67615
+ if (is_intermediate_node) {
67616
+ // is intermediate node
67750
67617
 
67751
- // read actual positions of each vertex
67752
- const aX = vertices[a];
67753
- const aY = vertices[a + 1];
67754
- const aZ = vertices[a + 2];
67618
+ const left_index = (node_index << 1) + 1;
67619
+ const right_index = left_index + 1;
67755
67620
 
67756
- const bX = vertices[b];
67757
- const bY = vertices[b + 1];
67758
- const bZ = vertices[b + 2];
67621
+ // left node ends up on top of the stack, which aligns with the desired access sequence
67622
+ if (right_index < last_valid_index) {
67623
+ stack$6[stack$6.pointer++] = right_index;
67624
+ // micro-optimization, since we know that right node is valid and left appears before that, left is valid too
67625
+ stack$6[stack$6.pointer++] = left_index;
67626
+ } else if (left_index < last_valid_index) {
67627
+ stack$6[stack$6.pointer++] = left_index;
67628
+ }
67759
67629
 
67760
- const cX = vertices[c];
67761
- const cY = vertices[c + 1];
67762
- const cZ = vertices[c + 2];
67763
67630
 
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);
67631
+ } else {
67632
+ // leaf node
67768
67633
 
67769
- const x1 = max3(aX, bX, cX);
67770
- const y1 = max3(aY, bY, cY);
67771
- const z1 = max3(aZ, bZ, cZ);
67634
+ // write to output
67635
+ result[result_offset + hit_count] = uint32[node_address + 6];
67772
67636
 
67773
- tree.writeLeaf(i, x0, y0, z0, x1, y1, z1);
67774
- }
67637
+ hit_count++;
67638
+ }
67775
67639
 
67776
- // finalize build
67777
- tree.unsortedBuiltIntermediate();
67640
+ } while (stack$6.pointer > stack_top)
67778
67641
 
67779
- return tree;
67642
+ return hit_count;
67780
67643
  }
67781
67644
 
67782
67645
  /**
@@ -67813,526 +67676,145 @@ function computeTrianglePlaneSide(
67813
67676
  return result;
67814
67677
  }
67815
67678
 
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;
67679
+ /**
67680
+ * @param {number[]|Float32Array} planes
67681
+ * @param {number} planes_offset
67682
+ * @param {number} plane_count
67683
+ * @param {number} ax
67684
+ * @param {number} ay
67685
+ * @param {number} az
67686
+ * @param {number} bx
67687
+ * @param {number} by
67688
+ * @param {number} bz
67689
+ * @param {number} cx
67690
+ * @param {number} cy
67691
+ * @param {number} cz
67692
+ * @returns {boolean}
67693
+ */
67694
+ function triangle_intersects_clipping_volume(
67695
+ planes, planes_offset, plane_count,
67696
+ ax, ay, az,
67697
+ bx, by, bz,
67698
+ cx, cy, cz
67699
+ ) {
68125
67700
 
68126
- /**
68127
- * @readonly
68128
- * @type {Vector3}
68129
- * @private
68130
- */
68131
- this.__ray_origin = new Vector3$1();
67701
+ for (let j = 0; j < plane_count; j++) {
68132
67702
 
68133
- /**
68134
- * @readonly
68135
- * @type {Vector3}
68136
- * @private
68137
- */
68138
- this.__ray_direction = new Vector3$1();
68139
- }
67703
+ const plane_address = planes_offset + j * 4;
68140
67704
 
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
- );
67705
+ const plane_normal_x = planes[plane_address];
67706
+ const plane_normal_y = planes[plane_address + 1];
67707
+ const plane_normal_z = planes[plane_address + 2];
67708
+ const plane_constant = planes[plane_address + 3];
68156
67709
 
68157
- this.__ray_direction.set(
68158
- direction_x,
68159
- direction_y,
68160
- direction_z
67710
+ const side = computeTrianglePlaneSide(
67711
+ plane_normal_x,
67712
+ plane_normal_y,
67713
+ plane_normal_z,
67714
+ plane_constant,
67715
+ ax, ay, az,
67716
+ bx, by, bz,
67717
+ cx, cy, cz
68161
67718
  );
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
67719
 
67720
+ if (side === -3) {
67721
+ // fully outside
68263
67722
  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
67723
  }
68289
67724
  }
67725
+
67726
+ return true;
68290
67727
  }
68291
67728
 
67729
+ const scratch_array$2 = [];
67730
+
68292
67731
  /**
68293
67732
  *
68294
- * @param {THREE.InterleavedBufferAttribute|THREE.BufferAttribute} source_attribute
68295
- * @returns {THREE.BufferAttribute}
67733
+ * @param {BinaryUint32BVH} bvh
67734
+ * @param {number[]|ArrayLike<number>} vertices
67735
+ * @param {number} vertex_offset Unless you're using an interleaved buffer of some kind, this will be 0
67736
+ * @param {number} vertex_stride Unless you're using an interleaved buffer, this should be 3
67737
+ * @param {number[]|ArrayLike<number>|undefined} indices if this is set to undefined - implicit indexing will be used
67738
+ * @param {number[]|Float32Array} planes
67739
+ * @param {number} planes_offset
67740
+ * @param {number} plane_count
67741
+ * @returns {boolean}
68296
67742
  */
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;
67743
+ function bvh32_geometry_overlap_clipping_volume(
67744
+ bvh,
67745
+ vertices, vertex_offset, vertex_stride,
67746
+ indices,
67747
+ planes, planes_offset, plane_count
67748
+ ) {
68305
67749
 
68306
- const item_count = source_attribute.count;
68307
- const itemSize = source_attribute.itemSize;
68308
- const array_size = item_count * itemSize;
67750
+ const hit_count = bvh32_query_user_data_overlaps_clipping_volume(
67751
+ scratch_array$2, 0,
67752
+ bvh,
67753
+ planes, planes_offset, plane_count
67754
+ );
68309
67755
 
68310
- const offset = source_attribute.offset;
67756
+ let a, b, c;
68311
67757
 
68312
- const destination_array = new source_data_array.constructor(array_size);
67758
+ for (let i = 0; i < hit_count; i++) {
67759
+ const triangle_index = scratch_array$2[i];
68313
67760
 
68314
- const attribute = new BufferAttribute(destination_array, itemSize);
67761
+ const index3 = triangle_index * 3;
68315
67762
 
68316
- attribute.normalized = source_attribute.normalized;
68317
- attribute.name = source_attribute.name;
67763
+ if (indices !== undefined) {
67764
+ assert.lessThan(index3 + 2, indices.length, 'triangle index overflow, possibly geometry changed but tree was not rebuilt?');
68318
67765
 
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];
67766
+ a = indices[index3];
67767
+ b = indices[index3 + 1];
67768
+ c = indices[index3 + 2];
67769
+ } else {
67770
+ // implicit indices
67771
+ a = index3;
67772
+ b = index3 + 1;
67773
+ c = index3 + 2;
67774
+ }
67775
+
67776
+ const a_address = a * vertex_stride + vertex_offset;
67777
+ const b_address = b * vertex_stride + vertex_offset;
67778
+ const c_address = c * vertex_stride + vertex_offset;
67779
+
67780
+ assert.lessThan(a_address + 2, vertices.length, 'a-vertex overflow');
67781
+ assert.lessThan(b_address + 2, vertices.length, 'b-vertex overflow');
67782
+ assert.lessThan(c_address + 2, vertices.length, 'c-vertex overflow');
67783
+
67784
+ const ax = vertices[a_address];
67785
+ const ay = vertices[a_address + 1];
67786
+ const az = vertices[a_address + 2];
67787
+
67788
+ const bx = vertices[b_address];
67789
+ const by = vertices[b_address + 1];
67790
+ const bz = vertices[b_address + 2];
67791
+
67792
+ const cx = vertices[c_address];
67793
+ const cy = vertices[c_address + 1];
67794
+ const cz = vertices[c_address + 2];
67795
+
67796
+ if (triangle_intersects_clipping_volume(
67797
+ planes, planes_offset, plane_count,
67798
+ ax, ay, az,
67799
+ bx, by, bz,
67800
+ cx, cy, cz
67801
+ )) {
67802
+ return true;
68324
67803
  }
67804
+
68325
67805
  }
68326
67806
 
68327
- return attribute;
67807
+ return false;
68328
67808
  }
68329
67809
 
67810
+ const scratch_planes = [];
67811
+
68330
67812
  class GeometrySpatialQueryAccelerator {
68331
67813
  constructor(cache_size = 100 * 1024 * 1024) {
68332
67814
 
68333
67815
  /**
68334
67816
  *
68335
- * @type {Cache<THREE.BufferGeometry, IndexedBinaryBVH>}
67817
+ * @type {Cache<THREE.BufferGeometry, BinaryUint32BVH>}
68336
67818
  */
68337
67819
  this.cache = new Cache({
68338
67820
  maxWeight: cache_size,
@@ -68344,15 +67826,13 @@ class GeometrySpatialQueryAccelerator {
68344
67826
  },
68345
67827
  /**
68346
67828
  *
68347
- * @param {IndexedBinaryBVH} tree
67829
+ * @param {BinaryUint32BVH} tree
68348
67830
  */
68349
67831
  valueWeigher(tree) {
68350
67832
  return tree.estimateByteSize();
68351
67833
  }
68352
67834
  });
68353
67835
 
68354
- this.__visitor_clip = new ClippingPlaneContainmentComputingVisitor();
68355
- this.__visitor_raycast = new RaycastNearestHitComputingVisitor();
68356
67836
  }
68357
67837
 
68358
67838
  /**
@@ -68375,23 +67855,46 @@ class GeometrySpatialQueryAccelerator {
68375
67855
  *
68376
67856
  * @param {THREE.BufferGeometry} geometry
68377
67857
  * @param {Plane[]} planes
68378
- * @returns {number} -1,0,1. -1 means fully outside, 0 means partially inside, 1 means fully inside
67858
+ * @returns {boolean} true means some overlap exists, false otherwise
68379
67859
  */
68380
67860
  queryContainmentViaClippingPlanes(geometry, planes) {
68381
67861
  assert.notNull(geometry, 'geometry');
68382
67862
  assert.defined(geometry, 'geometry');
68383
67863
 
67864
+
68384
67865
  const bvh = this.__acquireBVH(geometry);
68385
67866
 
68386
- this.__visitor_clip.reset();
67867
+ read_three_planes_to_array(planes, scratch_planes);
68387
67868
 
68388
- this.__visitor_clip.setGeometry(geometry);
68389
- this.__visitor_clip.setPlanes(planes);
68390
- this.__visitor_clip.setRoot(bvh);
67869
+ const geometryIndices = geometry.getIndex()?.array;
67870
+ const position_attribute = geometry.getAttribute('position');
67871
+
67872
+ let position_data;
67873
+ let stride = 3;
67874
+ let position_data_offset = 0;
67875
+
67876
+ if (position_attribute.isInterleavedBufferAttribute) {
67877
+
67878
+ position_data = position_attribute.data.array;
67879
+
67880
+ stride = position_attribute.data.stride;
67881
+ position_data_offset = position_attribute.offset;
68391
67882
 
68392
- bvh.traversePreOrderStack(this.__visitor_clip, 0);
67883
+ } else {
67884
+
67885
+ position_data = position_attribute.array;
67886
+
67887
+ stride = 3;
67888
+ position_data_offset = 0;
68393
67889
 
68394
- return this.__visitor_clip.getContainment();
67890
+ }
67891
+
67892
+ return bvh32_geometry_overlap_clipping_volume(
67893
+ bvh,
67894
+ position_data, position_data_offset, stride,
67895
+ geometryIndices,
67896
+ scratch_planes, 0, planes.length
67897
+ );
68395
67898
  }
68396
67899
 
68397
67900
  /**
@@ -68441,11 +67944,33 @@ class GeometrySpatialQueryAccelerator {
68441
67944
  return false;
68442
67945
  }
68443
67946
 
68444
- this.__visitor_raycast.reset();
67947
+ const geometryIndices = geometry.getIndex()?.array;
67948
+ const position_attribute = geometry.getAttribute('position');
67949
+
67950
+ let position_data;
67951
+ let stride = 3;
67952
+ let position_data_offset = 0;
67953
+
67954
+ if (position_attribute.isInterleavedBufferAttribute) {
67955
+
67956
+ position_data = position_attribute.data.array;
67957
+
67958
+ stride = position_attribute.data.stride;
67959
+ position_data_offset = position_attribute.offset;
68445
67960
 
68446
- this.__visitor_raycast.setGeometry(geometry);
68447
- this.__visitor_raycast.setRoot(bvh);
68448
- this.__visitor_raycast.setRay(
67961
+ } else {
67962
+
67963
+ position_data = position_attribute.array;
67964
+
67965
+ stride = 3;
67966
+ position_data_offset = 0;
67967
+
67968
+ }
67969
+
67970
+ return bvh32_geometry_raycast(
67971
+ destination, bvh,
67972
+ position_data, position_data_offset, stride,
67973
+ geometryIndices,
68449
67974
  ray_origin_x,
68450
67975
  ray_origin_y,
68451
67976
  ray_origin_z,
@@ -68454,16 +67979,6 @@ class GeometrySpatialQueryAccelerator {
68454
67979
  ray_direction_z
68455
67980
  );
68456
67981
 
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
67982
  }
68468
67983
 
68469
67984
  /**
@@ -68491,7 +68006,7 @@ class GeometrySpatialQueryAccelerator {
68491
68006
  /**
68492
68007
  * @private
68493
68008
  * @param {THREE.BufferGeometry} geometry
68494
- * @returns {IndexedBinaryBVH}
68009
+ * @returns {BinaryUint32BVH}
68495
68010
  */
68496
68011
  __acquireBVH(geometry) {
68497
68012
  assert.notNull(geometry, 'geometry');
@@ -68513,7 +68028,7 @@ class GeometrySpatialQueryAccelerator {
68513
68028
  /**
68514
68029
  * @private
68515
68030
  * @param {THREE.BufferGeometry} geometry
68516
- * @returns {IndexedBinaryBVH}
68031
+ * @returns {BinaryUint32BVH}
68517
68032
  */
68518
68033
  __buildBVH(geometry) {
68519
68034
  const position_attribute = geometry.getAttribute('position');
@@ -68522,14 +68037,19 @@ class GeometrySpatialQueryAccelerator {
68522
68037
  const de_interleaved_position_attribute = deinterleaveBufferAttribute(position_attribute);
68523
68038
  const vertices = de_interleaved_position_attribute.array;
68524
68039
 
68040
+ const bvh = new BinaryUint32BVH();
68041
+
68525
68042
  if (index_attribute === undefined || index_attribute === null) {
68526
- return buildUnsortedUnindexed(vertices);
68527
- }
68043
+ bvh32_from_unindexed_geometry(bvh, vertices);
68044
+ } else {
68528
68045
 
68529
- const de_interleaved_index_attribute = deinterleaveBufferAttribute(index_attribute);
68530
- const indices = de_interleaved_index_attribute.array;
68046
+ const de_interleaved_index_attribute = deinterleaveBufferAttribute(index_attribute);
68047
+ const indices = de_interleaved_index_attribute.array;
68531
68048
 
68532
- return buildUnsorted(vertices, indices);
68049
+ bvh32_from_indexed_geometry(bvh, vertices, indices);
68050
+ }
68051
+
68052
+ return bvh;
68533
68053
  }
68534
68054
 
68535
68055
  }
@@ -69348,29 +68868,6 @@ function bvh_query_user_data_overlaps_frustum(
69348
68868
  return result_cursor - result_offset;
69349
68869
  }
69350
68870
 
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
68871
  /**
69375
68872
  * @template CTX
69376
68873
  * @template Asset
@@ -71961,7 +71458,7 @@ class TerrainSystem extends System {
71961
71458
 
71962
71459
  for (let i = 0; i < frustums.length; i++) {
71963
71460
 
71964
- read_frustum_planes_to_array(frustums[i].planes, frustum);
71461
+ read_three_planes_to_array(frustums[i].planes, frustum);
71965
71462
 
71966
71463
  found_tiles += bvh_query_user_data_overlaps_frustum(tiles, tile_count, tileManager.bvh, frustum);
71967
71464
  }
@@ -91558,7 +91055,7 @@ class CameraView {
91558
91055
  frustum_from_camera(camera, scratch_frustum, false);
91559
91056
 
91560
91057
  // update view definition
91561
- read_frustum_planes_to_array(scratch_frustum.planes, this.frustum);
91058
+ read_three_planes_to_array(scratch_frustum.planes, this.frustum);
91562
91059
 
91563
91060
  // read projection matrix
91564
91061
  // TODO
@@ -111244,7 +110741,7 @@ function query_bvh_frustum_from_texture(
111244
110741
  ) {
111245
110742
  let result = 0;
111246
110743
 
111247
- const binary_node_count = bvh.getBinaryNodeCount();
110744
+ const binary_node_count = bvh.binary_node_count;
111248
110745
 
111249
110746
  if (binary_node_count <= 0) {
111250
110747
  // this should not happen
@@ -111263,7 +110760,7 @@ function query_bvh_frustum_from_texture(
111263
110760
  */
111264
110761
  stack[stack_top] = 0;
111265
110762
 
111266
- const last_valid_index = binary_node_count + bvh.getLeafNodeCount();
110763
+ const last_valid_index = binary_node_count + bvh.leaf_node_count;
111267
110764
 
111268
110765
  const float32 = bvh.float32;
111269
110766
  const uint32 = bvh.uint32;
@@ -112819,7 +112316,7 @@ class LightManager {
112819
112316
 
112820
112317
  const nodes = [];
112821
112318
 
112822
- read_frustum_planes_to_array(this.__view_frustum.planes, scratch_frustum_planes);
112319
+ read_three_planes_to_array(this.__view_frustum.planes, scratch_frustum_planes);
112823
112320
 
112824
112321
  /*
112825
112322
  Search is done in 2 phases:
@@ -119216,6 +118713,18 @@ class Blackboard extends AbstractBlackboard {
119216
118713
 
119217
118714
  Blackboard.typeName = 'Blackboard';
119218
118715
 
118716
+ /**
118717
+ * just in case you need that function also
118718
+ * @param {Vector3} axis
118719
+ * @param {number} angle
118720
+ * @param {Quaternion} result
118721
+ */
118722
+ function quat3_createFromAxisAngle(axis, angle, result) {
118723
+ const halfAngle = angle * .5;
118724
+ const s = Math.sin(halfAngle);
118725
+ result.set(axis.x * s, axis.y * s, axis.z * s, Math.cos(halfAngle));
118726
+ }
118727
+
119219
118728
  exports.AmbientOcclusionPostProcessEffect = AmbientOcclusionPostProcessEffect;
119220
118729
  exports.Behavior = Behavior;
119221
118730
  exports.BehaviorStatus = BehaviorStatus;