@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
@@ -1762,6 +1762,27 @@ function clamp$1(value, min, max) {
1762
1762
  }
1763
1763
  }
1764
1764
 
1765
+ /**
1766
+ * Very small value, used for comparison when compensation for rounding error is required
1767
+ * @type {number}
1768
+ */
1769
+ const EPSILON = 0.000001;
1770
+
1771
+ /**
1772
+ * Comparison of two numbers with a given tolerance
1773
+ * @param {number} a
1774
+ * @param {number} b
1775
+ * @param {number} tolerance
1776
+ * @returns {boolean}
1777
+ */
1778
+ function epsilonEquals(a, b, tolerance) {
1779
+ assert.isNumber(a, 'a');
1780
+ assert.isNumber(b, 'b');
1781
+ assert.isNumber(tolerance, 'tolerance');
1782
+
1783
+ return Math.abs(a - b) <= tolerance;
1784
+ }
1785
+
1765
1786
  /**
1766
1787
  * Linear interpolation between two values controlled by a given fraction
1767
1788
  * @param {number} a
@@ -1773,13 +1794,191 @@ function lerp$1(a, b, fraction) {
1773
1794
  return (b - a) * fraction + a;
1774
1795
  }
1775
1796
 
1797
+ /**
1798
+ * Returns lowest value out of 2 supplied
1799
+ * @param {number} a
1800
+ * @param {number} b
1801
+ * @returns {number}
1802
+ */
1803
+ function min2(a, b) {
1804
+ return a < b ? a : b;
1805
+ }
1806
+
1776
1807
  /**
1777
1808
  *
1778
1809
  * @param {number} v
1779
- * @returns {number} +1 if v>0, 0 if v == 0, -1 if v<0
1810
+ * @returns {number}
1780
1811
  */
1781
- function sign$1(v) {
1782
- return v > 0 ? 1 : (v < 0 ? -1 : 0);
1812
+ function computeHashFloat(v) {
1813
+ //we break the number up into fractional and whole parts
1814
+ const whole = v | 0;
1815
+
1816
+ const fraction = v - whole;
1817
+
1818
+ //fractional part is scaled up into int32 range, this inexact method, as it will produce 0 hash for values below a certain threshold
1819
+ const fractionHash = fraction * 1367130550;
1820
+
1821
+ //take XOR of both parts
1822
+ return fractionHash ^ whole;
1823
+ }
1824
+
1825
+ const K = Math.SQRT1_2 / 511;
1826
+
1827
+ /**
1828
+ * Based on GDC talk from Bungie on destiny, compressing quaternions for animation
1829
+ * @param {number[]} output
1830
+ * @param {number} output_offset
1831
+ * @param {number} value
1832
+ */
1833
+ function quat_decode_from_uint32(output, output_offset, value) {
1834
+ //read components
1835
+ const max = value & 0x3;
1836
+
1837
+ const iv0 = (value >> 2) & 0x3FF;
1838
+ const iv1 = (value >> 12) & 0x3FF;
1839
+ const iv2 = (value >> 22) & 0x3FF;
1840
+
1841
+ //scale components back to quaternion range
1842
+ const v0 = iv0 * K - Math.SQRT1_2;
1843
+ const v1 = iv1 * K - Math.SQRT1_2;
1844
+ const v2 = iv2 * K - Math.SQRT1_2;
1845
+
1846
+ //restore dropped component using quaternion identity: x^2 + y^2 + z^2 + w^2 = 1
1847
+ const dropped_2 = 1 - v0 * v0 - v1 * v1 - v2 * v2;
1848
+ const dropped = Math.sqrt(dropped_2);
1849
+
1850
+ let x, y, z, w;
1851
+ if (max === 0) {
1852
+ x = dropped;
1853
+ y = v0;
1854
+ z = v1;
1855
+ w = v2;
1856
+ } else if (max === 1) {
1857
+ x = v0;
1858
+ y = dropped;
1859
+ z = v1;
1860
+ w = v2;
1861
+ } else if (max === 2) {
1862
+ x = v0;
1863
+ y = v1;
1864
+ z = dropped;
1865
+ w = v2;
1866
+ } else {
1867
+ x = v0;
1868
+ y = v1;
1869
+ z = v2;
1870
+ w = dropped;
1871
+ }
1872
+
1873
+ output[output_offset] = x;
1874
+ output[output_offset + 1] = y;
1875
+ output[output_offset + 2] = z;
1876
+ output[output_offset + 3] = w;
1877
+ }
1878
+
1879
+ /**
1880
+ * Based on GDC talk from Bungie on destiny, compressing quaternions for animation
1881
+ * @param {number} x
1882
+ * @param {number} y
1883
+ * @param {number} z
1884
+ * @param {number} w
1885
+ * @returns {number}
1886
+ */
1887
+ function quat_encode_to_uint32(x, y, z, w) {
1888
+
1889
+ const absX = Math.abs(x);
1890
+ const absY = Math.abs(y);
1891
+ const absZ = Math.abs(z);
1892
+ const absW = Math.abs(w);
1893
+
1894
+ let max = 0;
1895
+
1896
+ //pick max component
1897
+ if (absY > absX) {
1898
+ if (absY > absZ) {
1899
+ if (absY > absW) {
1900
+ //absY is max
1901
+ max = 1;
1902
+ } else {
1903
+ //absW is max
1904
+ max = 3;
1905
+ }
1906
+ } else if (absZ > absW) {
1907
+ //absZ is max
1908
+ max = 2;
1909
+ } else {
1910
+ //absW is max
1911
+ max = 3;
1912
+ }
1913
+ } else if (absX > absZ) {
1914
+ if (absX > absW) {
1915
+ max = 0;
1916
+ } else {
1917
+ max = 3;
1918
+ }
1919
+ } else if (absZ > absW) {
1920
+ max = 2;
1921
+ } else {
1922
+ max = 3;
1923
+ }
1924
+
1925
+ let v0, v1, v2, dropped;
1926
+
1927
+ //max will be dropped
1928
+ if (max === 0) {
1929
+ //dropping x
1930
+ v0 = y;
1931
+ v1 = z;
1932
+ v2 = w;
1933
+
1934
+ dropped = x;
1935
+ } else if (max === 1) {
1936
+ //dropping y
1937
+ v0 = x;
1938
+ v1 = z;
1939
+ v2 = w;
1940
+
1941
+ dropped = y;
1942
+ } else if (max === 2) {
1943
+ //dropping z
1944
+ v0 = x;
1945
+ v1 = y;
1946
+ v2 = w;
1947
+
1948
+ dropped = z;
1949
+ } else {
1950
+ //dropping w
1951
+ v0 = x;
1952
+ v1 = y;
1953
+ v2 = z;
1954
+
1955
+ dropped = w;
1956
+ }
1957
+
1958
+ if (dropped < 0) {
1959
+ //reconstructing dropped value is only possible if it is positive, so we invert the quaternion to make dropped value positive
1960
+ v0 = -v0;
1961
+ v1 = -v1;
1962
+ v2 = -v2;
1963
+ }
1964
+
1965
+ const l = Math.sqrt(x * x + y * y + z * z + w * w);
1966
+ const m = 511 / (l * Math.SQRT1_2);
1967
+
1968
+ //re-normalize the remaining components to 10 bit UINT value
1969
+ const oV0 = Math.round(v0 * m + 511);
1970
+ const oV1 = Math.round(v1 * m + 511);
1971
+ const oV2 = Math.round(v2 * m + 511);
1972
+
1973
+ assert.ok(oV0 <= 1023 && oV0 >= 0, `expected 0 <= ov0 <= 1023, instead was '${oV0}'`);
1974
+ assert.ok(oV1 <= 1023 && oV1 >= 0, `expected 0 <= ov1 <= 1023, instead was '${oV1}'`);
1975
+ assert.ok(oV2 <= 1023 && oV2 >= 0, `expected 0 <= ov2 <= 1023, instead was '${oV2}'`);
1976
+
1977
+
1978
+ return (max & 0x3)
1979
+ | ((oV0 & 0x3FF) << 2)
1980
+ | ((oV1 & 0x3FF) << 12)
1981
+ | ((oV2 & 0x3FF) << 22);
1783
1982
  }
1784
1983
 
1785
1984
  /**
@@ -1798,13 +1997,11 @@ function v3_dot(x0, y0, z0, x1, y1, z1) {
1798
1997
 
1799
1998
  /**
1800
1999
  *
1801
- * @param {number} x
1802
- * @param {number} y
1803
- * @param {number} z
1804
- * @return {number}
2000
+ * @param {number} v
2001
+ * @returns {number} +1 if v>0, 0 if v == 0, -1 if v<0
1805
2002
  */
1806
- function v3_length_sqr(x, y, z) {
1807
- return x * x + y * y + z * z;
2003
+ function sign$1(v) {
2004
+ return v > 0 ? 1 : (v < 0 ? -1 : 0);
1808
2005
  }
1809
2006
 
1810
2007
  /**
@@ -1860,6 +2057,110 @@ function v3_angle_cos_between(x0, y0, z0, x1, y1, z1){
1860
2057
  return clamp$1(d / l, -1, 1);
1861
2058
  }
1862
2059
 
2060
+ /**
2061
+ *
2062
+ * @param {BinaryBuffer} buffer
2063
+ * @param {number[]} result
2064
+ * @param {number} result_offset
2065
+ */
2066
+ function v3_binary_equality_decode(buffer, result, result_offset) {
2067
+ const header = buffer.readUint8();
2068
+
2069
+ let x = 0;
2070
+ let y = 0;
2071
+ let z = 0;
2072
+
2073
+ if ((header & 7) === 7) {
2074
+ //all scale components are the same
2075
+ x = buffer.readFloat32();
2076
+ y = x;
2077
+ z = x;
2078
+ } else if ((header & 1) === 1) {
2079
+ //X and Y are the same, Z is different
2080
+ x = buffer.readFloat32();
2081
+ y = x;
2082
+ z = buffer.readFloat32();
2083
+ } else if ((header & 2) === 2) {
2084
+ //Y and Z are the same, X is different
2085
+ x = buffer.readFloat32();
2086
+ y = buffer.readFloat32();
2087
+ z = y;
2088
+ } else if ((header & 4) === 4) {
2089
+ //X and Z are the same, Y is different
2090
+ x = buffer.readFloat32();
2091
+ y = buffer.readFloat32();
2092
+ z = x;
2093
+ } else {
2094
+ //scale components are different
2095
+ x = buffer.readFloat32();
2096
+ y = buffer.readFloat32();
2097
+ z = buffer.readFloat32();
2098
+ }
2099
+
2100
+ result[result_offset] = x;
2101
+ result[result_offset + 1] = y;
2102
+ result[result_offset + 2] = z;
2103
+ }
2104
+
2105
+ /**
2106
+ *
2107
+ * @param {BinaryBuffer} buffer
2108
+ * @param {number} x
2109
+ * @param {number} y
2110
+ * @param {number} z
2111
+ */
2112
+ function v3_binary_equality_encode(buffer, x, y, z){
2113
+
2114
+ let header = 0;
2115
+
2116
+ if (x === y) {
2117
+ header |= 1;
2118
+ }
2119
+
2120
+ if (y === z) {
2121
+ header |= 2;
2122
+ }
2123
+
2124
+ if (x === z) {
2125
+ header |= 4;
2126
+ }
2127
+
2128
+ buffer.writeUint8(header);
2129
+
2130
+ if ((header & 7) === 7) {
2131
+ //all components are the same
2132
+ buffer.writeFloat32(x);
2133
+ } else if (header === 1) {
2134
+ //X and Y are the same, Z is different
2135
+ buffer.writeFloat32(x);
2136
+ buffer.writeFloat32(z);
2137
+ } else if (header === 2) {
2138
+ //Y and Z are the same, X is different
2139
+ buffer.writeFloat32(x);
2140
+ buffer.writeFloat32(y);
2141
+ } else if (header === 4) {
2142
+ //X and Z are the same, Y is different
2143
+ buffer.writeFloat32(x);
2144
+ buffer.writeFloat32(y);
2145
+ } else {
2146
+ //scale components are different
2147
+ buffer.writeFloat32(x);
2148
+ buffer.writeFloat32(y);
2149
+ buffer.writeFloat32(z);
2150
+ }
2151
+ }
2152
+
2153
+ /**
2154
+ *
2155
+ * @param {number} x
2156
+ * @param {number} y
2157
+ * @param {number} z
2158
+ * @return {number}
2159
+ */
2160
+ function v3_length_sqr(x, y, z) {
2161
+ return x * x + y * y + z * z;
2162
+ }
2163
+
1863
2164
  /**
1864
2165
  *
1865
2166
  * @param {Vector3} result
@@ -1931,45 +2232,6 @@ function v3_slerp(
1931
2232
  result.set(x, y, z);
1932
2233
  }
1933
2234
 
1934
- /**
1935
- *
1936
- * @param {number} v
1937
- * @returns {number}
1938
- */
1939
- function computeHashFloat(v) {
1940
- //we break the number up into fractional and whole parts
1941
- const fraction = v % 1;
1942
-
1943
- const whole = v | 0;
1944
-
1945
- //fractional part is scaled up into int32 range, this inexact method, as it will produce 0 hash for values below a certain threshold
1946
- const fractionHash = fraction * 1367130550;
1947
-
1948
- //take XOR of both parts
1949
- return fractionHash ^ whole;
1950
- }
1951
-
1952
- /**
1953
- * Comparison of two numbers with a given tolerance
1954
- * @param {number} a
1955
- * @param {number} b
1956
- * @param {number} tolerance
1957
- * @returns {boolean}
1958
- */
1959
- function epsilonEquals(a, b, tolerance) {
1960
- assert.isNumber(a, 'a');
1961
- assert.isNumber(b, 'b');
1962
- assert.isNumber(tolerance, 'tolerance');
1963
-
1964
- return Math.abs(a - b) <= tolerance;
1965
- }
1966
-
1967
- /**
1968
- * Very small value, used for comparison when compensation for rounding error is required
1969
- * @type {number}
1970
- */
1971
- const EPSILON = 0.000001;
1972
-
1973
2235
  /**
1974
2236
  * @author Alex Goldring
1975
2237
  * @copyright Alex Goldring 2015
@@ -2814,100 +3076,31 @@ let Vector3$1 = class Vector3 {
2814
3076
  /**
2815
3077
  *
2816
3078
  * @param {BinaryBuffer} buffer
3079
+ * @deprecated use dedicated method directly instead
2817
3080
  */
2818
3081
  toBinaryBufferFloat32_EqualityEncoded(buffer) {
2819
3082
  const x = this.x;
2820
3083
  const y = this.y;
2821
3084
  const z = this.z;
2822
3085
 
2823
- let header = 0;
2824
-
2825
- if (x === y) {
2826
- header |= 1;
2827
- }
2828
-
2829
- if (y === z) {
2830
- header |= 2;
2831
- }
2832
-
2833
- if (x === z) {
2834
- header |= 4;
2835
- }
2836
-
2837
- buffer.writeUint8(header);
2838
-
2839
- if ((header & 7) === 7) {
2840
- //all components are the same
2841
- buffer.writeFloat32(x);
2842
- } else if (header === 1) {
2843
- //X and Y are the same, Z is different
2844
- buffer.writeFloat32(x);
2845
- buffer.writeFloat32(z);
2846
- } else if (header === 2) {
2847
- //Y and Z are the same, X is different
2848
- buffer.writeFloat32(x);
2849
- buffer.writeFloat32(y);
2850
- } else if (header === 4) {
2851
- //X and Z are the same, Y is different
2852
- buffer.writeFloat32(x);
2853
- buffer.writeFloat32(y);
2854
- } else {
2855
- //scale components are different
2856
- buffer.writeFloat32(x);
2857
- buffer.writeFloat32(y);
2858
- buffer.writeFloat32(z);
2859
- }
3086
+ v3_binary_equality_encode(buffer, x, y, z);
2860
3087
  }
2861
3088
 
2862
3089
  /**
2863
3090
  * Uses an extra byte for a header. Only writes unique components. Useful for things like scale where all components usually have the same value
2864
3091
  * @param {BinaryBuffer} buffer
3092
+ * @deprecated use dedicated method directly instead
2865
3093
  */
2866
3094
  fromBinaryBufferFloat32_EqualityEncoded(buffer) {
2867
- const header = buffer.readUint8();
2868
-
2869
- let x = 0;
2870
- let y = 0;
2871
- let z = 0;
2872
-
2873
- if ((header & 7) === 7) {
2874
- //all scale components are the same
2875
- x = buffer.readFloat32();
2876
- y = x;
2877
- z = x;
2878
- } else if ((header & 1) === 1) {
2879
- //X and Y are the same, Z is different
2880
- x = buffer.readFloat32();
2881
- y = x;
2882
- z = buffer.readFloat32();
2883
- } else if ((header & 2) === 2) {
2884
- //Y and Z are the same, X is different
2885
- x = buffer.readFloat32();
2886
- y = buffer.readFloat32();
2887
- z = y;
2888
- } else if ((header & 4) === 4) {
2889
- //X and Z are the same, Y is different
2890
- x = buffer.readFloat32();
2891
- y = buffer.readFloat32();
2892
- z = x;
2893
- } else {
2894
- //scale components are different
2895
- x = buffer.readFloat32();
2896
- y = buffer.readFloat32();
2897
- z = buffer.readFloat32();
2898
- }
2899
-
2900
- this.set(x, y, z);
3095
+ v3_binary_equality_decode(buffer, this, 0);
2901
3096
  }
2902
3097
 
2903
3098
  hash() {
2904
- let hash = computeHashFloat(this.x);
2905
-
2906
- hash = ((hash << 5) - hash) + computeHashFloat(this.y);
2907
-
2908
- hash = ((hash << 5) - hash) + computeHashFloat(this.z);
3099
+ const x = computeHashFloat(this.x);
3100
+ const y = computeHashFloat(this.y);
3101
+ const z = computeHashFloat(this.z);
2909
3102
 
2910
- return hash;
3103
+ return x ^ (y << 1) ^ (z << 2);
2911
3104
  }
2912
3105
 
2913
3106
 
@@ -3065,16 +3258,6 @@ Vector3$1.typeName = "Vector3";
3065
3258
  */
3066
3259
  Vector3$1._dot = v3_dot;
3067
3260
 
3068
- /**
3069
- * Returns lowest value out of 2 supplied
3070
- * @param {number} a
3071
- * @param {number} b
3072
- * @returns {number}
3073
- */
3074
- function min2(a, b) {
3075
- return a < b ? a : b;
3076
- }
3077
-
3078
3261
  /**
3079
3262
  * Created by Alex on 10/03/14.
3080
3263
  */
@@ -3084,18 +3267,6 @@ const forward = new Vector3$1();
3084
3267
  const up = new Vector3$1();
3085
3268
  const right = new Vector3$1();
3086
3269
 
3087
- /**
3088
- * just in case you need that function also
3089
- * @param {Vector3} axis
3090
- * @param {number} angle
3091
- * @param {Quaternion} result
3092
- */
3093
- function quat3_createFromAxisAngle(axis, angle, result) {
3094
- const halfAngle = angle * .5;
3095
- const s = Math.sin(halfAngle);
3096
- result.set(axis.x * s, axis.y * s, axis.z * s, Math.cos(halfAngle));
3097
- }
3098
-
3099
3270
  let Quaternion$1 = class Quaternion {
3100
3271
  /**
3101
3272
  *
@@ -4518,31 +4689,7 @@ let Quaternion$1 = class Quaternion {
4518
4689
  * @param {number} value
4519
4690
  */
4520
4691
  decodeFromUint32(value) {
4521
- //read components
4522
- const max = value & 0x3;
4523
-
4524
- const iv0 = (value >> 2) & 0x3FF;
4525
- const iv1 = (value >> 12) & 0x3FF;
4526
- const iv2 = (value >> 22) & 0x3FF;
4527
-
4528
- //scale components back to quaternion range
4529
- const v0 = (iv0 / 511 - 1) * K_CONST;
4530
- const v1 = (iv1 / 511 - 1) * K_CONST;
4531
- const v2 = (iv2 / 511 - 1) * K_CONST;
4532
-
4533
- //restore dropped component using quaternion identity: x^2 + y^2 + z^2 + w^2 = 1
4534
- const dropped_2 = 1 - v0 * v0 - v1 * v1 - v2 * v2;
4535
- const dropped = Math.sqrt(dropped_2);
4536
-
4537
- if (max === 0) {
4538
- this.set(dropped, v0, v1, v2);
4539
- } else if (max === 1) {
4540
- this.set(v0, dropped, v1, v2);
4541
- } else if (max === 2) {
4542
- this.set(v0, v1, dropped, v2);
4543
- } else {
4544
- this.set(v0, v1, v2, dropped);
4545
- }
4692
+ quat_decode_from_uint32(this, 0, value);
4546
4693
  }
4547
4694
 
4548
4695
  /**
@@ -4550,107 +4697,7 @@ let Quaternion$1 = class Quaternion {
4550
4697
  * @returns {number}
4551
4698
  */
4552
4699
  encodeToUint32() {
4553
- const x = this.x;
4554
- const y = this.y;
4555
- const z = this.z;
4556
- const w = this.w;
4557
-
4558
- const absX = Math.abs(x);
4559
- const absY = Math.abs(y);
4560
- const absZ = Math.abs(z);
4561
- const absW = Math.abs(w);
4562
-
4563
- let max = 0;
4564
-
4565
- //pick max component
4566
- if (absY > absX) {
4567
- if (absY > absZ) {
4568
- if (absY > absW) {
4569
- //absY is max
4570
- max = 1;
4571
- } else {
4572
- //absW is max
4573
- max = 3;
4574
- }
4575
- } else if (absZ > absW) {
4576
- //absZ is max
4577
- max = 2;
4578
- } else {
4579
- //absW is max
4580
- max = 3;
4581
- }
4582
- } else if (absX > absZ) {
4583
- if (absX > absW) {
4584
- max = 0;
4585
- } else {
4586
- max = 3;
4587
- }
4588
- } else if (absZ > absW) {
4589
- max = 2;
4590
- } else {
4591
- max = 3;
4592
- }
4593
-
4594
- let v0, v1, v2, dropped;
4595
-
4596
- //max will be dropped
4597
- if (max === 0) {
4598
- //dropping x
4599
- v0 = y;
4600
- v1 = z;
4601
- v2 = w;
4602
-
4603
- dropped = x;
4604
- } else if (max === 1) {
4605
- //dropping y
4606
- v0 = x;
4607
- v1 = z;
4608
- v2 = w;
4609
-
4610
- dropped = y;
4611
- } else if (max === 2) {
4612
- //dropping z
4613
- v0 = x;
4614
- v1 = y;
4615
- v2 = w;
4616
-
4617
- dropped = z;
4618
- } else {
4619
- //dropping w
4620
- v0 = x;
4621
- v1 = y;
4622
- v2 = z;
4623
-
4624
- dropped = w;
4625
- }
4626
-
4627
- if (dropped < 0) {
4628
- //reconstructing dropped value is only possible if it is positive, so we invert the quaternion to make dropped value positive
4629
- v0 = -v0;
4630
- v1 = -v1;
4631
- v2 = -v2;
4632
- }
4633
-
4634
- const l = Math.sqrt(x * x + y * y + z * z + w * w);
4635
- const m = 1 / (l * K_CONST);
4636
-
4637
- //re-normalize the remaining components to 10 bit UINT value
4638
- const oV0 = Math.round((v0 * m + 1) * 511);
4639
- const oV1 = Math.round((v1 * m + 1) * 511);
4640
- const oV2 = Math.round((v2 * m + 1) * 511);
4641
-
4642
- assert.ok(oV0 <= 1023 && oV0 >= 0, `expected 0 <= ov0 <= 1023, instead was '${oV0}'`);
4643
- assert.ok(oV1 <= 1023 && oV1 >= 0, `expected 0 <= ov1 <= 1023, instead was '${oV1}'`);
4644
- assert.ok(oV2 <= 1023 && oV2 >= 0, `expected 0 <= ov2 <= 1023, instead was '${oV2}'`);
4645
-
4646
-
4647
- const result = (max & 0x3)
4648
- | ((oV0 & 0x3FF) << 2)
4649
- | ((oV1 & 0x3FF) << 12)
4650
- | ((oV2 & 0x3FF) << 22)
4651
- ;
4652
-
4653
- return result;
4700
+ return quat_encode_to_uint32(this.x, this.y, this.z, this.w);
4654
4701
  }
4655
4702
 
4656
4703
  /**
@@ -4837,13 +4884,7 @@ Quaternion$1.identity = Object.freeze(new Quaternion$1(0, 0, 0, 1));
4837
4884
  const axis = new Vector3$1();
4838
4885
 
4839
4886
 
4840
- const tempvec3 = new Vector3$1();
4841
-
4842
- /**
4843
- * Used in UINT32 packing
4844
- * @type {number}
4845
- */
4846
- const K_CONST = 0.70710678118; // 1/sqrt(2)
4887
+ const tempvec3 = new Vector3$1();
4847
4888
 
4848
4889
  /**
4849
4890
  * @readonly
@@ -5110,8 +5151,7 @@ class Transform {
5110
5151
  * @returns {boolean}
5111
5152
  */
5112
5153
  equals(other) {
5113
- return other.isTransform
5114
- && this.position.equals(other.position)
5154
+ return this.position.equals(other.position)
5115
5155
  && this.rotation.equals(other.rotation)
5116
5156
  && this.scale.equals(other.scale);
5117
5157
  }
@@ -48945,11 +48985,7 @@ class Vector2 {
48945
48985
  const x = computeHashFloat(this.x);
48946
48986
  const y = computeHashFloat(this.y);
48947
48987
 
48948
- let hash = ((x << 5) - x) + y;
48949
-
48950
- hash |= 0; //convert to 32bit int
48951
-
48952
- return hash;
48988
+ return ((x << 5) - x) + y;
48953
48989
  }
48954
48990
 
48955
48991
  /**
@@ -48960,8 +48996,11 @@ class Vector2 {
48960
48996
  const sin = Math.sin(angle);
48961
48997
  const cos = Math.cos(angle);
48962
48998
 
48963
- const x = this.x * cos - this.y * sin;
48964
- const y = this.x * sin + this.y * cos;
48999
+ const _x = this.x;
49000
+ const _y = this.y;
49001
+
49002
+ const x = _x * cos - _y * sin;
49003
+ const y = _x * sin + _y * cos;
48965
49004
 
48966
49005
  this.set(x, y);
48967
49006
  }
@@ -56784,6 +56823,39 @@ function mortonEncode_magicbits(x, y, z) {
56784
56823
  return x_bits | y_bits | z_bits;
56785
56824
  }
56786
56825
 
56826
+ /**
56827
+ * @param {number} x
56828
+ * @param {number} y
56829
+ * @param {number} z
56830
+ * @param {number[]} bounds
56831
+ * @returns {number}
56832
+ */
56833
+ function v3_morton_encode_bounded(x, y, z, bounds) {
56834
+
56835
+ const bounds_x0 = bounds[0];
56836
+ const bounds_y0 = bounds[1];
56837
+ const bounds_z0 = bounds[2];
56838
+
56839
+ const bounds_x1 = bounds[3];
56840
+ const bounds_y1 = bounds[4];
56841
+ const bounds_z1 = bounds[5];
56842
+
56843
+ const bounds_span_x = bounds_x1 - bounds_x0;
56844
+ const bounds_span_y = bounds_y1 - bounds_y0;
56845
+ const bounds_span_z = bounds_z1 - bounds_z0;
56846
+
56847
+ // scale to 10 bits
56848
+ const ndc_x = 1023 * (x - bounds_x0) / bounds_span_x;
56849
+ const ndc_y = 1023 * (y - bounds_y0) / bounds_span_y;
56850
+ const ndc_z = 1023 * (z - bounds_z0) / bounds_span_z;
56851
+
56852
+ return mortonEncode_magicbits(
56853
+ Math.round(ndc_x),
56854
+ Math.round(ndc_y),
56855
+ Math.round(ndc_z)
56856
+ );
56857
+ }
56858
+
56787
56859
  /**
56788
56860
  * Returns highest value out of 3 supplied
56789
56861
  * @param {number} a
@@ -56846,10 +56918,10 @@ function copy_box_zero_size(data, destination, source) {
56846
56918
  * Assumes data will be normalized to 0...1 value range
56847
56919
  * @param {Float32Array} data
56848
56920
  * @param {number} address
56849
- * @param {number[]} matrix
56921
+ * @param {number[]} bounds
56850
56922
  * @returns {number}
56851
56923
  */
56852
- function build_morton(data, address, matrix) {
56924
+ function build_morton(data, address, bounds) {
56853
56925
 
56854
56926
  const x0 = data[address];
56855
56927
  const y0 = data[address + 1];
@@ -56858,17 +56930,15 @@ function build_morton(data, address, matrix) {
56858
56930
  const y1 = data[address + 4];
56859
56931
  const z1 = data[address + 5];
56860
56932
 
56861
- const cx = (x0 + x1) / 2;
56862
- const cy = (y0 + y1) / 2;
56863
- const cz = (z0 + z1) / 2;
56933
+ const cx = (x0 + x1) * 0.5;
56934
+ const cy = (y0 + y1) * 0.5;
56935
+ const cz = (z0 + z1) * 0.5;
56864
56936
 
56865
- return mortonEncode_magicbits(cx, cy, cz);
56866
- // return v3_morton_encode_transformed(cx, cy, cz, matrix);
56937
+ return v3_morton_encode_bounded(cx, cy, cz, bounds);
56867
56938
 
56868
56939
  }
56869
56940
 
56870
- const scratch_box_0 = new Float32Array(18);
56871
- const stack$8 = [];
56941
+ const stack$8 = SCRATCH_UINT32_TRAVERSAL_STACK;
56872
56942
 
56873
56943
  class BinaryUint32BVH {
56874
56944
  /**
@@ -56892,34 +56962,41 @@ class BinaryUint32BVH {
56892
56962
  */
56893
56963
  __data_uint32;
56894
56964
 
56895
- constructor() {
56896
-
56897
- /**
56898
- *
56899
- * @type {number}
56900
- * @private
56901
- */
56902
- this.__node_count_binary = 0;
56965
+ /**
56966
+ *
56967
+ * @type {number}
56968
+ * @private
56969
+ */
56970
+ __node_count_binary = 0;
56903
56971
 
56904
- /**
56905
- *
56906
- * @type {number}
56907
- * @private
56908
- */
56909
- this.__node_count_leaf = 0;
56972
+ /**
56973
+ *
56974
+ * @type {number}
56975
+ * @private
56976
+ */
56977
+ __node_count_leaf = 0;
56910
56978
 
56979
+ constructor() {
56911
56980
  this.data = new ArrayBuffer(320);
56912
56981
  }
56913
56982
 
56983
+ /**
56984
+ * In bytes
56985
+ * @returns {number}
56986
+ */
56987
+ estimateByteSize() {
56988
+ return this.data.byteLength + 248;
56989
+ }
56990
+
56914
56991
  getTotalBoxCount() {
56915
56992
  return this.__node_count_binary + this.__node_count_leaf;
56916
56993
  }
56917
56994
 
56918
- getBinaryNodeCount() {
56995
+ get binary_node_count() {
56919
56996
  return this.__node_count_binary;
56920
56997
  }
56921
56998
 
56922
- getLeafNodeCount() {
56999
+ get leaf_node_count() {
56923
57000
  return this.__node_count_leaf;
56924
57001
  }
56925
57002
 
@@ -56941,10 +57018,12 @@ class BinaryUint32BVH {
56941
57018
 
56942
57019
  /**
56943
57020
  *
56944
- * @param {ArrayBuffer} v
57021
+ * @param {ArrayBuffer} buffer
56945
57022
  */
56946
- set data(v) {
56947
- this.__data_buffer = v;
57023
+ set data(buffer) {
57024
+ assert.defined(buffer, 'buffer');
57025
+
57026
+ this.__data_buffer = buffer;
56948
57027
 
56949
57028
  this.__data_float32 = new Float32Array(this.__data_buffer);
56950
57029
  this.__data_uint32 = new Uint32Array(this.__data_buffer);
@@ -56954,6 +57033,24 @@ class BinaryUint32BVH {
56954
57033
  return this.__data_buffer;
56955
57034
  }
56956
57035
 
57036
+ /**
57037
+ * Resolve index of the node to address where the node data starts, this is required to know where AABB is stored in memory
57038
+ * @param {number} node_index
57039
+ * @returns {number}
57040
+ */
57041
+ getNodeAddress(node_index) {
57042
+ const binary_node_count = this.__node_count_binary;
57043
+ const leaf_node_index = node_index - binary_node_count;
57044
+
57045
+ if (leaf_node_index < 0) {
57046
+ // binary node
57047
+ return node_index * BVH_BINARY_NODE_SIZE;
57048
+ } else {
57049
+ // leaf node
57050
+ return binary_node_count * BVH_BINARY_NODE_SIZE + leaf_node_index * BVH_LEAF_NODE_SIZE;
57051
+ }
57052
+ }
57053
+
56957
57054
  initialize_structure() {
56958
57055
  // compute memory requirements
56959
57056
  const word_count = this.__node_count_binary * BVH_BINARY_NODE_SIZE + this.__node_count_leaf * BVH_LEAF_NODE_SIZE;
@@ -57072,17 +57169,15 @@ class BinaryUint32BVH {
57072
57169
  * @private
57073
57170
  */
57074
57171
  __compute_bounds_area_of_3_boxes(a, b, c) {
57075
- this.readBounds(a, scratch_box_0, 0);
57076
- this.readBounds(b, scratch_box_0, 6);
57077
- this.readBounds(c, scratch_box_0, 12);
57172
+ const float32 = this.__data_float32;
57078
57173
 
57079
- const x0 = min3(scratch_box_0[0], scratch_box_0[6], scratch_box_0[12]);
57080
- const y0 = min3(scratch_box_0[1], scratch_box_0[7], scratch_box_0[13]);
57081
- const z0 = min3(scratch_box_0[2], scratch_box_0[8], scratch_box_0[14]);
57174
+ const x0 = min3(float32[a + 0], float32[b + 0], float32[c + 0]);
57175
+ const y0 = min3(float32[a + 1], float32[b + 1], float32[c + 1]);
57176
+ const z0 = min3(float32[a + 2], float32[b + 2], float32[c + 2]);
57082
57177
 
57083
- const x1 = max3(scratch_box_0[3], scratch_box_0[9], scratch_box_0[15]);
57084
- const y1 = max3(scratch_box_0[4], scratch_box_0[10], scratch_box_0[16]);
57085
- const z1 = max3(scratch_box_0[5], scratch_box_0[11], scratch_box_0[17]);
57178
+ const x1 = max3(float32[a + 3], float32[b + 3], float32[c + 3]);
57179
+ const y1 = max3(float32[a + 4], float32[b + 4], float32[c + 4]);
57180
+ const z1 = max3(float32[a + 5], float32[b + 5], float32[c + 5]);
57086
57181
 
57087
57182
  return aabb3_compute_half_surface_area(x0, y0, z0, x1, y1, z1);
57088
57183
  }
@@ -57134,9 +57229,9 @@ class BinaryUint32BVH {
57134
57229
 
57135
57230
  /**
57136
57231
  * Sort leaf nodes according to their morton codes
57137
- * @param {number[]} projection
57232
+ * @param {number[]} bounds
57138
57233
  */
57139
- sort_morton(projection) {
57234
+ sort_morton(bounds) {
57140
57235
 
57141
57236
  const leaf_block_address = this.__node_count_binary * BVH_BINARY_NODE_SIZE;
57142
57237
 
@@ -57166,15 +57261,15 @@ class BinaryUint32BVH {
57166
57261
 
57167
57262
  const pivot_address = pivotIndex * BVH_LEAF_NODE_SIZE + leaf_block_address;
57168
57263
 
57169
- const pivot = build_morton(data, pivot_address);
57264
+ const pivot = build_morton(data, pivot_address, bounds);
57170
57265
 
57171
57266
  /* partition */
57172
57267
  while (i <= j) {
57173
- while (build_morton(data, i * BVH_LEAF_NODE_SIZE + leaf_block_address) < pivot) {
57268
+ while (build_morton(data, i * BVH_LEAF_NODE_SIZE + leaf_block_address, bounds) < pivot) {
57174
57269
  i++;
57175
57270
  }
57176
57271
 
57177
- while (build_morton(data, j * BVH_LEAF_NODE_SIZE + leaf_block_address) > pivot) {
57272
+ while (build_morton(data, j * BVH_LEAF_NODE_SIZE + leaf_block_address, bounds) > pivot) {
57178
57273
  j--;
57179
57274
  }
57180
57275
 
@@ -57244,22 +57339,22 @@ class BinaryUint32BVH {
57244
57339
 
57245
57340
  // build bottom-most level, just above the leaves
57246
57341
  for (i = 0; i < level_node_count; i++) {
57247
- const leafIndex0 = i * 2;
57248
- const leafIndex1 = leafIndex0 + 1;
57342
+ const leaf_index_0 = i * 2;
57343
+ const leaf_index_1 = leaf_index_0 + 1;
57249
57344
 
57250
- const leafOffset0 = leaf_node_block_address + leafIndex0 * BVH_LEAF_NODE_SIZE;
57251
- const leafOffset1 = leaf_node_block_address + leafIndex1 * BVH_LEAF_NODE_SIZE;
57345
+ const leaf_offset_0 = leaf_node_block_address + leaf_index_0 * BVH_LEAF_NODE_SIZE;
57346
+ const leaf_offset_1 = leaf_node_block_address + leaf_index_1 * BVH_LEAF_NODE_SIZE;
57252
57347
 
57253
- if (leafIndex1 < node_count_leaf) {
57348
+ if (leaf_index_1 < node_count_leaf) {
57254
57349
  // both children nodes are valid
57255
57350
  aabb3_array_combine(
57256
57351
  float32, offset,
57257
- float32, leafOffset0,
57258
- float32, leafOffset1
57352
+ float32, leaf_offset_0,
57353
+ float32, leaf_offset_1
57259
57354
  );
57260
- } else if (leafIndex0 < node_count_leaf) {
57355
+ } else if (leaf_index_0 < node_count_leaf) {
57261
57356
  // only left child node is valid
57262
- array_copy(float32, leafOffset0, float32, offset, 6);
57357
+ array_copy(float32, leaf_offset_0, float32, offset, 6);
57263
57358
  } else {
57264
57359
  //initialize to 0-size box same position as previous node
57265
57360
  copy_box_zero_size(this.__data_float32, offset, (offset - BVH_BINARY_NODE_SIZE));
@@ -57299,127 +57394,6 @@ class BinaryUint32BVH {
57299
57394
 
57300
57395
  //
57301
57396
 
57302
- /**
57303
- *
57304
- * @param {ArrayLike<number>|number[]|Float32Array} aabb bounding box, order: x0,y0,z0,x1,y1,z1
57305
- * @param {number} aabb_offset
57306
- * @param {number} origin_x
57307
- * @param {number} origin_y
57308
- * @param {number} origin_z
57309
- * @param {number} direction_x
57310
- * @param {number} direction_y
57311
- * @param {number} direction_z
57312
- */
57313
- function aabb3_array_intersects_ray(
57314
- aabb, aabb_offset,
57315
- origin_x, origin_y, origin_z,
57316
- direction_x, direction_y, direction_z
57317
- ) {
57318
- return aabb3_intersects_ray(
57319
- aabb[aabb_offset], aabb[aabb_offset+1], aabb[aabb_offset+2],
57320
- aabb[aabb_offset+3], aabb[aabb_offset+4], aabb[aabb_offset+5],
57321
- origin_x, origin_y, origin_z,
57322
- direction_x, direction_y, direction_z
57323
- );
57324
- }
57325
-
57326
- const stack$7 = SCRATCH_UINT32_TRAVERSAL_STACK;
57327
-
57328
- /**
57329
- *
57330
- * @param {BinaryUint32BVH} bvh
57331
- * @param {number[]} result
57332
- * @param {number} result_offset
57333
- * @param {number} origin_x
57334
- * @param {number} origin_y
57335
- * @param {number} origin_z
57336
- * @param {number} direction_x
57337
- * @param {number} direction_y
57338
- * @param {number} direction_z
57339
- * @returns {number}
57340
- */
57341
- function bvh32_query_user_data_ray(
57342
- bvh,
57343
- result, result_offset,
57344
- origin_x, origin_y, origin_z,
57345
- direction_x, direction_y, direction_z
57346
- ) {
57347
- let hit_count = 0;
57348
-
57349
- const binary_node_count = bvh.getBinaryNodeCount();
57350
-
57351
- if (binary_node_count <= 0) {
57352
- // this should not happen
57353
- return 0;
57354
- }
57355
-
57356
- /**
57357
- *
57358
- * @type {number}
57359
- */
57360
- const stack_top = stack$7.pointer++;
57361
-
57362
- /**
57363
- * After performing empirical tests, stack-based depth-first traversal turns out faster than using a queue
57364
- * @type {number}
57365
- */
57366
- stack$7[stack_top] = 0;
57367
-
57368
- const last_valid_index = binary_node_count + bvh.getLeafNodeCount();
57369
-
57370
- const float32 = bvh.float32;
57371
- const uint32 = bvh.uint32;
57372
-
57373
- do {
57374
- stack$7.pointer--;
57375
-
57376
- // query_bvh_frustum_from_objects.iteration_count++;
57377
- const node_index = stack$7[stack$7.pointer];
57378
-
57379
- if (node_index < binary_node_count) {
57380
- // is intermediate node
57381
- const node_address = node_index * BVH_BINARY_NODE_SIZE;
57382
-
57383
- if (!aabb3_array_intersects_ray(
57384
- float32, node_address,
57385
- origin_x, origin_y, origin_z,
57386
- direction_x, direction_y, direction_z
57387
- )) {
57388
- continue;
57389
- }
57390
-
57391
- const left_index = (node_index << 1) + 1;
57392
- const right_index = left_index + 1;
57393
-
57394
- // left node ends up on top of the stack, which aligns with the desired access sequence
57395
- if (right_index < last_valid_index) {
57396
- stack$7[stack$7.pointer++] = right_index;
57397
- // micro-optimization, since we know that right node is valid and left appears before that, left is valid too
57398
- stack$7[stack$7.pointer++] = left_index;
57399
- } else if (left_index < last_valid_index) {
57400
- stack$7[stack$7.pointer++] = left_index;
57401
- }
57402
-
57403
-
57404
- } else {
57405
- // leaf node
57406
- const leaf_index = node_index - binary_node_count;
57407
-
57408
- const node_address = leaf_index * BVH_LEAF_NODE_SIZE + binary_node_count * BVH_BINARY_NODE_SIZE;
57409
-
57410
- // write to output
57411
- result[result_offset + hit_count] = uint32[node_address + 6];
57412
-
57413
- hit_count++;
57414
- }
57415
-
57416
- } while (stack$7.pointer > stack_top)
57417
-
57418
- return hit_count;
57419
- }
57420
-
57421
- //
57422
-
57423
57397
  /**
57424
57398
  *
57425
57399
  * @param {ArrayLike<number>|number[]|AABB3} aabb
@@ -57598,23 +57572,37 @@ function aabb3_compute_plane_side(
57598
57572
  }
57599
57573
 
57600
57574
  /**
57601
- *
57575
+ * Tests whether AABB intersects a clipping volume defined by a set of planes
57576
+ * Mainly useful for frustum checks
57602
57577
  * @param {number} x0
57603
57578
  * @param {number} y0
57604
57579
  * @param {number} z0
57605
57580
  * @param {number} x1
57606
57581
  * @param {number} y1
57607
57582
  * @param {number} z1
57608
- * @param {ArrayLike<number>|number[]|Float32Array|Float64Array} frustum
57583
+ * @param {ArrayLike<number>|number[]|Float32Array|Float64Array} planes
57584
+ * @param {number} planes_offset
57585
+ * @param {number} plane_count
57609
57586
  * @return {boolean}
57610
57587
  */
57611
- function aabb3_intersects_frustum_array(x0, y0, z0, x1, y1, z1, frustum) {
57612
- for (let i = 0; i < 24; i += 4) {
57588
+ function aabb3_intersects_clipping_volume_array(
57589
+ x0, y0, z0,
57590
+ x1, y1, z1,
57591
+ planes, planes_offset, plane_count
57592
+ ) {
57593
+
57594
+ assert.isNonNegativeInteger(planes_offset, 'frustum_offset');
57595
+
57596
+ const limit = plane_count * 4;
57597
+
57598
+ for (let i = 0; i < limit; i += 4) {
57599
+
57600
+ const offset = planes_offset + i;
57613
57601
 
57614
- const plane_x = frustum[i];
57615
- const plane_y = frustum[i + 1];
57616
- const plane_z = frustum[i + 2];
57617
- const plane_w = frustum[i + 3];
57602
+ const plane_x = planes[offset];
57603
+ const plane_y = planes[offset + 1];
57604
+ const plane_z = planes[offset + 2];
57605
+ const plane_w = planes[offset + 3];
57618
57606
 
57619
57607
  const plane_distance = aabb3_compute_distance_above_plane_max(
57620
57608
  plane_x, plane_y, plane_z, plane_w,
@@ -57629,6 +57617,7 @@ function aabb3_intersects_frustum_array(x0, y0, z0, x1, y1, z1, frustum) {
57629
57617
  }
57630
57618
 
57631
57619
  return true;
57620
+
57632
57621
  }
57633
57622
 
57634
57623
  //
@@ -58708,7 +58697,7 @@ class AABB3 {
58708
58697
  const y1 = this.y1;
58709
58698
  const z1 = this.z1;
58710
58699
 
58711
- return aabb3_intersects_frustum_array(x0, y0, z0, x1, y1, z1, frustum);
58700
+ return aabb3_intersects_clipping_volume_array(x0, y0, z0, x1, y1, z1, frustum, 0, 6);
58712
58701
  }
58713
58702
 
58714
58703
  /**
@@ -58843,6 +58832,127 @@ function ray3_array_compose(output, origin_x, origin_y, origin_z, direction_x, d
58843
58832
  output[5] = direction_z;
58844
58833
  }
58845
58834
 
58835
+ //
58836
+
58837
+ /**
58838
+ *
58839
+ * @param {ArrayLike<number>|number[]|Float32Array} aabb bounding box, order: x0,y0,z0,x1,y1,z1
58840
+ * @param {number} aabb_offset
58841
+ * @param {number} origin_x
58842
+ * @param {number} origin_y
58843
+ * @param {number} origin_z
58844
+ * @param {number} direction_x
58845
+ * @param {number} direction_y
58846
+ * @param {number} direction_z
58847
+ */
58848
+ function aabb3_array_intersects_ray(
58849
+ aabb, aabb_offset,
58850
+ origin_x, origin_y, origin_z,
58851
+ direction_x, direction_y, direction_z
58852
+ ) {
58853
+ return aabb3_intersects_ray(
58854
+ aabb[aabb_offset], aabb[aabb_offset+1], aabb[aabb_offset+2],
58855
+ aabb[aabb_offset+3], aabb[aabb_offset+4], aabb[aabb_offset+5],
58856
+ origin_x, origin_y, origin_z,
58857
+ direction_x, direction_y, direction_z
58858
+ );
58859
+ }
58860
+
58861
+ const stack$7 = SCRATCH_UINT32_TRAVERSAL_STACK;
58862
+
58863
+ /**
58864
+ *
58865
+ * @param {number[]} result
58866
+ * @param {number} result_offset
58867
+ * @param {BinaryUint32BVH} bvh
58868
+ * @param {number} origin_x
58869
+ * @param {number} origin_y
58870
+ * @param {number} origin_z
58871
+ * @param {number} direction_x
58872
+ * @param {number} direction_y
58873
+ * @param {number} direction_z
58874
+ * @returns {number}
58875
+ */
58876
+ function bvh32_query_user_data_ray(
58877
+ result, result_offset,
58878
+ bvh,
58879
+ origin_x, origin_y, origin_z,
58880
+ direction_x, direction_y, direction_z
58881
+ ) {
58882
+ let hit_count = 0;
58883
+
58884
+ const binary_node_count = bvh.binary_node_count;
58885
+
58886
+ if (binary_node_count <= 0) {
58887
+ // this should not happen
58888
+ return 0;
58889
+ }
58890
+
58891
+ /**
58892
+ *
58893
+ * @type {number}
58894
+ */
58895
+ const stack_top = stack$7.pointer++;
58896
+
58897
+ /**
58898
+ * After performing empirical tests, stack-based depth-first traversal turns out faster than using a queue
58899
+ * @type {number}
58900
+ */
58901
+ stack$7[stack_top] = 0;
58902
+
58903
+ const last_valid_index = binary_node_count + bvh.leaf_node_count;
58904
+
58905
+ const float32 = bvh.float32;
58906
+ const uint32 = bvh.uint32;
58907
+
58908
+ do {
58909
+ stack$7.pointer--;
58910
+
58911
+ // query_bvh_frustum_from_objects.iteration_count++;
58912
+ const node_index = stack$7[stack$7.pointer];
58913
+
58914
+ const node_address = bvh.getNodeAddress(node_index);
58915
+
58916
+ if (!aabb3_array_intersects_ray(
58917
+ float32, node_address,
58918
+ origin_x, origin_y, origin_z,
58919
+ direction_x, direction_y, direction_z
58920
+ )) {
58921
+ continue;
58922
+ }
58923
+
58924
+ const is_intermediate_node = node_index < binary_node_count;
58925
+
58926
+ if (is_intermediate_node) {
58927
+ // is intermediate node
58928
+
58929
+ const left_index = (node_index << 1) + 1;
58930
+ const right_index = left_index + 1;
58931
+
58932
+ // left node ends up on top of the stack, which aligns with the desired access sequence
58933
+ if (right_index < last_valid_index) {
58934
+ stack$7[stack$7.pointer++] = right_index;
58935
+ // micro-optimization, since we know that right node is valid and left appears before that, left is valid too
58936
+ stack$7[stack$7.pointer++] = left_index;
58937
+ } else if (left_index < last_valid_index) {
58938
+ stack$7[stack$7.pointer++] = left_index;
58939
+ }
58940
+
58941
+
58942
+ } else {
58943
+ // leaf node
58944
+
58945
+ // write to output
58946
+ result[result_offset + hit_count] = uint32[node_address + 6];
58947
+
58948
+ hit_count++;
58949
+ }
58950
+
58951
+ } while (stack$7.pointer > stack_top)
58952
+
58953
+ return hit_count;
58954
+ }
58955
+
58846
58956
  /**
58847
58957
  * NOTE: adapted from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteIntrRay3Triangle3.h
58848
58958
  * @source https://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm (Möller and Trumbore, « Fast, Minimum Storage Ray-Triangle Intersection », Journal of Graphics Tools, vol. 2,‎ 1997, p. 21–28)
@@ -59000,6 +59110,110 @@ function computeTriangleRayIntersection(
59000
59110
  return true;
59001
59111
  }
59002
59112
 
59113
+ const scratch_array$4 = [];
59114
+ const scratch_hit = new SurfacePoint3();
59115
+
59116
+ /**
59117
+ *
59118
+ * @param {SurfacePoint3} result
59119
+ * @param {BinaryUint32BVH} bvh
59120
+ * @param {number[]|ArrayLike<number>} vertices
59121
+ * @param {number} vertex_offset Unless you're using an interleaved buffer of some kind, this will be 0
59122
+ * @param {number} vertex_stride Unless you're using an interleaved buffer, this should be 3
59123
+ * @param {number[]|ArrayLike<number>|undefined} indices if this is set to undefined - implicit indexing will be used
59124
+ * @param {number} originX
59125
+ * @param {number} originY
59126
+ * @param {number} originZ
59127
+ * @param {number} directionX
59128
+ * @param {number} directionY
59129
+ * @param {number} directionZ
59130
+ * @returns {boolean}
59131
+ */
59132
+ function bvh32_geometry_raycast(
59133
+ result,
59134
+ bvh,
59135
+ vertices, vertex_offset, vertex_stride,
59136
+ indices,
59137
+ originX, originY, originZ,
59138
+ directionX, directionY, directionZ
59139
+ ) {
59140
+ let hit_found = false;
59141
+
59142
+ const hit_count = bvh32_query_user_data_ray(
59143
+ scratch_array$4, 0,
59144
+ bvh,
59145
+ originX, originY, originZ,
59146
+ directionX, directionY, directionZ
59147
+ );
59148
+
59149
+ let best_distance = Infinity;
59150
+
59151
+ let a, b, c;
59152
+
59153
+ for (let i = 0; i < hit_count; i++) {
59154
+ const triangle_index = scratch_array$4[i];
59155
+
59156
+ const index3 = triangle_index * 3;
59157
+
59158
+ if (indices !== undefined) {
59159
+ assert.lessThan(index3 + 2, indices.length, 'triangle index overflow, possibly geometry changed but tree was not rebuilt?');
59160
+
59161
+ a = indices[index3];
59162
+ b = indices[index3 + 1];
59163
+ c = indices[index3 + 2];
59164
+ } else {
59165
+ // implicit indices
59166
+ a = index3;
59167
+ b = index3 + 1;
59168
+ c = index3 + 2;
59169
+ }
59170
+
59171
+ const a_address = a * vertex_stride + vertex_offset;
59172
+ const b_address = b * vertex_stride + vertex_offset;
59173
+ const c_address = c * vertex_stride + vertex_offset;
59174
+
59175
+ assert.lessThan(a_address + 2, vertices.length, 'a-vertex overflow');
59176
+ assert.lessThan(b_address + 2, vertices.length, 'b-vertex overflow');
59177
+ assert.lessThan(c_address + 2, vertices.length, 'c-vertex overflow');
59178
+
59179
+ const ax = vertices[a_address];
59180
+ const ay = vertices[a_address + 1];
59181
+ const az = vertices[a_address + 2];
59182
+
59183
+ const bx = vertices[b_address];
59184
+ const by = vertices[b_address + 1];
59185
+ const bz = vertices[b_address + 2];
59186
+
59187
+ const cx = vertices[c_address];
59188
+ const cy = vertices[c_address + 1];
59189
+ const cz = vertices[c_address + 2];
59190
+
59191
+ const triangle_hit_found = computeTriangleRayIntersection(
59192
+ scratch_hit,
59193
+ originX, originY, originZ,
59194
+ directionX, directionY, directionZ,
59195
+ ax, ay, az,
59196
+ bx, by, bz,
59197
+ cx, cy, cz
59198
+ );
59199
+
59200
+ if (!triangle_hit_found) {
59201
+ continue;
59202
+ }
59203
+
59204
+ hit_found = true;
59205
+
59206
+ const distance_sqr = scratch_hit.position._distanceSqrTo(originX, originY, originZ);
59207
+
59208
+ if (distance_sqr < best_distance) {
59209
+ best_distance = distance_sqr;
59210
+ result.copy(scratch_hit);
59211
+ }
59212
+ }
59213
+
59214
+ return hit_found;
59215
+ }
59216
+
59003
59217
  /**
59004
59218
  * Created by Alex on 28/01/2017.
59005
59219
  */
@@ -59081,9 +59295,6 @@ var ThreeFactory = {
59081
59295
  const EMPTY_GEOMETRY = new BufferGeometry();
59082
59296
  const DEFAULT_MATERIAL = new MeshBasicMaterial();
59083
59297
 
59084
- const scratch_array$3 = [];
59085
- const scratch_hit = new SurfacePoint3();
59086
-
59087
59298
  const ray_tmp = [];
59088
59299
  const m4_tmp = [];
59089
59300
 
@@ -59239,52 +59450,19 @@ class TerrainTile {
59239
59450
  const _directionY = ray_tmp[4];
59240
59451
  const _directionZ = ray_tmp[5];
59241
59452
 
59242
- const hit_count = bvh32_query_user_data_ray(
59243
- this.bvh,
59244
- scratch_array$3, 0,
59245
- _originX, _originY, _originZ,
59246
- _directionX, _directionY, _directionZ
59247
- );
59248
-
59249
- let best_distance = Infinity;
59250
- let hit_found = false;
59251
-
59252
59453
  const geometry = this.geometry;
59253
59454
 
59254
59455
  const geometryIndices = geometry.getIndex().array;
59255
59456
  const geometryPositions = geometry.getAttribute('position').array;
59256
59457
 
59257
- for (let i = 0; i < hit_count; i++) {
59258
- const triangle_index = scratch_array$3[i];
59259
-
59260
- const index3 = triangle_index * 3;
59261
-
59262
- const a = geometryIndices[index3] * 3;
59263
- const b = geometryIndices[index3 + 1] * 3;
59264
- const c = geometryIndices[index3 + 2] * 3;
59265
-
59266
- const triangle_hit_found = computeTriangleRayIntersection(
59267
- scratch_hit,
59268
- _originX, _originY, _originZ,
59269
- _directionX, _directionY, _directionZ,
59270
- geometryPositions[a], geometryPositions[a + 1], geometryPositions[a + 2],
59271
- geometryPositions[b], geometryPositions[b + 1], geometryPositions[b + 2],
59272
- geometryPositions[c], geometryPositions[c + 1], geometryPositions[c + 2],
59273
- );
59274
-
59275
- if (!triangle_hit_found) {
59276
- continue;
59277
- }
59278
-
59279
- hit_found = true;
59280
-
59281
- const distance_sqr = scratch_hit.position._distanceSqrTo(_originX, _originY, _originZ);
59282
-
59283
- if (distance_sqr < best_distance) {
59284
- best_distance = distance_sqr;
59285
- result.copy(scratch_hit);
59286
- }
59287
- }
59458
+ let hit_found = bvh32_geometry_raycast(
59459
+ result,
59460
+ this.bvh,
59461
+ geometryPositions, 0, 3,
59462
+ geometryIndices,
59463
+ _originX, _originY, _originZ,
59464
+ _directionX, _directionY, _directionZ
59465
+ );
59288
59466
 
59289
59467
  if (hit_found) {
59290
59468
  result.applyMatrix4(m4);
@@ -59706,7 +59884,7 @@ class TerrainTile {
59706
59884
  *
59707
59885
  * @type {number[]}
59708
59886
  */
59709
- const scratch_array$2 = [];
59887
+ const scratch_array$3 = [];
59710
59888
  const scratch_contact = new SurfacePoint3();
59711
59889
 
59712
59890
  class TerrainTileManager {
@@ -60282,7 +60460,7 @@ class TerrainTileManager {
60282
60460
  const hit_count = bvh_query_leaves_ray(
60283
60461
  this.bvh,
60284
60462
  this.bvh.root,
60285
- scratch_array$2, 0,
60463
+ scratch_array$3, 0,
60286
60464
  originX, originY, originZ,
60287
60465
  directionX, directionY, directionZ
60288
60466
  );
@@ -60291,7 +60469,7 @@ class TerrainTileManager {
60291
60469
  let hit_found = false;
60292
60470
 
60293
60471
  for (let i = 0; i < hit_count; i++) {
60294
- const node_id = scratch_array$2[i];
60472
+ const node_id = scratch_array$3[i];
60295
60473
 
60296
60474
  const tile_index = this.bvh.node_get_user_data(node_id);
60297
60475
 
@@ -65199,7 +65377,7 @@ function makeTerrainWorkerProxy() {
65199
65377
  resolve({
65200
65378
  geometry: geometry,
65201
65379
  bvh: {
65202
- leaf_count: bvh.getLeafNodeCount(),
65380
+ leaf_count: bvh.leaf_node_count,
65203
65381
  data: bvh.data
65204
65382
  }
65205
65383
  });
@@ -67183,598 +67361,283 @@ function aabb3_from_threejs_geometry(result, geometry) {
67183
67361
  aabb3_from_min_max(result, min, max);
67184
67362
  }
67185
67363
 
67186
- class IndexedBinaryBVHVisitor {
67187
- /**
67188
- *
67189
- * @param {number} address
67190
- * @param {NodeType} type
67191
- * @returns {boolean}
67192
- */
67193
- visit(address, type) {
67194
-
67195
- }
67196
- }
67197
-
67198
67364
  /**
67199
67365
  *
67200
- * @enum {number}
67366
+ * @param {Plane[]} planes
67367
+ * @param {ArrayLike<number>|number[]|Float32Array|Float64Array} array
67201
67368
  */
67202
- const NodeType = {
67203
- LEAF: 0,
67204
- BINARY: 1
67205
- };
67206
-
67207
- class RayLeafIntersectionVisitor extends IndexedBinaryBVHVisitor {
67208
- constructor() {
67209
- super();
67210
- this.callback = noop;
67211
- this.callbackThisArg = null;
67212
-
67213
- this.originX = 0;
67214
- this.originY = 0;
67215
- this.originZ = 0;
67369
+ function read_three_planes_to_array(planes, array) {
67370
+ const plane_count = planes.length;
67216
67371
 
67217
- this.directionX = 0;
67218
- this.directionY = 0;
67219
- this.directionZ = 0;
67372
+ assert.greaterThanOrEqual(array.length, plane_count * 4, 'target array is too small');
67220
67373
 
67221
- /**
67222
- *
67223
- * @type {IndexedBinaryBVH}
67224
- */
67225
- this.root = null;
67226
- }
67227
-
67228
- visit(address, type) {
67229
- const root = this.root;
67230
-
67231
- const data = root.data;
67232
- const binaryNodeCount = root.binaryNodeCount;
67233
-
67234
- const x0 = data[address];
67235
- const y0 = data[address + 1];
67236
- const z0 = data[address + 2];
67237
- const x1 = data[address + 3];
67238
- const y1 = data[address + 4];
67239
- const z1 = data[address + 5];
67240
-
67241
- const intersectionFound = aabb3_intersects_ray(x0, y0, z0, x1, y1, z1,
67242
- this.originX, this.originY, this.originZ,
67243
- this.directionX, this.directionY, this.directionZ
67244
- );
67374
+ for (let i = 0; i < plane_count; i++) {
67375
+ const plane = planes[i];
67245
67376
 
67246
- if (!intersectionFound) {
67247
- return false;
67248
- }
67377
+ const offset = i * 4;
67249
67378
 
67250
- if (type === NodeType.LEAF) {
67251
- const value = address / 6 - binaryNodeCount;
67379
+ const normal = plane.normal;
67252
67380
 
67253
- this.callback.call(this.callbackThisArg, value, address, type);
67381
+ array[offset] = normal.x;
67382
+ array[offset + 1] = normal.y;
67383
+ array[offset + 2] = normal.z;
67254
67384
 
67255
- return false;
67256
- } else {
67257
- return true;
67258
- }
67385
+ array[offset + 3] = plane.constant;
67259
67386
  }
67260
67387
  }
67261
67388
 
67262
- /**
67263
- * Created by Alex on 29/05/2016.
67264
- */
67265
-
67266
-
67267
67389
  /**
67268
67390
  *
67269
- * @type {Float32Array|number[]}
67391
+ * @param {BinaryUint32BVH} bvh
67392
+ * @param {number} triangle_index
67393
+ * @param {number[]|Float32Array} vertices
67394
+ * @param {number} a_index
67395
+ * @param {number} b_index
67396
+ * @param {number} c_index
67270
67397
  */
67271
- const scratch_aabb_0 = new Float32Array(6);
67272
-
67273
-
67274
- class IndexedBinaryBVH {
67275
- /**
67276
- *
67277
- * @constructor
67278
- */
67279
- constructor() {
67280
- /**
67281
- *
67282
- * @type {number}
67283
- */
67284
- this.leafNodeCount = 0;
67285
-
67286
- /**
67287
- *
67288
- * @type {number}
67289
- */
67290
- this.binaryNodeCount = 0;
67291
-
67292
- /**
67293
- * Total number of boxes contained in the tree, some might be unused
67294
- * @type {number}
67295
- */
67296
- this.boxCount = 0;
67297
-
67298
- /**
67299
- *
67300
- * @type {Float32Array|number[]}
67301
- */
67302
- this.data = new Float32Array(16);
67303
- }
67304
-
67305
- /**
67306
- *
67307
- * @returns {number}
67308
- */
67309
- estimateByteSize(){
67310
- return this.data.buffer.byteLength + 248;
67311
- }
67312
-
67313
- /**
67314
- *
67315
- * @param {int} leafCount
67316
- */
67317
- initialize(leafCount) {
67318
-
67319
- const twoLog = Math.log(leafCount) / Math.log(2);
67320
-
67321
- const twoLeafLimit = Math.pow(2, Math.ceil(twoLog));
67322
- const binaryNodeCount = twoLeafLimit - 1;
67323
-
67324
- this.leafNodeCount = leafCount;
67325
-
67326
- this.binaryNodeCount = binaryNodeCount;
67327
-
67328
- this.boxCount = this.leafNodeCount + this.binaryNodeCount;
67329
-
67330
- // possibly resize the storage
67331
- const storage_size = this.boxCount * 6;
67332
-
67333
- if (this.data.length < storage_size) {
67334
- this.data = new Float32Array(storage_size);
67335
- } else {
67336
- this.data.fill(0);
67337
- }
67338
- }
67339
-
67340
- unsortedBuiltIntermediate() {
67341
- const data = this.data;
67342
-
67343
- const nodeCount = this.binaryNodeCount;
67344
-
67345
- const leafNodesOffset = this.binaryNodeCount * 6;
67346
-
67347
- let level = Math.floor(Math.log(nodeCount) / Math.log(2));
67348
-
67349
- let i, offset, levelNodeCount;
67350
- //NOTE: building first level separately allows to avoid some switching logic needed to determine what is the type of lower level node
67351
- //build one level above leaf nodes
67352
- levelNodeCount = Math.pow(2, level);
67353
- offset = (levelNodeCount - 1) * 6;
67354
-
67355
- let parentIndex, childIndex0, childIndex1;
67356
-
67357
- for (i = 0; i < levelNodeCount; i++) {
67358
- const leafIndex0 = i * 2;
67359
- const leafIndex1 = leafIndex0 + 1;
67360
-
67361
- const leafOffset0 = leafNodesOffset + leafIndex0 * 6;
67362
- const leafOffset1 = leafNodesOffset + leafIndex1 * 6;
67363
-
67364
- if (leafIndex1 < this.leafNodeCount) {
67365
- binaryNodeRefit(data, offset, leafOffset0, leafOffset1);
67366
- } else if (leafIndex0 < this.leafNodeCount) {
67367
- copyBox(leafOffset0, offset, data);
67368
- } else {
67369
- //initialize to 0-size box same position as previous node
67370
- copyBoxZeroSize(offset - 6, offset, data);
67371
- }
67372
-
67373
- offset += 6;
67374
- }
67375
-
67376
- level--;
67377
-
67378
- //build intermediate nodes
67379
- for (; level >= 0; level--) {
67380
- levelNodeCount = Math.pow(2, level);
67381
- parentIndex = (levelNodeCount - 1);
67382
-
67383
- for (i = 0; i < levelNodeCount; i++) {
67384
-
67385
- childIndex0 = (parentIndex << 1) + 1;
67386
- childIndex1 = childIndex0 + 1;
67387
-
67388
- binaryNodeRefit(data, parentIndex * 6, childIndex0 * 6, childIndex1 * 6);
67389
-
67390
- parentIndex++;
67391
- }
67392
- }
67393
-
67394
- //set bounds of the bvh
67395
- array_copy(data, 0, scratch_aabb_0, 0, 6);
67396
-
67397
- this.x0 = scratch_aabb_0[0];
67398
- this.y0 = scratch_aabb_0[1];
67399
- this.z0 = scratch_aabb_0[2];
67400
- this.x1 = scratch_aabb_0[3];
67401
- this.y1 = scratch_aabb_0[4];
67402
- this.z1 = scratch_aabb_0[5];
67403
- }
67404
-
67405
- /**
67406
- * Sets bounds of a given leaf
67407
- * NOTE: to build tree, must call {@link #unsortedBuiltIntermediate} after all leaves are set
67408
- * @param {number} leaf_index
67409
- * @param {number} x0
67410
- * @param {number} y0
67411
- * @param {number} z0
67412
- * @param {number} x1
67413
- * @param {number} y1
67414
- * @param {number} z1
67415
- */
67416
- writeLeaf(leaf_index, x0, y0, z0, x1, y1, z1) {
67417
- const offset = this.binaryNodeCount * 6 + leaf_index * 6;
67418
- writeBox(this.data, offset, x0, y0, z0, x1, y1, z1);
67419
- }
67420
-
67421
- /**
67422
- * @template T
67423
- * @deprecated use {@link #writeLeaf} instead followed by {@link #unsortedBuiltIntermediate}
67424
- * @param {function(index:number,offset:number,data:T, writeBox:function):void} visitor
67425
- */
67426
- setLeafs(visitor) {
67427
- let offset = this.binaryNodeCount * 6;
67428
-
67429
- const data = this.data;
67398
+ function bvh32_set_leaf_from_triangle(bvh, triangle_index, vertices, a_index, b_index, c_index) {
67399
+ const a = a_index * 3;
67400
+ const b = b_index * 3;
67401
+ const c = c_index * 3;
67430
67402
 
67431
- let i = 0;
67432
- const l = this.leafNodeCount;
67433
- for (; i < l; i++) {
67434
- visitor(i, offset, data, writeBox);
67403
+ // read actual positions of each vertex
67404
+ const aX = vertices[a];
67405
+ const aY = vertices[a + 1];
67406
+ const aZ = vertices[a + 2];
67435
67407
 
67436
- offset += 6;
67437
- }
67438
- this.unsortedBuiltIntermediate();
67439
- }
67408
+ const bX = vertices[b];
67409
+ const bY = vertices[b + 1];
67410
+ const bZ = vertices[b + 2];
67440
67411
 
67441
- /**
67442
- *
67443
- * @param {IndexedBinaryBVHVisitor} visitor
67444
- * @param {Number} startIndex
67445
- */
67446
- traversePreOrderStack(visitor, startIndex) {
67412
+ const cX = vertices[c];
67413
+ const cY = vertices[c + 1];
67414
+ const cZ = vertices[c + 2];
67447
67415
 
67448
- const stackOffset = stackPointer;
67416
+ // compute bounds of the triangle
67417
+ const x0 = min3(aX, bX, cX);
67418
+ const y0 = min3(aY, bY, cY);
67419
+ const z0 = min3(aZ, bZ, cZ);
67449
67420
 
67450
- stack$6[stackPointer++] = startIndex;
67421
+ const x1 = max3(aX, bX, cX);
67422
+ const y1 = max3(aY, bY, cY);
67423
+ const z1 = max3(aZ, bZ, cZ);
67451
67424
 
67452
- const nodeThreshold = this.binaryNodeCount * 6;
67453
- const endAddress = this.boxCount * 6;
67454
-
67455
- while (stackPointer-- > stackOffset) {
67456
-
67457
- const index = stack$6[stackPointer];
67458
-
67459
- const address = index * 6;
67425
+ bvh.setLeafData(triangle_index, triangle_index, x0, y0, z0, x1, y1, z1);
67426
+ }
67427
+
67428
+ /**
67429
+ *
67430
+ * @param {BinaryUint32BVH} bvh
67431
+ * @param {Float32Array} vertices
67432
+ * @param {Uint32Array} indices
67433
+ */
67434
+ function bvh32_from_indexed_geometry(bvh, vertices, indices) {
67460
67435
 
67461
- const split = visitor.visit(address, NodeType.BINARY);
67462
- if (split) {
67436
+ const triangle_count = indices.length / 3;
67463
67437
 
67464
- const leftIndex = (index << 1) + 1;
67465
- const rightIndex = leftIndex + 1;
67438
+ bvh.setLeafCount(triangle_count);
67439
+ bvh.initialize_structure();
67466
67440
 
67467
- const leftAddress = leftIndex * 6;
67468
- const rightAddress = rightIndex * 6;
67441
+ for (let i = 0; i < triangle_count; i++) {
67469
67442
 
67470
- //right
67471
- if (rightAddress < endAddress) {
67472
- if (rightAddress < nodeThreshold) {
67473
- stack$6[stackPointer++] = rightIndex;
67474
- } else {
67475
- visitor.visit(rightAddress, NodeType.LEAF);
67476
- }
67477
- }
67443
+ const index3 = i * 3;
67478
67444
 
67479
- //left
67480
- if (leftAddress < endAddress) {
67481
- if (leftAddress < nodeThreshold) {
67482
- stack$6[stackPointer++] = leftIndex;
67483
- } else {
67484
- visitor.visit(leftAddress, NodeType.LEAF);
67485
- }
67486
- }
67487
- }
67488
- }
67445
+ // read triangle vertex indices
67446
+ const iA = indices[index3];
67447
+ const iB = indices[index3 + 1];
67448
+ const iC = indices[index3 + 2];
67489
67449
 
67490
- //drop stack
67491
- stackPointer = stackOffset;
67450
+ bvh32_set_leaf_from_triangle(bvh, i, vertices, iA, iB, iC);
67492
67451
  }
67493
67452
 
67494
- /**
67495
- *
67496
- * @param {function} visitor
67497
- * @param {number} index
67498
- * @param {number} type
67499
- */
67500
- traversePreOrder(visitor, index, type) {
67501
- const address = index * 6;
67502
- const carryOn = visitor(address, type);
67503
- const nodeThreshold = this.binaryNodeCount * 6;
67504
- const endAddress = this.boxCount * 6;
67505
-
67506
- if (carryOn !== false) {
67453
+ // finalize build
67454
+ // bvh.sort_morton(MATRIX_4_IDENTITY);
67455
+ bvh.build();
67456
+ }
67457
+
67458
+ /**
67459
+ *
67460
+ * @param {BinaryUint32BVH} bvh
67461
+ * @param {Float32Array} vertices
67462
+ */
67463
+ function bvh32_from_unindexed_geometry(bvh, vertices) {
67507
67464
 
67508
- const leftIndex = (index << 1) + 1;
67509
- const rightIndex = leftIndex + 1;
67465
+ const triangle_count = indices.length / 3;
67510
67466
 
67511
- const leftAddress = leftIndex * 6;
67512
- const rightAddress = rightIndex * 6;
67513
- //left
67514
- if (leftAddress < endAddress) {
67515
- if (leftAddress < nodeThreshold) {
67516
- this.traversePreOrder(visitor, leftIndex, NodeType.BINARY);
67517
- } else {
67518
- visitor(leftAddress, NodeType.LEAF);
67519
- }
67520
- }
67521
- //right
67522
- if (rightAddress < endAddress) {
67523
- if (rightAddress < nodeThreshold) {
67524
- this.traversePreOrder(visitor, rightIndex, NodeType.BINARY);
67525
- } else {
67526
- visitor(rightAddress, NodeType.LEAF);
67527
- }
67528
- }
67529
- }
67530
- }
67467
+ bvh.setLeafCount(triangle_count);
67468
+ bvh.initialize_structure();
67531
67469
 
67532
- /**
67533
- * @deprecated use a visitor object instead
67534
- * @param {number} startX
67535
- * @param {number} startY
67536
- * @param {number} startZ
67537
- * @param {number} directionX
67538
- * @param {number} directionY
67539
- * @param {number} directionZ
67540
- * @param {function} visitor
67541
- * @param {*} [thisArg]
67542
- */
67543
- traverseRayLeafIntersections(startX, startY, startZ, directionX, directionY, directionZ, visitor, thisArg) {
67544
- rayLeafIntersectionVisitor.originX = startX;
67545
- rayLeafIntersectionVisitor.originY = startY;
67546
- rayLeafIntersectionVisitor.originZ = startZ;
67470
+ for (let i = 0; i < triangle_count; i++) {
67547
67471
 
67548
- rayLeafIntersectionVisitor.directionX = directionX;
67549
- rayLeafIntersectionVisitor.directionY = directionY;
67550
- rayLeafIntersectionVisitor.directionZ = directionZ;
67472
+ const index3 = i * 3;
67551
67473
 
67552
- rayLeafIntersectionVisitor.root = this;
67553
- rayLeafIntersectionVisitor.callback = visitor;
67554
- rayLeafIntersectionVisitor.callbackThisArg = thisArg;
67474
+ // generate triangle vertex indices
67475
+ const iA = index3;
67476
+ const iB = index3 + 1;
67477
+ const iC = index3 + 2;
67555
67478
 
67556
- this.traversePreOrderStack(rayLeafIntersectionVisitor, 0);
67479
+ bvh32_set_leaf_from_triangle(bvh, i, vertices, iA, iB, iC);
67557
67480
  }
67558
- }
67559
67481
 
67482
+ // finalize build
67483
+ // bvh.sort_morton(MATRIX_4_IDENTITY);
67484
+ bvh.build();
67485
+ }
67486
+
67560
67487
  /**
67561
67488
  *
67562
- * @param {number[]|Float32Array} source
67563
- * @param {number} source_address_0
67564
- * @param {number} source_address_1
67565
- * @param {number[]|Float32Array} destination
67566
- * @param {number} destination_offset
67489
+ * @param {THREE.InterleavedBufferAttribute|THREE.BufferAttribute} source_attribute
67490
+ * @returns {THREE.BufferAttribute}
67567
67491
  */
67568
- function contain_box_array(source, source_address_0, source_address_1, destination, destination_offset) {
67569
-
67570
- const ax0 = source[source_address_0];
67571
- const ay0 = source[source_address_0 + 1];
67572
- const az0 = source[source_address_0 + 2];
67573
- const ax1 = source[source_address_0 + 3];
67574
- const ay1 = source[source_address_0 + 4];
67575
- const az1 = source[source_address_0 + 5];
67576
-
67577
- const bx0 = source[source_address_1];
67578
- const by0 = source[source_address_1 + 1];
67579
- const bz0 = source[source_address_1 + 2];
67580
- const bx1 = source[source_address_1 + 3];
67581
- const by1 = source[source_address_1 + 4];
67582
- const bz1 = source[source_address_1 + 5];
67583
-
67584
- const x0 = min2(ax0, bx0);
67585
- const y0 = min2(ay0, by0);
67586
- const z0 = min2(az0, bz0);
67492
+ function deinterleaveBufferAttribute(source_attribute) {
67493
+ if (source_attribute.isInterleavedBufferAttribute !== true && source_attribute.isBufferAttribute) {
67494
+ return source_attribute;
67495
+ }
67587
67496
 
67588
- const x1 = max2(ax1, bx1);
67589
- const y1 = max2(ay1, by1);
67590
- const z1 = max2(az1, bz1);
67497
+ const source_data = source_attribute.data;
67498
+ const source_data_array = source_data.array;
67499
+ const stride = source_data.stride;
67591
67500
 
67592
- destination[destination_offset] = x0;
67593
- destination[destination_offset + 1] = y0;
67594
- destination[destination_offset + 2] = z0;
67595
- destination[destination_offset + 3] = x1;
67596
- destination[destination_offset + 4] = y1;
67597
- destination[destination_offset + 5] = z1;
67598
- }
67501
+ const item_count = source_attribute.count;
67502
+ const itemSize = source_attribute.itemSize;
67503
+ const array_size = item_count * itemSize;
67599
67504
 
67600
- /**
67601
- *
67602
- * @param {Float32Array} array
67603
- * @param {number} address
67604
- * @param {number} x0
67605
- * @param {number} y0
67606
- * @param {number} z0
67607
- * @param {number} x1
67608
- * @param {number} y1
67609
- * @param {number} z1
67610
- */
67611
- function writeBox(array, address, x0, y0, z0, x1, y1, z1) {
67612
- array[address] = x0;
67613
- array[address + 1] = y0;
67614
- array[address + 2] = z0;
67615
- array[address + 3] = x1;
67616
- array[address + 4] = y1;
67617
- array[address + 5] = z1;
67618
- }
67505
+ const offset = source_attribute.offset;
67619
67506
 
67620
- /**
67621
- *
67622
- * @param {number} from
67623
- * @param {number} to
67624
- * @param {Float32Array} array
67625
- */
67626
- function copyBox(from, to, array) {
67627
- array_copy(array, from, array, to, 6);
67628
- }
67507
+ const destination_array = new source_data_array.constructor(array_size);
67629
67508
 
67630
- /**
67631
- *
67632
- * @param {number} from
67633
- * @param {number} to
67634
- * @param {Float32Array|number[]} array
67635
- */
67636
- function copyBoxZeroSize(from, to, array) {
67637
- array_copy(array, from, scratch_aabb_0, 0, 3);
67509
+ const attribute = new BufferAttribute(destination_array, itemSize);
67638
67510
 
67639
- scratch_aabb_0[3] = scratch_aabb_0[0];
67640
- scratch_aabb_0[4] = scratch_aabb_0[1];
67641
- scratch_aabb_0[5] = scratch_aabb_0[2];
67511
+ attribute.normalized = source_attribute.normalized;
67512
+ attribute.name = source_attribute.name;
67642
67513
 
67643
- array_copy(scratch_aabb_0, 0, array, to, 6);
67644
- }
67514
+ let i = 0, j = 0;
67515
+ // copy data
67516
+ for (; i < item_count; i++) {
67517
+ for (j = 0; j < itemSize; j++) {
67518
+ destination_array[i * itemSize + j] = source_data_array[i * stride + offset + j];
67519
+ }
67520
+ }
67645
67521
 
67522
+ return attribute;
67523
+ }
67524
+
67646
67525
  /**
67647
67526
  *
67648
- * @param {Float32Array} array
67649
- * @param {number} binaryNode
67650
- * @param {number} childNode0
67651
- * @param {number} childNode1
67527
+ * @param {Float32Array|number[]} aabb
67528
+ * @param {number} aabb_offset
67529
+ * @param {Float32Array|number[]} planes
67530
+ * @param {number} planes_offset
67531
+ * @param {number} plane_count
67532
+ * @return {boolean}
67652
67533
  */
67653
- function binaryNodeRefit(array, binaryNode, childNode0, childNode1) {
67654
- contain_box_array(array, childNode0, childNode1, array, binaryNode);
67655
- }
67656
-
67534
+ function aabb3_array_intersects_clipping_volume_array(
67535
+ aabb, aabb_offset,
67536
+ planes, planes_offset, plane_count
67537
+ ) {
67657
67538
 
67658
- const stack$6 = [];
67659
- let stackPointer = 0;
67539
+ const x0 = aabb[aabb_offset + 0];
67540
+ const y0 = aabb[aabb_offset + 1];
67541
+ const z0 = aabb[aabb_offset + 2];
67542
+ const x1 = aabb[aabb_offset + 3];
67543
+ const y1 = aabb[aabb_offset + 4];
67544
+ const z1 = aabb[aabb_offset + 5];
67660
67545
 
67661
- const rayLeafIntersectionVisitor = new RayLeafIntersectionVisitor();
67546
+ return aabb3_intersects_clipping_volume_array(
67547
+ x0, y0, z0,
67548
+ x1, y1, z1,
67549
+ planes, planes_offset, plane_count
67550
+ );
67551
+ }
67662
67552
 
67663
- /**
67664
- * Created by Alex on 29/05/2016.
67665
- */
67553
+ const stack$6 = SCRATCH_UINT32_TRAVERSAL_STACK;
67666
67554
 
67667
67555
  /**
67668
67556
  *
67669
- * @param {Float32Array|Float64Array|Array.<Number>} vertices
67670
- * @param {Uint8Array|Uint16Array|Uint32Array|Array.<Number>} indices
67671
- * @returns {IndexedBinaryBVH}
67557
+ * @param {number[]} result
67558
+ * @param {number} result_offset
67559
+ * @param {BinaryUint32BVH} bvh
67560
+ * @param {Float32Array|number[]} planes
67561
+ * @param {number} planes_offset
67562
+ * @param {number} plane_count
67563
+ * @returns {number}
67672
67564
  */
67673
- function buildUnsorted(vertices, indices) {
67674
- //
67675
- const numNodes = indices.length / 3;
67676
-
67677
- const tree = new IndexedBinaryBVH();
67678
- tree.initialize(numNodes);
67679
-
67680
- for (let i = 0; i < numNodes; i++) {
67681
-
67682
- const index3 = i * 3;
67683
-
67684
- // read triangle vertex indices
67685
- const iA = indices[index3];
67686
- const iB = indices[index3 + 1];
67687
- const iC = indices[index3 + 2];
67688
-
67689
- const a = iA * 3;
67690
- const b = iB * 3;
67691
- const c = iC * 3;
67692
-
67693
- // read actual positions of each vertex
67694
- const aX = vertices[a];
67695
- const aY = vertices[a + 1];
67696
- const aZ = vertices[a + 2];
67697
-
67698
- const bX = vertices[b];
67699
- const bY = vertices[b + 1];
67700
- const bZ = vertices[b + 2];
67565
+ function bvh32_query_user_data_overlaps_clipping_volume(
67566
+ result, result_offset,
67567
+ bvh,
67568
+ planes, planes_offset, plane_count
67569
+ ) {
67570
+ let hit_count = 0;
67701
67571
 
67702
- const cX = vertices[c];
67703
- const cY = vertices[c + 1];
67704
- const cZ = vertices[c + 2];
67572
+ const binary_node_count = bvh.binary_node_count;
67705
67573
 
67706
- // compute bounds of the triangle
67707
- const x0 = min3(aX, bX, cX);
67708
- const y0 = min3(aY, bY, cY);
67709
- const z0 = min3(aZ, bZ, cZ);
67574
+ if (binary_node_count <= 0) {
67575
+ // this should not happen
67576
+ return 0;
67577
+ }
67710
67578
 
67711
- const x1 = max3(aX, bX, cX);
67712
- const y1 = max3(aY, bY, cY);
67713
- const z1 = max3(aZ, bZ, cZ);
67579
+ /**
67580
+ *
67581
+ * @type {number}
67582
+ */
67583
+ const stack_top = stack$6.pointer++;
67714
67584
 
67715
- tree.writeLeaf(i, x0, y0, z0, x1, y1, z1);
67716
- }
67585
+ /**
67586
+ * After performing empirical tests, stack-based depth-first traversal turns out faster than using a queue
67587
+ * @type {number}
67588
+ */
67589
+ stack$6[stack_top] = 0;
67717
67590
 
67718
- // finalize build
67719
- tree.unsortedBuiltIntermediate();
67591
+ const last_valid_index = binary_node_count + bvh.leaf_node_count;
67720
67592
 
67721
- return tree;
67722
- }
67593
+ const float32 = bvh.float32;
67594
+ const uint32 = bvh.uint32;
67723
67595
 
67724
- /**
67725
- *
67726
- * @param {Float32Array|Float64Array|Array.<Number>} vertices
67727
- * @returns {IndexedBinaryBVH}
67728
- */
67729
- function buildUnsortedUnindexed(vertices) {
67730
- //
67731
- const numNodes = vertices.length / 9;
67596
+ do {
67597
+ stack$6.pointer--;
67732
67598
 
67733
- const tree = new IndexedBinaryBVH();
67734
- tree.initialize(numNodes);
67599
+ // query_bvh_frustum_from_objects.iteration_count++;
67600
+ const node_index = stack$6[stack$6.pointer];
67735
67601
 
67736
- for (let i = 0; i < numNodes; i++) {
67602
+ const node_address = bvh.getNodeAddress(node_index);
67737
67603
 
67738
- const index3 = i * 3;
67604
+ if (!aabb3_array_intersects_clipping_volume_array(
67605
+ float32, node_address,
67606
+ planes, planes_offset, plane_count
67607
+ )) {
67608
+ continue;
67609
+ }
67739
67610
 
67740
- // read triangle vertex indices
67741
- const iA = index3;
67742
- const iB = index3 + 1;
67743
- const iC = index3 + 2;
67611
+ const is_intermediate_node = node_index < binary_node_count;
67744
67612
 
67745
- const a = iA * 3;
67746
- const b = iB * 3;
67747
- const c = iC * 3;
67613
+ if (is_intermediate_node) {
67614
+ // is intermediate node
67748
67615
 
67749
- // read actual positions of each vertex
67750
- const aX = vertices[a];
67751
- const aY = vertices[a + 1];
67752
- const aZ = vertices[a + 2];
67616
+ const left_index = (node_index << 1) + 1;
67617
+ const right_index = left_index + 1;
67753
67618
 
67754
- const bX = vertices[b];
67755
- const bY = vertices[b + 1];
67756
- const bZ = vertices[b + 2];
67619
+ // left node ends up on top of the stack, which aligns with the desired access sequence
67620
+ if (right_index < last_valid_index) {
67621
+ stack$6[stack$6.pointer++] = right_index;
67622
+ // micro-optimization, since we know that right node is valid and left appears before that, left is valid too
67623
+ stack$6[stack$6.pointer++] = left_index;
67624
+ } else if (left_index < last_valid_index) {
67625
+ stack$6[stack$6.pointer++] = left_index;
67626
+ }
67757
67627
 
67758
- const cX = vertices[c];
67759
- const cY = vertices[c + 1];
67760
- const cZ = vertices[c + 2];
67761
67628
 
67762
- // compute bounds of the triangle
67763
- const x0 = min3(aX, bX, cX);
67764
- const y0 = min3(aY, bY, cY);
67765
- const z0 = min3(aZ, bZ, cZ);
67629
+ } else {
67630
+ // leaf node
67766
67631
 
67767
- const x1 = max3(aX, bX, cX);
67768
- const y1 = max3(aY, bY, cY);
67769
- const z1 = max3(aZ, bZ, cZ);
67632
+ // write to output
67633
+ result[result_offset + hit_count] = uint32[node_address + 6];
67770
67634
 
67771
- tree.writeLeaf(i, x0, y0, z0, x1, y1, z1);
67772
- }
67635
+ hit_count++;
67636
+ }
67773
67637
 
67774
- // finalize build
67775
- tree.unsortedBuiltIntermediate();
67638
+ } while (stack$6.pointer > stack_top)
67776
67639
 
67777
- return tree;
67640
+ return hit_count;
67778
67641
  }
67779
67642
 
67780
67643
  /**
@@ -67811,526 +67674,145 @@ function computeTrianglePlaneSide(
67811
67674
  return result;
67812
67675
  }
67813
67676
 
67814
- class GeometrySpatialAcceleratorVisitor extends IndexedBinaryBVHVisitor {
67815
- constructor() {
67816
- super();
67817
-
67818
-
67819
- /**
67820
- * @protected
67821
- * @type {THREE.BufferGeometry}
67822
- */
67823
- this.__geometry = null;
67824
-
67825
- /**
67826
- *
67827
- * @type {number[]}
67828
- * @protected
67829
- */
67830
- this.__buffer_indices = null;
67831
-
67832
- /**
67833
- *
67834
- * @type {number[]}
67835
- * @protected
67836
- */
67837
- this.__buffer_vertices = null;
67838
-
67839
- /**
67840
- *
67841
- * @type {number}
67842
- * @protected
67843
- */
67844
- this.__buffer_vertex_stride = 3;
67845
-
67846
- /**
67847
- *
67848
- * @type {number}
67849
- * @protected
67850
- */
67851
- this.__buffer_position_offset = 0;
67852
-
67853
- /**
67854
- * @protected
67855
- * @type {IndexedBinaryBVH}
67856
- */
67857
- this.__root = null;
67858
- }
67859
-
67860
- /**
67861
- * @param {IndexedBinaryBVH} root
67862
- */
67863
- setRoot(root) {
67864
- this.__root = root;
67865
- }
67866
-
67867
-
67868
- /**
67869
- * @param {THREE.BufferGeometry} geometry
67870
- */
67871
- setGeometry(geometry) {
67872
- this.geometry = geometry;
67873
-
67874
- const index_attribute = geometry.getIndex();
67875
-
67876
- if (index_attribute) {
67877
- this.__buffer_indices = index_attribute.array;
67878
- } else {
67879
- // no index attribute
67880
- this.__buffer_indices = null;
67881
- }
67882
-
67883
- const position_attribute = geometry.getAttribute('position');
67884
-
67885
- if (position_attribute.isInterleavedBufferAttribute) {
67886
- const data = position_attribute.data;
67887
-
67888
- this.__buffer_vertices = data.array;
67889
- this.__buffer_vertex_stride = data.stride;
67890
- this.__buffer_position_offset = position_attribute.offset;
67891
- } else {
67892
- this.__buffer_vertices = position_attribute.array;
67893
- this.__buffer_vertex_stride = 3;
67894
- this.__buffer_position_offset = 0;
67895
- }
67896
- }
67897
-
67898
- }
67899
-
67900
- class ClippingPlaneContainmentComputingVisitor extends GeometrySpatialAcceleratorVisitor {
67901
- constructor() {
67902
- super();
67903
-
67904
- /**
67905
- * @private
67906
- * @type {Plane[]}
67907
- */
67908
- this.planes = [];
67909
-
67910
- /**
67911
- *
67912
- * @private
67913
- * @type {number}
67914
- */
67915
- this.plane_count = 0;
67916
-
67917
- this.__hit_count_in = 0;
67918
- this.__hit_count_out = 0;
67919
- this.__hit_count_intersect = 0;
67920
- }
67921
-
67922
- reset() {
67923
- this.__hit_count_in = 0;
67924
- this.__hit_count_intersect = 0;
67925
- this.__hit_count_out = 0;
67926
- }
67927
-
67928
- /**
67929
- *
67930
- * @returns {number}
67931
- */
67932
- getContainment() {
67933
- if (this.__hit_count_out === 0) {
67934
- if (this.__hit_count_intersect > 0) {
67935
- return 0;
67936
- } else {
67937
- // fully in
67938
- return 1;
67939
- }
67940
- } else {
67941
- if (this.__hit_count_intersect > 0 || this.__hit_count_in > 0) {
67942
- return 0;
67943
- } else {
67944
- // fully out
67945
- return -1;
67946
- }
67947
- }
67948
- }
67949
-
67950
- /**
67951
- * @param {Plane[]} planes
67952
- */
67953
- setPlanes(planes) {
67954
- this.planes = planes;
67955
- this.plane_count = planes.length;
67956
- }
67957
-
67958
-
67959
- visit(address, type) {
67960
- const root = this.__root;
67961
-
67962
- const data = root.data;
67963
- const binaryNodeCount = root.binaryNodeCount;
67964
-
67965
- const planes = this.planes;
67966
- const plane_count = this.plane_count;
67967
-
67968
- let intersect_flag = false;
67969
- if (type === NodeType.LEAF) {
67970
- // check triangle intersection
67971
-
67972
- const index = address / 6 - binaryNodeCount;
67973
-
67974
- const index3 = index * 3;
67975
-
67976
- const indices = this.__buffer_indices;
67977
-
67978
- const a = indices[index3];
67979
- const b = indices[index3 + 1];
67980
- const c = indices[index3 + 2];
67981
-
67982
- const vertices = this.__buffer_vertices;
67983
-
67984
- const stride = this.__buffer_vertex_stride;
67985
- const offset = this.__buffer_position_offset;
67986
-
67987
- const a_address = a * stride + offset;
67988
- const b_address = b * stride + offset;
67989
- const c_address = c * stride + offset;
67990
-
67991
- const ax = vertices[a_address];
67992
- const ay = vertices[a_address + 1];
67993
- const az = vertices[a_address + 2];
67994
-
67995
- const bx = vertices[b_address];
67996
- const by = vertices[b_address + 1];
67997
- const bz = vertices[b_address + 2];
67998
-
67999
- const cx = vertices[c_address];
68000
- const cy = vertices[c_address + 1];
68001
- const cz = vertices[c_address + 2];
68002
-
68003
- for (let i = 0; i < plane_count; i++) {
68004
- const plane = planes[i];
68005
-
68006
- const plane_normal_x = plane.normal.x;
68007
- const plane_normal_y = plane.normal.y;
68008
- const plane_normal_z = plane.normal.z;
68009
- const plane_constant = plane.constant;
68010
-
68011
- const side = computeTrianglePlaneSide(
68012
- plane_normal_x,
68013
- plane_normal_y,
68014
- plane_normal_z,
68015
- plane_constant,
68016
- ax, ay, az,
68017
- bx, by, bz,
68018
- cx, cy, cz
68019
- );
68020
-
68021
- if (side === -3) {
68022
- // fully outside
68023
- this.__hit_count_out++;
68024
- return false;
68025
- } else if (side < 3) {
68026
- intersect_flag = true;
68027
- }
68028
- }
68029
-
68030
- if (intersect_flag) {
68031
- this.__hit_count_intersect++;
68032
- } else {
68033
- this.__hit_count_in++;
68034
- }
68035
-
68036
- return false;
68037
- } else {
68038
- // this is an intermediate node (binary node)
68039
-
68040
- // check AABB intersection
68041
-
68042
-
68043
- const x0 = data[address];
68044
- const y0 = data[address + 1];
68045
- const z0 = data[address + 2];
68046
- const x1 = data[address + 3];
68047
- const y1 = data[address + 4];
68048
- const z1 = data[address + 5];
68049
-
68050
-
68051
- for (let i = 0; i < plane_count; i++) {
68052
- const plane = planes[i];
68053
-
68054
- const plane_normal_x = plane.normal.x;
68055
- const plane_normal_y = plane.normal.y;
68056
- const plane_normal_z = plane.normal.z;
68057
- const plane_constant = plane.constant;
68058
-
68059
- const side = aabb3_compute_plane_side(
68060
- plane_normal_x,
68061
- plane_normal_y,
68062
- plane_normal_z,
68063
- plane_constant,
68064
-
68065
- x0, y0, z0,
68066
- x1, y1, z1
68067
- );
68068
-
68069
- if (side === -2) {
68070
- this.__hit_count_out++;
68071
-
68072
- return false;
68073
- } else if (side === 0) {
68074
- intersect_flag = true;
68075
- }
68076
- }
68077
-
68078
- if (intersect_flag) {
68079
- return true;
68080
- } else {
68081
- // no need to traverse further down, the whole node is in
68082
- this.__hit_count_in++;
68083
- return false;
68084
- }
68085
- }
68086
-
68087
-
68088
- }
68089
- }
68090
-
68091
- class RaycastNearestHitComputingVisitor extends GeometrySpatialAcceleratorVisitor {
68092
- constructor() {
68093
- super();
68094
-
68095
-
68096
- /**
68097
- *
68098
- * @type {number}
68099
- * @private
68100
- */
68101
- this.__nearest_distance = Number.POSITIVE_INFINITY;
68102
-
68103
- /**
68104
- * @readonly
68105
- * @type {SurfacePoint3}
68106
- * @private
68107
- */
68108
- this.__nearest_hit = new SurfacePoint3();
68109
-
68110
- /**
68111
- * @readonly
68112
- * @type {SurfacePoint3}
68113
- * @private
68114
- */
68115
- this.__temp_hit = new SurfacePoint3();
68116
-
68117
- /**
68118
- *
68119
- * @type {boolean}
68120
- * @private
68121
- */
68122
- this.__hit_found = false;
67677
+ /**
67678
+ * @param {number[]|Float32Array} planes
67679
+ * @param {number} planes_offset
67680
+ * @param {number} plane_count
67681
+ * @param {number} ax
67682
+ * @param {number} ay
67683
+ * @param {number} az
67684
+ * @param {number} bx
67685
+ * @param {number} by
67686
+ * @param {number} bz
67687
+ * @param {number} cx
67688
+ * @param {number} cy
67689
+ * @param {number} cz
67690
+ * @returns {boolean}
67691
+ */
67692
+ function triangle_intersects_clipping_volume(
67693
+ planes, planes_offset, plane_count,
67694
+ ax, ay, az,
67695
+ bx, by, bz,
67696
+ cx, cy, cz
67697
+ ) {
68123
67698
 
68124
- /**
68125
- * @readonly
68126
- * @type {Vector3}
68127
- * @private
68128
- */
68129
- this.__ray_origin = new Vector3$1();
67699
+ for (let j = 0; j < plane_count; j++) {
68130
67700
 
68131
- /**
68132
- * @readonly
68133
- * @type {Vector3}
68134
- * @private
68135
- */
68136
- this.__ray_direction = new Vector3$1();
68137
- }
67701
+ const plane_address = planes_offset + j * 4;
68138
67702
 
68139
- /**
68140
- *
68141
- * @param {number} origin_x
68142
- * @param {number} origin_y
68143
- * @param {number} origin_z
68144
- * @param {number} direction_x
68145
- * @param {number} direction_y
68146
- * @param {number} direction_z
68147
- */
68148
- setRay(origin_x, origin_y, origin_z, direction_x, direction_y, direction_z) {
68149
- this.__ray_origin.set(
68150
- origin_x,
68151
- origin_y,
68152
- origin_z
68153
- );
67703
+ const plane_normal_x = planes[plane_address];
67704
+ const plane_normal_y = planes[plane_address + 1];
67705
+ const plane_normal_z = planes[plane_address + 2];
67706
+ const plane_constant = planes[plane_address + 3];
68154
67707
 
68155
- this.__ray_direction.set(
68156
- direction_x,
68157
- direction_y,
68158
- direction_z
67708
+ const side = computeTrianglePlaneSide(
67709
+ plane_normal_x,
67710
+ plane_normal_y,
67711
+ plane_normal_z,
67712
+ plane_constant,
67713
+ ax, ay, az,
67714
+ bx, by, bz,
67715
+ cx, cy, cz
68159
67716
  );
68160
- }
68161
-
68162
- reset() {
68163
- this.__nearest_distance = Number.POSITIVE_INFINITY;
68164
- this.__hit_found = false;
68165
- }
68166
-
68167
- getNearestHit() {
68168
- return this.__nearest_hit;
68169
- }
68170
-
68171
- isHitFound() {
68172
- return this.__hit_found;
68173
- }
68174
-
68175
-
68176
- visit(address, type) {
68177
- const root = this.__root;
68178
-
68179
- const data = root.data;
68180
- const binaryNodeCount = root.binaryNodeCount;
68181
-
68182
- const rayOrigin = this.__ray_origin;
68183
- const rayDirection = this.__ray_direction;
68184
-
68185
- if (type === NodeType.LEAF) {
68186
- // do triangle test
68187
-
68188
- const index = address / 6 - binaryNodeCount;
68189
-
68190
- const index3 = index * 3;
68191
-
68192
- const indices = this.__buffer_indices;
68193
-
68194
- let a, b, c;
68195
-
68196
- if (indices !== null) {
68197
- assert.lessThan(index3 + 2, indices.length, 'triangle index overflow, possibly geometry changed but tree was not rebuilt?');
68198
-
68199
- a = indices[index3];
68200
- b = indices[index3 + 1];
68201
- c = indices[index3 + 2];
68202
- } else {
68203
- // implicit indices
68204
- a = index3;
68205
- b = index3 + 1;
68206
- c = index3 + 2;
68207
- }
68208
-
68209
- const vertices = this.__buffer_vertices;
68210
-
68211
- const stride = this.__buffer_vertex_stride;
68212
- const offset = this.__buffer_position_offset;
68213
-
68214
- const a_address = a * stride + offset;
68215
- const b_address = b * stride + offset;
68216
- const c_address = c * stride + offset;
68217
-
68218
- assert.lessThan(a_address + 2, vertices.length, 'a-vertex overflow');
68219
- assert.lessThan(b_address + 2, vertices.length, 'b-vertex overflow');
68220
- assert.lessThan(c_address + 2, vertices.length, 'c-vertex overflow');
68221
-
68222
- const ax = vertices[a_address];
68223
- const ay = vertices[a_address + 1];
68224
- const az = vertices[a_address + 2];
68225
-
68226
- const bx = vertices[b_address];
68227
- const by = vertices[b_address + 1];
68228
- const bz = vertices[b_address + 2];
68229
-
68230
- const cx = vertices[c_address];
68231
- const cy = vertices[c_address + 1];
68232
- const cz = vertices[c_address + 2];
68233
-
68234
- const temp_hit = this.__temp_hit;
68235
-
68236
- if (computeTriangleRayIntersection(
68237
- temp_hit,
68238
- rayOrigin.x,
68239
- rayOrigin.y,
68240
- rayOrigin.z,
68241
- rayDirection.x,
68242
- rayDirection.y,
68243
- rayDirection.z,
68244
- ax, ay, az,
68245
- bx, by, bz,
68246
- cx, cy, cz
68247
- )) {
68248
- const d = temp_hit.position.distanceSqrTo(rayOrigin);
68249
-
68250
- if (d < this.__nearest_distance) {
68251
- this.__nearest_hit.copy(temp_hit);
68252
- this.__nearest_hit.index = index;
68253
-
68254
- this.__nearest_distance = d;
68255
-
68256
- this.__hit_found = true;
68257
- }
68258
-
68259
- }
68260
67717
 
67718
+ if (side === -3) {
67719
+ // fully outside
68261
67720
  return false;
68262
-
68263
- } else {
68264
- // do AABB test
68265
-
68266
- const x0 = data[address];
68267
- const y0 = data[address + 1];
68268
- const z0 = data[address + 2];
68269
- const x1 = data[address + 3];
68270
- const y1 = data[address + 4];
68271
- const z1 = data[address + 5];
68272
-
68273
- return aabb3_intersects_ray(
68274
- x0, y0, z0,
68275
- x1, y1, z1,
68276
-
68277
- rayOrigin.x,
68278
- rayOrigin.y,
68279
- rayOrigin.z,
68280
-
68281
- rayDirection.x,
68282
- rayDirection.y,
68283
- rayDirection.z
68284
- );
68285
-
68286
67721
  }
68287
67722
  }
67723
+
67724
+ return true;
68288
67725
  }
68289
67726
 
67727
+ const scratch_array$2 = [];
67728
+
68290
67729
  /**
68291
67730
  *
68292
- * @param {THREE.InterleavedBufferAttribute|THREE.BufferAttribute} source_attribute
68293
- * @returns {THREE.BufferAttribute}
67731
+ * @param {BinaryUint32BVH} bvh
67732
+ * @param {number[]|ArrayLike<number>} vertices
67733
+ * @param {number} vertex_offset Unless you're using an interleaved buffer of some kind, this will be 0
67734
+ * @param {number} vertex_stride Unless you're using an interleaved buffer, this should be 3
67735
+ * @param {number[]|ArrayLike<number>|undefined} indices if this is set to undefined - implicit indexing will be used
67736
+ * @param {number[]|Float32Array} planes
67737
+ * @param {number} planes_offset
67738
+ * @param {number} plane_count
67739
+ * @returns {boolean}
68294
67740
  */
68295
- function deinterleaveBufferAttribute(source_attribute) {
68296
- if (source_attribute.isInterleavedBufferAttribute !== true && source_attribute.isBufferAttribute) {
68297
- return source_attribute;
68298
- }
68299
-
68300
- const source_data = source_attribute.data;
68301
- const source_data_array = source_data.array;
68302
- const stride = source_data.stride;
67741
+ function bvh32_geometry_overlap_clipping_volume(
67742
+ bvh,
67743
+ vertices, vertex_offset, vertex_stride,
67744
+ indices,
67745
+ planes, planes_offset, plane_count
67746
+ ) {
68303
67747
 
68304
- const item_count = source_attribute.count;
68305
- const itemSize = source_attribute.itemSize;
68306
- const array_size = item_count * itemSize;
67748
+ const hit_count = bvh32_query_user_data_overlaps_clipping_volume(
67749
+ scratch_array$2, 0,
67750
+ bvh,
67751
+ planes, planes_offset, plane_count
67752
+ );
68307
67753
 
68308
- const offset = source_attribute.offset;
67754
+ let a, b, c;
68309
67755
 
68310
- const destination_array = new source_data_array.constructor(array_size);
67756
+ for (let i = 0; i < hit_count; i++) {
67757
+ const triangle_index = scratch_array$2[i];
68311
67758
 
68312
- const attribute = new BufferAttribute(destination_array, itemSize);
67759
+ const index3 = triangle_index * 3;
68313
67760
 
68314
- attribute.normalized = source_attribute.normalized;
68315
- attribute.name = source_attribute.name;
67761
+ if (indices !== undefined) {
67762
+ assert.lessThan(index3 + 2, indices.length, 'triangle index overflow, possibly geometry changed but tree was not rebuilt?');
68316
67763
 
68317
- let i = 0, j = 0;
68318
- // copy data
68319
- for (; i < item_count; i++) {
68320
- for (j = 0; j < itemSize; j++) {
68321
- destination_array[i * itemSize + j] = source_data_array[i * stride + offset + j];
67764
+ a = indices[index3];
67765
+ b = indices[index3 + 1];
67766
+ c = indices[index3 + 2];
67767
+ } else {
67768
+ // implicit indices
67769
+ a = index3;
67770
+ b = index3 + 1;
67771
+ c = index3 + 2;
67772
+ }
67773
+
67774
+ const a_address = a * vertex_stride + vertex_offset;
67775
+ const b_address = b * vertex_stride + vertex_offset;
67776
+ const c_address = c * vertex_stride + vertex_offset;
67777
+
67778
+ assert.lessThan(a_address + 2, vertices.length, 'a-vertex overflow');
67779
+ assert.lessThan(b_address + 2, vertices.length, 'b-vertex overflow');
67780
+ assert.lessThan(c_address + 2, vertices.length, 'c-vertex overflow');
67781
+
67782
+ const ax = vertices[a_address];
67783
+ const ay = vertices[a_address + 1];
67784
+ const az = vertices[a_address + 2];
67785
+
67786
+ const bx = vertices[b_address];
67787
+ const by = vertices[b_address + 1];
67788
+ const bz = vertices[b_address + 2];
67789
+
67790
+ const cx = vertices[c_address];
67791
+ const cy = vertices[c_address + 1];
67792
+ const cz = vertices[c_address + 2];
67793
+
67794
+ if (triangle_intersects_clipping_volume(
67795
+ planes, planes_offset, plane_count,
67796
+ ax, ay, az,
67797
+ bx, by, bz,
67798
+ cx, cy, cz
67799
+ )) {
67800
+ return true;
68322
67801
  }
67802
+
68323
67803
  }
68324
67804
 
68325
- return attribute;
67805
+ return false;
68326
67806
  }
68327
67807
 
67808
+ const scratch_planes = [];
67809
+
68328
67810
  class GeometrySpatialQueryAccelerator {
68329
67811
  constructor(cache_size = 100 * 1024 * 1024) {
68330
67812
 
68331
67813
  /**
68332
67814
  *
68333
- * @type {Cache<THREE.BufferGeometry, IndexedBinaryBVH>}
67815
+ * @type {Cache<THREE.BufferGeometry, BinaryUint32BVH>}
68334
67816
  */
68335
67817
  this.cache = new Cache({
68336
67818
  maxWeight: cache_size,
@@ -68342,15 +67824,13 @@ class GeometrySpatialQueryAccelerator {
68342
67824
  },
68343
67825
  /**
68344
67826
  *
68345
- * @param {IndexedBinaryBVH} tree
67827
+ * @param {BinaryUint32BVH} tree
68346
67828
  */
68347
67829
  valueWeigher(tree) {
68348
67830
  return tree.estimateByteSize();
68349
67831
  }
68350
67832
  });
68351
67833
 
68352
- this.__visitor_clip = new ClippingPlaneContainmentComputingVisitor();
68353
- this.__visitor_raycast = new RaycastNearestHitComputingVisitor();
68354
67834
  }
68355
67835
 
68356
67836
  /**
@@ -68373,23 +67853,46 @@ class GeometrySpatialQueryAccelerator {
68373
67853
  *
68374
67854
  * @param {THREE.BufferGeometry} geometry
68375
67855
  * @param {Plane[]} planes
68376
- * @returns {number} -1,0,1. -1 means fully outside, 0 means partially inside, 1 means fully inside
67856
+ * @returns {boolean} true means some overlap exists, false otherwise
68377
67857
  */
68378
67858
  queryContainmentViaClippingPlanes(geometry, planes) {
68379
67859
  assert.notNull(geometry, 'geometry');
68380
67860
  assert.defined(geometry, 'geometry');
68381
67861
 
67862
+
68382
67863
  const bvh = this.__acquireBVH(geometry);
68383
67864
 
68384
- this.__visitor_clip.reset();
67865
+ read_three_planes_to_array(planes, scratch_planes);
68385
67866
 
68386
- this.__visitor_clip.setGeometry(geometry);
68387
- this.__visitor_clip.setPlanes(planes);
68388
- this.__visitor_clip.setRoot(bvh);
67867
+ const geometryIndices = geometry.getIndex()?.array;
67868
+ const position_attribute = geometry.getAttribute('position');
67869
+
67870
+ let position_data;
67871
+ let stride = 3;
67872
+ let position_data_offset = 0;
67873
+
67874
+ if (position_attribute.isInterleavedBufferAttribute) {
67875
+
67876
+ position_data = position_attribute.data.array;
67877
+
67878
+ stride = position_attribute.data.stride;
67879
+ position_data_offset = position_attribute.offset;
68389
67880
 
68390
- bvh.traversePreOrderStack(this.__visitor_clip, 0);
67881
+ } else {
67882
+
67883
+ position_data = position_attribute.array;
67884
+
67885
+ stride = 3;
67886
+ position_data_offset = 0;
68391
67887
 
68392
- return this.__visitor_clip.getContainment();
67888
+ }
67889
+
67890
+ return bvh32_geometry_overlap_clipping_volume(
67891
+ bvh,
67892
+ position_data, position_data_offset, stride,
67893
+ geometryIndices,
67894
+ scratch_planes, 0, planes.length
67895
+ );
68393
67896
  }
68394
67897
 
68395
67898
  /**
@@ -68439,11 +67942,33 @@ class GeometrySpatialQueryAccelerator {
68439
67942
  return false;
68440
67943
  }
68441
67944
 
68442
- this.__visitor_raycast.reset();
67945
+ const geometryIndices = geometry.getIndex()?.array;
67946
+ const position_attribute = geometry.getAttribute('position');
67947
+
67948
+ let position_data;
67949
+ let stride = 3;
67950
+ let position_data_offset = 0;
67951
+
67952
+ if (position_attribute.isInterleavedBufferAttribute) {
67953
+
67954
+ position_data = position_attribute.data.array;
67955
+
67956
+ stride = position_attribute.data.stride;
67957
+ position_data_offset = position_attribute.offset;
68443
67958
 
68444
- this.__visitor_raycast.setGeometry(geometry);
68445
- this.__visitor_raycast.setRoot(bvh);
68446
- this.__visitor_raycast.setRay(
67959
+ } else {
67960
+
67961
+ position_data = position_attribute.array;
67962
+
67963
+ stride = 3;
67964
+ position_data_offset = 0;
67965
+
67966
+ }
67967
+
67968
+ return bvh32_geometry_raycast(
67969
+ destination, bvh,
67970
+ position_data, position_data_offset, stride,
67971
+ geometryIndices,
68447
67972
  ray_origin_x,
68448
67973
  ray_origin_y,
68449
67974
  ray_origin_z,
@@ -68452,16 +67977,6 @@ class GeometrySpatialQueryAccelerator {
68452
67977
  ray_direction_z
68453
67978
  );
68454
67979
 
68455
- bvh.traversePreOrderStack(this.__visitor_raycast, 0);
68456
-
68457
- if (this.__visitor_raycast.isHitFound()) {
68458
-
68459
- destination.copy(this.__visitor_raycast.getNearestHit());
68460
-
68461
- return true;
68462
- } else {
68463
- return false;
68464
- }
68465
67980
  }
68466
67981
 
68467
67982
  /**
@@ -68489,7 +68004,7 @@ class GeometrySpatialQueryAccelerator {
68489
68004
  /**
68490
68005
  * @private
68491
68006
  * @param {THREE.BufferGeometry} geometry
68492
- * @returns {IndexedBinaryBVH}
68007
+ * @returns {BinaryUint32BVH}
68493
68008
  */
68494
68009
  __acquireBVH(geometry) {
68495
68010
  assert.notNull(geometry, 'geometry');
@@ -68511,7 +68026,7 @@ class GeometrySpatialQueryAccelerator {
68511
68026
  /**
68512
68027
  * @private
68513
68028
  * @param {THREE.BufferGeometry} geometry
68514
- * @returns {IndexedBinaryBVH}
68029
+ * @returns {BinaryUint32BVH}
68515
68030
  */
68516
68031
  __buildBVH(geometry) {
68517
68032
  const position_attribute = geometry.getAttribute('position');
@@ -68520,14 +68035,19 @@ class GeometrySpatialQueryAccelerator {
68520
68035
  const de_interleaved_position_attribute = deinterleaveBufferAttribute(position_attribute);
68521
68036
  const vertices = de_interleaved_position_attribute.array;
68522
68037
 
68038
+ const bvh = new BinaryUint32BVH();
68039
+
68523
68040
  if (index_attribute === undefined || index_attribute === null) {
68524
- return buildUnsortedUnindexed(vertices);
68525
- }
68041
+ bvh32_from_unindexed_geometry(bvh, vertices);
68042
+ } else {
68526
68043
 
68527
- const de_interleaved_index_attribute = deinterleaveBufferAttribute(index_attribute);
68528
- const indices = de_interleaved_index_attribute.array;
68044
+ const de_interleaved_index_attribute = deinterleaveBufferAttribute(index_attribute);
68045
+ const indices = de_interleaved_index_attribute.array;
68529
68046
 
68530
- return buildUnsorted(vertices, indices);
68047
+ bvh32_from_indexed_geometry(bvh, vertices, indices);
68048
+ }
68049
+
68050
+ return bvh;
68531
68051
  }
68532
68052
 
68533
68053
  }
@@ -69346,29 +68866,6 @@ function bvh_query_user_data_overlaps_frustum(
69346
68866
  return result_cursor - result_offset;
69347
68867
  }
69348
68868
 
69349
- /**
69350
- *
69351
- * @param {Plane[]} planes
69352
- * @param {ArrayLike<number>|number[]|Float32Array|Float64Array} array
69353
- */
69354
- function read_frustum_planes_to_array(planes, array) {
69355
- assert.greaterThanOrEqual(array.length, 24, 'target array is too small');
69356
-
69357
- for (let i = 0; i < 6; i++) {
69358
- const plane = planes[i];
69359
-
69360
- const offset = i * 4;
69361
-
69362
- const normal = plane.normal;
69363
-
69364
- array[offset] = normal.x;
69365
- array[offset + 1] = normal.y;
69366
- array[offset + 2] = normal.z;
69367
-
69368
- array[offset + 3] = plane.constant;
69369
- }
69370
- }
69371
-
69372
68869
  /**
69373
68870
  * @template CTX
69374
68871
  * @template Asset
@@ -71959,7 +71456,7 @@ class TerrainSystem extends System {
71959
71456
 
71960
71457
  for (let i = 0; i < frustums.length; i++) {
71961
71458
 
71962
- read_frustum_planes_to_array(frustums[i].planes, frustum);
71459
+ read_three_planes_to_array(frustums[i].planes, frustum);
71963
71460
 
71964
71461
  found_tiles += bvh_query_user_data_overlaps_frustum(tiles, tile_count, tileManager.bvh, frustum);
71965
71462
  }
@@ -91556,7 +91053,7 @@ class CameraView {
91556
91053
  frustum_from_camera(camera, scratch_frustum, false);
91557
91054
 
91558
91055
  // update view definition
91559
- read_frustum_planes_to_array(scratch_frustum.planes, this.frustum);
91056
+ read_three_planes_to_array(scratch_frustum.planes, this.frustum);
91560
91057
 
91561
91058
  // read projection matrix
91562
91059
  // TODO
@@ -111242,7 +110739,7 @@ function query_bvh_frustum_from_texture(
111242
110739
  ) {
111243
110740
  let result = 0;
111244
110741
 
111245
- const binary_node_count = bvh.getBinaryNodeCount();
110742
+ const binary_node_count = bvh.binary_node_count;
111246
110743
 
111247
110744
  if (binary_node_count <= 0) {
111248
110745
  // this should not happen
@@ -111261,7 +110758,7 @@ function query_bvh_frustum_from_texture(
111261
110758
  */
111262
110759
  stack[stack_top] = 0;
111263
110760
 
111264
- const last_valid_index = binary_node_count + bvh.getLeafNodeCount();
110761
+ const last_valid_index = binary_node_count + bvh.leaf_node_count;
111265
110762
 
111266
110763
  const float32 = bvh.float32;
111267
110764
  const uint32 = bvh.uint32;
@@ -112817,7 +112314,7 @@ class LightManager {
112817
112314
 
112818
112315
  const nodes = [];
112819
112316
 
112820
- read_frustum_planes_to_array(this.__view_frustum.planes, scratch_frustum_planes);
112317
+ read_three_planes_to_array(this.__view_frustum.planes, scratch_frustum_planes);
112821
112318
 
112822
112319
  /*
112823
112320
  Search is done in 2 phases:
@@ -119214,4 +118711,16 @@ class Blackboard extends AbstractBlackboard {
119214
118711
 
119215
118712
  Blackboard.typeName = 'Blackboard';
119216
118713
 
118714
+ /**
118715
+ * just in case you need that function also
118716
+ * @param {Vector3} axis
118717
+ * @param {number} angle
118718
+ * @param {Quaternion} result
118719
+ */
118720
+ function quat3_createFromAxisAngle(axis, angle, result) {
118721
+ const halfAngle = angle * .5;
118722
+ const s = Math.sin(halfAngle);
118723
+ result.set(axis.x * s, axis.y * s, axis.z * s, Math.cos(halfAngle));
118724
+ }
118725
+
119217
118726
  export { AmbientOcclusionPostProcessEffect, Behavior, BehaviorStatus, Blackboard, Cache, EngineConfiguration, EngineHarness, ForwardPlusRenderingPlugin, HashMap, Light, ParallelBehavior, ParallelBehaviorPolicy, SGMesh, SGMeshSystem, SelectorBehavior, SequenceBehavior, ShadedGeometry, ShadedGeometrySystem, Signal, SignalBinding, Transform, dispatchViaProxy, findSignalHandlerIndexByHandle, findSignalHandlerIndexByHandleAndContext, quat3_createFromAxisAngle, v2_angleBetween, v2_bearing_angle_towards, v2_distance, v2_dot, v2_length_sqr, v2_magnitude, v4_applyMatrix4, v4_distance_sqr, v4_dot, v4_length_sqr };