@perceptimagery/dita-configurator-staging 0.1.6300 → 0.1.7100
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +4250 -71
- package/package.json +4 -3
package/dist/index.js
CHANGED
|
@@ -111,7 +111,7 @@ var __publicField = (obj, key, value) => {
|
|
|
111
111
|
host: "https://api.sprie.io"
|
|
112
112
|
};
|
|
113
113
|
const config = Object.freeze(Config$1);
|
|
114
|
-
const version = "0.1.
|
|
114
|
+
const version$1 = "0.1.7100";
|
|
115
115
|
function modifyLensArr(arr, element) {
|
|
116
116
|
const index = arr.findIndex((e) => e["sku"] === element["sku"]);
|
|
117
117
|
if (index !== -1) {
|
|
@@ -6721,17 +6721,17 @@ var __publicField = (obj, key, value) => {
|
|
|
6721
6721
|
function BlowFish_Encrypt(ctx, left, right) {
|
|
6722
6722
|
let Xl = left;
|
|
6723
6723
|
let Xr = right;
|
|
6724
|
-
let
|
|
6724
|
+
let temp5;
|
|
6725
6725
|
for (let i = 0; i < N; ++i) {
|
|
6726
6726
|
Xl = Xl ^ ctx.pbox[i];
|
|
6727
6727
|
Xr = F2(ctx, Xl) ^ Xr;
|
|
6728
|
-
|
|
6728
|
+
temp5 = Xl;
|
|
6729
6729
|
Xl = Xr;
|
|
6730
|
-
Xr =
|
|
6730
|
+
Xr = temp5;
|
|
6731
6731
|
}
|
|
6732
|
-
|
|
6732
|
+
temp5 = Xl;
|
|
6733
6733
|
Xl = Xr;
|
|
6734
|
-
Xr =
|
|
6734
|
+
Xr = temp5;
|
|
6735
6735
|
Xr = Xr ^ ctx.pbox[N];
|
|
6736
6736
|
Xl = Xl ^ ctx.pbox[N + 1];
|
|
6737
6737
|
return { left: Xl, right: Xr };
|
|
@@ -6739,17 +6739,17 @@ var __publicField = (obj, key, value) => {
|
|
|
6739
6739
|
function BlowFish_Decrypt(ctx, left, right) {
|
|
6740
6740
|
let Xl = left;
|
|
6741
6741
|
let Xr = right;
|
|
6742
|
-
let
|
|
6742
|
+
let temp5;
|
|
6743
6743
|
for (let i = N + 1; i > 1; --i) {
|
|
6744
6744
|
Xl = Xl ^ ctx.pbox[i];
|
|
6745
6745
|
Xr = F2(ctx, Xl) ^ Xr;
|
|
6746
|
-
|
|
6746
|
+
temp5 = Xl;
|
|
6747
6747
|
Xl = Xr;
|
|
6748
|
-
Xr =
|
|
6748
|
+
Xr = temp5;
|
|
6749
6749
|
}
|
|
6750
|
-
|
|
6750
|
+
temp5 = Xl;
|
|
6751
6751
|
Xl = Xr;
|
|
6752
|
-
Xr =
|
|
6752
|
+
Xr = temp5;
|
|
6753
6753
|
Xr = Xr ^ ctx.pbox[1];
|
|
6754
6754
|
Xl = Xl ^ ctx.pbox[0];
|
|
6755
6755
|
return { left: Xl, right: Xr };
|
|
@@ -13891,15 +13891,15 @@ var __publicField = (obj, key, value) => {
|
|
|
13891
13891
|
}
|
|
13892
13892
|
return min <= -plane.constant && max >= -plane.constant;
|
|
13893
13893
|
}
|
|
13894
|
-
intersectsTriangle(
|
|
13894
|
+
intersectsTriangle(triangle3) {
|
|
13895
13895
|
if (this.isEmpty()) {
|
|
13896
13896
|
return false;
|
|
13897
13897
|
}
|
|
13898
13898
|
this.getCenter(_center);
|
|
13899
13899
|
_extents.subVectors(this.max, _center);
|
|
13900
|
-
_v0$2.subVectors(
|
|
13901
|
-
_v1$7.subVectors(
|
|
13902
|
-
_v2$4.subVectors(
|
|
13900
|
+
_v0$2.subVectors(triangle3.a, _center);
|
|
13901
|
+
_v1$7.subVectors(triangle3.b, _center);
|
|
13902
|
+
_v2$4.subVectors(triangle3.c, _center);
|
|
13903
13903
|
_f0.subVectors(_v1$7, _v0$2);
|
|
13904
13904
|
_f1.subVectors(_v2$4, _v1$7);
|
|
13905
13905
|
_f2.subVectors(_v0$2, _v2$4);
|
|
@@ -16006,10 +16006,10 @@ var __publicField = (obj, key, value) => {
|
|
|
16006
16006
|
clone() {
|
|
16007
16007
|
return new this.constructor().copy(this);
|
|
16008
16008
|
}
|
|
16009
|
-
copy(
|
|
16010
|
-
this.a.copy(
|
|
16011
|
-
this.b.copy(
|
|
16012
|
-
this.c.copy(
|
|
16009
|
+
copy(triangle3) {
|
|
16010
|
+
this.a.copy(triangle3.a);
|
|
16011
|
+
this.b.copy(triangle3.b);
|
|
16012
|
+
this.c.copy(triangle3.c);
|
|
16013
16013
|
return this;
|
|
16014
16014
|
}
|
|
16015
16015
|
getArea() {
|
|
@@ -16092,8 +16092,8 @@ var __publicField = (obj, key, value) => {
|
|
|
16092
16092
|
w2 = vc * denom;
|
|
16093
16093
|
return target.copy(a).addScaledVector(_vab, v).addScaledVector(_vac, w2);
|
|
16094
16094
|
}
|
|
16095
|
-
equals(
|
|
16096
|
-
return
|
|
16095
|
+
equals(triangle3) {
|
|
16096
|
+
return triangle3.a.equals(this.a) && triangle3.b.equals(this.b) && triangle3.c.equals(this.c);
|
|
16097
16097
|
}
|
|
16098
16098
|
}
|
|
16099
16099
|
const _colorKeywords = {
|
|
@@ -17919,9 +17919,9 @@ var __publicField = (obj, key, value) => {
|
|
|
17919
17919
|
const group = groups[i];
|
|
17920
17920
|
this.addGroup(group.start, group.count, group.materialIndex);
|
|
17921
17921
|
}
|
|
17922
|
-
const
|
|
17923
|
-
if (
|
|
17924
|
-
this.boundingBox =
|
|
17922
|
+
const boundingBox2 = source.boundingBox;
|
|
17923
|
+
if (boundingBox2 !== null) {
|
|
17924
|
+
this.boundingBox = boundingBox2.clone();
|
|
17925
17925
|
}
|
|
17926
17926
|
const boundingSphere = source.boundingSphere;
|
|
17927
17927
|
if (boundingSphere !== null) {
|
|
@@ -17948,10 +17948,10 @@ var __publicField = (obj, key, value) => {
|
|
|
17948
17948
|
const _uvA$1 = /* @__PURE__ */ new Vector2();
|
|
17949
17949
|
const _uvB$1 = /* @__PURE__ */ new Vector2();
|
|
17950
17950
|
const _uvC$1 = /* @__PURE__ */ new Vector2();
|
|
17951
|
-
const _normalA = /* @__PURE__ */ new Vector3();
|
|
17952
|
-
const _normalB = /* @__PURE__ */ new Vector3();
|
|
17953
|
-
const _normalC = /* @__PURE__ */ new Vector3();
|
|
17954
|
-
const _intersectionPoint = /* @__PURE__ */ new Vector3();
|
|
17951
|
+
const _normalA$1 = /* @__PURE__ */ new Vector3();
|
|
17952
|
+
const _normalB$1 = /* @__PURE__ */ new Vector3();
|
|
17953
|
+
const _normalC$1 = /* @__PURE__ */ new Vector3();
|
|
17954
|
+
const _intersectionPoint$1 = /* @__PURE__ */ new Vector3();
|
|
17955
17955
|
const _intersectionPointWorld = /* @__PURE__ */ new Vector3();
|
|
17956
17956
|
class Mesh extends Object3D {
|
|
17957
17957
|
constructor(geometry = new BufferGeometry(), material = new MeshBasicMaterial()) {
|
|
@@ -18121,7 +18121,7 @@ var __publicField = (obj, key, value) => {
|
|
|
18121
18121
|
}
|
|
18122
18122
|
}
|
|
18123
18123
|
}
|
|
18124
|
-
function checkIntersection(object, material, raycaster, ray, pA, pB, pC, point) {
|
|
18124
|
+
function checkIntersection$1(object, material, raycaster, ray, pA, pB, pC, point) {
|
|
18125
18125
|
let intersect;
|
|
18126
18126
|
if (material.side === BackSide) {
|
|
18127
18127
|
intersect = ray.intersectTriangle(pC, pB, pA, true, point);
|
|
@@ -18145,26 +18145,26 @@ var __publicField = (obj, key, value) => {
|
|
|
18145
18145
|
object.getVertexPosition(a, _vA$1);
|
|
18146
18146
|
object.getVertexPosition(b, _vB$1);
|
|
18147
18147
|
object.getVertexPosition(c2, _vC$1);
|
|
18148
|
-
const intersection = checkIntersection(object, material, raycaster, ray, _vA$1, _vB$1, _vC$1, _intersectionPoint);
|
|
18148
|
+
const intersection = checkIntersection$1(object, material, raycaster, ray, _vA$1, _vB$1, _vC$1, _intersectionPoint$1);
|
|
18149
18149
|
if (intersection) {
|
|
18150
18150
|
if (uv) {
|
|
18151
18151
|
_uvA$1.fromBufferAttribute(uv, a);
|
|
18152
18152
|
_uvB$1.fromBufferAttribute(uv, b);
|
|
18153
18153
|
_uvC$1.fromBufferAttribute(uv, c2);
|
|
18154
|
-
intersection.uv = Triangle.getInterpolation(_intersectionPoint, _vA$1, _vB$1, _vC$1, _uvA$1, _uvB$1, _uvC$1, new Vector2());
|
|
18154
|
+
intersection.uv = Triangle.getInterpolation(_intersectionPoint$1, _vA$1, _vB$1, _vC$1, _uvA$1, _uvB$1, _uvC$1, new Vector2());
|
|
18155
18155
|
}
|
|
18156
18156
|
if (uv1) {
|
|
18157
18157
|
_uvA$1.fromBufferAttribute(uv1, a);
|
|
18158
18158
|
_uvB$1.fromBufferAttribute(uv1, b);
|
|
18159
18159
|
_uvC$1.fromBufferAttribute(uv1, c2);
|
|
18160
|
-
intersection.uv1 = Triangle.getInterpolation(_intersectionPoint, _vA$1, _vB$1, _vC$1, _uvA$1, _uvB$1, _uvC$1, new Vector2());
|
|
18160
|
+
intersection.uv1 = Triangle.getInterpolation(_intersectionPoint$1, _vA$1, _vB$1, _vC$1, _uvA$1, _uvB$1, _uvC$1, new Vector2());
|
|
18161
18161
|
intersection.uv2 = intersection.uv1;
|
|
18162
18162
|
}
|
|
18163
18163
|
if (normal) {
|
|
18164
|
-
_normalA.fromBufferAttribute(normal, a);
|
|
18165
|
-
_normalB.fromBufferAttribute(normal, b);
|
|
18166
|
-
_normalC.fromBufferAttribute(normal, c2);
|
|
18167
|
-
intersection.normal = Triangle.getInterpolation(_intersectionPoint, _vA$1, _vB$1, _vC$1, _normalA, _normalB, _normalC, new Vector3());
|
|
18164
|
+
_normalA$1.fromBufferAttribute(normal, a);
|
|
18165
|
+
_normalB$1.fromBufferAttribute(normal, b);
|
|
18166
|
+
_normalC$1.fromBufferAttribute(normal, c2);
|
|
18167
|
+
intersection.normal = Triangle.getInterpolation(_intersectionPoint$1, _vA$1, _vB$1, _vC$1, _normalA$1, _normalB$1, _normalC$1, new Vector3());
|
|
18168
18168
|
if (intersection.normal.dot(ray.direction) > 0) {
|
|
18169
18169
|
intersection.normal.multiplyScalar(-1);
|
|
18170
18170
|
}
|
|
@@ -21194,7 +21194,7 @@ var __publicField = (obj, key, value) => {
|
|
|
21194
21194
|
function _getBlurShader(lodMax, width, height) {
|
|
21195
21195
|
const weights = new Float32Array(MAX_SAMPLES);
|
|
21196
21196
|
const poleAxis = new Vector3(0, 1, 0);
|
|
21197
|
-
const
|
|
21197
|
+
const shaderMaterial2 = new ShaderMaterial({
|
|
21198
21198
|
name: "SphericalGaussianBlur",
|
|
21199
21199
|
defines: {
|
|
21200
21200
|
"n": MAX_SAMPLES,
|
|
@@ -21280,7 +21280,7 @@ var __publicField = (obj, key, value) => {
|
|
|
21280
21280
|
depthTest: false,
|
|
21281
21281
|
depthWrite: false
|
|
21282
21282
|
});
|
|
21283
|
-
return
|
|
21283
|
+
return shaderMaterial2;
|
|
21284
21284
|
}
|
|
21285
21285
|
function _getEquirectMaterial() {
|
|
21286
21286
|
return new ShaderMaterial({
|
|
@@ -23284,8 +23284,8 @@ var __publicField = (obj, key, value) => {
|
|
|
23284
23284
|
const fog = scene.fog;
|
|
23285
23285
|
const geometry = object.geometry;
|
|
23286
23286
|
const environment = material.isMeshStandardMaterial ? scene.environment : null;
|
|
23287
|
-
const
|
|
23288
|
-
const envMapCubeUVHeight = !!
|
|
23287
|
+
const envMap2 = (material.isMeshStandardMaterial ? cubeuvmaps : cubemaps).get(material.envMap || environment);
|
|
23288
|
+
const envMapCubeUVHeight = !!envMap2 && envMap2.mapping === CubeUVReflectionMapping ? envMap2.image.height : null;
|
|
23289
23289
|
const shaderID = shaderIDs[material.type];
|
|
23290
23290
|
if (material.precision !== null) {
|
|
23291
23291
|
precision = capabilities.getMaxPrecision(material.precision);
|
|
@@ -23319,7 +23319,7 @@ var __publicField = (obj, key, value) => {
|
|
|
23319
23319
|
const IS_INSTANCEDMESH = object.isInstancedMesh === true;
|
|
23320
23320
|
const HAS_MAP = !!material.map;
|
|
23321
23321
|
const HAS_MATCAP = !!material.matcap;
|
|
23322
|
-
const HAS_ENVMAP = !!
|
|
23322
|
+
const HAS_ENVMAP = !!envMap2;
|
|
23323
23323
|
const HAS_AOMAP = !!material.aoMap;
|
|
23324
23324
|
const HAS_LIGHTMAP = !!material.lightMap;
|
|
23325
23325
|
const HAS_BUMPMAP = !!material.bumpMap;
|
|
@@ -23380,7 +23380,7 @@ var __publicField = (obj, key, value) => {
|
|
|
23380
23380
|
map: HAS_MAP,
|
|
23381
23381
|
matcap: HAS_MATCAP,
|
|
23382
23382
|
envMap: HAS_ENVMAP,
|
|
23383
|
-
envMapMode: HAS_ENVMAP &&
|
|
23383
|
+
envMapMode: HAS_ENVMAP && envMap2.mapping,
|
|
23384
23384
|
envMapCubeUVHeight,
|
|
23385
23385
|
aoMap: HAS_AOMAP,
|
|
23386
23386
|
lightMap: HAS_LIGHTMAP,
|
|
@@ -27403,10 +27403,10 @@ var __publicField = (obj, key, value) => {
|
|
|
27403
27403
|
if (material.alphaTest > 0) {
|
|
27404
27404
|
uniforms.alphaTest.value = material.alphaTest;
|
|
27405
27405
|
}
|
|
27406
|
-
const
|
|
27407
|
-
if (
|
|
27408
|
-
uniforms.envMap.value =
|
|
27409
|
-
uniforms.flipEnvMap.value =
|
|
27406
|
+
const envMap2 = properties.get(material).envMap;
|
|
27407
|
+
if (envMap2) {
|
|
27408
|
+
uniforms.envMap.value = envMap2;
|
|
27409
|
+
uniforms.flipEnvMap.value = envMap2.isCubeTexture && envMap2.isRenderTargetTexture === false ? -1 : 1;
|
|
27410
27410
|
uniforms.reflectivity.value = material.reflectivity;
|
|
27411
27411
|
uniforms.ior.value = material.ior;
|
|
27412
27412
|
uniforms.refractionRatio.value = material.refractionRatio;
|
|
@@ -27489,8 +27489,8 @@ var __publicField = (obj, key, value) => {
|
|
|
27489
27489
|
uniforms.roughnessMap.value = material.roughnessMap;
|
|
27490
27490
|
refreshTransformUniform(material.roughnessMap, uniforms.roughnessMapTransform);
|
|
27491
27491
|
}
|
|
27492
|
-
const
|
|
27493
|
-
if (
|
|
27492
|
+
const envMap2 = properties.get(material).envMap;
|
|
27493
|
+
if (envMap2) {
|
|
27494
27494
|
uniforms.envMapIntensity.value = material.envMapIntensity;
|
|
27495
27495
|
}
|
|
27496
27496
|
}
|
|
@@ -28721,7 +28721,7 @@ var __publicField = (obj, key, value) => {
|
|
|
28721
28721
|
const fog = scene.fog;
|
|
28722
28722
|
const environment = material.isMeshStandardMaterial ? scene.environment : null;
|
|
28723
28723
|
const colorSpace = _currentRenderTarget === null ? _this.outputColorSpace : _currentRenderTarget.isXRRenderTarget === true ? _currentRenderTarget.texture.colorSpace : LinearSRGBColorSpace;
|
|
28724
|
-
const
|
|
28724
|
+
const envMap2 = (material.isMeshStandardMaterial ? cubeuvmaps : cubemaps).get(material.envMap || environment);
|
|
28725
28725
|
const vertexAlphas = material.vertexColors === true && !!geometry.attributes.color && geometry.attributes.color.itemSize === 4;
|
|
28726
28726
|
const vertexTangents = !!geometry.attributes.tangent && (!!material.normalMap || material.anisotropy > 0);
|
|
28727
28727
|
const morphTargets = !!geometry.morphAttributes.position;
|
|
@@ -28761,7 +28761,7 @@ var __publicField = (obj, key, value) => {
|
|
|
28761
28761
|
needsProgramChange = true;
|
|
28762
28762
|
} else if (object.isInstancedMesh && materialProperties.instancingColor === false && object.instanceColor !== null) {
|
|
28763
28763
|
needsProgramChange = true;
|
|
28764
|
-
} else if (materialProperties.envMap !==
|
|
28764
|
+
} else if (materialProperties.envMap !== envMap2) {
|
|
28765
28765
|
needsProgramChange = true;
|
|
28766
28766
|
} else if (material.fog === true && materialProperties.fog !== fog) {
|
|
28767
28767
|
needsProgramChange = true;
|
|
@@ -28850,8 +28850,8 @@ var __publicField = (obj, key, value) => {
|
|
|
28850
28850
|
p_uniforms.setValue(_gl, "receiveShadow", object.receiveShadow);
|
|
28851
28851
|
}
|
|
28852
28852
|
if (material.isMeshGouraudMaterial && material.envMap !== null) {
|
|
28853
|
-
m_uniforms.envMap.value =
|
|
28854
|
-
m_uniforms.flipEnvMap.value =
|
|
28853
|
+
m_uniforms.envMap.value = envMap2;
|
|
28854
|
+
m_uniforms.flipEnvMap.value = envMap2.isCubeTexture && envMap2.isRenderTargetTexture === false ? -1 : 1;
|
|
28855
28855
|
}
|
|
28856
28856
|
if (refreshMaterial) {
|
|
28857
28857
|
p_uniforms.setValue(_gl, "toneMappingExposure", _this.toneMappingExposure);
|
|
@@ -32526,6 +32526,65 @@ var __publicField = (obj, key, value) => {
|
|
|
32526
32526
|
return new this.constructor().copy(this);
|
|
32527
32527
|
}
|
|
32528
32528
|
}
|
|
32529
|
+
const _startP = /* @__PURE__ */ new Vector3();
|
|
32530
|
+
const _startEnd = /* @__PURE__ */ new Vector3();
|
|
32531
|
+
class Line3 {
|
|
32532
|
+
constructor(start = new Vector3(), end = new Vector3()) {
|
|
32533
|
+
this.start = start;
|
|
32534
|
+
this.end = end;
|
|
32535
|
+
}
|
|
32536
|
+
set(start, end) {
|
|
32537
|
+
this.start.copy(start);
|
|
32538
|
+
this.end.copy(end);
|
|
32539
|
+
return this;
|
|
32540
|
+
}
|
|
32541
|
+
copy(line) {
|
|
32542
|
+
this.start.copy(line.start);
|
|
32543
|
+
this.end.copy(line.end);
|
|
32544
|
+
return this;
|
|
32545
|
+
}
|
|
32546
|
+
getCenter(target) {
|
|
32547
|
+
return target.addVectors(this.start, this.end).multiplyScalar(0.5);
|
|
32548
|
+
}
|
|
32549
|
+
delta(target) {
|
|
32550
|
+
return target.subVectors(this.end, this.start);
|
|
32551
|
+
}
|
|
32552
|
+
distanceSq() {
|
|
32553
|
+
return this.start.distanceToSquared(this.end);
|
|
32554
|
+
}
|
|
32555
|
+
distance() {
|
|
32556
|
+
return this.start.distanceTo(this.end);
|
|
32557
|
+
}
|
|
32558
|
+
at(t2, target) {
|
|
32559
|
+
return this.delta(target).multiplyScalar(t2).add(this.start);
|
|
32560
|
+
}
|
|
32561
|
+
closestPointToPointParameter(point, clampToLine) {
|
|
32562
|
+
_startP.subVectors(point, this.start);
|
|
32563
|
+
_startEnd.subVectors(this.end, this.start);
|
|
32564
|
+
const startEnd2 = _startEnd.dot(_startEnd);
|
|
32565
|
+
const startEnd_startP = _startEnd.dot(_startP);
|
|
32566
|
+
let t2 = startEnd_startP / startEnd2;
|
|
32567
|
+
if (clampToLine) {
|
|
32568
|
+
t2 = clamp(t2, 0, 1);
|
|
32569
|
+
}
|
|
32570
|
+
return t2;
|
|
32571
|
+
}
|
|
32572
|
+
closestPointToPoint(point, clampToLine, target) {
|
|
32573
|
+
const t2 = this.closestPointToPointParameter(point, clampToLine);
|
|
32574
|
+
return this.delta(target).multiplyScalar(t2).add(this.start);
|
|
32575
|
+
}
|
|
32576
|
+
applyMatrix4(matrix) {
|
|
32577
|
+
this.start.applyMatrix4(matrix);
|
|
32578
|
+
this.end.applyMatrix4(matrix);
|
|
32579
|
+
return this;
|
|
32580
|
+
}
|
|
32581
|
+
equals(line) {
|
|
32582
|
+
return line.start.equals(this.start) && line.end.equals(this.end);
|
|
32583
|
+
}
|
|
32584
|
+
clone() {
|
|
32585
|
+
return new this.constructor().copy(this);
|
|
32586
|
+
}
|
|
32587
|
+
}
|
|
32529
32588
|
if (typeof __THREE_DEVTOOLS__ !== "undefined") {
|
|
32530
32589
|
__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("register", { detail: {
|
|
32531
32590
|
revision: REVISION
|
|
@@ -37282,7 +37341,4085 @@ var __publicField = (obj, key, value) => {
|
|
|
37282
37341
|
}`
|
|
37283
37342
|
)
|
|
37284
37343
|
};
|
|
37344
|
+
const CENTER = 0;
|
|
37345
|
+
const AVERAGE = 1;
|
|
37346
|
+
const SAH = 2;
|
|
37347
|
+
const CONTAINED = 2;
|
|
37348
|
+
const TRIANGLE_INTERSECT_COST = 1.25;
|
|
37349
|
+
const TRAVERSAL_COST = 1;
|
|
37350
|
+
const BYTES_PER_NODE = 6 * 4 + 4 + 4;
|
|
37351
|
+
const IS_LEAFNODE_FLAG = 65535;
|
|
37352
|
+
const FLOAT32_EPSILON = Math.pow(2, -24);
|
|
37353
|
+
const SKIP_GENERATION = Symbol("SKIP_GENERATION");
|
|
37354
|
+
function getVertexCount(geo) {
|
|
37355
|
+
return geo.index ? geo.index.count : geo.attributes.position.count;
|
|
37356
|
+
}
|
|
37357
|
+
function getTriCount(geo) {
|
|
37358
|
+
return getVertexCount(geo) / 3;
|
|
37359
|
+
}
|
|
37360
|
+
function getIndexArray(vertexCount, BufferConstructor = ArrayBuffer) {
|
|
37361
|
+
if (vertexCount > 65535) {
|
|
37362
|
+
return new Uint32Array(new BufferConstructor(4 * vertexCount));
|
|
37363
|
+
} else {
|
|
37364
|
+
return new Uint16Array(new BufferConstructor(2 * vertexCount));
|
|
37365
|
+
}
|
|
37366
|
+
}
|
|
37367
|
+
function ensureIndex(geo, options) {
|
|
37368
|
+
if (!geo.index) {
|
|
37369
|
+
const vertexCount = geo.attributes.position.count;
|
|
37370
|
+
const BufferConstructor = options.useSharedArrayBuffer ? SharedArrayBuffer : ArrayBuffer;
|
|
37371
|
+
const index = getIndexArray(vertexCount, BufferConstructor);
|
|
37372
|
+
geo.setIndex(new BufferAttribute(index, 1));
|
|
37373
|
+
for (let i = 0; i < vertexCount; i++) {
|
|
37374
|
+
index[i] = i;
|
|
37375
|
+
}
|
|
37376
|
+
}
|
|
37377
|
+
}
|
|
37378
|
+
function getFullGeometryRange(geo) {
|
|
37379
|
+
const triCount = getTriCount(geo);
|
|
37380
|
+
const drawRange = geo.drawRange;
|
|
37381
|
+
const start = drawRange.start / 3;
|
|
37382
|
+
const end = (drawRange.start + drawRange.count) / 3;
|
|
37383
|
+
const offset = Math.max(0, start);
|
|
37384
|
+
const count = Math.min(triCount, end) - offset;
|
|
37385
|
+
return [{
|
|
37386
|
+
offset: Math.floor(offset),
|
|
37387
|
+
count: Math.floor(count)
|
|
37388
|
+
}];
|
|
37389
|
+
}
|
|
37390
|
+
function getRootIndexRanges(geo) {
|
|
37391
|
+
if (!geo.groups || !geo.groups.length) {
|
|
37392
|
+
return getFullGeometryRange(geo);
|
|
37393
|
+
}
|
|
37394
|
+
const ranges = [];
|
|
37395
|
+
const rangeBoundaries = /* @__PURE__ */ new Set();
|
|
37396
|
+
const drawRange = geo.drawRange;
|
|
37397
|
+
const drawRangeStart = drawRange.start / 3;
|
|
37398
|
+
const drawRangeEnd = (drawRange.start + drawRange.count) / 3;
|
|
37399
|
+
for (const group of geo.groups) {
|
|
37400
|
+
const groupStart = group.start / 3;
|
|
37401
|
+
const groupEnd = (group.start + group.count) / 3;
|
|
37402
|
+
rangeBoundaries.add(Math.max(drawRangeStart, groupStart));
|
|
37403
|
+
rangeBoundaries.add(Math.min(drawRangeEnd, groupEnd));
|
|
37404
|
+
}
|
|
37405
|
+
const sortedBoundaries = Array.from(rangeBoundaries.values()).sort((a, b) => a - b);
|
|
37406
|
+
for (let i = 0; i < sortedBoundaries.length - 1; i++) {
|
|
37407
|
+
const start = sortedBoundaries[i];
|
|
37408
|
+
const end = sortedBoundaries[i + 1];
|
|
37409
|
+
ranges.push({
|
|
37410
|
+
offset: Math.floor(start),
|
|
37411
|
+
count: Math.floor(end - start)
|
|
37412
|
+
});
|
|
37413
|
+
}
|
|
37414
|
+
return ranges;
|
|
37415
|
+
}
|
|
37416
|
+
function hasGroupGaps(geometry) {
|
|
37417
|
+
if (geometry.groups.length === 0) {
|
|
37418
|
+
return false;
|
|
37419
|
+
}
|
|
37420
|
+
const vertexCount = getTriCount(geometry);
|
|
37421
|
+
const groups = getRootIndexRanges(geometry).sort((a, b) => a.offset - b.offset);
|
|
37422
|
+
const finalGroup = groups[groups.length - 1];
|
|
37423
|
+
finalGroup.count = Math.min(vertexCount - finalGroup.offset, finalGroup.count);
|
|
37424
|
+
let total = 0;
|
|
37425
|
+
groups.forEach(({ count }) => total += count);
|
|
37426
|
+
return vertexCount !== total;
|
|
37427
|
+
}
|
|
37428
|
+
function arrayToBox(nodeIndex32, array, target) {
|
|
37429
|
+
target.min.x = array[nodeIndex32];
|
|
37430
|
+
target.min.y = array[nodeIndex32 + 1];
|
|
37431
|
+
target.min.z = array[nodeIndex32 + 2];
|
|
37432
|
+
target.max.x = array[nodeIndex32 + 3];
|
|
37433
|
+
target.max.y = array[nodeIndex32 + 4];
|
|
37434
|
+
target.max.z = array[nodeIndex32 + 5];
|
|
37435
|
+
return target;
|
|
37436
|
+
}
|
|
37437
|
+
function makeEmptyBounds(target) {
|
|
37438
|
+
target[0] = target[1] = target[2] = Infinity;
|
|
37439
|
+
target[3] = target[4] = target[5] = -Infinity;
|
|
37440
|
+
}
|
|
37441
|
+
function getLongestEdgeIndex(bounds) {
|
|
37442
|
+
let splitDimIdx = -1;
|
|
37443
|
+
let splitDist = -Infinity;
|
|
37444
|
+
for (let i = 0; i < 3; i++) {
|
|
37445
|
+
const dist = bounds[i + 3] - bounds[i];
|
|
37446
|
+
if (dist > splitDist) {
|
|
37447
|
+
splitDist = dist;
|
|
37448
|
+
splitDimIdx = i;
|
|
37449
|
+
}
|
|
37450
|
+
}
|
|
37451
|
+
return splitDimIdx;
|
|
37452
|
+
}
|
|
37453
|
+
function copyBounds(source, target) {
|
|
37454
|
+
target.set(source);
|
|
37455
|
+
}
|
|
37456
|
+
function unionBounds(a, b, target) {
|
|
37457
|
+
let aVal, bVal;
|
|
37458
|
+
for (let d = 0; d < 3; d++) {
|
|
37459
|
+
const d3 = d + 3;
|
|
37460
|
+
aVal = a[d];
|
|
37461
|
+
bVal = b[d];
|
|
37462
|
+
target[d] = aVal < bVal ? aVal : bVal;
|
|
37463
|
+
aVal = a[d3];
|
|
37464
|
+
bVal = b[d3];
|
|
37465
|
+
target[d3] = aVal > bVal ? aVal : bVal;
|
|
37466
|
+
}
|
|
37467
|
+
}
|
|
37468
|
+
function expandByTriangleBounds(startIndex, triangleBounds, bounds) {
|
|
37469
|
+
for (let d = 0; d < 3; d++) {
|
|
37470
|
+
const tCenter = triangleBounds[startIndex + 2 * d];
|
|
37471
|
+
const tHalf = triangleBounds[startIndex + 2 * d + 1];
|
|
37472
|
+
const tMin = tCenter - tHalf;
|
|
37473
|
+
const tMax = tCenter + tHalf;
|
|
37474
|
+
if (tMin < bounds[d]) {
|
|
37475
|
+
bounds[d] = tMin;
|
|
37476
|
+
}
|
|
37477
|
+
if (tMax > bounds[d + 3]) {
|
|
37478
|
+
bounds[d + 3] = tMax;
|
|
37479
|
+
}
|
|
37480
|
+
}
|
|
37481
|
+
}
|
|
37482
|
+
function computeSurfaceArea(bounds) {
|
|
37483
|
+
const d0 = bounds[3] - bounds[0];
|
|
37484
|
+
const d1 = bounds[4] - bounds[1];
|
|
37485
|
+
const d2 = bounds[5] - bounds[2];
|
|
37486
|
+
return 2 * (d0 * d1 + d1 * d2 + d2 * d0);
|
|
37487
|
+
}
|
|
37488
|
+
function getBounds(triangleBounds, offset, count, target, centroidTarget = null) {
|
|
37489
|
+
let minx = Infinity;
|
|
37490
|
+
let miny = Infinity;
|
|
37491
|
+
let minz = Infinity;
|
|
37492
|
+
let maxx = -Infinity;
|
|
37493
|
+
let maxy = -Infinity;
|
|
37494
|
+
let maxz = -Infinity;
|
|
37495
|
+
let cminx = Infinity;
|
|
37496
|
+
let cminy = Infinity;
|
|
37497
|
+
let cminz = Infinity;
|
|
37498
|
+
let cmaxx = -Infinity;
|
|
37499
|
+
let cmaxy = -Infinity;
|
|
37500
|
+
let cmaxz = -Infinity;
|
|
37501
|
+
const includeCentroid = centroidTarget !== null;
|
|
37502
|
+
for (let i = offset * 6, end = (offset + count) * 6; i < end; i += 6) {
|
|
37503
|
+
const cx = triangleBounds[i + 0];
|
|
37504
|
+
const hx = triangleBounds[i + 1];
|
|
37505
|
+
const lx = cx - hx;
|
|
37506
|
+
const rx = cx + hx;
|
|
37507
|
+
if (lx < minx)
|
|
37508
|
+
minx = lx;
|
|
37509
|
+
if (rx > maxx)
|
|
37510
|
+
maxx = rx;
|
|
37511
|
+
if (includeCentroid && cx < cminx)
|
|
37512
|
+
cminx = cx;
|
|
37513
|
+
if (includeCentroid && cx > cmaxx)
|
|
37514
|
+
cmaxx = cx;
|
|
37515
|
+
const cy = triangleBounds[i + 2];
|
|
37516
|
+
const hy = triangleBounds[i + 3];
|
|
37517
|
+
const ly = cy - hy;
|
|
37518
|
+
const ry = cy + hy;
|
|
37519
|
+
if (ly < miny)
|
|
37520
|
+
miny = ly;
|
|
37521
|
+
if (ry > maxy)
|
|
37522
|
+
maxy = ry;
|
|
37523
|
+
if (includeCentroid && cy < cminy)
|
|
37524
|
+
cminy = cy;
|
|
37525
|
+
if (includeCentroid && cy > cmaxy)
|
|
37526
|
+
cmaxy = cy;
|
|
37527
|
+
const cz = triangleBounds[i + 4];
|
|
37528
|
+
const hz = triangleBounds[i + 5];
|
|
37529
|
+
const lz = cz - hz;
|
|
37530
|
+
const rz = cz + hz;
|
|
37531
|
+
if (lz < minz)
|
|
37532
|
+
minz = lz;
|
|
37533
|
+
if (rz > maxz)
|
|
37534
|
+
maxz = rz;
|
|
37535
|
+
if (includeCentroid && cz < cminz)
|
|
37536
|
+
cminz = cz;
|
|
37537
|
+
if (includeCentroid && cz > cmaxz)
|
|
37538
|
+
cmaxz = cz;
|
|
37539
|
+
}
|
|
37540
|
+
target[0] = minx;
|
|
37541
|
+
target[1] = miny;
|
|
37542
|
+
target[2] = minz;
|
|
37543
|
+
target[3] = maxx;
|
|
37544
|
+
target[4] = maxy;
|
|
37545
|
+
target[5] = maxz;
|
|
37546
|
+
if (includeCentroid) {
|
|
37547
|
+
centroidTarget[0] = cminx;
|
|
37548
|
+
centroidTarget[1] = cminy;
|
|
37549
|
+
centroidTarget[2] = cminz;
|
|
37550
|
+
centroidTarget[3] = cmaxx;
|
|
37551
|
+
centroidTarget[4] = cmaxy;
|
|
37552
|
+
centroidTarget[5] = cmaxz;
|
|
37553
|
+
}
|
|
37554
|
+
}
|
|
37555
|
+
function getCentroidBounds(triangleBounds, offset, count, centroidTarget) {
|
|
37556
|
+
let cminx = Infinity;
|
|
37557
|
+
let cminy = Infinity;
|
|
37558
|
+
let cminz = Infinity;
|
|
37559
|
+
let cmaxx = -Infinity;
|
|
37560
|
+
let cmaxy = -Infinity;
|
|
37561
|
+
let cmaxz = -Infinity;
|
|
37562
|
+
for (let i = offset * 6, end = (offset + count) * 6; i < end; i += 6) {
|
|
37563
|
+
const cx = triangleBounds[i + 0];
|
|
37564
|
+
if (cx < cminx)
|
|
37565
|
+
cminx = cx;
|
|
37566
|
+
if (cx > cmaxx)
|
|
37567
|
+
cmaxx = cx;
|
|
37568
|
+
const cy = triangleBounds[i + 2];
|
|
37569
|
+
if (cy < cminy)
|
|
37570
|
+
cminy = cy;
|
|
37571
|
+
if (cy > cmaxy)
|
|
37572
|
+
cmaxy = cy;
|
|
37573
|
+
const cz = triangleBounds[i + 4];
|
|
37574
|
+
if (cz < cminz)
|
|
37575
|
+
cminz = cz;
|
|
37576
|
+
if (cz > cmaxz)
|
|
37577
|
+
cmaxz = cz;
|
|
37578
|
+
}
|
|
37579
|
+
centroidTarget[0] = cminx;
|
|
37580
|
+
centroidTarget[1] = cminy;
|
|
37581
|
+
centroidTarget[2] = cminz;
|
|
37582
|
+
centroidTarget[3] = cmaxx;
|
|
37583
|
+
centroidTarget[4] = cmaxy;
|
|
37584
|
+
centroidTarget[5] = cmaxz;
|
|
37585
|
+
}
|
|
37586
|
+
function computeTriangleBounds(geo, fullBounds) {
|
|
37587
|
+
makeEmptyBounds(fullBounds);
|
|
37588
|
+
const posAttr = geo.attributes.position;
|
|
37589
|
+
const index = geo.index ? geo.index.array : null;
|
|
37590
|
+
const triCount = getTriCount(geo);
|
|
37591
|
+
const triangleBounds = new Float32Array(triCount * 6);
|
|
37592
|
+
const normalized = posAttr.normalized;
|
|
37593
|
+
const posArr = posAttr.array;
|
|
37594
|
+
const bufferOffset = posAttr.offset || 0;
|
|
37595
|
+
let stride = 3;
|
|
37596
|
+
if (posAttr.isInterleavedBufferAttribute) {
|
|
37597
|
+
stride = posAttr.data.stride;
|
|
37598
|
+
}
|
|
37599
|
+
const getters = ["getX", "getY", "getZ"];
|
|
37600
|
+
for (let tri = 0; tri < triCount; tri++) {
|
|
37601
|
+
const tri3 = tri * 3;
|
|
37602
|
+
const tri6 = tri * 6;
|
|
37603
|
+
let ai = tri3 + 0;
|
|
37604
|
+
let bi = tri3 + 1;
|
|
37605
|
+
let ci = tri3 + 2;
|
|
37606
|
+
if (index) {
|
|
37607
|
+
ai = index[ai];
|
|
37608
|
+
bi = index[bi];
|
|
37609
|
+
ci = index[ci];
|
|
37610
|
+
}
|
|
37611
|
+
if (!normalized) {
|
|
37612
|
+
ai = ai * stride + bufferOffset;
|
|
37613
|
+
bi = bi * stride + bufferOffset;
|
|
37614
|
+
ci = ci * stride + bufferOffset;
|
|
37615
|
+
}
|
|
37616
|
+
for (let el = 0; el < 3; el++) {
|
|
37617
|
+
let a, b, c2;
|
|
37618
|
+
if (normalized) {
|
|
37619
|
+
a = posAttr[getters[el]](ai);
|
|
37620
|
+
b = posAttr[getters[el]](bi);
|
|
37621
|
+
c2 = posAttr[getters[el]](ci);
|
|
37622
|
+
} else {
|
|
37623
|
+
a = posArr[ai + el];
|
|
37624
|
+
b = posArr[bi + el];
|
|
37625
|
+
c2 = posArr[ci + el];
|
|
37626
|
+
}
|
|
37627
|
+
let min = a;
|
|
37628
|
+
if (b < min)
|
|
37629
|
+
min = b;
|
|
37630
|
+
if (c2 < min)
|
|
37631
|
+
min = c2;
|
|
37632
|
+
let max = a;
|
|
37633
|
+
if (b > max)
|
|
37634
|
+
max = b;
|
|
37635
|
+
if (c2 > max)
|
|
37636
|
+
max = c2;
|
|
37637
|
+
const halfExtents = (max - min) / 2;
|
|
37638
|
+
const el2 = el * 2;
|
|
37639
|
+
triangleBounds[tri6 + el2 + 0] = min + halfExtents;
|
|
37640
|
+
triangleBounds[tri6 + el2 + 1] = halfExtents + (Math.abs(min) + halfExtents) * FLOAT32_EPSILON;
|
|
37641
|
+
if (min < fullBounds[el])
|
|
37642
|
+
fullBounds[el] = min;
|
|
37643
|
+
if (max > fullBounds[el + 3])
|
|
37644
|
+
fullBounds[el + 3] = max;
|
|
37645
|
+
}
|
|
37646
|
+
}
|
|
37647
|
+
return triangleBounds;
|
|
37648
|
+
}
|
|
37649
|
+
const BIN_COUNT = 32;
|
|
37650
|
+
const binsSort = (a, b) => a.candidate - b.candidate;
|
|
37651
|
+
const sahBins = new Array(BIN_COUNT).fill().map(() => {
|
|
37652
|
+
return {
|
|
37653
|
+
count: 0,
|
|
37654
|
+
bounds: new Float32Array(6),
|
|
37655
|
+
rightCacheBounds: new Float32Array(6),
|
|
37656
|
+
leftCacheBounds: new Float32Array(6),
|
|
37657
|
+
candidate: 0
|
|
37658
|
+
};
|
|
37659
|
+
});
|
|
37660
|
+
const leftBounds = new Float32Array(6);
|
|
37661
|
+
function getOptimalSplit(nodeBoundingData, centroidBoundingData, triangleBounds, offset, count, strategy) {
|
|
37662
|
+
let axis = -1;
|
|
37663
|
+
let pos = 0;
|
|
37664
|
+
if (strategy === CENTER) {
|
|
37665
|
+
axis = getLongestEdgeIndex(centroidBoundingData);
|
|
37666
|
+
if (axis !== -1) {
|
|
37667
|
+
pos = (centroidBoundingData[axis] + centroidBoundingData[axis + 3]) / 2;
|
|
37668
|
+
}
|
|
37669
|
+
} else if (strategy === AVERAGE) {
|
|
37670
|
+
axis = getLongestEdgeIndex(nodeBoundingData);
|
|
37671
|
+
if (axis !== -1) {
|
|
37672
|
+
pos = getAverage(triangleBounds, offset, count, axis);
|
|
37673
|
+
}
|
|
37674
|
+
} else if (strategy === SAH) {
|
|
37675
|
+
const rootSurfaceArea = computeSurfaceArea(nodeBoundingData);
|
|
37676
|
+
let bestCost = TRIANGLE_INTERSECT_COST * count;
|
|
37677
|
+
const cStart = offset * 6;
|
|
37678
|
+
const cEnd = (offset + count) * 6;
|
|
37679
|
+
for (let a = 0; a < 3; a++) {
|
|
37680
|
+
const axisLeft = centroidBoundingData[a];
|
|
37681
|
+
const axisRight = centroidBoundingData[a + 3];
|
|
37682
|
+
const axisLength = axisRight - axisLeft;
|
|
37683
|
+
const binWidth = axisLength / BIN_COUNT;
|
|
37684
|
+
if (count < BIN_COUNT / 4) {
|
|
37685
|
+
const truncatedBins = [...sahBins];
|
|
37686
|
+
truncatedBins.length = count;
|
|
37687
|
+
let b = 0;
|
|
37688
|
+
for (let c2 = cStart; c2 < cEnd; c2 += 6, b++) {
|
|
37689
|
+
const bin = truncatedBins[b];
|
|
37690
|
+
bin.candidate = triangleBounds[c2 + 2 * a];
|
|
37691
|
+
bin.count = 0;
|
|
37692
|
+
const {
|
|
37693
|
+
bounds,
|
|
37694
|
+
leftCacheBounds,
|
|
37695
|
+
rightCacheBounds
|
|
37696
|
+
} = bin;
|
|
37697
|
+
for (let d = 0; d < 3; d++) {
|
|
37698
|
+
rightCacheBounds[d] = Infinity;
|
|
37699
|
+
rightCacheBounds[d + 3] = -Infinity;
|
|
37700
|
+
leftCacheBounds[d] = Infinity;
|
|
37701
|
+
leftCacheBounds[d + 3] = -Infinity;
|
|
37702
|
+
bounds[d] = Infinity;
|
|
37703
|
+
bounds[d + 3] = -Infinity;
|
|
37704
|
+
}
|
|
37705
|
+
expandByTriangleBounds(c2, triangleBounds, bounds);
|
|
37706
|
+
}
|
|
37707
|
+
truncatedBins.sort(binsSort);
|
|
37708
|
+
let splitCount = count;
|
|
37709
|
+
for (let bi = 0; bi < splitCount; bi++) {
|
|
37710
|
+
const bin = truncatedBins[bi];
|
|
37711
|
+
while (bi + 1 < splitCount && truncatedBins[bi + 1].candidate === bin.candidate) {
|
|
37712
|
+
truncatedBins.splice(bi + 1, 1);
|
|
37713
|
+
splitCount--;
|
|
37714
|
+
}
|
|
37715
|
+
}
|
|
37716
|
+
for (let c2 = cStart; c2 < cEnd; c2 += 6) {
|
|
37717
|
+
const center = triangleBounds[c2 + 2 * a];
|
|
37718
|
+
for (let bi = 0; bi < splitCount; bi++) {
|
|
37719
|
+
const bin = truncatedBins[bi];
|
|
37720
|
+
if (center >= bin.candidate) {
|
|
37721
|
+
expandByTriangleBounds(c2, triangleBounds, bin.rightCacheBounds);
|
|
37722
|
+
} else {
|
|
37723
|
+
expandByTriangleBounds(c2, triangleBounds, bin.leftCacheBounds);
|
|
37724
|
+
bin.count++;
|
|
37725
|
+
}
|
|
37726
|
+
}
|
|
37727
|
+
}
|
|
37728
|
+
for (let bi = 0; bi < splitCount; bi++) {
|
|
37729
|
+
const bin = truncatedBins[bi];
|
|
37730
|
+
const leftCount = bin.count;
|
|
37731
|
+
const rightCount = count - bin.count;
|
|
37732
|
+
const leftBounds2 = bin.leftCacheBounds;
|
|
37733
|
+
const rightBounds = bin.rightCacheBounds;
|
|
37734
|
+
let leftProb = 0;
|
|
37735
|
+
if (leftCount !== 0) {
|
|
37736
|
+
leftProb = computeSurfaceArea(leftBounds2) / rootSurfaceArea;
|
|
37737
|
+
}
|
|
37738
|
+
let rightProb = 0;
|
|
37739
|
+
if (rightCount !== 0) {
|
|
37740
|
+
rightProb = computeSurfaceArea(rightBounds) / rootSurfaceArea;
|
|
37741
|
+
}
|
|
37742
|
+
const cost = TRAVERSAL_COST + TRIANGLE_INTERSECT_COST * (leftProb * leftCount + rightProb * rightCount);
|
|
37743
|
+
if (cost < bestCost) {
|
|
37744
|
+
axis = a;
|
|
37745
|
+
bestCost = cost;
|
|
37746
|
+
pos = bin.candidate;
|
|
37747
|
+
}
|
|
37748
|
+
}
|
|
37749
|
+
} else {
|
|
37750
|
+
for (let i = 0; i < BIN_COUNT; i++) {
|
|
37751
|
+
const bin = sahBins[i];
|
|
37752
|
+
bin.count = 0;
|
|
37753
|
+
bin.candidate = axisLeft + binWidth + i * binWidth;
|
|
37754
|
+
const bounds = bin.bounds;
|
|
37755
|
+
for (let d = 0; d < 3; d++) {
|
|
37756
|
+
bounds[d] = Infinity;
|
|
37757
|
+
bounds[d + 3] = -Infinity;
|
|
37758
|
+
}
|
|
37759
|
+
}
|
|
37760
|
+
for (let c2 = cStart; c2 < cEnd; c2 += 6) {
|
|
37761
|
+
const triCenter = triangleBounds[c2 + 2 * a];
|
|
37762
|
+
const relativeCenter = triCenter - axisLeft;
|
|
37763
|
+
let binIndex = ~~(relativeCenter / binWidth);
|
|
37764
|
+
if (binIndex >= BIN_COUNT)
|
|
37765
|
+
binIndex = BIN_COUNT - 1;
|
|
37766
|
+
const bin = sahBins[binIndex];
|
|
37767
|
+
bin.count++;
|
|
37768
|
+
expandByTriangleBounds(c2, triangleBounds, bin.bounds);
|
|
37769
|
+
}
|
|
37770
|
+
const lastBin = sahBins[BIN_COUNT - 1];
|
|
37771
|
+
copyBounds(lastBin.bounds, lastBin.rightCacheBounds);
|
|
37772
|
+
for (let i = BIN_COUNT - 2; i >= 0; i--) {
|
|
37773
|
+
const bin = sahBins[i];
|
|
37774
|
+
const nextBin = sahBins[i + 1];
|
|
37775
|
+
unionBounds(bin.bounds, nextBin.rightCacheBounds, bin.rightCacheBounds);
|
|
37776
|
+
}
|
|
37777
|
+
let leftCount = 0;
|
|
37778
|
+
for (let i = 0; i < BIN_COUNT - 1; i++) {
|
|
37779
|
+
const bin = sahBins[i];
|
|
37780
|
+
const binCount = bin.count;
|
|
37781
|
+
const bounds = bin.bounds;
|
|
37782
|
+
const nextBin = sahBins[i + 1];
|
|
37783
|
+
const rightBounds = nextBin.rightCacheBounds;
|
|
37784
|
+
if (binCount !== 0) {
|
|
37785
|
+
if (leftCount === 0) {
|
|
37786
|
+
copyBounds(bounds, leftBounds);
|
|
37787
|
+
} else {
|
|
37788
|
+
unionBounds(bounds, leftBounds, leftBounds);
|
|
37789
|
+
}
|
|
37790
|
+
}
|
|
37791
|
+
leftCount += binCount;
|
|
37792
|
+
let leftProb = 0;
|
|
37793
|
+
let rightProb = 0;
|
|
37794
|
+
if (leftCount !== 0) {
|
|
37795
|
+
leftProb = computeSurfaceArea(leftBounds) / rootSurfaceArea;
|
|
37796
|
+
}
|
|
37797
|
+
const rightCount = count - leftCount;
|
|
37798
|
+
if (rightCount !== 0) {
|
|
37799
|
+
rightProb = computeSurfaceArea(rightBounds) / rootSurfaceArea;
|
|
37800
|
+
}
|
|
37801
|
+
const cost = TRAVERSAL_COST + TRIANGLE_INTERSECT_COST * (leftProb * leftCount + rightProb * rightCount);
|
|
37802
|
+
if (cost < bestCost) {
|
|
37803
|
+
axis = a;
|
|
37804
|
+
bestCost = cost;
|
|
37805
|
+
pos = bin.candidate;
|
|
37806
|
+
}
|
|
37807
|
+
}
|
|
37808
|
+
}
|
|
37809
|
+
}
|
|
37810
|
+
} else {
|
|
37811
|
+
console.warn(`MeshBVH: Invalid build strategy value ${strategy} used.`);
|
|
37812
|
+
}
|
|
37813
|
+
return { axis, pos };
|
|
37814
|
+
}
|
|
37815
|
+
function getAverage(triangleBounds, offset, count, axis) {
|
|
37816
|
+
let avg = 0;
|
|
37817
|
+
for (let i = offset, end = offset + count; i < end; i++) {
|
|
37818
|
+
avg += triangleBounds[i * 6 + axis * 2];
|
|
37819
|
+
}
|
|
37820
|
+
return avg / count;
|
|
37821
|
+
}
|
|
37822
|
+
class MeshBVHNode {
|
|
37823
|
+
constructor() {
|
|
37824
|
+
}
|
|
37825
|
+
}
|
|
37826
|
+
function partition(indirectBuffer, index, triangleBounds, offset, count, split) {
|
|
37827
|
+
let left = offset;
|
|
37828
|
+
let right = offset + count - 1;
|
|
37829
|
+
const pos = split.pos;
|
|
37830
|
+
const axisOffset = split.axis * 2;
|
|
37831
|
+
while (true) {
|
|
37832
|
+
while (left <= right && triangleBounds[left * 6 + axisOffset] < pos) {
|
|
37833
|
+
left++;
|
|
37834
|
+
}
|
|
37835
|
+
while (left <= right && triangleBounds[right * 6 + axisOffset] >= pos) {
|
|
37836
|
+
right--;
|
|
37837
|
+
}
|
|
37838
|
+
if (left < right) {
|
|
37839
|
+
for (let i = 0; i < 3; i++) {
|
|
37840
|
+
let t0 = index[left * 3 + i];
|
|
37841
|
+
index[left * 3 + i] = index[right * 3 + i];
|
|
37842
|
+
index[right * 3 + i] = t0;
|
|
37843
|
+
}
|
|
37844
|
+
for (let i = 0; i < 6; i++) {
|
|
37845
|
+
let tb = triangleBounds[left * 6 + i];
|
|
37846
|
+
triangleBounds[left * 6 + i] = triangleBounds[right * 6 + i];
|
|
37847
|
+
triangleBounds[right * 6 + i] = tb;
|
|
37848
|
+
}
|
|
37849
|
+
left++;
|
|
37850
|
+
right--;
|
|
37851
|
+
} else {
|
|
37852
|
+
return left;
|
|
37853
|
+
}
|
|
37854
|
+
}
|
|
37855
|
+
}
|
|
37856
|
+
function partition_indirect(indirectBuffer, index, triangleBounds, offset, count, split) {
|
|
37857
|
+
let left = offset;
|
|
37858
|
+
let right = offset + count - 1;
|
|
37859
|
+
const pos = split.pos;
|
|
37860
|
+
const axisOffset = split.axis * 2;
|
|
37861
|
+
while (true) {
|
|
37862
|
+
while (left <= right && triangleBounds[left * 6 + axisOffset] < pos) {
|
|
37863
|
+
left++;
|
|
37864
|
+
}
|
|
37865
|
+
while (left <= right && triangleBounds[right * 6 + axisOffset] >= pos) {
|
|
37866
|
+
right--;
|
|
37867
|
+
}
|
|
37868
|
+
if (left < right) {
|
|
37869
|
+
let t2 = indirectBuffer[left];
|
|
37870
|
+
indirectBuffer[left] = indirectBuffer[right];
|
|
37871
|
+
indirectBuffer[right] = t2;
|
|
37872
|
+
for (let i = 0; i < 6; i++) {
|
|
37873
|
+
let tb = triangleBounds[left * 6 + i];
|
|
37874
|
+
triangleBounds[left * 6 + i] = triangleBounds[right * 6 + i];
|
|
37875
|
+
triangleBounds[right * 6 + i] = tb;
|
|
37876
|
+
}
|
|
37877
|
+
left++;
|
|
37878
|
+
right--;
|
|
37879
|
+
} else {
|
|
37880
|
+
return left;
|
|
37881
|
+
}
|
|
37882
|
+
}
|
|
37883
|
+
}
|
|
37884
|
+
function generateIndirectBuffer(geometry, useSharedArrayBuffer) {
|
|
37885
|
+
const triCount = (geometry.index ? geometry.index.count : geometry.attributes.position.count) / 3;
|
|
37886
|
+
const useUint32 = triCount > 2 ** 16;
|
|
37887
|
+
const byteCount = useUint32 ? 4 : 2;
|
|
37888
|
+
const buffer = useSharedArrayBuffer ? new SharedArrayBuffer(triCount * byteCount) : new ArrayBuffer(triCount * byteCount);
|
|
37889
|
+
const indirectBuffer = useUint32 ? new Uint32Array(buffer) : new Uint16Array(buffer);
|
|
37890
|
+
for (let i = 0, l = indirectBuffer.length; i < l; i++) {
|
|
37891
|
+
indirectBuffer[i] = i;
|
|
37892
|
+
}
|
|
37893
|
+
return indirectBuffer;
|
|
37894
|
+
}
|
|
37895
|
+
function buildTree(bvh, options) {
|
|
37896
|
+
const geometry = bvh.geometry;
|
|
37897
|
+
const indexArray = geometry.index ? geometry.index.array : null;
|
|
37898
|
+
const maxDepth = options.maxDepth;
|
|
37899
|
+
const verbose = options.verbose;
|
|
37900
|
+
const maxLeafTris = options.maxLeafTris;
|
|
37901
|
+
const strategy = options.strategy;
|
|
37902
|
+
const onProgress = options.onProgress;
|
|
37903
|
+
const totalTriangles = getTriCount(geometry);
|
|
37904
|
+
const indirectBuffer = bvh._indirectBuffer;
|
|
37905
|
+
let reachedMaxDepth = false;
|
|
37906
|
+
const fullBounds = new Float32Array(6);
|
|
37907
|
+
const cacheCentroidBoundingData = new Float32Array(6);
|
|
37908
|
+
const triangleBounds = computeTriangleBounds(geometry, fullBounds);
|
|
37909
|
+
const partionFunc = options.indirect ? partition_indirect : partition;
|
|
37910
|
+
const roots = [];
|
|
37911
|
+
const ranges = options.indirect ? getFullGeometryRange(geometry) : getRootIndexRanges(geometry);
|
|
37912
|
+
if (ranges.length === 1) {
|
|
37913
|
+
const range = ranges[0];
|
|
37914
|
+
const root = new MeshBVHNode();
|
|
37915
|
+
root.boundingData = fullBounds;
|
|
37916
|
+
getCentroidBounds(triangleBounds, range.offset, range.count, cacheCentroidBoundingData);
|
|
37917
|
+
splitNode(root, range.offset, range.count, cacheCentroidBoundingData);
|
|
37918
|
+
roots.push(root);
|
|
37919
|
+
} else {
|
|
37920
|
+
for (let range of ranges) {
|
|
37921
|
+
const root = new MeshBVHNode();
|
|
37922
|
+
root.boundingData = new Float32Array(6);
|
|
37923
|
+
getBounds(triangleBounds, range.offset, range.count, root.boundingData, cacheCentroidBoundingData);
|
|
37924
|
+
splitNode(root, range.offset, range.count, cacheCentroidBoundingData);
|
|
37925
|
+
roots.push(root);
|
|
37926
|
+
}
|
|
37927
|
+
}
|
|
37928
|
+
return roots;
|
|
37929
|
+
function triggerProgress(trianglesProcessed) {
|
|
37930
|
+
if (onProgress) {
|
|
37931
|
+
onProgress(trianglesProcessed / totalTriangles);
|
|
37932
|
+
}
|
|
37933
|
+
}
|
|
37934
|
+
function splitNode(node, offset, count, centroidBoundingData = null, depth = 0) {
|
|
37935
|
+
if (!reachedMaxDepth && depth >= maxDepth) {
|
|
37936
|
+
reachedMaxDepth = true;
|
|
37937
|
+
if (verbose) {
|
|
37938
|
+
console.warn(`MeshBVH: Max depth of ${maxDepth} reached when generating BVH. Consider increasing maxDepth.`);
|
|
37939
|
+
console.warn(geometry);
|
|
37940
|
+
}
|
|
37941
|
+
}
|
|
37942
|
+
if (count <= maxLeafTris || depth >= maxDepth) {
|
|
37943
|
+
triggerProgress(offset + count);
|
|
37944
|
+
node.offset = offset;
|
|
37945
|
+
node.count = count;
|
|
37946
|
+
return node;
|
|
37947
|
+
}
|
|
37948
|
+
const split = getOptimalSplit(node.boundingData, centroidBoundingData, triangleBounds, offset, count, strategy);
|
|
37949
|
+
if (split.axis === -1) {
|
|
37950
|
+
triggerProgress(offset + count);
|
|
37951
|
+
node.offset = offset;
|
|
37952
|
+
node.count = count;
|
|
37953
|
+
return node;
|
|
37954
|
+
}
|
|
37955
|
+
const splitOffset = partionFunc(indirectBuffer, indexArray, triangleBounds, offset, count, split);
|
|
37956
|
+
if (splitOffset === offset || splitOffset === offset + count) {
|
|
37957
|
+
triggerProgress(offset + count);
|
|
37958
|
+
node.offset = offset;
|
|
37959
|
+
node.count = count;
|
|
37960
|
+
} else {
|
|
37961
|
+
node.splitAxis = split.axis;
|
|
37962
|
+
const left = new MeshBVHNode();
|
|
37963
|
+
const lstart = offset;
|
|
37964
|
+
const lcount = splitOffset - offset;
|
|
37965
|
+
node.left = left;
|
|
37966
|
+
left.boundingData = new Float32Array(6);
|
|
37967
|
+
getBounds(triangleBounds, lstart, lcount, left.boundingData, cacheCentroidBoundingData);
|
|
37968
|
+
splitNode(left, lstart, lcount, cacheCentroidBoundingData, depth + 1);
|
|
37969
|
+
const right = new MeshBVHNode();
|
|
37970
|
+
const rstart = splitOffset;
|
|
37971
|
+
const rcount = count - lcount;
|
|
37972
|
+
node.right = right;
|
|
37973
|
+
right.boundingData = new Float32Array(6);
|
|
37974
|
+
getBounds(triangleBounds, rstart, rcount, right.boundingData, cacheCentroidBoundingData);
|
|
37975
|
+
splitNode(right, rstart, rcount, cacheCentroidBoundingData, depth + 1);
|
|
37976
|
+
}
|
|
37977
|
+
return node;
|
|
37978
|
+
}
|
|
37979
|
+
}
|
|
37980
|
+
function buildPackedTree(bvh, options) {
|
|
37981
|
+
const geometry = bvh.geometry;
|
|
37982
|
+
if (options.indirect) {
|
|
37983
|
+
bvh._indirectBuffer = generateIndirectBuffer(geometry, options.useSharedArrayBuffer);
|
|
37984
|
+
if (hasGroupGaps(geometry) && !options.verbose) {
|
|
37985
|
+
console.warn(
|
|
37986
|
+
'MeshBVH: Provided geometry contains groups that do not fully span the vertex contents while using the "indirect" option. BVH may incorrectly report intersections on unrendered portions of the geometry.'
|
|
37987
|
+
);
|
|
37988
|
+
}
|
|
37989
|
+
}
|
|
37990
|
+
if (!bvh._indirectBuffer) {
|
|
37991
|
+
ensureIndex(geometry, options);
|
|
37992
|
+
}
|
|
37993
|
+
const roots = buildTree(bvh, options);
|
|
37994
|
+
let float32Array;
|
|
37995
|
+
let uint32Array;
|
|
37996
|
+
let uint16Array;
|
|
37997
|
+
const packedRoots = [];
|
|
37998
|
+
const BufferConstructor = options.useSharedArrayBuffer ? SharedArrayBuffer : ArrayBuffer;
|
|
37999
|
+
for (let i = 0; i < roots.length; i++) {
|
|
38000
|
+
const root = roots[i];
|
|
38001
|
+
let nodeCount = countNodes(root);
|
|
38002
|
+
const buffer = new BufferConstructor(BYTES_PER_NODE * nodeCount);
|
|
38003
|
+
float32Array = new Float32Array(buffer);
|
|
38004
|
+
uint32Array = new Uint32Array(buffer);
|
|
38005
|
+
uint16Array = new Uint16Array(buffer);
|
|
38006
|
+
populateBuffer(0, root);
|
|
38007
|
+
packedRoots.push(buffer);
|
|
38008
|
+
}
|
|
38009
|
+
bvh._roots = packedRoots;
|
|
38010
|
+
return;
|
|
38011
|
+
function countNodes(node) {
|
|
38012
|
+
if (node.count) {
|
|
38013
|
+
return 1;
|
|
38014
|
+
} else {
|
|
38015
|
+
return 1 + countNodes(node.left) + countNodes(node.right);
|
|
38016
|
+
}
|
|
38017
|
+
}
|
|
38018
|
+
function populateBuffer(byteOffset, node) {
|
|
38019
|
+
const stride4Offset = byteOffset / 4;
|
|
38020
|
+
const stride2Offset = byteOffset / 2;
|
|
38021
|
+
const isLeaf = !!node.count;
|
|
38022
|
+
const boundingData = node.boundingData;
|
|
38023
|
+
for (let i = 0; i < 6; i++) {
|
|
38024
|
+
float32Array[stride4Offset + i] = boundingData[i];
|
|
38025
|
+
}
|
|
38026
|
+
if (isLeaf) {
|
|
38027
|
+
const offset = node.offset;
|
|
38028
|
+
const count = node.count;
|
|
38029
|
+
uint32Array[stride4Offset + 6] = offset;
|
|
38030
|
+
uint16Array[stride2Offset + 14] = count;
|
|
38031
|
+
uint16Array[stride2Offset + 15] = IS_LEAFNODE_FLAG;
|
|
38032
|
+
return byteOffset + BYTES_PER_NODE;
|
|
38033
|
+
} else {
|
|
38034
|
+
const left = node.left;
|
|
38035
|
+
const right = node.right;
|
|
38036
|
+
const splitAxis = node.splitAxis;
|
|
38037
|
+
let nextUnusedPointer;
|
|
38038
|
+
nextUnusedPointer = populateBuffer(byteOffset + BYTES_PER_NODE, left);
|
|
38039
|
+
if (nextUnusedPointer / 4 > Math.pow(2, 32)) {
|
|
38040
|
+
throw new Error("MeshBVH: Cannot store child pointer greater than 32 bits.");
|
|
38041
|
+
}
|
|
38042
|
+
uint32Array[stride4Offset + 6] = nextUnusedPointer / 4;
|
|
38043
|
+
nextUnusedPointer = populateBuffer(nextUnusedPointer, right);
|
|
38044
|
+
uint32Array[stride4Offset + 7] = splitAxis;
|
|
38045
|
+
return nextUnusedPointer;
|
|
38046
|
+
}
|
|
38047
|
+
}
|
|
38048
|
+
}
|
|
38049
|
+
class SeparatingAxisBounds {
|
|
38050
|
+
constructor() {
|
|
38051
|
+
this.min = Infinity;
|
|
38052
|
+
this.max = -Infinity;
|
|
38053
|
+
}
|
|
38054
|
+
setFromPointsField(points, field) {
|
|
38055
|
+
let min = Infinity;
|
|
38056
|
+
let max = -Infinity;
|
|
38057
|
+
for (let i = 0, l = points.length; i < l; i++) {
|
|
38058
|
+
const p2 = points[i];
|
|
38059
|
+
const val = p2[field];
|
|
38060
|
+
min = val < min ? val : min;
|
|
38061
|
+
max = val > max ? val : max;
|
|
38062
|
+
}
|
|
38063
|
+
this.min = min;
|
|
38064
|
+
this.max = max;
|
|
38065
|
+
}
|
|
38066
|
+
setFromPoints(axis, points) {
|
|
38067
|
+
let min = Infinity;
|
|
38068
|
+
let max = -Infinity;
|
|
38069
|
+
for (let i = 0, l = points.length; i < l; i++) {
|
|
38070
|
+
const p2 = points[i];
|
|
38071
|
+
const val = axis.dot(p2);
|
|
38072
|
+
min = val < min ? val : min;
|
|
38073
|
+
max = val > max ? val : max;
|
|
38074
|
+
}
|
|
38075
|
+
this.min = min;
|
|
38076
|
+
this.max = max;
|
|
38077
|
+
}
|
|
38078
|
+
isSeparated(other) {
|
|
38079
|
+
return this.min > other.max || other.min > this.max;
|
|
38080
|
+
}
|
|
38081
|
+
}
|
|
38082
|
+
SeparatingAxisBounds.prototype.setFromBox = function() {
|
|
38083
|
+
const p2 = new Vector3();
|
|
38084
|
+
return function setFromBox(axis, box) {
|
|
38085
|
+
const boxMin = box.min;
|
|
38086
|
+
const boxMax = box.max;
|
|
38087
|
+
let min = Infinity;
|
|
38088
|
+
let max = -Infinity;
|
|
38089
|
+
for (let x2 = 0; x2 <= 1; x2++) {
|
|
38090
|
+
for (let y = 0; y <= 1; y++) {
|
|
38091
|
+
for (let z = 0; z <= 1; z++) {
|
|
38092
|
+
p2.x = boxMin.x * x2 + boxMax.x * (1 - x2);
|
|
38093
|
+
p2.y = boxMin.y * y + boxMax.y * (1 - y);
|
|
38094
|
+
p2.z = boxMin.z * z + boxMax.z * (1 - z);
|
|
38095
|
+
const val = axis.dot(p2);
|
|
38096
|
+
min = Math.min(val, min);
|
|
38097
|
+
max = Math.max(val, max);
|
|
38098
|
+
}
|
|
38099
|
+
}
|
|
38100
|
+
}
|
|
38101
|
+
this.min = min;
|
|
38102
|
+
this.max = max;
|
|
38103
|
+
};
|
|
38104
|
+
}();
|
|
38105
|
+
const closestPointLineToLine = function() {
|
|
38106
|
+
const dir1 = new Vector3();
|
|
38107
|
+
const dir2 = new Vector3();
|
|
38108
|
+
const v02 = new Vector3();
|
|
38109
|
+
return function closestPointLineToLine2(l1, l2, result) {
|
|
38110
|
+
const v0 = l1.start;
|
|
38111
|
+
const v10 = dir1;
|
|
38112
|
+
const v2 = l2.start;
|
|
38113
|
+
const v32 = dir2;
|
|
38114
|
+
v02.subVectors(v0, v2);
|
|
38115
|
+
dir1.subVectors(l1.end, l1.start);
|
|
38116
|
+
dir2.subVectors(l2.end, l2.start);
|
|
38117
|
+
const d0232 = v02.dot(v32);
|
|
38118
|
+
const d3210 = v32.dot(v10);
|
|
38119
|
+
const d3232 = v32.dot(v32);
|
|
38120
|
+
const d0210 = v02.dot(v10);
|
|
38121
|
+
const d1010 = v10.dot(v10);
|
|
38122
|
+
const denom = d1010 * d3232 - d3210 * d3210;
|
|
38123
|
+
let d, d2;
|
|
38124
|
+
if (denom !== 0) {
|
|
38125
|
+
d = (d0232 * d3210 - d0210 * d3232) / denom;
|
|
38126
|
+
} else {
|
|
38127
|
+
d = 0;
|
|
38128
|
+
}
|
|
38129
|
+
d2 = (d0232 + d * d3210) / d3232;
|
|
38130
|
+
result.x = d;
|
|
38131
|
+
result.y = d2;
|
|
38132
|
+
};
|
|
38133
|
+
}();
|
|
38134
|
+
const closestPointsSegmentToSegment = function() {
|
|
38135
|
+
const paramResult = new Vector2();
|
|
38136
|
+
const temp12 = new Vector3();
|
|
38137
|
+
const temp22 = new Vector3();
|
|
38138
|
+
return function closestPointsSegmentToSegment2(l1, l2, target1, target2) {
|
|
38139
|
+
closestPointLineToLine(l1, l2, paramResult);
|
|
38140
|
+
let d = paramResult.x;
|
|
38141
|
+
let d2 = paramResult.y;
|
|
38142
|
+
if (d >= 0 && d <= 1 && d2 >= 0 && d2 <= 1) {
|
|
38143
|
+
l1.at(d, target1);
|
|
38144
|
+
l2.at(d2, target2);
|
|
38145
|
+
return;
|
|
38146
|
+
} else if (d >= 0 && d <= 1) {
|
|
38147
|
+
if (d2 < 0) {
|
|
38148
|
+
l2.at(0, target2);
|
|
38149
|
+
} else {
|
|
38150
|
+
l2.at(1, target2);
|
|
38151
|
+
}
|
|
38152
|
+
l1.closestPointToPoint(target2, true, target1);
|
|
38153
|
+
return;
|
|
38154
|
+
} else if (d2 >= 0 && d2 <= 1) {
|
|
38155
|
+
if (d < 0) {
|
|
38156
|
+
l1.at(0, target1);
|
|
38157
|
+
} else {
|
|
38158
|
+
l1.at(1, target1);
|
|
38159
|
+
}
|
|
38160
|
+
l2.closestPointToPoint(target1, true, target2);
|
|
38161
|
+
return;
|
|
38162
|
+
} else {
|
|
38163
|
+
let p2;
|
|
38164
|
+
if (d < 0) {
|
|
38165
|
+
p2 = l1.start;
|
|
38166
|
+
} else {
|
|
38167
|
+
p2 = l1.end;
|
|
38168
|
+
}
|
|
38169
|
+
let p22;
|
|
38170
|
+
if (d2 < 0) {
|
|
38171
|
+
p22 = l2.start;
|
|
38172
|
+
} else {
|
|
38173
|
+
p22 = l2.end;
|
|
38174
|
+
}
|
|
38175
|
+
const closestPoint = temp12;
|
|
38176
|
+
const closestPoint2 = temp22;
|
|
38177
|
+
l1.closestPointToPoint(p22, true, temp12);
|
|
38178
|
+
l2.closestPointToPoint(p2, true, temp22);
|
|
38179
|
+
if (closestPoint.distanceToSquared(p22) <= closestPoint2.distanceToSquared(p2)) {
|
|
38180
|
+
target1.copy(closestPoint);
|
|
38181
|
+
target2.copy(p22);
|
|
38182
|
+
return;
|
|
38183
|
+
} else {
|
|
38184
|
+
target1.copy(p2);
|
|
38185
|
+
target2.copy(closestPoint2);
|
|
38186
|
+
return;
|
|
38187
|
+
}
|
|
38188
|
+
}
|
|
38189
|
+
};
|
|
38190
|
+
}();
|
|
38191
|
+
const sphereIntersectTriangle = function() {
|
|
38192
|
+
const closestPointTemp = new Vector3();
|
|
38193
|
+
const projectedPointTemp = new Vector3();
|
|
38194
|
+
const planeTemp = new Plane();
|
|
38195
|
+
const lineTemp = new Line3();
|
|
38196
|
+
return function sphereIntersectTriangle2(sphere, triangle3) {
|
|
38197
|
+
const { radius, center } = sphere;
|
|
38198
|
+
const { a, b, c: c2 } = triangle3;
|
|
38199
|
+
lineTemp.start = a;
|
|
38200
|
+
lineTemp.end = b;
|
|
38201
|
+
const closestPoint1 = lineTemp.closestPointToPoint(center, true, closestPointTemp);
|
|
38202
|
+
if (closestPoint1.distanceTo(center) <= radius)
|
|
38203
|
+
return true;
|
|
38204
|
+
lineTemp.start = a;
|
|
38205
|
+
lineTemp.end = c2;
|
|
38206
|
+
const closestPoint2 = lineTemp.closestPointToPoint(center, true, closestPointTemp);
|
|
38207
|
+
if (closestPoint2.distanceTo(center) <= radius)
|
|
38208
|
+
return true;
|
|
38209
|
+
lineTemp.start = b;
|
|
38210
|
+
lineTemp.end = c2;
|
|
38211
|
+
const closestPoint3 = lineTemp.closestPointToPoint(center, true, closestPointTemp);
|
|
38212
|
+
if (closestPoint3.distanceTo(center) <= radius)
|
|
38213
|
+
return true;
|
|
38214
|
+
const plane = triangle3.getPlane(planeTemp);
|
|
38215
|
+
const dp = Math.abs(plane.distanceToPoint(center));
|
|
38216
|
+
if (dp <= radius) {
|
|
38217
|
+
const pp = plane.projectPoint(center, projectedPointTemp);
|
|
38218
|
+
const cp = triangle3.containsPoint(pp);
|
|
38219
|
+
if (cp)
|
|
38220
|
+
return true;
|
|
38221
|
+
}
|
|
38222
|
+
return false;
|
|
38223
|
+
};
|
|
38224
|
+
}();
|
|
38225
|
+
const ZERO_EPSILON = 1e-15;
|
|
38226
|
+
function isNearZero(value) {
|
|
38227
|
+
return Math.abs(value) < ZERO_EPSILON;
|
|
38228
|
+
}
|
|
38229
|
+
class ExtendedTriangle extends Triangle {
|
|
38230
|
+
constructor(...args) {
|
|
38231
|
+
super(...args);
|
|
38232
|
+
this.isExtendedTriangle = true;
|
|
38233
|
+
this.satAxes = new Array(4).fill().map(() => new Vector3());
|
|
38234
|
+
this.satBounds = new Array(4).fill().map(() => new SeparatingAxisBounds());
|
|
38235
|
+
this.points = [this.a, this.b, this.c];
|
|
38236
|
+
this.sphere = new Sphere();
|
|
38237
|
+
this.plane = new Plane();
|
|
38238
|
+
this.needsUpdate = true;
|
|
38239
|
+
}
|
|
38240
|
+
intersectsSphere(sphere) {
|
|
38241
|
+
return sphereIntersectTriangle(sphere, this);
|
|
38242
|
+
}
|
|
38243
|
+
update() {
|
|
38244
|
+
const a = this.a;
|
|
38245
|
+
const b = this.b;
|
|
38246
|
+
const c2 = this.c;
|
|
38247
|
+
const points = this.points;
|
|
38248
|
+
const satAxes = this.satAxes;
|
|
38249
|
+
const satBounds = this.satBounds;
|
|
38250
|
+
const axis0 = satAxes[0];
|
|
38251
|
+
const sab0 = satBounds[0];
|
|
38252
|
+
this.getNormal(axis0);
|
|
38253
|
+
sab0.setFromPoints(axis0, points);
|
|
38254
|
+
const axis1 = satAxes[1];
|
|
38255
|
+
const sab1 = satBounds[1];
|
|
38256
|
+
axis1.subVectors(a, b);
|
|
38257
|
+
sab1.setFromPoints(axis1, points);
|
|
38258
|
+
const axis2 = satAxes[2];
|
|
38259
|
+
const sab2 = satBounds[2];
|
|
38260
|
+
axis2.subVectors(b, c2);
|
|
38261
|
+
sab2.setFromPoints(axis2, points);
|
|
38262
|
+
const axis3 = satAxes[3];
|
|
38263
|
+
const sab3 = satBounds[3];
|
|
38264
|
+
axis3.subVectors(c2, a);
|
|
38265
|
+
sab3.setFromPoints(axis3, points);
|
|
38266
|
+
this.sphere.setFromPoints(this.points);
|
|
38267
|
+
this.plane.setFromNormalAndCoplanarPoint(axis0, a);
|
|
38268
|
+
this.needsUpdate = false;
|
|
38269
|
+
}
|
|
38270
|
+
}
|
|
38271
|
+
ExtendedTriangle.prototype.closestPointToSegment = function() {
|
|
38272
|
+
const point1 = new Vector3();
|
|
38273
|
+
const point2 = new Vector3();
|
|
38274
|
+
const edge = new Line3();
|
|
38275
|
+
return function distanceToSegment(segment, target1 = null, target2 = null) {
|
|
38276
|
+
const { start, end } = segment;
|
|
38277
|
+
const points = this.points;
|
|
38278
|
+
let distSq;
|
|
38279
|
+
let closestDistanceSq = Infinity;
|
|
38280
|
+
for (let i = 0; i < 3; i++) {
|
|
38281
|
+
const nexti = (i + 1) % 3;
|
|
38282
|
+
edge.start.copy(points[i]);
|
|
38283
|
+
edge.end.copy(points[nexti]);
|
|
38284
|
+
closestPointsSegmentToSegment(edge, segment, point1, point2);
|
|
38285
|
+
distSq = point1.distanceToSquared(point2);
|
|
38286
|
+
if (distSq < closestDistanceSq) {
|
|
38287
|
+
closestDistanceSq = distSq;
|
|
38288
|
+
if (target1)
|
|
38289
|
+
target1.copy(point1);
|
|
38290
|
+
if (target2)
|
|
38291
|
+
target2.copy(point2);
|
|
38292
|
+
}
|
|
38293
|
+
}
|
|
38294
|
+
this.closestPointToPoint(start, point1);
|
|
38295
|
+
distSq = start.distanceToSquared(point1);
|
|
38296
|
+
if (distSq < closestDistanceSq) {
|
|
38297
|
+
closestDistanceSq = distSq;
|
|
38298
|
+
if (target1)
|
|
38299
|
+
target1.copy(point1);
|
|
38300
|
+
if (target2)
|
|
38301
|
+
target2.copy(start);
|
|
38302
|
+
}
|
|
38303
|
+
this.closestPointToPoint(end, point1);
|
|
38304
|
+
distSq = end.distanceToSquared(point1);
|
|
38305
|
+
if (distSq < closestDistanceSq) {
|
|
38306
|
+
closestDistanceSq = distSq;
|
|
38307
|
+
if (target1)
|
|
38308
|
+
target1.copy(point1);
|
|
38309
|
+
if (target2)
|
|
38310
|
+
target2.copy(end);
|
|
38311
|
+
}
|
|
38312
|
+
return Math.sqrt(closestDistanceSq);
|
|
38313
|
+
};
|
|
38314
|
+
}();
|
|
38315
|
+
ExtendedTriangle.prototype.intersectsTriangle = function() {
|
|
38316
|
+
const saTri2 = new ExtendedTriangle();
|
|
38317
|
+
const arr1 = new Array(3);
|
|
38318
|
+
const arr2 = new Array(3);
|
|
38319
|
+
const cachedSatBounds = new SeparatingAxisBounds();
|
|
38320
|
+
const cachedSatBounds2 = new SeparatingAxisBounds();
|
|
38321
|
+
const cachedAxis = new Vector3();
|
|
38322
|
+
const dir = new Vector3();
|
|
38323
|
+
const dir1 = new Vector3();
|
|
38324
|
+
const dir2 = new Vector3();
|
|
38325
|
+
const tempDir = new Vector3();
|
|
38326
|
+
const edge = new Line3();
|
|
38327
|
+
const edge1 = new Line3();
|
|
38328
|
+
const edge2 = new Line3();
|
|
38329
|
+
const tempPoint = new Vector3();
|
|
38330
|
+
function triIntersectPlane(tri, plane, targetEdge) {
|
|
38331
|
+
const points = tri.points;
|
|
38332
|
+
let count = 0;
|
|
38333
|
+
let startPointIntersection = -1;
|
|
38334
|
+
for (let i = 0; i < 3; i++) {
|
|
38335
|
+
const { start, end } = edge;
|
|
38336
|
+
start.copy(points[i]);
|
|
38337
|
+
end.copy(points[(i + 1) % 3]);
|
|
38338
|
+
edge.delta(dir);
|
|
38339
|
+
const startIntersects = isNearZero(plane.distanceToPoint(start));
|
|
38340
|
+
if (isNearZero(plane.normal.dot(dir)) && startIntersects) {
|
|
38341
|
+
targetEdge.copy(edge);
|
|
38342
|
+
count = 2;
|
|
38343
|
+
break;
|
|
38344
|
+
}
|
|
38345
|
+
const doesIntersect = plane.intersectLine(edge, tempPoint);
|
|
38346
|
+
if (!doesIntersect && startIntersects) {
|
|
38347
|
+
tempPoint.copy(start);
|
|
38348
|
+
}
|
|
38349
|
+
if ((doesIntersect || startIntersects) && !isNearZero(tempPoint.distanceTo(end))) {
|
|
38350
|
+
if (count <= 1) {
|
|
38351
|
+
const point = count === 1 ? targetEdge.start : targetEdge.end;
|
|
38352
|
+
point.copy(tempPoint);
|
|
38353
|
+
if (startIntersects) {
|
|
38354
|
+
startPointIntersection = count;
|
|
38355
|
+
}
|
|
38356
|
+
} else if (count >= 2) {
|
|
38357
|
+
const point = startPointIntersection === 1 ? targetEdge.start : targetEdge.end;
|
|
38358
|
+
point.copy(tempPoint);
|
|
38359
|
+
count = 2;
|
|
38360
|
+
break;
|
|
38361
|
+
}
|
|
38362
|
+
count++;
|
|
38363
|
+
if (count === 2 && startPointIntersection === -1) {
|
|
38364
|
+
break;
|
|
38365
|
+
}
|
|
38366
|
+
}
|
|
38367
|
+
}
|
|
38368
|
+
return count;
|
|
38369
|
+
}
|
|
38370
|
+
return function intersectsTriangle(other, target = null, suppressLog = false) {
|
|
38371
|
+
if (this.needsUpdate) {
|
|
38372
|
+
this.update();
|
|
38373
|
+
}
|
|
38374
|
+
if (!other.isExtendedTriangle) {
|
|
38375
|
+
saTri2.copy(other);
|
|
38376
|
+
saTri2.update();
|
|
38377
|
+
other = saTri2;
|
|
38378
|
+
} else if (other.needsUpdate) {
|
|
38379
|
+
other.update();
|
|
38380
|
+
}
|
|
38381
|
+
const plane1 = this.plane;
|
|
38382
|
+
const plane2 = other.plane;
|
|
38383
|
+
if (Math.abs(plane1.normal.dot(plane2.normal)) > 1 - 1e-10) {
|
|
38384
|
+
const satBounds1 = this.satBounds;
|
|
38385
|
+
const satAxes1 = this.satAxes;
|
|
38386
|
+
arr2[0] = other.a;
|
|
38387
|
+
arr2[1] = other.b;
|
|
38388
|
+
arr2[2] = other.c;
|
|
38389
|
+
for (let i = 0; i < 4; i++) {
|
|
38390
|
+
const sb = satBounds1[i];
|
|
38391
|
+
const sa = satAxes1[i];
|
|
38392
|
+
cachedSatBounds.setFromPoints(sa, arr2);
|
|
38393
|
+
if (sb.isSeparated(cachedSatBounds))
|
|
38394
|
+
return false;
|
|
38395
|
+
}
|
|
38396
|
+
const satBounds2 = other.satBounds;
|
|
38397
|
+
const satAxes2 = other.satAxes;
|
|
38398
|
+
arr1[0] = this.a;
|
|
38399
|
+
arr1[1] = this.b;
|
|
38400
|
+
arr1[2] = this.c;
|
|
38401
|
+
for (let i = 0; i < 4; i++) {
|
|
38402
|
+
const sb = satBounds2[i];
|
|
38403
|
+
const sa = satAxes2[i];
|
|
38404
|
+
cachedSatBounds.setFromPoints(sa, arr1);
|
|
38405
|
+
if (sb.isSeparated(cachedSatBounds))
|
|
38406
|
+
return false;
|
|
38407
|
+
}
|
|
38408
|
+
for (let i = 0; i < 4; i++) {
|
|
38409
|
+
const sa1 = satAxes1[i];
|
|
38410
|
+
for (let i2 = 0; i2 < 4; i2++) {
|
|
38411
|
+
const sa2 = satAxes2[i2];
|
|
38412
|
+
cachedAxis.crossVectors(sa1, sa2);
|
|
38413
|
+
cachedSatBounds.setFromPoints(cachedAxis, arr1);
|
|
38414
|
+
cachedSatBounds2.setFromPoints(cachedAxis, arr2);
|
|
38415
|
+
if (cachedSatBounds.isSeparated(cachedSatBounds2))
|
|
38416
|
+
return false;
|
|
38417
|
+
}
|
|
38418
|
+
}
|
|
38419
|
+
if (target) {
|
|
38420
|
+
if (!suppressLog) {
|
|
38421
|
+
console.warn("ExtendedTriangle.intersectsTriangle: Triangles are coplanar which does not support an output edge. Setting edge to 0, 0, 0.");
|
|
38422
|
+
}
|
|
38423
|
+
target.start.set(0, 0, 0);
|
|
38424
|
+
target.end.set(0, 0, 0);
|
|
38425
|
+
}
|
|
38426
|
+
return true;
|
|
38427
|
+
} else {
|
|
38428
|
+
const count1 = triIntersectPlane(this, plane2, edge1);
|
|
38429
|
+
if (count1 === 1 && other.containsPoint(edge1.end)) {
|
|
38430
|
+
if (target) {
|
|
38431
|
+
target.start.copy(edge1.end);
|
|
38432
|
+
target.end.copy(edge1.end);
|
|
38433
|
+
}
|
|
38434
|
+
return true;
|
|
38435
|
+
} else if (count1 !== 2) {
|
|
38436
|
+
return false;
|
|
38437
|
+
}
|
|
38438
|
+
const count2 = triIntersectPlane(other, plane1, edge2);
|
|
38439
|
+
if (count2 === 1 && this.containsPoint(edge2.end)) {
|
|
38440
|
+
if (target) {
|
|
38441
|
+
target.start.copy(edge2.end);
|
|
38442
|
+
target.end.copy(edge2.end);
|
|
38443
|
+
}
|
|
38444
|
+
return true;
|
|
38445
|
+
} else if (count2 !== 2) {
|
|
38446
|
+
return false;
|
|
38447
|
+
}
|
|
38448
|
+
edge1.delta(dir1);
|
|
38449
|
+
edge2.delta(dir2);
|
|
38450
|
+
if (dir1.dot(dir2) < 0) {
|
|
38451
|
+
let tmp = edge2.start;
|
|
38452
|
+
edge2.start = edge2.end;
|
|
38453
|
+
edge2.end = tmp;
|
|
38454
|
+
}
|
|
38455
|
+
const s1 = edge1.start.dot(dir1);
|
|
38456
|
+
const e1 = edge1.end.dot(dir1);
|
|
38457
|
+
const s2 = edge2.start.dot(dir1);
|
|
38458
|
+
const e2 = edge2.end.dot(dir1);
|
|
38459
|
+
const separated1 = e1 < s2;
|
|
38460
|
+
const separated2 = s1 < e2;
|
|
38461
|
+
if (s1 !== e2 && s2 !== e1 && separated1 === separated2) {
|
|
38462
|
+
return false;
|
|
38463
|
+
}
|
|
38464
|
+
if (target) {
|
|
38465
|
+
tempDir.subVectors(edge1.start, edge2.start);
|
|
38466
|
+
if (tempDir.dot(dir1) > 0) {
|
|
38467
|
+
target.start.copy(edge1.start);
|
|
38468
|
+
} else {
|
|
38469
|
+
target.start.copy(edge2.start);
|
|
38470
|
+
}
|
|
38471
|
+
tempDir.subVectors(edge1.end, edge2.end);
|
|
38472
|
+
if (tempDir.dot(dir1) < 0) {
|
|
38473
|
+
target.end.copy(edge1.end);
|
|
38474
|
+
} else {
|
|
38475
|
+
target.end.copy(edge2.end);
|
|
38476
|
+
}
|
|
38477
|
+
}
|
|
38478
|
+
return true;
|
|
38479
|
+
}
|
|
38480
|
+
};
|
|
38481
|
+
}();
|
|
38482
|
+
ExtendedTriangle.prototype.distanceToPoint = function() {
|
|
38483
|
+
const target = new Vector3();
|
|
38484
|
+
return function distanceToPoint(point) {
|
|
38485
|
+
this.closestPointToPoint(point, target);
|
|
38486
|
+
return point.distanceTo(target);
|
|
38487
|
+
};
|
|
38488
|
+
}();
|
|
38489
|
+
ExtendedTriangle.prototype.distanceToTriangle = function() {
|
|
38490
|
+
const point = new Vector3();
|
|
38491
|
+
const point2 = new Vector3();
|
|
38492
|
+
const cornerFields = ["a", "b", "c"];
|
|
38493
|
+
const line1 = new Line3();
|
|
38494
|
+
const line2 = new Line3();
|
|
38495
|
+
return function distanceToTriangle(other, target1 = null, target2 = null) {
|
|
38496
|
+
const lineTarget = target1 || target2 ? line1 : null;
|
|
38497
|
+
if (this.intersectsTriangle(other, lineTarget)) {
|
|
38498
|
+
if (target1 || target2) {
|
|
38499
|
+
if (target1)
|
|
38500
|
+
lineTarget.getCenter(target1);
|
|
38501
|
+
if (target2)
|
|
38502
|
+
lineTarget.getCenter(target2);
|
|
38503
|
+
}
|
|
38504
|
+
return 0;
|
|
38505
|
+
}
|
|
38506
|
+
let closestDistanceSq = Infinity;
|
|
38507
|
+
for (let i = 0; i < 3; i++) {
|
|
38508
|
+
let dist;
|
|
38509
|
+
const field = cornerFields[i];
|
|
38510
|
+
const otherVec = other[field];
|
|
38511
|
+
this.closestPointToPoint(otherVec, point);
|
|
38512
|
+
dist = otherVec.distanceToSquared(point);
|
|
38513
|
+
if (dist < closestDistanceSq) {
|
|
38514
|
+
closestDistanceSq = dist;
|
|
38515
|
+
if (target1)
|
|
38516
|
+
target1.copy(point);
|
|
38517
|
+
if (target2)
|
|
38518
|
+
target2.copy(otherVec);
|
|
38519
|
+
}
|
|
38520
|
+
const thisVec = this[field];
|
|
38521
|
+
other.closestPointToPoint(thisVec, point);
|
|
38522
|
+
dist = thisVec.distanceToSquared(point);
|
|
38523
|
+
if (dist < closestDistanceSq) {
|
|
38524
|
+
closestDistanceSq = dist;
|
|
38525
|
+
if (target1)
|
|
38526
|
+
target1.copy(thisVec);
|
|
38527
|
+
if (target2)
|
|
38528
|
+
target2.copy(point);
|
|
38529
|
+
}
|
|
38530
|
+
}
|
|
38531
|
+
for (let i = 0; i < 3; i++) {
|
|
38532
|
+
const f11 = cornerFields[i];
|
|
38533
|
+
const f12 = cornerFields[(i + 1) % 3];
|
|
38534
|
+
line1.set(this[f11], this[f12]);
|
|
38535
|
+
for (let i2 = 0; i2 < 3; i2++) {
|
|
38536
|
+
const f21 = cornerFields[i2];
|
|
38537
|
+
const f22 = cornerFields[(i2 + 1) % 3];
|
|
38538
|
+
line2.set(other[f21], other[f22]);
|
|
38539
|
+
closestPointsSegmentToSegment(line1, line2, point, point2);
|
|
38540
|
+
const dist = point.distanceToSquared(point2);
|
|
38541
|
+
if (dist < closestDistanceSq) {
|
|
38542
|
+
closestDistanceSq = dist;
|
|
38543
|
+
if (target1)
|
|
38544
|
+
target1.copy(point);
|
|
38545
|
+
if (target2)
|
|
38546
|
+
target2.copy(point2);
|
|
38547
|
+
}
|
|
38548
|
+
}
|
|
38549
|
+
}
|
|
38550
|
+
return Math.sqrt(closestDistanceSq);
|
|
38551
|
+
};
|
|
38552
|
+
}();
|
|
38553
|
+
class OrientedBox {
|
|
38554
|
+
constructor(min, max, matrix) {
|
|
38555
|
+
this.isOrientedBox = true;
|
|
38556
|
+
this.min = new Vector3();
|
|
38557
|
+
this.max = new Vector3();
|
|
38558
|
+
this.matrix = new Matrix4();
|
|
38559
|
+
this.invMatrix = new Matrix4();
|
|
38560
|
+
this.points = new Array(8).fill().map(() => new Vector3());
|
|
38561
|
+
this.satAxes = new Array(3).fill().map(() => new Vector3());
|
|
38562
|
+
this.satBounds = new Array(3).fill().map(() => new SeparatingAxisBounds());
|
|
38563
|
+
this.alignedSatBounds = new Array(3).fill().map(() => new SeparatingAxisBounds());
|
|
38564
|
+
this.needsUpdate = false;
|
|
38565
|
+
if (min)
|
|
38566
|
+
this.min.copy(min);
|
|
38567
|
+
if (max)
|
|
38568
|
+
this.max.copy(max);
|
|
38569
|
+
if (matrix)
|
|
38570
|
+
this.matrix.copy(matrix);
|
|
38571
|
+
}
|
|
38572
|
+
set(min, max, matrix) {
|
|
38573
|
+
this.min.copy(min);
|
|
38574
|
+
this.max.copy(max);
|
|
38575
|
+
this.matrix.copy(matrix);
|
|
38576
|
+
this.needsUpdate = true;
|
|
38577
|
+
}
|
|
38578
|
+
copy(other) {
|
|
38579
|
+
this.min.copy(other.min);
|
|
38580
|
+
this.max.copy(other.max);
|
|
38581
|
+
this.matrix.copy(other.matrix);
|
|
38582
|
+
this.needsUpdate = true;
|
|
38583
|
+
}
|
|
38584
|
+
}
|
|
38585
|
+
OrientedBox.prototype.update = function() {
|
|
38586
|
+
return function update() {
|
|
38587
|
+
const matrix = this.matrix;
|
|
38588
|
+
const min = this.min;
|
|
38589
|
+
const max = this.max;
|
|
38590
|
+
const points = this.points;
|
|
38591
|
+
for (let x2 = 0; x2 <= 1; x2++) {
|
|
38592
|
+
for (let y = 0; y <= 1; y++) {
|
|
38593
|
+
for (let z = 0; z <= 1; z++) {
|
|
38594
|
+
const i = (1 << 0) * x2 | (1 << 1) * y | (1 << 2) * z;
|
|
38595
|
+
const v = points[i];
|
|
38596
|
+
v.x = x2 ? max.x : min.x;
|
|
38597
|
+
v.y = y ? max.y : min.y;
|
|
38598
|
+
v.z = z ? max.z : min.z;
|
|
38599
|
+
v.applyMatrix4(matrix);
|
|
38600
|
+
}
|
|
38601
|
+
}
|
|
38602
|
+
}
|
|
38603
|
+
const satBounds = this.satBounds;
|
|
38604
|
+
const satAxes = this.satAxes;
|
|
38605
|
+
const minVec = points[0];
|
|
38606
|
+
for (let i = 0; i < 3; i++) {
|
|
38607
|
+
const axis = satAxes[i];
|
|
38608
|
+
const sb = satBounds[i];
|
|
38609
|
+
const index = 1 << i;
|
|
38610
|
+
const pi = points[index];
|
|
38611
|
+
axis.subVectors(minVec, pi);
|
|
38612
|
+
sb.setFromPoints(axis, points);
|
|
38613
|
+
}
|
|
38614
|
+
const alignedSatBounds = this.alignedSatBounds;
|
|
38615
|
+
alignedSatBounds[0].setFromPointsField(points, "x");
|
|
38616
|
+
alignedSatBounds[1].setFromPointsField(points, "y");
|
|
38617
|
+
alignedSatBounds[2].setFromPointsField(points, "z");
|
|
38618
|
+
this.invMatrix.copy(this.matrix).invert();
|
|
38619
|
+
this.needsUpdate = false;
|
|
38620
|
+
};
|
|
38621
|
+
}();
|
|
38622
|
+
OrientedBox.prototype.intersectsBox = function() {
|
|
38623
|
+
const aabbBounds = new SeparatingAxisBounds();
|
|
38624
|
+
return function intersectsBox(box) {
|
|
38625
|
+
if (this.needsUpdate) {
|
|
38626
|
+
this.update();
|
|
38627
|
+
}
|
|
38628
|
+
const min = box.min;
|
|
38629
|
+
const max = box.max;
|
|
38630
|
+
const satBounds = this.satBounds;
|
|
38631
|
+
const satAxes = this.satAxes;
|
|
38632
|
+
const alignedSatBounds = this.alignedSatBounds;
|
|
38633
|
+
aabbBounds.min = min.x;
|
|
38634
|
+
aabbBounds.max = max.x;
|
|
38635
|
+
if (alignedSatBounds[0].isSeparated(aabbBounds))
|
|
38636
|
+
return false;
|
|
38637
|
+
aabbBounds.min = min.y;
|
|
38638
|
+
aabbBounds.max = max.y;
|
|
38639
|
+
if (alignedSatBounds[1].isSeparated(aabbBounds))
|
|
38640
|
+
return false;
|
|
38641
|
+
aabbBounds.min = min.z;
|
|
38642
|
+
aabbBounds.max = max.z;
|
|
38643
|
+
if (alignedSatBounds[2].isSeparated(aabbBounds))
|
|
38644
|
+
return false;
|
|
38645
|
+
for (let i = 0; i < 3; i++) {
|
|
38646
|
+
const axis = satAxes[i];
|
|
38647
|
+
const sb = satBounds[i];
|
|
38648
|
+
aabbBounds.setFromBox(axis, box);
|
|
38649
|
+
if (sb.isSeparated(aabbBounds))
|
|
38650
|
+
return false;
|
|
38651
|
+
}
|
|
38652
|
+
return true;
|
|
38653
|
+
};
|
|
38654
|
+
}();
|
|
38655
|
+
OrientedBox.prototype.intersectsTriangle = function() {
|
|
38656
|
+
const saTri = new ExtendedTriangle();
|
|
38657
|
+
const pointsArr = new Array(3);
|
|
38658
|
+
const cachedSatBounds = new SeparatingAxisBounds();
|
|
38659
|
+
const cachedSatBounds2 = new SeparatingAxisBounds();
|
|
38660
|
+
const cachedAxis = new Vector3();
|
|
38661
|
+
return function intersectsTriangle(triangle3) {
|
|
38662
|
+
if (this.needsUpdate) {
|
|
38663
|
+
this.update();
|
|
38664
|
+
}
|
|
38665
|
+
if (!triangle3.isExtendedTriangle) {
|
|
38666
|
+
saTri.copy(triangle3);
|
|
38667
|
+
saTri.update();
|
|
38668
|
+
triangle3 = saTri;
|
|
38669
|
+
} else if (triangle3.needsUpdate) {
|
|
38670
|
+
triangle3.update();
|
|
38671
|
+
}
|
|
38672
|
+
const satBounds = this.satBounds;
|
|
38673
|
+
const satAxes = this.satAxes;
|
|
38674
|
+
pointsArr[0] = triangle3.a;
|
|
38675
|
+
pointsArr[1] = triangle3.b;
|
|
38676
|
+
pointsArr[2] = triangle3.c;
|
|
38677
|
+
for (let i = 0; i < 3; i++) {
|
|
38678
|
+
const sb = satBounds[i];
|
|
38679
|
+
const sa = satAxes[i];
|
|
38680
|
+
cachedSatBounds.setFromPoints(sa, pointsArr);
|
|
38681
|
+
if (sb.isSeparated(cachedSatBounds))
|
|
38682
|
+
return false;
|
|
38683
|
+
}
|
|
38684
|
+
const triSatBounds = triangle3.satBounds;
|
|
38685
|
+
const triSatAxes = triangle3.satAxes;
|
|
38686
|
+
const points = this.points;
|
|
38687
|
+
for (let i = 0; i < 3; i++) {
|
|
38688
|
+
const sb = triSatBounds[i];
|
|
38689
|
+
const sa = triSatAxes[i];
|
|
38690
|
+
cachedSatBounds.setFromPoints(sa, points);
|
|
38691
|
+
if (sb.isSeparated(cachedSatBounds))
|
|
38692
|
+
return false;
|
|
38693
|
+
}
|
|
38694
|
+
for (let i = 0; i < 3; i++) {
|
|
38695
|
+
const sa1 = satAxes[i];
|
|
38696
|
+
for (let i2 = 0; i2 < 4; i2++) {
|
|
38697
|
+
const sa2 = triSatAxes[i2];
|
|
38698
|
+
cachedAxis.crossVectors(sa1, sa2);
|
|
38699
|
+
cachedSatBounds.setFromPoints(cachedAxis, pointsArr);
|
|
38700
|
+
cachedSatBounds2.setFromPoints(cachedAxis, points);
|
|
38701
|
+
if (cachedSatBounds.isSeparated(cachedSatBounds2))
|
|
38702
|
+
return false;
|
|
38703
|
+
}
|
|
38704
|
+
}
|
|
38705
|
+
return true;
|
|
38706
|
+
};
|
|
38707
|
+
}();
|
|
38708
|
+
OrientedBox.prototype.closestPointToPoint = function() {
|
|
38709
|
+
return function closestPointToPoint2(point, target1) {
|
|
38710
|
+
if (this.needsUpdate) {
|
|
38711
|
+
this.update();
|
|
38712
|
+
}
|
|
38713
|
+
target1.copy(point).applyMatrix4(this.invMatrix).clamp(this.min, this.max).applyMatrix4(this.matrix);
|
|
38714
|
+
return target1;
|
|
38715
|
+
};
|
|
38716
|
+
}();
|
|
38717
|
+
OrientedBox.prototype.distanceToPoint = function() {
|
|
38718
|
+
const target = new Vector3();
|
|
38719
|
+
return function distanceToPoint(point) {
|
|
38720
|
+
this.closestPointToPoint(point, target);
|
|
38721
|
+
return point.distanceTo(target);
|
|
38722
|
+
};
|
|
38723
|
+
}();
|
|
38724
|
+
OrientedBox.prototype.distanceToBox = function() {
|
|
38725
|
+
const xyzFields = ["x", "y", "z"];
|
|
38726
|
+
const segments1 = new Array(12).fill().map(() => new Line3());
|
|
38727
|
+
const segments2 = new Array(12).fill().map(() => new Line3());
|
|
38728
|
+
const point1 = new Vector3();
|
|
38729
|
+
const point2 = new Vector3();
|
|
38730
|
+
return function distanceToBox(box, threshold = 0, target1 = null, target2 = null) {
|
|
38731
|
+
if (this.needsUpdate) {
|
|
38732
|
+
this.update();
|
|
38733
|
+
}
|
|
38734
|
+
if (this.intersectsBox(box)) {
|
|
38735
|
+
if (target1 || target2) {
|
|
38736
|
+
box.getCenter(point2);
|
|
38737
|
+
this.closestPointToPoint(point2, point1);
|
|
38738
|
+
box.closestPointToPoint(point1, point2);
|
|
38739
|
+
if (target1)
|
|
38740
|
+
target1.copy(point1);
|
|
38741
|
+
if (target2)
|
|
38742
|
+
target2.copy(point2);
|
|
38743
|
+
}
|
|
38744
|
+
return 0;
|
|
38745
|
+
}
|
|
38746
|
+
const threshold2 = threshold * threshold;
|
|
38747
|
+
const min = box.min;
|
|
38748
|
+
const max = box.max;
|
|
38749
|
+
const points = this.points;
|
|
38750
|
+
let closestDistanceSq = Infinity;
|
|
38751
|
+
for (let i = 0; i < 8; i++) {
|
|
38752
|
+
const p2 = points[i];
|
|
38753
|
+
point2.copy(p2).clamp(min, max);
|
|
38754
|
+
const dist = p2.distanceToSquared(point2);
|
|
38755
|
+
if (dist < closestDistanceSq) {
|
|
38756
|
+
closestDistanceSq = dist;
|
|
38757
|
+
if (target1)
|
|
38758
|
+
target1.copy(p2);
|
|
38759
|
+
if (target2)
|
|
38760
|
+
target2.copy(point2);
|
|
38761
|
+
if (dist < threshold2)
|
|
38762
|
+
return Math.sqrt(dist);
|
|
38763
|
+
}
|
|
38764
|
+
}
|
|
38765
|
+
let count = 0;
|
|
38766
|
+
for (let i = 0; i < 3; i++) {
|
|
38767
|
+
for (let i1 = 0; i1 <= 1; i1++) {
|
|
38768
|
+
for (let i2 = 0; i2 <= 1; i2++) {
|
|
38769
|
+
const nextIndex = (i + 1) % 3;
|
|
38770
|
+
const nextIndex2 = (i + 2) % 3;
|
|
38771
|
+
const index = i1 << nextIndex | i2 << nextIndex2;
|
|
38772
|
+
const index2 = 1 << i | i1 << nextIndex | i2 << nextIndex2;
|
|
38773
|
+
const p1 = points[index];
|
|
38774
|
+
const p2 = points[index2];
|
|
38775
|
+
const line1 = segments1[count];
|
|
38776
|
+
line1.set(p1, p2);
|
|
38777
|
+
const f1 = xyzFields[i];
|
|
38778
|
+
const f2 = xyzFields[nextIndex];
|
|
38779
|
+
const f3 = xyzFields[nextIndex2];
|
|
38780
|
+
const line2 = segments2[count];
|
|
38781
|
+
const start = line2.start;
|
|
38782
|
+
const end = line2.end;
|
|
38783
|
+
start[f1] = min[f1];
|
|
38784
|
+
start[f2] = i1 ? min[f2] : max[f2];
|
|
38785
|
+
start[f3] = i2 ? min[f3] : max[f2];
|
|
38786
|
+
end[f1] = max[f1];
|
|
38787
|
+
end[f2] = i1 ? min[f2] : max[f2];
|
|
38788
|
+
end[f3] = i2 ? min[f3] : max[f2];
|
|
38789
|
+
count++;
|
|
38790
|
+
}
|
|
38791
|
+
}
|
|
38792
|
+
}
|
|
38793
|
+
for (let x2 = 0; x2 <= 1; x2++) {
|
|
38794
|
+
for (let y = 0; y <= 1; y++) {
|
|
38795
|
+
for (let z = 0; z <= 1; z++) {
|
|
38796
|
+
point2.x = x2 ? max.x : min.x;
|
|
38797
|
+
point2.y = y ? max.y : min.y;
|
|
38798
|
+
point2.z = z ? max.z : min.z;
|
|
38799
|
+
this.closestPointToPoint(point2, point1);
|
|
38800
|
+
const dist = point2.distanceToSquared(point1);
|
|
38801
|
+
if (dist < closestDistanceSq) {
|
|
38802
|
+
closestDistanceSq = dist;
|
|
38803
|
+
if (target1)
|
|
38804
|
+
target1.copy(point1);
|
|
38805
|
+
if (target2)
|
|
38806
|
+
target2.copy(point2);
|
|
38807
|
+
if (dist < threshold2)
|
|
38808
|
+
return Math.sqrt(dist);
|
|
38809
|
+
}
|
|
38810
|
+
}
|
|
38811
|
+
}
|
|
38812
|
+
}
|
|
38813
|
+
for (let i = 0; i < 12; i++) {
|
|
38814
|
+
const l1 = segments1[i];
|
|
38815
|
+
for (let i2 = 0; i2 < 12; i2++) {
|
|
38816
|
+
const l2 = segments2[i2];
|
|
38817
|
+
closestPointsSegmentToSegment(l1, l2, point1, point2);
|
|
38818
|
+
const dist = point1.distanceToSquared(point2);
|
|
38819
|
+
if (dist < closestDistanceSq) {
|
|
38820
|
+
closestDistanceSq = dist;
|
|
38821
|
+
if (target1)
|
|
38822
|
+
target1.copy(point1);
|
|
38823
|
+
if (target2)
|
|
38824
|
+
target2.copy(point2);
|
|
38825
|
+
if (dist < threshold2)
|
|
38826
|
+
return Math.sqrt(dist);
|
|
38827
|
+
}
|
|
38828
|
+
}
|
|
38829
|
+
}
|
|
38830
|
+
return Math.sqrt(closestDistanceSq);
|
|
38831
|
+
};
|
|
38832
|
+
}();
|
|
38833
|
+
class PrimitivePool {
|
|
38834
|
+
constructor(getNewPrimitive) {
|
|
38835
|
+
this._getNewPrimitive = getNewPrimitive;
|
|
38836
|
+
this._primitives = [];
|
|
38837
|
+
}
|
|
38838
|
+
getPrimitive() {
|
|
38839
|
+
const primitives = this._primitives;
|
|
38840
|
+
if (primitives.length === 0) {
|
|
38841
|
+
return this._getNewPrimitive();
|
|
38842
|
+
} else {
|
|
38843
|
+
return primitives.pop();
|
|
38844
|
+
}
|
|
38845
|
+
}
|
|
38846
|
+
releasePrimitive(primitive) {
|
|
38847
|
+
this._primitives.push(primitive);
|
|
38848
|
+
}
|
|
38849
|
+
}
|
|
38850
|
+
class ExtendedTrianglePoolBase extends PrimitivePool {
|
|
38851
|
+
constructor() {
|
|
38852
|
+
super(() => new ExtendedTriangle());
|
|
38853
|
+
}
|
|
38854
|
+
}
|
|
38855
|
+
const ExtendedTrianglePool = /* @__PURE__ */ new ExtendedTrianglePoolBase();
|
|
38856
|
+
function IS_LEAF(n16, uint16Array) {
|
|
38857
|
+
return uint16Array[n16 + 15] === 65535;
|
|
38858
|
+
}
|
|
38859
|
+
function OFFSET(n32, uint32Array) {
|
|
38860
|
+
return uint32Array[n32 + 6];
|
|
38861
|
+
}
|
|
38862
|
+
function COUNT(n16, uint16Array) {
|
|
38863
|
+
return uint16Array[n16 + 14];
|
|
38864
|
+
}
|
|
38865
|
+
function LEFT_NODE(n32) {
|
|
38866
|
+
return n32 + 8;
|
|
38867
|
+
}
|
|
38868
|
+
function RIGHT_NODE(n32, uint32Array) {
|
|
38869
|
+
return uint32Array[n32 + 6];
|
|
38870
|
+
}
|
|
38871
|
+
function SPLIT_AXIS(n32, uint32Array) {
|
|
38872
|
+
return uint32Array[n32 + 7];
|
|
38873
|
+
}
|
|
38874
|
+
function BOUNDING_DATA_INDEX(n32) {
|
|
38875
|
+
return n32;
|
|
38876
|
+
}
|
|
38877
|
+
class _BufferStack {
|
|
38878
|
+
constructor() {
|
|
38879
|
+
this.float32Array = null;
|
|
38880
|
+
this.uint16Array = null;
|
|
38881
|
+
this.uint32Array = null;
|
|
38882
|
+
const stack = [];
|
|
38883
|
+
let prevBuffer = null;
|
|
38884
|
+
this.setBuffer = (buffer) => {
|
|
38885
|
+
if (prevBuffer) {
|
|
38886
|
+
stack.push(prevBuffer);
|
|
38887
|
+
}
|
|
38888
|
+
prevBuffer = buffer;
|
|
38889
|
+
this.float32Array = new Float32Array(buffer);
|
|
38890
|
+
this.uint16Array = new Uint16Array(buffer);
|
|
38891
|
+
this.uint32Array = new Uint32Array(buffer);
|
|
38892
|
+
};
|
|
38893
|
+
this.clearBuffer = () => {
|
|
38894
|
+
prevBuffer = null;
|
|
38895
|
+
this.float32Array = null;
|
|
38896
|
+
this.uint16Array = null;
|
|
38897
|
+
this.uint32Array = null;
|
|
38898
|
+
if (stack.length !== 0) {
|
|
38899
|
+
this.setBuffer(stack.pop());
|
|
38900
|
+
}
|
|
38901
|
+
};
|
|
38902
|
+
}
|
|
38903
|
+
}
|
|
38904
|
+
const BufferStack = new _BufferStack();
|
|
38905
|
+
let _box1, _box2;
|
|
38906
|
+
const boxStack = [];
|
|
38907
|
+
const boxPool = /* @__PURE__ */ new PrimitivePool(() => new Box3());
|
|
38908
|
+
function shapecast(bvh, root, intersectsBounds, intersectsRange, boundsTraverseOrder, byteOffset) {
|
|
38909
|
+
_box1 = boxPool.getPrimitive();
|
|
38910
|
+
_box2 = boxPool.getPrimitive();
|
|
38911
|
+
boxStack.push(_box1, _box2);
|
|
38912
|
+
BufferStack.setBuffer(bvh._roots[root]);
|
|
38913
|
+
const result = shapecastTraverse(0, bvh.geometry, intersectsBounds, intersectsRange, boundsTraverseOrder, byteOffset);
|
|
38914
|
+
BufferStack.clearBuffer();
|
|
38915
|
+
boxPool.releasePrimitive(_box1);
|
|
38916
|
+
boxPool.releasePrimitive(_box2);
|
|
38917
|
+
boxStack.pop();
|
|
38918
|
+
boxStack.pop();
|
|
38919
|
+
const length = boxStack.length;
|
|
38920
|
+
if (length > 0) {
|
|
38921
|
+
_box2 = boxStack[length - 1];
|
|
38922
|
+
_box1 = boxStack[length - 2];
|
|
38923
|
+
}
|
|
38924
|
+
return result;
|
|
38925
|
+
}
|
|
38926
|
+
function shapecastTraverse(nodeIndex32, geometry, intersectsBoundsFunc, intersectsRangeFunc, nodeScoreFunc = null, nodeIndexByteOffset = 0, depth = 0) {
|
|
38927
|
+
const { float32Array, uint16Array, uint32Array } = BufferStack;
|
|
38928
|
+
let nodeIndex16 = nodeIndex32 * 2;
|
|
38929
|
+
const isLeaf = IS_LEAF(nodeIndex16, uint16Array);
|
|
38930
|
+
if (isLeaf) {
|
|
38931
|
+
const offset = OFFSET(nodeIndex32, uint32Array);
|
|
38932
|
+
const count = COUNT(nodeIndex16, uint16Array);
|
|
38933
|
+
arrayToBox(BOUNDING_DATA_INDEX(nodeIndex32), float32Array, _box1);
|
|
38934
|
+
return intersectsRangeFunc(offset, count, false, depth, nodeIndexByteOffset + nodeIndex32, _box1);
|
|
38935
|
+
} else {
|
|
38936
|
+
let getLeftOffset = function(nodeIndex322) {
|
|
38937
|
+
const { uint16Array: uint16Array2, uint32Array: uint32Array2 } = BufferStack;
|
|
38938
|
+
let nodeIndex162 = nodeIndex322 * 2;
|
|
38939
|
+
while (!IS_LEAF(nodeIndex162, uint16Array2)) {
|
|
38940
|
+
nodeIndex322 = LEFT_NODE(nodeIndex322);
|
|
38941
|
+
nodeIndex162 = nodeIndex322 * 2;
|
|
38942
|
+
}
|
|
38943
|
+
return OFFSET(nodeIndex322, uint32Array2);
|
|
38944
|
+
}, getRightEndOffset = function(nodeIndex322) {
|
|
38945
|
+
const { uint16Array: uint16Array2, uint32Array: uint32Array2 } = BufferStack;
|
|
38946
|
+
let nodeIndex162 = nodeIndex322 * 2;
|
|
38947
|
+
while (!IS_LEAF(nodeIndex162, uint16Array2)) {
|
|
38948
|
+
nodeIndex322 = RIGHT_NODE(nodeIndex322, uint32Array2);
|
|
38949
|
+
nodeIndex162 = nodeIndex322 * 2;
|
|
38950
|
+
}
|
|
38951
|
+
return OFFSET(nodeIndex322, uint32Array2) + COUNT(nodeIndex162, uint16Array2);
|
|
38952
|
+
};
|
|
38953
|
+
const left = LEFT_NODE(nodeIndex32);
|
|
38954
|
+
const right = RIGHT_NODE(nodeIndex32, uint32Array);
|
|
38955
|
+
let c1 = left;
|
|
38956
|
+
let c2 = right;
|
|
38957
|
+
let score1, score2;
|
|
38958
|
+
let box1, box2;
|
|
38959
|
+
if (nodeScoreFunc) {
|
|
38960
|
+
box1 = _box1;
|
|
38961
|
+
box2 = _box2;
|
|
38962
|
+
arrayToBox(BOUNDING_DATA_INDEX(c1), float32Array, box1);
|
|
38963
|
+
arrayToBox(BOUNDING_DATA_INDEX(c2), float32Array, box2);
|
|
38964
|
+
score1 = nodeScoreFunc(box1);
|
|
38965
|
+
score2 = nodeScoreFunc(box2);
|
|
38966
|
+
if (score2 < score1) {
|
|
38967
|
+
c1 = right;
|
|
38968
|
+
c2 = left;
|
|
38969
|
+
const temp5 = score1;
|
|
38970
|
+
score1 = score2;
|
|
38971
|
+
score2 = temp5;
|
|
38972
|
+
box1 = box2;
|
|
38973
|
+
}
|
|
38974
|
+
}
|
|
38975
|
+
if (!box1) {
|
|
38976
|
+
box1 = _box1;
|
|
38977
|
+
arrayToBox(BOUNDING_DATA_INDEX(c1), float32Array, box1);
|
|
38978
|
+
}
|
|
38979
|
+
const isC1Leaf = IS_LEAF(c1 * 2, uint16Array);
|
|
38980
|
+
const c1Intersection = intersectsBoundsFunc(box1, isC1Leaf, score1, depth + 1, nodeIndexByteOffset + c1);
|
|
38981
|
+
let c1StopTraversal;
|
|
38982
|
+
if (c1Intersection === CONTAINED) {
|
|
38983
|
+
const offset = getLeftOffset(c1);
|
|
38984
|
+
const end = getRightEndOffset(c1);
|
|
38985
|
+
const count = end - offset;
|
|
38986
|
+
c1StopTraversal = intersectsRangeFunc(offset, count, true, depth + 1, nodeIndexByteOffset + c1, box1);
|
|
38987
|
+
} else {
|
|
38988
|
+
c1StopTraversal = c1Intersection && shapecastTraverse(
|
|
38989
|
+
c1,
|
|
38990
|
+
geometry,
|
|
38991
|
+
intersectsBoundsFunc,
|
|
38992
|
+
intersectsRangeFunc,
|
|
38993
|
+
nodeScoreFunc,
|
|
38994
|
+
nodeIndexByteOffset,
|
|
38995
|
+
depth + 1
|
|
38996
|
+
);
|
|
38997
|
+
}
|
|
38998
|
+
if (c1StopTraversal)
|
|
38999
|
+
return true;
|
|
39000
|
+
box2 = _box2;
|
|
39001
|
+
arrayToBox(BOUNDING_DATA_INDEX(c2), float32Array, box2);
|
|
39002
|
+
const isC2Leaf = IS_LEAF(c2 * 2, uint16Array);
|
|
39003
|
+
const c2Intersection = intersectsBoundsFunc(box2, isC2Leaf, score2, depth + 1, nodeIndexByteOffset + c2);
|
|
39004
|
+
let c2StopTraversal;
|
|
39005
|
+
if (c2Intersection === CONTAINED) {
|
|
39006
|
+
const offset = getLeftOffset(c2);
|
|
39007
|
+
const end = getRightEndOffset(c2);
|
|
39008
|
+
const count = end - offset;
|
|
39009
|
+
c2StopTraversal = intersectsRangeFunc(offset, count, true, depth + 1, nodeIndexByteOffset + c2, box2);
|
|
39010
|
+
} else {
|
|
39011
|
+
c2StopTraversal = c2Intersection && shapecastTraverse(
|
|
39012
|
+
c2,
|
|
39013
|
+
geometry,
|
|
39014
|
+
intersectsBoundsFunc,
|
|
39015
|
+
intersectsRangeFunc,
|
|
39016
|
+
nodeScoreFunc,
|
|
39017
|
+
nodeIndexByteOffset,
|
|
39018
|
+
depth + 1
|
|
39019
|
+
);
|
|
39020
|
+
}
|
|
39021
|
+
if (c2StopTraversal)
|
|
39022
|
+
return true;
|
|
39023
|
+
return false;
|
|
39024
|
+
}
|
|
39025
|
+
}
|
|
39026
|
+
const temp = /* @__PURE__ */ new Vector3();
|
|
39027
|
+
const temp1$2 = /* @__PURE__ */ new Vector3();
|
|
39028
|
+
function closestPointToPoint(bvh, point, target = {}, minThreshold = 0, maxThreshold = Infinity) {
|
|
39029
|
+
const minThresholdSq = minThreshold * minThreshold;
|
|
39030
|
+
const maxThresholdSq = maxThreshold * maxThreshold;
|
|
39031
|
+
let closestDistanceSq = Infinity;
|
|
39032
|
+
let closestDistanceTriIndex = null;
|
|
39033
|
+
bvh.shapecast(
|
|
39034
|
+
{
|
|
39035
|
+
boundsTraverseOrder: (box) => {
|
|
39036
|
+
temp.copy(point).clamp(box.min, box.max);
|
|
39037
|
+
return temp.distanceToSquared(point);
|
|
39038
|
+
},
|
|
39039
|
+
intersectsBounds: (box, isLeaf, score) => {
|
|
39040
|
+
return score < closestDistanceSq && score < maxThresholdSq;
|
|
39041
|
+
},
|
|
39042
|
+
intersectsTriangle: (tri, triIndex) => {
|
|
39043
|
+
tri.closestPointToPoint(point, temp);
|
|
39044
|
+
const distSq = point.distanceToSquared(temp);
|
|
39045
|
+
if (distSq < closestDistanceSq) {
|
|
39046
|
+
temp1$2.copy(temp);
|
|
39047
|
+
closestDistanceSq = distSq;
|
|
39048
|
+
closestDistanceTriIndex = triIndex;
|
|
39049
|
+
}
|
|
39050
|
+
if (distSq < minThresholdSq) {
|
|
39051
|
+
return true;
|
|
39052
|
+
} else {
|
|
39053
|
+
return false;
|
|
39054
|
+
}
|
|
39055
|
+
}
|
|
39056
|
+
}
|
|
39057
|
+
);
|
|
39058
|
+
if (closestDistanceSq === Infinity)
|
|
39059
|
+
return null;
|
|
39060
|
+
const closestDistance = Math.sqrt(closestDistanceSq);
|
|
39061
|
+
if (!target.point)
|
|
39062
|
+
target.point = temp1$2.clone();
|
|
39063
|
+
else
|
|
39064
|
+
target.point.copy(temp1$2);
|
|
39065
|
+
target.distance = closestDistance, target.faceIndex = closestDistanceTriIndex;
|
|
39066
|
+
return target;
|
|
39067
|
+
}
|
|
39068
|
+
const _vA = /* @__PURE__ */ new Vector3();
|
|
39069
|
+
const _vB = /* @__PURE__ */ new Vector3();
|
|
39070
|
+
const _vC = /* @__PURE__ */ new Vector3();
|
|
39071
|
+
const _uvA = /* @__PURE__ */ new Vector2();
|
|
39072
|
+
const _uvB = /* @__PURE__ */ new Vector2();
|
|
39073
|
+
const _uvC = /* @__PURE__ */ new Vector2();
|
|
39074
|
+
const _normalA = /* @__PURE__ */ new Vector3();
|
|
39075
|
+
const _normalB = /* @__PURE__ */ new Vector3();
|
|
39076
|
+
const _normalC = /* @__PURE__ */ new Vector3();
|
|
39077
|
+
const _intersectionPoint = /* @__PURE__ */ new Vector3();
|
|
39078
|
+
function checkIntersection(ray, pA, pB, pC, point, side) {
|
|
39079
|
+
let intersect;
|
|
39080
|
+
if (side === BackSide) {
|
|
39081
|
+
intersect = ray.intersectTriangle(pC, pB, pA, true, point);
|
|
39082
|
+
} else {
|
|
39083
|
+
intersect = ray.intersectTriangle(pA, pB, pC, side !== DoubleSide, point);
|
|
39084
|
+
}
|
|
39085
|
+
if (intersect === null)
|
|
39086
|
+
return null;
|
|
39087
|
+
const distance = ray.origin.distanceTo(point);
|
|
39088
|
+
return {
|
|
39089
|
+
distance,
|
|
39090
|
+
point: point.clone()
|
|
39091
|
+
};
|
|
39092
|
+
}
|
|
39093
|
+
function checkBufferGeometryIntersection(ray, position, normal, uv, uv1, a, b, c2, side) {
|
|
39094
|
+
_vA.fromBufferAttribute(position, a);
|
|
39095
|
+
_vB.fromBufferAttribute(position, b);
|
|
39096
|
+
_vC.fromBufferAttribute(position, c2);
|
|
39097
|
+
const intersection = checkIntersection(ray, _vA, _vB, _vC, _intersectionPoint, side);
|
|
39098
|
+
if (intersection) {
|
|
39099
|
+
if (uv) {
|
|
39100
|
+
_uvA.fromBufferAttribute(uv, a);
|
|
39101
|
+
_uvB.fromBufferAttribute(uv, b);
|
|
39102
|
+
_uvC.fromBufferAttribute(uv, c2);
|
|
39103
|
+
intersection.uv = Triangle.getInterpolation(_intersectionPoint, _vA, _vB, _vC, _uvA, _uvB, _uvC, new Vector2());
|
|
39104
|
+
}
|
|
39105
|
+
if (uv1) {
|
|
39106
|
+
_uvA.fromBufferAttribute(uv1, a);
|
|
39107
|
+
_uvB.fromBufferAttribute(uv1, b);
|
|
39108
|
+
_uvC.fromBufferAttribute(uv1, c2);
|
|
39109
|
+
intersection.uv1 = Triangle.getInterpolation(_intersectionPoint, _vA, _vB, _vC, _uvA, _uvB, _uvC, new Vector2());
|
|
39110
|
+
}
|
|
39111
|
+
if (normal) {
|
|
39112
|
+
_normalA.fromBufferAttribute(normal, a);
|
|
39113
|
+
_normalB.fromBufferAttribute(normal, b);
|
|
39114
|
+
_normalC.fromBufferAttribute(normal, c2);
|
|
39115
|
+
intersection.normal = Triangle.getInterpolation(_intersectionPoint, _vA, _vB, _vC, _normalA, _normalB, _normalC, new Vector3());
|
|
39116
|
+
if (intersection.normal.dot(ray.direction) > 0) {
|
|
39117
|
+
intersection.normal.multiplyScalar(-1);
|
|
39118
|
+
}
|
|
39119
|
+
}
|
|
39120
|
+
const face = {
|
|
39121
|
+
a,
|
|
39122
|
+
b,
|
|
39123
|
+
c: c2,
|
|
39124
|
+
normal: new Vector3(),
|
|
39125
|
+
materialIndex: 0
|
|
39126
|
+
};
|
|
39127
|
+
Triangle.getNormal(_vA, _vB, _vC, face.normal);
|
|
39128
|
+
intersection.face = face;
|
|
39129
|
+
intersection.faceIndex = a;
|
|
39130
|
+
}
|
|
39131
|
+
return intersection;
|
|
39132
|
+
}
|
|
39133
|
+
function intersectTri(geo, side, ray, tri, intersections) {
|
|
39134
|
+
const triOffset = tri * 3;
|
|
39135
|
+
let a = triOffset + 0;
|
|
39136
|
+
let b = triOffset + 1;
|
|
39137
|
+
let c2 = triOffset + 2;
|
|
39138
|
+
const index = geo.index;
|
|
39139
|
+
if (geo.index) {
|
|
39140
|
+
a = index.getX(a);
|
|
39141
|
+
b = index.getX(b);
|
|
39142
|
+
c2 = index.getX(c2);
|
|
39143
|
+
}
|
|
39144
|
+
const { position, normal, uv, uv1 } = geo.attributes;
|
|
39145
|
+
const intersection = checkBufferGeometryIntersection(ray, position, normal, uv, uv1, a, b, c2, side);
|
|
39146
|
+
if (intersection) {
|
|
39147
|
+
intersection.faceIndex = tri;
|
|
39148
|
+
if (intersections)
|
|
39149
|
+
intersections.push(intersection);
|
|
39150
|
+
return intersection;
|
|
39151
|
+
}
|
|
39152
|
+
return null;
|
|
39153
|
+
}
|
|
39154
|
+
function setTriangle(tri, i, index, pos) {
|
|
39155
|
+
const ta = tri.a;
|
|
39156
|
+
const tb = tri.b;
|
|
39157
|
+
const tc = tri.c;
|
|
39158
|
+
let i0 = i;
|
|
39159
|
+
let i1 = i + 1;
|
|
39160
|
+
let i2 = i + 2;
|
|
39161
|
+
if (index) {
|
|
39162
|
+
i0 = index.getX(i0);
|
|
39163
|
+
i1 = index.getX(i1);
|
|
39164
|
+
i2 = index.getX(i2);
|
|
39165
|
+
}
|
|
39166
|
+
ta.x = pos.getX(i0);
|
|
39167
|
+
ta.y = pos.getY(i0);
|
|
39168
|
+
ta.z = pos.getZ(i0);
|
|
39169
|
+
tb.x = pos.getX(i1);
|
|
39170
|
+
tb.y = pos.getY(i1);
|
|
39171
|
+
tb.z = pos.getZ(i1);
|
|
39172
|
+
tc.x = pos.getX(i2);
|
|
39173
|
+
tc.y = pos.getY(i2);
|
|
39174
|
+
tc.z = pos.getZ(i2);
|
|
39175
|
+
}
|
|
39176
|
+
function intersectTris(bvh, side, ray, offset, count, intersections) {
|
|
39177
|
+
const { geometry, _indirectBuffer } = bvh;
|
|
39178
|
+
for (let i = offset, end = offset + count; i < end; i++) {
|
|
39179
|
+
intersectTri(geometry, side, ray, i, intersections);
|
|
39180
|
+
}
|
|
39181
|
+
}
|
|
39182
|
+
function intersectClosestTri(bvh, side, ray, offset, count) {
|
|
39183
|
+
const { geometry, _indirectBuffer } = bvh;
|
|
39184
|
+
let dist = Infinity;
|
|
39185
|
+
let res = null;
|
|
39186
|
+
for (let i = offset, end = offset + count; i < end; i++) {
|
|
39187
|
+
let intersection;
|
|
39188
|
+
intersection = intersectTri(geometry, side, ray, i);
|
|
39189
|
+
if (intersection && intersection.distance < dist) {
|
|
39190
|
+
res = intersection;
|
|
39191
|
+
dist = intersection.distance;
|
|
39192
|
+
}
|
|
39193
|
+
}
|
|
39194
|
+
return res;
|
|
39195
|
+
}
|
|
39196
|
+
function iterateOverTriangles(offset, count, bvh, intersectsTriangleFunc, contained, depth, triangle3) {
|
|
39197
|
+
const { geometry } = bvh;
|
|
39198
|
+
const { index } = geometry;
|
|
39199
|
+
const pos = geometry.attributes.position;
|
|
39200
|
+
for (let i = offset, l = count + offset; i < l; i++) {
|
|
39201
|
+
let tri;
|
|
39202
|
+
tri = i;
|
|
39203
|
+
setTriangle(triangle3, tri * 3, index, pos);
|
|
39204
|
+
triangle3.needsUpdate = true;
|
|
39205
|
+
if (intersectsTriangleFunc(triangle3, tri, contained, depth)) {
|
|
39206
|
+
return true;
|
|
39207
|
+
}
|
|
39208
|
+
}
|
|
39209
|
+
return false;
|
|
39210
|
+
}
|
|
39211
|
+
function refit(bvh, nodeIndices = null) {
|
|
39212
|
+
if (nodeIndices && Array.isArray(nodeIndices)) {
|
|
39213
|
+
nodeIndices = new Set(nodeIndices);
|
|
39214
|
+
}
|
|
39215
|
+
const geometry = bvh.geometry;
|
|
39216
|
+
const indexArr = geometry.index ? geometry.index.array : null;
|
|
39217
|
+
const posAttr = geometry.attributes.position;
|
|
39218
|
+
let buffer, uint32Array, uint16Array, float32Array;
|
|
39219
|
+
let byteOffset = 0;
|
|
39220
|
+
const roots = bvh._roots;
|
|
39221
|
+
for (let i = 0, l = roots.length; i < l; i++) {
|
|
39222
|
+
buffer = roots[i];
|
|
39223
|
+
uint32Array = new Uint32Array(buffer);
|
|
39224
|
+
uint16Array = new Uint16Array(buffer);
|
|
39225
|
+
float32Array = new Float32Array(buffer);
|
|
39226
|
+
_traverse2(0, byteOffset);
|
|
39227
|
+
byteOffset += buffer.byteLength;
|
|
39228
|
+
}
|
|
39229
|
+
function _traverse2(node32Index, byteOffset2, force = false) {
|
|
39230
|
+
const node16Index = node32Index * 2;
|
|
39231
|
+
const isLeaf = uint16Array[node16Index + 15] === IS_LEAFNODE_FLAG;
|
|
39232
|
+
if (isLeaf) {
|
|
39233
|
+
const offset = uint32Array[node32Index + 6];
|
|
39234
|
+
const count = uint16Array[node16Index + 14];
|
|
39235
|
+
let minx = Infinity;
|
|
39236
|
+
let miny = Infinity;
|
|
39237
|
+
let minz = Infinity;
|
|
39238
|
+
let maxx = -Infinity;
|
|
39239
|
+
let maxy = -Infinity;
|
|
39240
|
+
let maxz = -Infinity;
|
|
39241
|
+
for (let i = 3 * offset, l = 3 * (offset + count); i < l; i++) {
|
|
39242
|
+
let index = indexArr[i];
|
|
39243
|
+
const x2 = posAttr.getX(index);
|
|
39244
|
+
const y = posAttr.getY(index);
|
|
39245
|
+
const z = posAttr.getZ(index);
|
|
39246
|
+
if (x2 < minx)
|
|
39247
|
+
minx = x2;
|
|
39248
|
+
if (x2 > maxx)
|
|
39249
|
+
maxx = x2;
|
|
39250
|
+
if (y < miny)
|
|
39251
|
+
miny = y;
|
|
39252
|
+
if (y > maxy)
|
|
39253
|
+
maxy = y;
|
|
39254
|
+
if (z < minz)
|
|
39255
|
+
minz = z;
|
|
39256
|
+
if (z > maxz)
|
|
39257
|
+
maxz = z;
|
|
39258
|
+
}
|
|
39259
|
+
if (float32Array[node32Index + 0] !== minx || float32Array[node32Index + 1] !== miny || float32Array[node32Index + 2] !== minz || float32Array[node32Index + 3] !== maxx || float32Array[node32Index + 4] !== maxy || float32Array[node32Index + 5] !== maxz) {
|
|
39260
|
+
float32Array[node32Index + 0] = minx;
|
|
39261
|
+
float32Array[node32Index + 1] = miny;
|
|
39262
|
+
float32Array[node32Index + 2] = minz;
|
|
39263
|
+
float32Array[node32Index + 3] = maxx;
|
|
39264
|
+
float32Array[node32Index + 4] = maxy;
|
|
39265
|
+
float32Array[node32Index + 5] = maxz;
|
|
39266
|
+
return true;
|
|
39267
|
+
} else {
|
|
39268
|
+
return false;
|
|
39269
|
+
}
|
|
39270
|
+
} else {
|
|
39271
|
+
const left = node32Index + 8;
|
|
39272
|
+
const right = uint32Array[node32Index + 6];
|
|
39273
|
+
const offsetLeft = left + byteOffset2;
|
|
39274
|
+
const offsetRight = right + byteOffset2;
|
|
39275
|
+
let forceChildren = force;
|
|
39276
|
+
let includesLeft = false;
|
|
39277
|
+
let includesRight = false;
|
|
39278
|
+
if (nodeIndices) {
|
|
39279
|
+
if (!forceChildren) {
|
|
39280
|
+
includesLeft = nodeIndices.has(offsetLeft);
|
|
39281
|
+
includesRight = nodeIndices.has(offsetRight);
|
|
39282
|
+
forceChildren = !includesLeft && !includesRight;
|
|
39283
|
+
}
|
|
39284
|
+
} else {
|
|
39285
|
+
includesLeft = true;
|
|
39286
|
+
includesRight = true;
|
|
39287
|
+
}
|
|
39288
|
+
const traverseLeft = forceChildren || includesLeft;
|
|
39289
|
+
const traverseRight = forceChildren || includesRight;
|
|
39290
|
+
let leftChange = false;
|
|
39291
|
+
if (traverseLeft) {
|
|
39292
|
+
leftChange = _traverse2(left, byteOffset2, forceChildren);
|
|
39293
|
+
}
|
|
39294
|
+
let rightChange = false;
|
|
39295
|
+
if (traverseRight) {
|
|
39296
|
+
rightChange = _traverse2(right, byteOffset2, forceChildren);
|
|
39297
|
+
}
|
|
39298
|
+
const didChange = leftChange || rightChange;
|
|
39299
|
+
if (didChange) {
|
|
39300
|
+
for (let i = 0; i < 3; i++) {
|
|
39301
|
+
const lefti = left + i;
|
|
39302
|
+
const righti = right + i;
|
|
39303
|
+
const minLeftValue = float32Array[lefti];
|
|
39304
|
+
const maxLeftValue = float32Array[lefti + 3];
|
|
39305
|
+
const minRightValue = float32Array[righti];
|
|
39306
|
+
const maxRightValue = float32Array[righti + 3];
|
|
39307
|
+
float32Array[node32Index + i] = minLeftValue < minRightValue ? minLeftValue : minRightValue;
|
|
39308
|
+
float32Array[node32Index + i + 3] = maxLeftValue > maxRightValue ? maxLeftValue : maxRightValue;
|
|
39309
|
+
}
|
|
39310
|
+
}
|
|
39311
|
+
return didChange;
|
|
39312
|
+
}
|
|
39313
|
+
}
|
|
39314
|
+
}
|
|
39315
|
+
const _boundingBox = /* @__PURE__ */ new Box3();
|
|
39316
|
+
function intersectRay(nodeIndex32, array, ray, target) {
|
|
39317
|
+
arrayToBox(nodeIndex32, array, _boundingBox);
|
|
39318
|
+
return ray.intersectBox(_boundingBox, target);
|
|
39319
|
+
}
|
|
39320
|
+
function intersectTris_indirect(bvh, side, ray, offset, count, intersections) {
|
|
39321
|
+
const { geometry, _indirectBuffer } = bvh;
|
|
39322
|
+
for (let i = offset, end = offset + count; i < end; i++) {
|
|
39323
|
+
let vi = _indirectBuffer ? _indirectBuffer[i] : i;
|
|
39324
|
+
intersectTri(geometry, side, ray, vi, intersections);
|
|
39325
|
+
}
|
|
39326
|
+
}
|
|
39327
|
+
function intersectClosestTri_indirect(bvh, side, ray, offset, count) {
|
|
39328
|
+
const { geometry, _indirectBuffer } = bvh;
|
|
39329
|
+
let dist = Infinity;
|
|
39330
|
+
let res = null;
|
|
39331
|
+
for (let i = offset, end = offset + count; i < end; i++) {
|
|
39332
|
+
let intersection;
|
|
39333
|
+
intersection = intersectTri(geometry, side, ray, _indirectBuffer ? _indirectBuffer[i] : i);
|
|
39334
|
+
if (intersection && intersection.distance < dist) {
|
|
39335
|
+
res = intersection;
|
|
39336
|
+
dist = intersection.distance;
|
|
39337
|
+
}
|
|
39338
|
+
}
|
|
39339
|
+
return res;
|
|
39340
|
+
}
|
|
39341
|
+
function iterateOverTriangles_indirect(offset, count, bvh, intersectsTriangleFunc, contained, depth, triangle3) {
|
|
39342
|
+
const { geometry } = bvh;
|
|
39343
|
+
const { index } = geometry;
|
|
39344
|
+
const pos = geometry.attributes.position;
|
|
39345
|
+
for (let i = offset, l = count + offset; i < l; i++) {
|
|
39346
|
+
let tri;
|
|
39347
|
+
tri = bvh.resolveTriangleIndex(i);
|
|
39348
|
+
setTriangle(triangle3, tri * 3, index, pos);
|
|
39349
|
+
triangle3.needsUpdate = true;
|
|
39350
|
+
if (intersectsTriangleFunc(triangle3, tri, contained, depth)) {
|
|
39351
|
+
return true;
|
|
39352
|
+
}
|
|
39353
|
+
}
|
|
39354
|
+
return false;
|
|
39355
|
+
}
|
|
39356
|
+
const _boxIntersection$3 = /* @__PURE__ */ new Vector3();
|
|
39357
|
+
function raycast(bvh, root, side, ray, intersects) {
|
|
39358
|
+
BufferStack.setBuffer(bvh._roots[root]);
|
|
39359
|
+
_raycast$1(0, bvh, side, ray, intersects);
|
|
39360
|
+
BufferStack.clearBuffer();
|
|
39361
|
+
}
|
|
39362
|
+
function _raycast$1(nodeIndex32, bvh, side, ray, intersects) {
|
|
39363
|
+
const { float32Array, uint16Array, uint32Array } = BufferStack;
|
|
39364
|
+
const nodeIndex16 = nodeIndex32 * 2;
|
|
39365
|
+
const isLeaf = IS_LEAF(nodeIndex16, uint16Array);
|
|
39366
|
+
if (isLeaf) {
|
|
39367
|
+
const offset = OFFSET(nodeIndex32, uint32Array);
|
|
39368
|
+
const count = COUNT(nodeIndex16, uint16Array);
|
|
39369
|
+
intersectTris(bvh, side, ray, offset, count, intersects);
|
|
39370
|
+
} else {
|
|
39371
|
+
const leftIndex = LEFT_NODE(nodeIndex32);
|
|
39372
|
+
if (intersectRay(leftIndex, float32Array, ray, _boxIntersection$3)) {
|
|
39373
|
+
_raycast$1(leftIndex, bvh, side, ray, intersects);
|
|
39374
|
+
}
|
|
39375
|
+
const rightIndex = RIGHT_NODE(nodeIndex32, uint32Array);
|
|
39376
|
+
if (intersectRay(rightIndex, float32Array, ray, _boxIntersection$3)) {
|
|
39377
|
+
_raycast$1(rightIndex, bvh, side, ray, intersects);
|
|
39378
|
+
}
|
|
39379
|
+
}
|
|
39380
|
+
}
|
|
39381
|
+
const _boxIntersection$2 = /* @__PURE__ */ new Vector3();
|
|
39382
|
+
const _xyzFields$1 = ["x", "y", "z"];
|
|
39383
|
+
function raycastFirst(bvh, root, side, ray) {
|
|
39384
|
+
BufferStack.setBuffer(bvh._roots[root]);
|
|
39385
|
+
const result = _raycastFirst$1(0, bvh, side, ray);
|
|
39386
|
+
BufferStack.clearBuffer();
|
|
39387
|
+
return result;
|
|
39388
|
+
}
|
|
39389
|
+
function _raycastFirst$1(nodeIndex32, bvh, side, ray) {
|
|
39390
|
+
const { float32Array, uint16Array, uint32Array } = BufferStack;
|
|
39391
|
+
let nodeIndex16 = nodeIndex32 * 2;
|
|
39392
|
+
const isLeaf = IS_LEAF(nodeIndex16, uint16Array);
|
|
39393
|
+
if (isLeaf) {
|
|
39394
|
+
const offset = OFFSET(nodeIndex32, uint32Array);
|
|
39395
|
+
const count = COUNT(nodeIndex16, uint16Array);
|
|
39396
|
+
return intersectClosestTri(bvh, side, ray, offset, count);
|
|
39397
|
+
} else {
|
|
39398
|
+
const splitAxis = SPLIT_AXIS(nodeIndex32, uint32Array);
|
|
39399
|
+
const xyzAxis = _xyzFields$1[splitAxis];
|
|
39400
|
+
const rayDir = ray.direction[xyzAxis];
|
|
39401
|
+
const leftToRight = rayDir >= 0;
|
|
39402
|
+
let c1, c2;
|
|
39403
|
+
if (leftToRight) {
|
|
39404
|
+
c1 = LEFT_NODE(nodeIndex32);
|
|
39405
|
+
c2 = RIGHT_NODE(nodeIndex32, uint32Array);
|
|
39406
|
+
} else {
|
|
39407
|
+
c1 = RIGHT_NODE(nodeIndex32, uint32Array);
|
|
39408
|
+
c2 = LEFT_NODE(nodeIndex32);
|
|
39409
|
+
}
|
|
39410
|
+
const c1Intersection = intersectRay(c1, float32Array, ray, _boxIntersection$2);
|
|
39411
|
+
const c1Result = c1Intersection ? _raycastFirst$1(c1, bvh, side, ray) : null;
|
|
39412
|
+
if (c1Result) {
|
|
39413
|
+
const point = c1Result.point[xyzAxis];
|
|
39414
|
+
const isOutside = leftToRight ? point <= float32Array[c2 + splitAxis] : (
|
|
39415
|
+
// min bounding data
|
|
39416
|
+
point >= float32Array[c2 + splitAxis + 3]
|
|
39417
|
+
);
|
|
39418
|
+
if (isOutside) {
|
|
39419
|
+
return c1Result;
|
|
39420
|
+
}
|
|
39421
|
+
}
|
|
39422
|
+
const c2Intersection = intersectRay(c2, float32Array, ray, _boxIntersection$2);
|
|
39423
|
+
const c2Result = c2Intersection ? _raycastFirst$1(c2, bvh, side, ray) : null;
|
|
39424
|
+
if (c1Result && c2Result) {
|
|
39425
|
+
return c1Result.distance <= c2Result.distance ? c1Result : c2Result;
|
|
39426
|
+
} else {
|
|
39427
|
+
return c1Result || c2Result || null;
|
|
39428
|
+
}
|
|
39429
|
+
}
|
|
39430
|
+
}
|
|
39431
|
+
const boundingBox$1 = /* @__PURE__ */ new Box3();
|
|
39432
|
+
const triangle$1 = /* @__PURE__ */ new ExtendedTriangle();
|
|
39433
|
+
const triangle2$1 = /* @__PURE__ */ new ExtendedTriangle();
|
|
39434
|
+
const invertedMat$1 = /* @__PURE__ */ new Matrix4();
|
|
39435
|
+
const obb$4 = /* @__PURE__ */ new OrientedBox();
|
|
39436
|
+
const obb2$3 = /* @__PURE__ */ new OrientedBox();
|
|
39437
|
+
function intersectsGeometry(bvh, root, otherGeometry, geometryToBvh) {
|
|
39438
|
+
BufferStack.setBuffer(bvh._roots[root]);
|
|
39439
|
+
const result = _intersectsGeometry$1(0, bvh, otherGeometry, geometryToBvh);
|
|
39440
|
+
BufferStack.clearBuffer();
|
|
39441
|
+
return result;
|
|
39442
|
+
}
|
|
39443
|
+
function _intersectsGeometry$1(nodeIndex32, bvh, otherGeometry, geometryToBvh, cachedObb = null) {
|
|
39444
|
+
const { float32Array, uint16Array, uint32Array } = BufferStack;
|
|
39445
|
+
let nodeIndex16 = nodeIndex32 * 2;
|
|
39446
|
+
if (cachedObb === null) {
|
|
39447
|
+
if (!otherGeometry.boundingBox) {
|
|
39448
|
+
otherGeometry.computeBoundingBox();
|
|
39449
|
+
}
|
|
39450
|
+
obb$4.set(otherGeometry.boundingBox.min, otherGeometry.boundingBox.max, geometryToBvh);
|
|
39451
|
+
cachedObb = obb$4;
|
|
39452
|
+
}
|
|
39453
|
+
const isLeaf = IS_LEAF(nodeIndex16, uint16Array);
|
|
39454
|
+
if (isLeaf) {
|
|
39455
|
+
const thisGeometry = bvh.geometry;
|
|
39456
|
+
const thisIndex = thisGeometry.index;
|
|
39457
|
+
const thisPos = thisGeometry.attributes.position;
|
|
39458
|
+
const index = otherGeometry.index;
|
|
39459
|
+
const pos = otherGeometry.attributes.position;
|
|
39460
|
+
const offset = OFFSET(nodeIndex32, uint32Array);
|
|
39461
|
+
const count = COUNT(nodeIndex16, uint16Array);
|
|
39462
|
+
invertedMat$1.copy(geometryToBvh).invert();
|
|
39463
|
+
if (otherGeometry.boundsTree) {
|
|
39464
|
+
arrayToBox(BOUNDING_DATA_INDEX(nodeIndex32), float32Array, obb2$3);
|
|
39465
|
+
obb2$3.matrix.copy(invertedMat$1);
|
|
39466
|
+
obb2$3.needsUpdate = true;
|
|
39467
|
+
const res = otherGeometry.boundsTree.shapecast({
|
|
39468
|
+
intersectsBounds: (box) => obb2$3.intersectsBox(box),
|
|
39469
|
+
intersectsTriangle: (tri) => {
|
|
39470
|
+
tri.a.applyMatrix4(geometryToBvh);
|
|
39471
|
+
tri.b.applyMatrix4(geometryToBvh);
|
|
39472
|
+
tri.c.applyMatrix4(geometryToBvh);
|
|
39473
|
+
tri.needsUpdate = true;
|
|
39474
|
+
for (let i = offset * 3, l = (count + offset) * 3; i < l; i += 3) {
|
|
39475
|
+
setTriangle(triangle2$1, i, thisIndex, thisPos);
|
|
39476
|
+
triangle2$1.needsUpdate = true;
|
|
39477
|
+
if (tri.intersectsTriangle(triangle2$1)) {
|
|
39478
|
+
return true;
|
|
39479
|
+
}
|
|
39480
|
+
}
|
|
39481
|
+
return false;
|
|
39482
|
+
}
|
|
39483
|
+
});
|
|
39484
|
+
return res;
|
|
39485
|
+
} else {
|
|
39486
|
+
for (let i = offset * 3, l = (count + offset) * 3; i < l; i += 3) {
|
|
39487
|
+
setTriangle(triangle$1, i, thisIndex, thisPos);
|
|
39488
|
+
triangle$1.a.applyMatrix4(invertedMat$1);
|
|
39489
|
+
triangle$1.b.applyMatrix4(invertedMat$1);
|
|
39490
|
+
triangle$1.c.applyMatrix4(invertedMat$1);
|
|
39491
|
+
triangle$1.needsUpdate = true;
|
|
39492
|
+
for (let i2 = 0, l2 = index.count; i2 < l2; i2 += 3) {
|
|
39493
|
+
setTriangle(triangle2$1, i2, index, pos);
|
|
39494
|
+
triangle2$1.needsUpdate = true;
|
|
39495
|
+
if (triangle$1.intersectsTriangle(triangle2$1)) {
|
|
39496
|
+
return true;
|
|
39497
|
+
}
|
|
39498
|
+
}
|
|
39499
|
+
}
|
|
39500
|
+
}
|
|
39501
|
+
} else {
|
|
39502
|
+
const left = nodeIndex32 + 8;
|
|
39503
|
+
const right = uint32Array[nodeIndex32 + 6];
|
|
39504
|
+
arrayToBox(BOUNDING_DATA_INDEX(left), float32Array, boundingBox$1);
|
|
39505
|
+
const leftIntersection = cachedObb.intersectsBox(boundingBox$1) && _intersectsGeometry$1(left, bvh, otherGeometry, geometryToBvh, cachedObb);
|
|
39506
|
+
if (leftIntersection)
|
|
39507
|
+
return true;
|
|
39508
|
+
arrayToBox(BOUNDING_DATA_INDEX(right), float32Array, boundingBox$1);
|
|
39509
|
+
const rightIntersection = cachedObb.intersectsBox(boundingBox$1) && _intersectsGeometry$1(right, bvh, otherGeometry, geometryToBvh, cachedObb);
|
|
39510
|
+
if (rightIntersection)
|
|
39511
|
+
return true;
|
|
39512
|
+
return false;
|
|
39513
|
+
}
|
|
39514
|
+
}
|
|
39515
|
+
const tempMatrix$1 = /* @__PURE__ */ new Matrix4();
|
|
39516
|
+
const obb$3 = /* @__PURE__ */ new OrientedBox();
|
|
39517
|
+
const obb2$2 = /* @__PURE__ */ new OrientedBox();
|
|
39518
|
+
const temp1$1 = /* @__PURE__ */ new Vector3();
|
|
39519
|
+
const temp2$1 = /* @__PURE__ */ new Vector3();
|
|
39520
|
+
const temp3$1 = /* @__PURE__ */ new Vector3();
|
|
39521
|
+
const temp4$1 = /* @__PURE__ */ new Vector3();
|
|
39522
|
+
function closestPointToGeometry(bvh, otherGeometry, geometryToBvh, target1 = {}, target2 = {}, minThreshold = 0, maxThreshold = Infinity) {
|
|
39523
|
+
if (!otherGeometry.boundingBox) {
|
|
39524
|
+
otherGeometry.computeBoundingBox();
|
|
39525
|
+
}
|
|
39526
|
+
obb$3.set(otherGeometry.boundingBox.min, otherGeometry.boundingBox.max, geometryToBvh);
|
|
39527
|
+
obb$3.needsUpdate = true;
|
|
39528
|
+
const geometry = bvh.geometry;
|
|
39529
|
+
const pos = geometry.attributes.position;
|
|
39530
|
+
const index = geometry.index;
|
|
39531
|
+
const otherPos = otherGeometry.attributes.position;
|
|
39532
|
+
const otherIndex = otherGeometry.index;
|
|
39533
|
+
const triangle3 = ExtendedTrianglePool.getPrimitive();
|
|
39534
|
+
const triangle22 = ExtendedTrianglePool.getPrimitive();
|
|
39535
|
+
let tempTarget1 = temp1$1;
|
|
39536
|
+
let tempTargetDest1 = temp2$1;
|
|
39537
|
+
let tempTarget2 = null;
|
|
39538
|
+
let tempTargetDest2 = null;
|
|
39539
|
+
if (target2) {
|
|
39540
|
+
tempTarget2 = temp3$1;
|
|
39541
|
+
tempTargetDest2 = temp4$1;
|
|
39542
|
+
}
|
|
39543
|
+
let closestDistance = Infinity;
|
|
39544
|
+
let closestDistanceTriIndex = null;
|
|
39545
|
+
let closestDistanceOtherTriIndex = null;
|
|
39546
|
+
tempMatrix$1.copy(geometryToBvh).invert();
|
|
39547
|
+
obb2$2.matrix.copy(tempMatrix$1);
|
|
39548
|
+
bvh.shapecast(
|
|
39549
|
+
{
|
|
39550
|
+
boundsTraverseOrder: (box) => {
|
|
39551
|
+
return obb$3.distanceToBox(box);
|
|
39552
|
+
},
|
|
39553
|
+
intersectsBounds: (box, isLeaf, score) => {
|
|
39554
|
+
if (score < closestDistance && score < maxThreshold) {
|
|
39555
|
+
if (isLeaf) {
|
|
39556
|
+
obb2$2.min.copy(box.min);
|
|
39557
|
+
obb2$2.max.copy(box.max);
|
|
39558
|
+
obb2$2.needsUpdate = true;
|
|
39559
|
+
}
|
|
39560
|
+
return true;
|
|
39561
|
+
}
|
|
39562
|
+
return false;
|
|
39563
|
+
},
|
|
39564
|
+
intersectsRange: (offset, count) => {
|
|
39565
|
+
if (otherGeometry.boundsTree) {
|
|
39566
|
+
const otherBvh = otherGeometry.boundsTree;
|
|
39567
|
+
return otherBvh.shapecast({
|
|
39568
|
+
boundsTraverseOrder: (box) => {
|
|
39569
|
+
return obb2$2.distanceToBox(box);
|
|
39570
|
+
},
|
|
39571
|
+
intersectsBounds: (box, isLeaf, score) => {
|
|
39572
|
+
return score < closestDistance && score < maxThreshold;
|
|
39573
|
+
},
|
|
39574
|
+
intersectsRange: (otherOffset, otherCount) => {
|
|
39575
|
+
for (let i2 = otherOffset, l2 = otherOffset + otherCount; i2 < l2; i2++) {
|
|
39576
|
+
setTriangle(triangle22, 3 * i2, otherIndex, otherPos);
|
|
39577
|
+
triangle22.a.applyMatrix4(geometryToBvh);
|
|
39578
|
+
triangle22.b.applyMatrix4(geometryToBvh);
|
|
39579
|
+
triangle22.c.applyMatrix4(geometryToBvh);
|
|
39580
|
+
triangle22.needsUpdate = true;
|
|
39581
|
+
for (let i = offset, l = offset + count; i < l; i++) {
|
|
39582
|
+
setTriangle(triangle3, 3 * i, index, pos);
|
|
39583
|
+
triangle3.needsUpdate = true;
|
|
39584
|
+
const dist = triangle3.distanceToTriangle(triangle22, tempTarget1, tempTarget2);
|
|
39585
|
+
if (dist < closestDistance) {
|
|
39586
|
+
tempTargetDest1.copy(tempTarget1);
|
|
39587
|
+
if (tempTargetDest2) {
|
|
39588
|
+
tempTargetDest2.copy(tempTarget2);
|
|
39589
|
+
}
|
|
39590
|
+
closestDistance = dist;
|
|
39591
|
+
closestDistanceTriIndex = i;
|
|
39592
|
+
closestDistanceOtherTriIndex = i2;
|
|
39593
|
+
}
|
|
39594
|
+
if (dist < minThreshold) {
|
|
39595
|
+
return true;
|
|
39596
|
+
}
|
|
39597
|
+
}
|
|
39598
|
+
}
|
|
39599
|
+
}
|
|
39600
|
+
});
|
|
39601
|
+
} else {
|
|
39602
|
+
const triCount = getTriCount(otherGeometry);
|
|
39603
|
+
for (let i2 = 0, l2 = triCount; i2 < l2; i2++) {
|
|
39604
|
+
setTriangle(triangle22, 3 * i2, otherIndex, otherPos);
|
|
39605
|
+
triangle22.a.applyMatrix4(geometryToBvh);
|
|
39606
|
+
triangle22.b.applyMatrix4(geometryToBvh);
|
|
39607
|
+
triangle22.c.applyMatrix4(geometryToBvh);
|
|
39608
|
+
triangle22.needsUpdate = true;
|
|
39609
|
+
for (let i = offset, l = offset + count; i < l; i++) {
|
|
39610
|
+
setTriangle(triangle3, 3 * i, index, pos);
|
|
39611
|
+
triangle3.needsUpdate = true;
|
|
39612
|
+
const dist = triangle3.distanceToTriangle(triangle22, tempTarget1, tempTarget2);
|
|
39613
|
+
if (dist < closestDistance) {
|
|
39614
|
+
tempTargetDest1.copy(tempTarget1);
|
|
39615
|
+
if (tempTargetDest2) {
|
|
39616
|
+
tempTargetDest2.copy(tempTarget2);
|
|
39617
|
+
}
|
|
39618
|
+
closestDistance = dist;
|
|
39619
|
+
closestDistanceTriIndex = i;
|
|
39620
|
+
closestDistanceOtherTriIndex = i2;
|
|
39621
|
+
}
|
|
39622
|
+
if (dist < minThreshold) {
|
|
39623
|
+
return true;
|
|
39624
|
+
}
|
|
39625
|
+
}
|
|
39626
|
+
}
|
|
39627
|
+
}
|
|
39628
|
+
}
|
|
39629
|
+
}
|
|
39630
|
+
);
|
|
39631
|
+
ExtendedTrianglePool.releasePrimitive(triangle3);
|
|
39632
|
+
ExtendedTrianglePool.releasePrimitive(triangle22);
|
|
39633
|
+
if (closestDistance === Infinity) {
|
|
39634
|
+
return null;
|
|
39635
|
+
}
|
|
39636
|
+
if (!target1.point) {
|
|
39637
|
+
target1.point = tempTargetDest1.clone();
|
|
39638
|
+
} else {
|
|
39639
|
+
target1.point.copy(tempTargetDest1);
|
|
39640
|
+
}
|
|
39641
|
+
target1.distance = closestDistance, target1.faceIndex = closestDistanceTriIndex;
|
|
39642
|
+
if (target2) {
|
|
39643
|
+
if (!target2.point)
|
|
39644
|
+
target2.point = tempTargetDest2.clone();
|
|
39645
|
+
else
|
|
39646
|
+
target2.point.copy(tempTargetDest2);
|
|
39647
|
+
target2.point.applyMatrix4(tempMatrix$1);
|
|
39648
|
+
tempTargetDest1.applyMatrix4(tempMatrix$1);
|
|
39649
|
+
target2.distance = tempTargetDest1.sub(target2.point).length();
|
|
39650
|
+
target2.faceIndex = closestDistanceOtherTriIndex;
|
|
39651
|
+
}
|
|
39652
|
+
return target1;
|
|
39653
|
+
}
|
|
39654
|
+
function refit_indirect(bvh, nodeIndices = null) {
|
|
39655
|
+
if (nodeIndices && Array.isArray(nodeIndices)) {
|
|
39656
|
+
nodeIndices = new Set(nodeIndices);
|
|
39657
|
+
}
|
|
39658
|
+
const geometry = bvh.geometry;
|
|
39659
|
+
const indexArr = geometry.index ? geometry.index.array : null;
|
|
39660
|
+
const posAttr = geometry.attributes.position;
|
|
39661
|
+
let buffer, uint32Array, uint16Array, float32Array;
|
|
39662
|
+
let byteOffset = 0;
|
|
39663
|
+
const roots = bvh._roots;
|
|
39664
|
+
for (let i = 0, l = roots.length; i < l; i++) {
|
|
39665
|
+
buffer = roots[i];
|
|
39666
|
+
uint32Array = new Uint32Array(buffer);
|
|
39667
|
+
uint16Array = new Uint16Array(buffer);
|
|
39668
|
+
float32Array = new Float32Array(buffer);
|
|
39669
|
+
_traverse2(0, byteOffset);
|
|
39670
|
+
byteOffset += buffer.byteLength;
|
|
39671
|
+
}
|
|
39672
|
+
function _traverse2(node32Index, byteOffset2, force = false) {
|
|
39673
|
+
const node16Index = node32Index * 2;
|
|
39674
|
+
const isLeaf = uint16Array[node16Index + 15] === IS_LEAFNODE_FLAG;
|
|
39675
|
+
if (isLeaf) {
|
|
39676
|
+
const offset = uint32Array[node32Index + 6];
|
|
39677
|
+
const count = uint16Array[node16Index + 14];
|
|
39678
|
+
let minx = Infinity;
|
|
39679
|
+
let miny = Infinity;
|
|
39680
|
+
let minz = Infinity;
|
|
39681
|
+
let maxx = -Infinity;
|
|
39682
|
+
let maxy = -Infinity;
|
|
39683
|
+
let maxz = -Infinity;
|
|
39684
|
+
for (let i = offset, l = offset + count; i < l; i++) {
|
|
39685
|
+
const t2 = 3 * bvh.resolveTriangleIndex(i);
|
|
39686
|
+
for (let j = 0; j < 3; j++) {
|
|
39687
|
+
let index = t2 + j;
|
|
39688
|
+
index = indexArr ? indexArr[index] : index;
|
|
39689
|
+
const x2 = posAttr.getX(index);
|
|
39690
|
+
const y = posAttr.getY(index);
|
|
39691
|
+
const z = posAttr.getZ(index);
|
|
39692
|
+
if (x2 < minx)
|
|
39693
|
+
minx = x2;
|
|
39694
|
+
if (x2 > maxx)
|
|
39695
|
+
maxx = x2;
|
|
39696
|
+
if (y < miny)
|
|
39697
|
+
miny = y;
|
|
39698
|
+
if (y > maxy)
|
|
39699
|
+
maxy = y;
|
|
39700
|
+
if (z < minz)
|
|
39701
|
+
minz = z;
|
|
39702
|
+
if (z > maxz)
|
|
39703
|
+
maxz = z;
|
|
39704
|
+
}
|
|
39705
|
+
}
|
|
39706
|
+
if (float32Array[node32Index + 0] !== minx || float32Array[node32Index + 1] !== miny || float32Array[node32Index + 2] !== minz || float32Array[node32Index + 3] !== maxx || float32Array[node32Index + 4] !== maxy || float32Array[node32Index + 5] !== maxz) {
|
|
39707
|
+
float32Array[node32Index + 0] = minx;
|
|
39708
|
+
float32Array[node32Index + 1] = miny;
|
|
39709
|
+
float32Array[node32Index + 2] = minz;
|
|
39710
|
+
float32Array[node32Index + 3] = maxx;
|
|
39711
|
+
float32Array[node32Index + 4] = maxy;
|
|
39712
|
+
float32Array[node32Index + 5] = maxz;
|
|
39713
|
+
return true;
|
|
39714
|
+
} else {
|
|
39715
|
+
return false;
|
|
39716
|
+
}
|
|
39717
|
+
} else {
|
|
39718
|
+
const left = node32Index + 8;
|
|
39719
|
+
const right = uint32Array[node32Index + 6];
|
|
39720
|
+
const offsetLeft = left + byteOffset2;
|
|
39721
|
+
const offsetRight = right + byteOffset2;
|
|
39722
|
+
let forceChildren = force;
|
|
39723
|
+
let includesLeft = false;
|
|
39724
|
+
let includesRight = false;
|
|
39725
|
+
if (nodeIndices) {
|
|
39726
|
+
if (!forceChildren) {
|
|
39727
|
+
includesLeft = nodeIndices.has(offsetLeft);
|
|
39728
|
+
includesRight = nodeIndices.has(offsetRight);
|
|
39729
|
+
forceChildren = !includesLeft && !includesRight;
|
|
39730
|
+
}
|
|
39731
|
+
} else {
|
|
39732
|
+
includesLeft = true;
|
|
39733
|
+
includesRight = true;
|
|
39734
|
+
}
|
|
39735
|
+
const traverseLeft = forceChildren || includesLeft;
|
|
39736
|
+
const traverseRight = forceChildren || includesRight;
|
|
39737
|
+
let leftChange = false;
|
|
39738
|
+
if (traverseLeft) {
|
|
39739
|
+
leftChange = _traverse2(left, byteOffset2, forceChildren);
|
|
39740
|
+
}
|
|
39741
|
+
let rightChange = false;
|
|
39742
|
+
if (traverseRight) {
|
|
39743
|
+
rightChange = _traverse2(right, byteOffset2, forceChildren);
|
|
39744
|
+
}
|
|
39745
|
+
const didChange = leftChange || rightChange;
|
|
39746
|
+
if (didChange) {
|
|
39747
|
+
for (let i = 0; i < 3; i++) {
|
|
39748
|
+
const lefti = left + i;
|
|
39749
|
+
const righti = right + i;
|
|
39750
|
+
const minLeftValue = float32Array[lefti];
|
|
39751
|
+
const maxLeftValue = float32Array[lefti + 3];
|
|
39752
|
+
const minRightValue = float32Array[righti];
|
|
39753
|
+
const maxRightValue = float32Array[righti + 3];
|
|
39754
|
+
float32Array[node32Index + i] = minLeftValue < minRightValue ? minLeftValue : minRightValue;
|
|
39755
|
+
float32Array[node32Index + i + 3] = maxLeftValue > maxRightValue ? maxLeftValue : maxRightValue;
|
|
39756
|
+
}
|
|
39757
|
+
}
|
|
39758
|
+
return didChange;
|
|
39759
|
+
}
|
|
39760
|
+
}
|
|
39761
|
+
}
|
|
39762
|
+
const _boxIntersection$1 = /* @__PURE__ */ new Vector3();
|
|
39763
|
+
function raycast_indirect(bvh, root, side, ray, intersects) {
|
|
39764
|
+
BufferStack.setBuffer(bvh._roots[root]);
|
|
39765
|
+
_raycast(0, bvh, side, ray, intersects);
|
|
39766
|
+
BufferStack.clearBuffer();
|
|
39767
|
+
}
|
|
39768
|
+
function _raycast(nodeIndex32, bvh, side, ray, intersects) {
|
|
39769
|
+
const { float32Array, uint16Array, uint32Array } = BufferStack;
|
|
39770
|
+
const nodeIndex16 = nodeIndex32 * 2;
|
|
39771
|
+
const isLeaf = IS_LEAF(nodeIndex16, uint16Array);
|
|
39772
|
+
if (isLeaf) {
|
|
39773
|
+
const offset = OFFSET(nodeIndex32, uint32Array);
|
|
39774
|
+
const count = COUNT(nodeIndex16, uint16Array);
|
|
39775
|
+
intersectTris_indirect(bvh, side, ray, offset, count, intersects);
|
|
39776
|
+
} else {
|
|
39777
|
+
const leftIndex = LEFT_NODE(nodeIndex32);
|
|
39778
|
+
if (intersectRay(leftIndex, float32Array, ray, _boxIntersection$1)) {
|
|
39779
|
+
_raycast(leftIndex, bvh, side, ray, intersects);
|
|
39780
|
+
}
|
|
39781
|
+
const rightIndex = RIGHT_NODE(nodeIndex32, uint32Array);
|
|
39782
|
+
if (intersectRay(rightIndex, float32Array, ray, _boxIntersection$1)) {
|
|
39783
|
+
_raycast(rightIndex, bvh, side, ray, intersects);
|
|
39784
|
+
}
|
|
39785
|
+
}
|
|
39786
|
+
}
|
|
39787
|
+
const _boxIntersection = /* @__PURE__ */ new Vector3();
|
|
39788
|
+
const _xyzFields = ["x", "y", "z"];
|
|
39789
|
+
function raycastFirst_indirect(bvh, root, side, ray) {
|
|
39790
|
+
BufferStack.setBuffer(bvh._roots[root]);
|
|
39791
|
+
const result = _raycastFirst(0, bvh, side, ray);
|
|
39792
|
+
BufferStack.clearBuffer();
|
|
39793
|
+
return result;
|
|
39794
|
+
}
|
|
39795
|
+
function _raycastFirst(nodeIndex32, bvh, side, ray) {
|
|
39796
|
+
const { float32Array, uint16Array, uint32Array } = BufferStack;
|
|
39797
|
+
let nodeIndex16 = nodeIndex32 * 2;
|
|
39798
|
+
const isLeaf = IS_LEAF(nodeIndex16, uint16Array);
|
|
39799
|
+
if (isLeaf) {
|
|
39800
|
+
const offset = OFFSET(nodeIndex32, uint32Array);
|
|
39801
|
+
const count = COUNT(nodeIndex16, uint16Array);
|
|
39802
|
+
return intersectClosestTri_indirect(bvh, side, ray, offset, count);
|
|
39803
|
+
} else {
|
|
39804
|
+
const splitAxis = SPLIT_AXIS(nodeIndex32, uint32Array);
|
|
39805
|
+
const xyzAxis = _xyzFields[splitAxis];
|
|
39806
|
+
const rayDir = ray.direction[xyzAxis];
|
|
39807
|
+
const leftToRight = rayDir >= 0;
|
|
39808
|
+
let c1, c2;
|
|
39809
|
+
if (leftToRight) {
|
|
39810
|
+
c1 = LEFT_NODE(nodeIndex32);
|
|
39811
|
+
c2 = RIGHT_NODE(nodeIndex32, uint32Array);
|
|
39812
|
+
} else {
|
|
39813
|
+
c1 = RIGHT_NODE(nodeIndex32, uint32Array);
|
|
39814
|
+
c2 = LEFT_NODE(nodeIndex32);
|
|
39815
|
+
}
|
|
39816
|
+
const c1Intersection = intersectRay(c1, float32Array, ray, _boxIntersection);
|
|
39817
|
+
const c1Result = c1Intersection ? _raycastFirst(c1, bvh, side, ray) : null;
|
|
39818
|
+
if (c1Result) {
|
|
39819
|
+
const point = c1Result.point[xyzAxis];
|
|
39820
|
+
const isOutside = leftToRight ? point <= float32Array[c2 + splitAxis] : (
|
|
39821
|
+
// min bounding data
|
|
39822
|
+
point >= float32Array[c2 + splitAxis + 3]
|
|
39823
|
+
);
|
|
39824
|
+
if (isOutside) {
|
|
39825
|
+
return c1Result;
|
|
39826
|
+
}
|
|
39827
|
+
}
|
|
39828
|
+
const c2Intersection = intersectRay(c2, float32Array, ray, _boxIntersection);
|
|
39829
|
+
const c2Result = c2Intersection ? _raycastFirst(c2, bvh, side, ray) : null;
|
|
39830
|
+
if (c1Result && c2Result) {
|
|
39831
|
+
return c1Result.distance <= c2Result.distance ? c1Result : c2Result;
|
|
39832
|
+
} else {
|
|
39833
|
+
return c1Result || c2Result || null;
|
|
39834
|
+
}
|
|
39835
|
+
}
|
|
39836
|
+
}
|
|
39837
|
+
const boundingBox = /* @__PURE__ */ new Box3();
|
|
39838
|
+
const triangle = /* @__PURE__ */ new ExtendedTriangle();
|
|
39839
|
+
const triangle2 = /* @__PURE__ */ new ExtendedTriangle();
|
|
39840
|
+
const invertedMat = /* @__PURE__ */ new Matrix4();
|
|
39841
|
+
const obb$2 = /* @__PURE__ */ new OrientedBox();
|
|
39842
|
+
const obb2$1 = /* @__PURE__ */ new OrientedBox();
|
|
39843
|
+
function intersectsGeometry_indirect(bvh, root, otherGeometry, geometryToBvh) {
|
|
39844
|
+
BufferStack.setBuffer(bvh._roots[root]);
|
|
39845
|
+
const result = _intersectsGeometry(0, bvh, otherGeometry, geometryToBvh);
|
|
39846
|
+
BufferStack.clearBuffer();
|
|
39847
|
+
return result;
|
|
39848
|
+
}
|
|
39849
|
+
function _intersectsGeometry(nodeIndex32, bvh, otherGeometry, geometryToBvh, cachedObb = null) {
|
|
39850
|
+
const { float32Array, uint16Array, uint32Array } = BufferStack;
|
|
39851
|
+
let nodeIndex16 = nodeIndex32 * 2;
|
|
39852
|
+
if (cachedObb === null) {
|
|
39853
|
+
if (!otherGeometry.boundingBox) {
|
|
39854
|
+
otherGeometry.computeBoundingBox();
|
|
39855
|
+
}
|
|
39856
|
+
obb$2.set(otherGeometry.boundingBox.min, otherGeometry.boundingBox.max, geometryToBvh);
|
|
39857
|
+
cachedObb = obb$2;
|
|
39858
|
+
}
|
|
39859
|
+
const isLeaf = IS_LEAF(nodeIndex16, uint16Array);
|
|
39860
|
+
if (isLeaf) {
|
|
39861
|
+
const thisGeometry = bvh.geometry;
|
|
39862
|
+
const thisIndex = thisGeometry.index;
|
|
39863
|
+
const thisPos = thisGeometry.attributes.position;
|
|
39864
|
+
const index = otherGeometry.index;
|
|
39865
|
+
const pos = otherGeometry.attributes.position;
|
|
39866
|
+
const offset = OFFSET(nodeIndex32, uint32Array);
|
|
39867
|
+
const count = COUNT(nodeIndex16, uint16Array);
|
|
39868
|
+
invertedMat.copy(geometryToBvh).invert();
|
|
39869
|
+
if (otherGeometry.boundsTree) {
|
|
39870
|
+
arrayToBox(BOUNDING_DATA_INDEX(nodeIndex32), float32Array, obb2$1);
|
|
39871
|
+
obb2$1.matrix.copy(invertedMat);
|
|
39872
|
+
obb2$1.needsUpdate = true;
|
|
39873
|
+
const res = otherGeometry.boundsTree.shapecast({
|
|
39874
|
+
intersectsBounds: (box) => obb2$1.intersectsBox(box),
|
|
39875
|
+
intersectsTriangle: (tri) => {
|
|
39876
|
+
tri.a.applyMatrix4(geometryToBvh);
|
|
39877
|
+
tri.b.applyMatrix4(geometryToBvh);
|
|
39878
|
+
tri.c.applyMatrix4(geometryToBvh);
|
|
39879
|
+
tri.needsUpdate = true;
|
|
39880
|
+
for (let i = offset, l = count + offset; i < l; i++) {
|
|
39881
|
+
setTriangle(triangle2, 3 * bvh.resolveTriangleIndex(i), thisIndex, thisPos);
|
|
39882
|
+
triangle2.needsUpdate = true;
|
|
39883
|
+
if (tri.intersectsTriangle(triangle2)) {
|
|
39884
|
+
return true;
|
|
39885
|
+
}
|
|
39886
|
+
}
|
|
39887
|
+
return false;
|
|
39888
|
+
}
|
|
39889
|
+
});
|
|
39890
|
+
return res;
|
|
39891
|
+
} else {
|
|
39892
|
+
for (let i = offset, l = count + offset; i < l; i++) {
|
|
39893
|
+
const ti = bvh.resolveTriangleIndex(i);
|
|
39894
|
+
setTriangle(triangle, 3 * ti, thisIndex, thisPos);
|
|
39895
|
+
triangle.a.applyMatrix4(invertedMat);
|
|
39896
|
+
triangle.b.applyMatrix4(invertedMat);
|
|
39897
|
+
triangle.c.applyMatrix4(invertedMat);
|
|
39898
|
+
triangle.needsUpdate = true;
|
|
39899
|
+
for (let i2 = 0, l2 = index.count; i2 < l2; i2 += 3) {
|
|
39900
|
+
setTriangle(triangle2, i2, index, pos);
|
|
39901
|
+
triangle2.needsUpdate = true;
|
|
39902
|
+
if (triangle.intersectsTriangle(triangle2)) {
|
|
39903
|
+
return true;
|
|
39904
|
+
}
|
|
39905
|
+
}
|
|
39906
|
+
}
|
|
39907
|
+
}
|
|
39908
|
+
} else {
|
|
39909
|
+
const left = nodeIndex32 + 8;
|
|
39910
|
+
const right = uint32Array[nodeIndex32 + 6];
|
|
39911
|
+
arrayToBox(BOUNDING_DATA_INDEX(left), float32Array, boundingBox);
|
|
39912
|
+
const leftIntersection = cachedObb.intersectsBox(boundingBox) && _intersectsGeometry(left, bvh, otherGeometry, geometryToBvh, cachedObb);
|
|
39913
|
+
if (leftIntersection)
|
|
39914
|
+
return true;
|
|
39915
|
+
arrayToBox(BOUNDING_DATA_INDEX(right), float32Array, boundingBox);
|
|
39916
|
+
const rightIntersection = cachedObb.intersectsBox(boundingBox) && _intersectsGeometry(right, bvh, otherGeometry, geometryToBvh, cachedObb);
|
|
39917
|
+
if (rightIntersection)
|
|
39918
|
+
return true;
|
|
39919
|
+
return false;
|
|
39920
|
+
}
|
|
39921
|
+
}
|
|
39922
|
+
const tempMatrix = /* @__PURE__ */ new Matrix4();
|
|
39923
|
+
const obb$1 = /* @__PURE__ */ new OrientedBox();
|
|
39924
|
+
const obb2 = /* @__PURE__ */ new OrientedBox();
|
|
39925
|
+
const temp1 = /* @__PURE__ */ new Vector3();
|
|
39926
|
+
const temp2 = /* @__PURE__ */ new Vector3();
|
|
39927
|
+
const temp3 = /* @__PURE__ */ new Vector3();
|
|
39928
|
+
const temp4 = /* @__PURE__ */ new Vector3();
|
|
39929
|
+
function closestPointToGeometry_indirect(bvh, otherGeometry, geometryToBvh, target1 = {}, target2 = {}, minThreshold = 0, maxThreshold = Infinity) {
|
|
39930
|
+
if (!otherGeometry.boundingBox) {
|
|
39931
|
+
otherGeometry.computeBoundingBox();
|
|
39932
|
+
}
|
|
39933
|
+
obb$1.set(otherGeometry.boundingBox.min, otherGeometry.boundingBox.max, geometryToBvh);
|
|
39934
|
+
obb$1.needsUpdate = true;
|
|
39935
|
+
const geometry = bvh.geometry;
|
|
39936
|
+
const pos = geometry.attributes.position;
|
|
39937
|
+
const index = geometry.index;
|
|
39938
|
+
const otherPos = otherGeometry.attributes.position;
|
|
39939
|
+
const otherIndex = otherGeometry.index;
|
|
39940
|
+
const triangle3 = ExtendedTrianglePool.getPrimitive();
|
|
39941
|
+
const triangle22 = ExtendedTrianglePool.getPrimitive();
|
|
39942
|
+
let tempTarget1 = temp1;
|
|
39943
|
+
let tempTargetDest1 = temp2;
|
|
39944
|
+
let tempTarget2 = null;
|
|
39945
|
+
let tempTargetDest2 = null;
|
|
39946
|
+
if (target2) {
|
|
39947
|
+
tempTarget2 = temp3;
|
|
39948
|
+
tempTargetDest2 = temp4;
|
|
39949
|
+
}
|
|
39950
|
+
let closestDistance = Infinity;
|
|
39951
|
+
let closestDistanceTriIndex = null;
|
|
39952
|
+
let closestDistanceOtherTriIndex = null;
|
|
39953
|
+
tempMatrix.copy(geometryToBvh).invert();
|
|
39954
|
+
obb2.matrix.copy(tempMatrix);
|
|
39955
|
+
bvh.shapecast(
|
|
39956
|
+
{
|
|
39957
|
+
boundsTraverseOrder: (box) => {
|
|
39958
|
+
return obb$1.distanceToBox(box);
|
|
39959
|
+
},
|
|
39960
|
+
intersectsBounds: (box, isLeaf, score) => {
|
|
39961
|
+
if (score < closestDistance && score < maxThreshold) {
|
|
39962
|
+
if (isLeaf) {
|
|
39963
|
+
obb2.min.copy(box.min);
|
|
39964
|
+
obb2.max.copy(box.max);
|
|
39965
|
+
obb2.needsUpdate = true;
|
|
39966
|
+
}
|
|
39967
|
+
return true;
|
|
39968
|
+
}
|
|
39969
|
+
return false;
|
|
39970
|
+
},
|
|
39971
|
+
intersectsRange: (offset, count) => {
|
|
39972
|
+
if (otherGeometry.boundsTree) {
|
|
39973
|
+
const otherBvh = otherGeometry.boundsTree;
|
|
39974
|
+
return otherBvh.shapecast({
|
|
39975
|
+
boundsTraverseOrder: (box) => {
|
|
39976
|
+
return obb2.distanceToBox(box);
|
|
39977
|
+
},
|
|
39978
|
+
intersectsBounds: (box, isLeaf, score) => {
|
|
39979
|
+
return score < closestDistance && score < maxThreshold;
|
|
39980
|
+
},
|
|
39981
|
+
intersectsRange: (otherOffset, otherCount) => {
|
|
39982
|
+
for (let i2 = otherOffset, l2 = otherOffset + otherCount; i2 < l2; i2++) {
|
|
39983
|
+
const ti2 = otherBvh.resolveTriangleIndex(i2);
|
|
39984
|
+
setTriangle(triangle22, 3 * ti2, otherIndex, otherPos);
|
|
39985
|
+
triangle22.a.applyMatrix4(geometryToBvh);
|
|
39986
|
+
triangle22.b.applyMatrix4(geometryToBvh);
|
|
39987
|
+
triangle22.c.applyMatrix4(geometryToBvh);
|
|
39988
|
+
triangle22.needsUpdate = true;
|
|
39989
|
+
for (let i = offset, l = offset + count; i < l; i++) {
|
|
39990
|
+
const ti = bvh.resolveTriangleIndex(i);
|
|
39991
|
+
setTriangle(triangle3, 3 * ti, index, pos);
|
|
39992
|
+
triangle3.needsUpdate = true;
|
|
39993
|
+
const dist = triangle3.distanceToTriangle(triangle22, tempTarget1, tempTarget2);
|
|
39994
|
+
if (dist < closestDistance) {
|
|
39995
|
+
tempTargetDest1.copy(tempTarget1);
|
|
39996
|
+
if (tempTargetDest2) {
|
|
39997
|
+
tempTargetDest2.copy(tempTarget2);
|
|
39998
|
+
}
|
|
39999
|
+
closestDistance = dist;
|
|
40000
|
+
closestDistanceTriIndex = i;
|
|
40001
|
+
closestDistanceOtherTriIndex = i2;
|
|
40002
|
+
}
|
|
40003
|
+
if (dist < minThreshold) {
|
|
40004
|
+
return true;
|
|
40005
|
+
}
|
|
40006
|
+
}
|
|
40007
|
+
}
|
|
40008
|
+
}
|
|
40009
|
+
});
|
|
40010
|
+
} else {
|
|
40011
|
+
const triCount = getTriCount(otherGeometry);
|
|
40012
|
+
for (let i2 = 0, l2 = triCount; i2 < l2; i2++) {
|
|
40013
|
+
setTriangle(triangle22, 3 * i2, otherIndex, otherPos);
|
|
40014
|
+
triangle22.a.applyMatrix4(geometryToBvh);
|
|
40015
|
+
triangle22.b.applyMatrix4(geometryToBvh);
|
|
40016
|
+
triangle22.c.applyMatrix4(geometryToBvh);
|
|
40017
|
+
triangle22.needsUpdate = true;
|
|
40018
|
+
for (let i = offset, l = offset + count; i < l; i++) {
|
|
40019
|
+
const ti = bvh.resolveTriangleIndex(i);
|
|
40020
|
+
setTriangle(triangle3, 3 * ti, index, pos);
|
|
40021
|
+
triangle3.needsUpdate = true;
|
|
40022
|
+
const dist = triangle3.distanceToTriangle(triangle22, tempTarget1, tempTarget2);
|
|
40023
|
+
if (dist < closestDistance) {
|
|
40024
|
+
tempTargetDest1.copy(tempTarget1);
|
|
40025
|
+
if (tempTargetDest2) {
|
|
40026
|
+
tempTargetDest2.copy(tempTarget2);
|
|
40027
|
+
}
|
|
40028
|
+
closestDistance = dist;
|
|
40029
|
+
closestDistanceTriIndex = i;
|
|
40030
|
+
closestDistanceOtherTriIndex = i2;
|
|
40031
|
+
}
|
|
40032
|
+
if (dist < minThreshold) {
|
|
40033
|
+
return true;
|
|
40034
|
+
}
|
|
40035
|
+
}
|
|
40036
|
+
}
|
|
40037
|
+
}
|
|
40038
|
+
}
|
|
40039
|
+
}
|
|
40040
|
+
);
|
|
40041
|
+
ExtendedTrianglePool.releasePrimitive(triangle3);
|
|
40042
|
+
ExtendedTrianglePool.releasePrimitive(triangle22);
|
|
40043
|
+
if (closestDistance === Infinity) {
|
|
40044
|
+
return null;
|
|
40045
|
+
}
|
|
40046
|
+
if (!target1.point) {
|
|
40047
|
+
target1.point = tempTargetDest1.clone();
|
|
40048
|
+
} else {
|
|
40049
|
+
target1.point.copy(tempTargetDest1);
|
|
40050
|
+
}
|
|
40051
|
+
target1.distance = closestDistance, target1.faceIndex = closestDistanceTriIndex;
|
|
40052
|
+
if (target2) {
|
|
40053
|
+
if (!target2.point)
|
|
40054
|
+
target2.point = tempTargetDest2.clone();
|
|
40055
|
+
else
|
|
40056
|
+
target2.point.copy(tempTargetDest2);
|
|
40057
|
+
target2.point.applyMatrix4(tempMatrix);
|
|
40058
|
+
tempTargetDest1.applyMatrix4(tempMatrix);
|
|
40059
|
+
target2.distance = tempTargetDest1.sub(target2.point).length();
|
|
40060
|
+
target2.faceIndex = closestDistanceOtherTriIndex;
|
|
40061
|
+
}
|
|
40062
|
+
return target1;
|
|
40063
|
+
}
|
|
40064
|
+
function isSharedArrayBufferSupported() {
|
|
40065
|
+
return typeof SharedArrayBuffer !== "undefined";
|
|
40066
|
+
}
|
|
40067
|
+
const _bufferStack1 = new BufferStack.constructor();
|
|
40068
|
+
const _bufferStack2 = new BufferStack.constructor();
|
|
40069
|
+
const _boxPool = new PrimitivePool(() => new Box3());
|
|
40070
|
+
const _leftBox1 = new Box3();
|
|
40071
|
+
const _rightBox1 = new Box3();
|
|
40072
|
+
const _leftBox2 = new Box3();
|
|
40073
|
+
const _rightBox2 = new Box3();
|
|
40074
|
+
let _active = false;
|
|
40075
|
+
function bvhcast(bvh, otherBvh, matrixToLocal, intersectsRanges) {
|
|
40076
|
+
if (_active) {
|
|
40077
|
+
throw new Error("MeshBVH: Recursive calls to bvhcast not supported.");
|
|
40078
|
+
}
|
|
40079
|
+
_active = true;
|
|
40080
|
+
const roots = bvh._roots;
|
|
40081
|
+
const otherRoots = otherBvh._roots;
|
|
40082
|
+
let result;
|
|
40083
|
+
let offset1 = 0;
|
|
40084
|
+
let offset2 = 0;
|
|
40085
|
+
const invMat = new Matrix4().copy(matrixToLocal).invert();
|
|
40086
|
+
for (let i = 0, il = roots.length; i < il; i++) {
|
|
40087
|
+
_bufferStack1.setBuffer(roots[i]);
|
|
40088
|
+
offset2 = 0;
|
|
40089
|
+
const localBox = _boxPool.getPrimitive();
|
|
40090
|
+
arrayToBox(BOUNDING_DATA_INDEX(0), _bufferStack1.float32Array, localBox);
|
|
40091
|
+
localBox.applyMatrix4(invMat);
|
|
40092
|
+
for (let j = 0, jl = otherRoots.length; j < jl; j++) {
|
|
40093
|
+
_bufferStack2.setBuffer(otherRoots[i]);
|
|
40094
|
+
result = _traverse(
|
|
40095
|
+
0,
|
|
40096
|
+
0,
|
|
40097
|
+
matrixToLocal,
|
|
40098
|
+
invMat,
|
|
40099
|
+
intersectsRanges,
|
|
40100
|
+
offset1,
|
|
40101
|
+
offset2,
|
|
40102
|
+
0,
|
|
40103
|
+
0,
|
|
40104
|
+
localBox
|
|
40105
|
+
);
|
|
40106
|
+
_bufferStack2.clearBuffer();
|
|
40107
|
+
offset2 += otherRoots[j].length;
|
|
40108
|
+
if (result) {
|
|
40109
|
+
break;
|
|
40110
|
+
}
|
|
40111
|
+
}
|
|
40112
|
+
_boxPool.releasePrimitive(localBox);
|
|
40113
|
+
_bufferStack1.clearBuffer();
|
|
40114
|
+
offset1 += roots[i].length;
|
|
40115
|
+
if (result) {
|
|
40116
|
+
break;
|
|
40117
|
+
}
|
|
40118
|
+
}
|
|
40119
|
+
_active = false;
|
|
40120
|
+
return result;
|
|
40121
|
+
}
|
|
40122
|
+
function _traverse(node1Index32, node2Index32, matrix2to1, matrix1to2, intersectsRangesFunc, node1IndexByteOffset = 0, node2IndexByteOffset = 0, depth1 = 0, depth2 = 0, currBox = null, reversed = false) {
|
|
40123
|
+
let bufferStack1, bufferStack2;
|
|
40124
|
+
if (reversed) {
|
|
40125
|
+
bufferStack1 = _bufferStack2;
|
|
40126
|
+
bufferStack2 = _bufferStack1;
|
|
40127
|
+
} else {
|
|
40128
|
+
bufferStack1 = _bufferStack1;
|
|
40129
|
+
bufferStack2 = _bufferStack2;
|
|
40130
|
+
}
|
|
40131
|
+
const float32Array1 = bufferStack1.float32Array, uint32Array1 = bufferStack1.uint32Array, uint16Array1 = bufferStack1.uint16Array, float32Array2 = bufferStack2.float32Array, uint32Array2 = bufferStack2.uint32Array, uint16Array2 = bufferStack2.uint16Array;
|
|
40132
|
+
const node1Index16 = node1Index32 * 2;
|
|
40133
|
+
const node2Index16 = node2Index32 * 2;
|
|
40134
|
+
const isLeaf1 = IS_LEAF(node1Index16, uint16Array1);
|
|
40135
|
+
const isLeaf2 = IS_LEAF(node2Index16, uint16Array2);
|
|
40136
|
+
let result = false;
|
|
40137
|
+
if (isLeaf2 && isLeaf1) {
|
|
40138
|
+
if (reversed) {
|
|
40139
|
+
result = intersectsRangesFunc(
|
|
40140
|
+
OFFSET(node2Index32, uint32Array2),
|
|
40141
|
+
COUNT(node2Index32 * 2, uint16Array2),
|
|
40142
|
+
OFFSET(node1Index32, uint32Array1),
|
|
40143
|
+
COUNT(node1Index32 * 2, uint16Array1),
|
|
40144
|
+
depth2,
|
|
40145
|
+
node2IndexByteOffset + node2Index32,
|
|
40146
|
+
depth1,
|
|
40147
|
+
node1IndexByteOffset + node1Index32
|
|
40148
|
+
);
|
|
40149
|
+
} else {
|
|
40150
|
+
result = intersectsRangesFunc(
|
|
40151
|
+
OFFSET(node1Index32, uint32Array1),
|
|
40152
|
+
COUNT(node1Index32 * 2, uint16Array1),
|
|
40153
|
+
OFFSET(node2Index32, uint32Array2),
|
|
40154
|
+
COUNT(node2Index32 * 2, uint16Array2),
|
|
40155
|
+
depth1,
|
|
40156
|
+
node1IndexByteOffset + node1Index32,
|
|
40157
|
+
depth2,
|
|
40158
|
+
node2IndexByteOffset + node2Index32
|
|
40159
|
+
);
|
|
40160
|
+
}
|
|
40161
|
+
} else if (isLeaf2) {
|
|
40162
|
+
const newBox = _boxPool.getPrimitive();
|
|
40163
|
+
arrayToBox(BOUNDING_DATA_INDEX(node2Index32), float32Array2, newBox);
|
|
40164
|
+
newBox.applyMatrix4(matrix2to1);
|
|
40165
|
+
const cl1 = LEFT_NODE(node1Index32);
|
|
40166
|
+
const cr1 = RIGHT_NODE(node1Index32, uint32Array1);
|
|
40167
|
+
arrayToBox(BOUNDING_DATA_INDEX(cl1), float32Array1, _leftBox1);
|
|
40168
|
+
arrayToBox(BOUNDING_DATA_INDEX(cr1), float32Array1, _rightBox1);
|
|
40169
|
+
const intersectCl1 = newBox.intersectsBox(_leftBox1);
|
|
40170
|
+
const intersectCr1 = newBox.intersectsBox(_rightBox1);
|
|
40171
|
+
result = intersectCl1 && _traverse(
|
|
40172
|
+
node2Index32,
|
|
40173
|
+
cl1,
|
|
40174
|
+
matrix1to2,
|
|
40175
|
+
matrix2to1,
|
|
40176
|
+
intersectsRangesFunc,
|
|
40177
|
+
node2IndexByteOffset,
|
|
40178
|
+
node1IndexByteOffset,
|
|
40179
|
+
depth2,
|
|
40180
|
+
depth1 + 1,
|
|
40181
|
+
newBox,
|
|
40182
|
+
!reversed
|
|
40183
|
+
) || intersectCr1 && _traverse(
|
|
40184
|
+
node2Index32,
|
|
40185
|
+
cr1,
|
|
40186
|
+
matrix1to2,
|
|
40187
|
+
matrix2to1,
|
|
40188
|
+
intersectsRangesFunc,
|
|
40189
|
+
node2IndexByteOffset,
|
|
40190
|
+
node1IndexByteOffset,
|
|
40191
|
+
depth2,
|
|
40192
|
+
depth1 + 1,
|
|
40193
|
+
newBox,
|
|
40194
|
+
!reversed
|
|
40195
|
+
);
|
|
40196
|
+
_boxPool.releasePrimitive(newBox);
|
|
40197
|
+
} else {
|
|
40198
|
+
const cl2 = LEFT_NODE(node2Index32);
|
|
40199
|
+
const cr2 = RIGHT_NODE(node2Index32, uint32Array2);
|
|
40200
|
+
arrayToBox(BOUNDING_DATA_INDEX(cl2), float32Array2, _leftBox2);
|
|
40201
|
+
arrayToBox(BOUNDING_DATA_INDEX(cr2), float32Array2, _rightBox2);
|
|
40202
|
+
const leftIntersects = currBox.intersectsBox(_leftBox2);
|
|
40203
|
+
const rightIntersects = currBox.intersectsBox(_rightBox2);
|
|
40204
|
+
if (leftIntersects && rightIntersects) {
|
|
40205
|
+
result = _traverse(
|
|
40206
|
+
node1Index32,
|
|
40207
|
+
cl2,
|
|
40208
|
+
matrix2to1,
|
|
40209
|
+
matrix1to2,
|
|
40210
|
+
intersectsRangesFunc,
|
|
40211
|
+
node1IndexByteOffset,
|
|
40212
|
+
node2IndexByteOffset,
|
|
40213
|
+
depth1,
|
|
40214
|
+
depth2 + 1,
|
|
40215
|
+
currBox,
|
|
40216
|
+
reversed
|
|
40217
|
+
) || _traverse(
|
|
40218
|
+
node1Index32,
|
|
40219
|
+
cr2,
|
|
40220
|
+
matrix2to1,
|
|
40221
|
+
matrix1to2,
|
|
40222
|
+
intersectsRangesFunc,
|
|
40223
|
+
node1IndexByteOffset,
|
|
40224
|
+
node2IndexByteOffset,
|
|
40225
|
+
depth1,
|
|
40226
|
+
depth2 + 1,
|
|
40227
|
+
currBox,
|
|
40228
|
+
reversed
|
|
40229
|
+
);
|
|
40230
|
+
} else if (leftIntersects) {
|
|
40231
|
+
if (isLeaf1) {
|
|
40232
|
+
result = _traverse(
|
|
40233
|
+
node1Index32,
|
|
40234
|
+
cl2,
|
|
40235
|
+
matrix2to1,
|
|
40236
|
+
matrix1to2,
|
|
40237
|
+
intersectsRangesFunc,
|
|
40238
|
+
node1IndexByteOffset,
|
|
40239
|
+
node2IndexByteOffset,
|
|
40240
|
+
depth1,
|
|
40241
|
+
depth2 + 1,
|
|
40242
|
+
currBox,
|
|
40243
|
+
reversed
|
|
40244
|
+
);
|
|
40245
|
+
} else {
|
|
40246
|
+
const newBox = _boxPool.getPrimitive();
|
|
40247
|
+
newBox.copy(_leftBox2).applyMatrix4(matrix2to1);
|
|
40248
|
+
const cl1 = LEFT_NODE(node1Index32);
|
|
40249
|
+
const cr1 = RIGHT_NODE(node1Index32, uint32Array1);
|
|
40250
|
+
arrayToBox(BOUNDING_DATA_INDEX(cl1), float32Array1, _leftBox1);
|
|
40251
|
+
arrayToBox(BOUNDING_DATA_INDEX(cr1), float32Array1, _rightBox1);
|
|
40252
|
+
const intersectCl1 = newBox.intersectsBox(_leftBox1);
|
|
40253
|
+
const intersectCr1 = newBox.intersectsBox(_rightBox1);
|
|
40254
|
+
result = intersectCl1 && _traverse(
|
|
40255
|
+
cl2,
|
|
40256
|
+
cl1,
|
|
40257
|
+
matrix1to2,
|
|
40258
|
+
matrix2to1,
|
|
40259
|
+
intersectsRangesFunc,
|
|
40260
|
+
node2IndexByteOffset,
|
|
40261
|
+
node1IndexByteOffset,
|
|
40262
|
+
depth2,
|
|
40263
|
+
depth1 + 1,
|
|
40264
|
+
newBox,
|
|
40265
|
+
!reversed
|
|
40266
|
+
) || intersectCr1 && _traverse(
|
|
40267
|
+
cl2,
|
|
40268
|
+
cr1,
|
|
40269
|
+
matrix1to2,
|
|
40270
|
+
matrix2to1,
|
|
40271
|
+
intersectsRangesFunc,
|
|
40272
|
+
node2IndexByteOffset,
|
|
40273
|
+
node1IndexByteOffset,
|
|
40274
|
+
depth2,
|
|
40275
|
+
depth1 + 1,
|
|
40276
|
+
newBox,
|
|
40277
|
+
!reversed
|
|
40278
|
+
);
|
|
40279
|
+
_boxPool.releasePrimitive(newBox);
|
|
40280
|
+
}
|
|
40281
|
+
} else if (rightIntersects) {
|
|
40282
|
+
if (isLeaf1) {
|
|
40283
|
+
result = _traverse(
|
|
40284
|
+
node1Index32,
|
|
40285
|
+
cr2,
|
|
40286
|
+
matrix2to1,
|
|
40287
|
+
matrix1to2,
|
|
40288
|
+
intersectsRangesFunc,
|
|
40289
|
+
node1IndexByteOffset,
|
|
40290
|
+
node2IndexByteOffset,
|
|
40291
|
+
depth1,
|
|
40292
|
+
depth2 + 1,
|
|
40293
|
+
currBox,
|
|
40294
|
+
reversed
|
|
40295
|
+
);
|
|
40296
|
+
} else {
|
|
40297
|
+
const newBox = _boxPool.getPrimitive();
|
|
40298
|
+
newBox.copy(_rightBox2).applyMatrix4(matrix2to1);
|
|
40299
|
+
const cl1 = LEFT_NODE(node1Index32);
|
|
40300
|
+
const cr1 = RIGHT_NODE(node1Index32, uint32Array1);
|
|
40301
|
+
arrayToBox(BOUNDING_DATA_INDEX(cl1), float32Array1, _leftBox1);
|
|
40302
|
+
arrayToBox(BOUNDING_DATA_INDEX(cr1), float32Array1, _rightBox1);
|
|
40303
|
+
const intersectCl1 = newBox.intersectsBox(_leftBox1);
|
|
40304
|
+
const intersectCr1 = newBox.intersectsBox(_rightBox1);
|
|
40305
|
+
result = intersectCl1 && _traverse(
|
|
40306
|
+
cr2,
|
|
40307
|
+
cl1,
|
|
40308
|
+
matrix1to2,
|
|
40309
|
+
matrix2to1,
|
|
40310
|
+
intersectsRangesFunc,
|
|
40311
|
+
node2IndexByteOffset,
|
|
40312
|
+
node1IndexByteOffset,
|
|
40313
|
+
depth2,
|
|
40314
|
+
depth1 + 1,
|
|
40315
|
+
newBox,
|
|
40316
|
+
!reversed
|
|
40317
|
+
) || intersectCr1 && _traverse(
|
|
40318
|
+
cr2,
|
|
40319
|
+
cr1,
|
|
40320
|
+
matrix1to2,
|
|
40321
|
+
matrix2to1,
|
|
40322
|
+
intersectsRangesFunc,
|
|
40323
|
+
node2IndexByteOffset,
|
|
40324
|
+
node1IndexByteOffset,
|
|
40325
|
+
depth2,
|
|
40326
|
+
depth1 + 1,
|
|
40327
|
+
newBox,
|
|
40328
|
+
!reversed
|
|
40329
|
+
);
|
|
40330
|
+
_boxPool.releasePrimitive(newBox);
|
|
40331
|
+
}
|
|
40332
|
+
}
|
|
40333
|
+
}
|
|
40334
|
+
return result;
|
|
40335
|
+
}
|
|
40336
|
+
const obb = /* @__PURE__ */ new OrientedBox();
|
|
40337
|
+
const tempBox = /* @__PURE__ */ new Box3();
|
|
40338
|
+
class MeshBVH {
|
|
40339
|
+
static serialize(bvh, options = {}) {
|
|
40340
|
+
options = {
|
|
40341
|
+
cloneBuffers: true,
|
|
40342
|
+
...options
|
|
40343
|
+
};
|
|
40344
|
+
const geometry = bvh.geometry;
|
|
40345
|
+
const rootData = bvh._roots;
|
|
40346
|
+
const indirectBuffer = bvh._indirectBuffer;
|
|
40347
|
+
const indexAttribute = geometry.getIndex();
|
|
40348
|
+
let result;
|
|
40349
|
+
if (options.cloneBuffers) {
|
|
40350
|
+
result = {
|
|
40351
|
+
roots: rootData.map((root) => root.slice()),
|
|
40352
|
+
index: indexAttribute.array.slice(),
|
|
40353
|
+
indirectBuffer: indirectBuffer ? indirectBuffer.slice() : null
|
|
40354
|
+
};
|
|
40355
|
+
} else {
|
|
40356
|
+
result = {
|
|
40357
|
+
roots: rootData,
|
|
40358
|
+
index: indexAttribute.array,
|
|
40359
|
+
indirectBuffer
|
|
40360
|
+
};
|
|
40361
|
+
}
|
|
40362
|
+
return result;
|
|
40363
|
+
}
|
|
40364
|
+
static deserialize(data, geometry, options = {}) {
|
|
40365
|
+
options = {
|
|
40366
|
+
setIndex: true,
|
|
40367
|
+
indirect: Boolean(data.indirectBuffer),
|
|
40368
|
+
...options
|
|
40369
|
+
};
|
|
40370
|
+
const { index, roots, indirectBuffer } = data;
|
|
40371
|
+
const bvh = new MeshBVH(geometry, { ...options, [SKIP_GENERATION]: true });
|
|
40372
|
+
bvh._roots = roots;
|
|
40373
|
+
bvh._indirectBuffer = indirectBuffer || null;
|
|
40374
|
+
if (options.setIndex) {
|
|
40375
|
+
const indexAttribute = geometry.getIndex();
|
|
40376
|
+
if (indexAttribute === null) {
|
|
40377
|
+
const newIndex = new BufferAttribute(data.index, 1, false);
|
|
40378
|
+
geometry.setIndex(newIndex);
|
|
40379
|
+
} else if (indexAttribute.array !== index) {
|
|
40380
|
+
indexAttribute.array.set(index);
|
|
40381
|
+
indexAttribute.needsUpdate = true;
|
|
40382
|
+
}
|
|
40383
|
+
}
|
|
40384
|
+
return bvh;
|
|
40385
|
+
}
|
|
40386
|
+
get indirect() {
|
|
40387
|
+
return !!this._indirectBuffer;
|
|
40388
|
+
}
|
|
40389
|
+
constructor(geometry, options = {}) {
|
|
40390
|
+
if (!geometry.isBufferGeometry) {
|
|
40391
|
+
throw new Error("MeshBVH: Only BufferGeometries are supported.");
|
|
40392
|
+
} else if (geometry.index && geometry.index.isInterleavedBufferAttribute) {
|
|
40393
|
+
throw new Error("MeshBVH: InterleavedBufferAttribute is not supported for the index attribute.");
|
|
40394
|
+
}
|
|
40395
|
+
options = Object.assign({
|
|
40396
|
+
strategy: CENTER,
|
|
40397
|
+
maxDepth: 40,
|
|
40398
|
+
maxLeafTris: 10,
|
|
40399
|
+
verbose: true,
|
|
40400
|
+
useSharedArrayBuffer: false,
|
|
40401
|
+
setBoundingBox: true,
|
|
40402
|
+
onProgress: null,
|
|
40403
|
+
indirect: false,
|
|
40404
|
+
// undocumented options
|
|
40405
|
+
// Whether to skip generating the tree. Used for deserialization.
|
|
40406
|
+
[SKIP_GENERATION]: false
|
|
40407
|
+
}, options);
|
|
40408
|
+
if (options.useSharedArrayBuffer && !isSharedArrayBufferSupported()) {
|
|
40409
|
+
throw new Error("MeshBVH: SharedArrayBuffer is not available.");
|
|
40410
|
+
}
|
|
40411
|
+
this.geometry = geometry;
|
|
40412
|
+
this._roots = null;
|
|
40413
|
+
this._indirectBuffer = null;
|
|
40414
|
+
if (!options[SKIP_GENERATION]) {
|
|
40415
|
+
buildPackedTree(this, options);
|
|
40416
|
+
if (!geometry.boundingBox && options.setBoundingBox) {
|
|
40417
|
+
geometry.boundingBox = this.getBoundingBox(new Box3());
|
|
40418
|
+
}
|
|
40419
|
+
}
|
|
40420
|
+
const { _indirectBuffer } = this;
|
|
40421
|
+
this.resolveTriangleIndex = options.indirect ? (i) => _indirectBuffer[i] : (i) => i;
|
|
40422
|
+
}
|
|
40423
|
+
refit(nodeIndices = null) {
|
|
40424
|
+
const refitFunc = this.indirect ? refit_indirect : refit;
|
|
40425
|
+
return refitFunc(this, nodeIndices);
|
|
40426
|
+
}
|
|
40427
|
+
traverse(callback, rootIndex = 0) {
|
|
40428
|
+
const buffer = this._roots[rootIndex];
|
|
40429
|
+
const uint32Array = new Uint32Array(buffer);
|
|
40430
|
+
const uint16Array = new Uint16Array(buffer);
|
|
40431
|
+
_traverse2(0);
|
|
40432
|
+
function _traverse2(node32Index, depth = 0) {
|
|
40433
|
+
const node16Index = node32Index * 2;
|
|
40434
|
+
const isLeaf = uint16Array[node16Index + 15] === IS_LEAFNODE_FLAG;
|
|
40435
|
+
if (isLeaf) {
|
|
40436
|
+
const offset = uint32Array[node32Index + 6];
|
|
40437
|
+
const count = uint16Array[node16Index + 14];
|
|
40438
|
+
callback(depth, isLeaf, new Float32Array(buffer, node32Index * 4, 6), offset, count);
|
|
40439
|
+
} else {
|
|
40440
|
+
const left = node32Index + BYTES_PER_NODE / 4;
|
|
40441
|
+
const right = uint32Array[node32Index + 6];
|
|
40442
|
+
const splitAxis = uint32Array[node32Index + 7];
|
|
40443
|
+
const stopTraversal = callback(depth, isLeaf, new Float32Array(buffer, node32Index * 4, 6), splitAxis);
|
|
40444
|
+
if (!stopTraversal) {
|
|
40445
|
+
_traverse2(left, depth + 1);
|
|
40446
|
+
_traverse2(right, depth + 1);
|
|
40447
|
+
}
|
|
40448
|
+
}
|
|
40449
|
+
}
|
|
40450
|
+
}
|
|
40451
|
+
/* Core Cast Functions */
|
|
40452
|
+
raycast(ray, materialOrSide = FrontSide) {
|
|
40453
|
+
const roots = this._roots;
|
|
40454
|
+
const geometry = this.geometry;
|
|
40455
|
+
const intersects = [];
|
|
40456
|
+
const isMaterial = materialOrSide.isMaterial;
|
|
40457
|
+
const isArrayMaterial = Array.isArray(materialOrSide);
|
|
40458
|
+
const groups = geometry.groups;
|
|
40459
|
+
const side = isMaterial ? materialOrSide.side : materialOrSide;
|
|
40460
|
+
const raycastFunc = this.indirect ? raycast_indirect : raycast;
|
|
40461
|
+
for (let i = 0, l = roots.length; i < l; i++) {
|
|
40462
|
+
const materialSide = isArrayMaterial ? materialOrSide[groups[i].materialIndex].side : side;
|
|
40463
|
+
const startCount = intersects.length;
|
|
40464
|
+
raycastFunc(this, i, materialSide, ray, intersects);
|
|
40465
|
+
if (isArrayMaterial) {
|
|
40466
|
+
const materialIndex = groups[i].materialIndex;
|
|
40467
|
+
for (let j = startCount, jl = intersects.length; j < jl; j++) {
|
|
40468
|
+
intersects[j].face.materialIndex = materialIndex;
|
|
40469
|
+
}
|
|
40470
|
+
}
|
|
40471
|
+
}
|
|
40472
|
+
return intersects;
|
|
40473
|
+
}
|
|
40474
|
+
raycastFirst(ray, materialOrSide = FrontSide) {
|
|
40475
|
+
const roots = this._roots;
|
|
40476
|
+
const geometry = this.geometry;
|
|
40477
|
+
const isMaterial = materialOrSide.isMaterial;
|
|
40478
|
+
const isArrayMaterial = Array.isArray(materialOrSide);
|
|
40479
|
+
let closestResult = null;
|
|
40480
|
+
const groups = geometry.groups;
|
|
40481
|
+
const side = isMaterial ? materialOrSide.side : materialOrSide;
|
|
40482
|
+
const raycastFirstFunc = this.indirect ? raycastFirst_indirect : raycastFirst;
|
|
40483
|
+
for (let i = 0, l = roots.length; i < l; i++) {
|
|
40484
|
+
const materialSide = isArrayMaterial ? materialOrSide[groups[i].materialIndex].side : side;
|
|
40485
|
+
const result = raycastFirstFunc(this, i, materialSide, ray);
|
|
40486
|
+
if (result != null && (closestResult == null || result.distance < closestResult.distance)) {
|
|
40487
|
+
closestResult = result;
|
|
40488
|
+
if (isArrayMaterial) {
|
|
40489
|
+
result.face.materialIndex = groups[i].materialIndex;
|
|
40490
|
+
}
|
|
40491
|
+
}
|
|
40492
|
+
}
|
|
40493
|
+
return closestResult;
|
|
40494
|
+
}
|
|
40495
|
+
intersectsGeometry(otherGeometry, geomToMesh) {
|
|
40496
|
+
let result = false;
|
|
40497
|
+
const roots = this._roots;
|
|
40498
|
+
const intersectsGeometryFunc = this.indirect ? intersectsGeometry_indirect : intersectsGeometry;
|
|
40499
|
+
for (let i = 0, l = roots.length; i < l; i++) {
|
|
40500
|
+
result = intersectsGeometryFunc(this, i, otherGeometry, geomToMesh);
|
|
40501
|
+
if (result) {
|
|
40502
|
+
break;
|
|
40503
|
+
}
|
|
40504
|
+
}
|
|
40505
|
+
return result;
|
|
40506
|
+
}
|
|
40507
|
+
shapecast(callbacks) {
|
|
40508
|
+
const triangle3 = ExtendedTrianglePool.getPrimitive();
|
|
40509
|
+
const iterateFunc = this.indirect ? iterateOverTriangles_indirect : iterateOverTriangles;
|
|
40510
|
+
let {
|
|
40511
|
+
boundsTraverseOrder,
|
|
40512
|
+
intersectsBounds,
|
|
40513
|
+
intersectsRange,
|
|
40514
|
+
intersectsTriangle
|
|
40515
|
+
} = callbacks;
|
|
40516
|
+
if (intersectsRange && intersectsTriangle) {
|
|
40517
|
+
const originalIntersectsRange = intersectsRange;
|
|
40518
|
+
intersectsRange = (offset, count, contained, depth, nodeIndex) => {
|
|
40519
|
+
if (!originalIntersectsRange(offset, count, contained, depth, nodeIndex)) {
|
|
40520
|
+
return iterateFunc(offset, count, this, intersectsTriangle, contained, depth, triangle3);
|
|
40521
|
+
}
|
|
40522
|
+
return true;
|
|
40523
|
+
};
|
|
40524
|
+
} else if (!intersectsRange) {
|
|
40525
|
+
if (intersectsTriangle) {
|
|
40526
|
+
intersectsRange = (offset, count, contained, depth) => {
|
|
40527
|
+
return iterateFunc(offset, count, this, intersectsTriangle, contained, depth, triangle3);
|
|
40528
|
+
};
|
|
40529
|
+
} else {
|
|
40530
|
+
intersectsRange = (offset, count, contained) => {
|
|
40531
|
+
return contained;
|
|
40532
|
+
};
|
|
40533
|
+
}
|
|
40534
|
+
}
|
|
40535
|
+
let result = false;
|
|
40536
|
+
let byteOffset = 0;
|
|
40537
|
+
const roots = this._roots;
|
|
40538
|
+
for (let i = 0, l = roots.length; i < l; i++) {
|
|
40539
|
+
const root = roots[i];
|
|
40540
|
+
result = shapecast(this, i, intersectsBounds, intersectsRange, boundsTraverseOrder, byteOffset);
|
|
40541
|
+
if (result) {
|
|
40542
|
+
break;
|
|
40543
|
+
}
|
|
40544
|
+
byteOffset += root.byteLength;
|
|
40545
|
+
}
|
|
40546
|
+
ExtendedTrianglePool.releasePrimitive(triangle3);
|
|
40547
|
+
return result;
|
|
40548
|
+
}
|
|
40549
|
+
bvhcast(otherBvh, matrixToLocal, callbacks) {
|
|
40550
|
+
let {
|
|
40551
|
+
intersectsRanges,
|
|
40552
|
+
intersectsTriangles
|
|
40553
|
+
} = callbacks;
|
|
40554
|
+
const triangle1 = ExtendedTrianglePool.getPrimitive();
|
|
40555
|
+
const indexAttr1 = this.geometry.index;
|
|
40556
|
+
const positionAttr1 = this.geometry.attributes.position;
|
|
40557
|
+
const assignTriangle1 = this.indirect ? (i1) => {
|
|
40558
|
+
const ti = this.resolveTriangleIndex(i1);
|
|
40559
|
+
setTriangle(triangle1, ti * 3, indexAttr1, positionAttr1);
|
|
40560
|
+
} : (i1) => {
|
|
40561
|
+
setTriangle(triangle1, i1 * 3, indexAttr1, positionAttr1);
|
|
40562
|
+
};
|
|
40563
|
+
const triangle22 = ExtendedTrianglePool.getPrimitive();
|
|
40564
|
+
const indexAttr2 = otherBvh.geometry.index;
|
|
40565
|
+
const positionAttr2 = otherBvh.geometry.attributes.position;
|
|
40566
|
+
const assignTriangle2 = otherBvh.indirect ? (i2) => {
|
|
40567
|
+
const ti2 = otherBvh.resolveTriangleIndex(i2);
|
|
40568
|
+
setTriangle(triangle22, ti2 * 3, indexAttr2, positionAttr2);
|
|
40569
|
+
} : (i2) => {
|
|
40570
|
+
setTriangle(triangle22, i2 * 3, indexAttr2, positionAttr2);
|
|
40571
|
+
};
|
|
40572
|
+
if (intersectsTriangles) {
|
|
40573
|
+
const iterateOverDoubleTriangles = (offset1, count1, offset2, count2, depth1, index1, depth2, index2) => {
|
|
40574
|
+
for (let i2 = offset2, l2 = offset2 + count2; i2 < l2; i2++) {
|
|
40575
|
+
assignTriangle2(i2);
|
|
40576
|
+
triangle22.a.applyMatrix4(matrixToLocal);
|
|
40577
|
+
triangle22.b.applyMatrix4(matrixToLocal);
|
|
40578
|
+
triangle22.c.applyMatrix4(matrixToLocal);
|
|
40579
|
+
triangle22.needsUpdate = true;
|
|
40580
|
+
for (let i1 = offset1, l1 = offset1 + count1; i1 < l1; i1++) {
|
|
40581
|
+
assignTriangle1(i1);
|
|
40582
|
+
triangle1.needsUpdate = true;
|
|
40583
|
+
if (intersectsTriangles(triangle1, triangle22, i1, i2, depth1, index1, depth2, index2)) {
|
|
40584
|
+
return true;
|
|
40585
|
+
}
|
|
40586
|
+
}
|
|
40587
|
+
}
|
|
40588
|
+
return false;
|
|
40589
|
+
};
|
|
40590
|
+
if (intersectsRanges) {
|
|
40591
|
+
const originalIntersectsRanges = intersectsRanges;
|
|
40592
|
+
intersectsRanges = function(offset1, count1, offset2, count2, depth1, index1, depth2, index2) {
|
|
40593
|
+
if (!originalIntersectsRanges(offset1, count1, offset2, count2, depth1, index1, depth2, index2)) {
|
|
40594
|
+
return iterateOverDoubleTriangles(offset1, count1, offset2, count2, depth1, index1, depth2, index2);
|
|
40595
|
+
}
|
|
40596
|
+
return true;
|
|
40597
|
+
};
|
|
40598
|
+
} else {
|
|
40599
|
+
intersectsRanges = iterateOverDoubleTriangles;
|
|
40600
|
+
}
|
|
40601
|
+
}
|
|
40602
|
+
return bvhcast(this, otherBvh, matrixToLocal, intersectsRanges);
|
|
40603
|
+
}
|
|
40604
|
+
/* Derived Cast Functions */
|
|
40605
|
+
intersectsBox(box, boxToMesh) {
|
|
40606
|
+
obb.set(box.min, box.max, boxToMesh);
|
|
40607
|
+
obb.needsUpdate = true;
|
|
40608
|
+
return this.shapecast(
|
|
40609
|
+
{
|
|
40610
|
+
intersectsBounds: (box2) => obb.intersectsBox(box2),
|
|
40611
|
+
intersectsTriangle: (tri) => obb.intersectsTriangle(tri)
|
|
40612
|
+
}
|
|
40613
|
+
);
|
|
40614
|
+
}
|
|
40615
|
+
intersectsSphere(sphere) {
|
|
40616
|
+
return this.shapecast(
|
|
40617
|
+
{
|
|
40618
|
+
intersectsBounds: (box) => sphere.intersectsBox(box),
|
|
40619
|
+
intersectsTriangle: (tri) => tri.intersectsSphere(sphere)
|
|
40620
|
+
}
|
|
40621
|
+
);
|
|
40622
|
+
}
|
|
40623
|
+
closestPointToGeometry(otherGeometry, geometryToBvh, target1 = {}, target2 = {}, minThreshold = 0, maxThreshold = Infinity) {
|
|
40624
|
+
const closestPointToGeometryFunc = this.indirect ? closestPointToGeometry_indirect : closestPointToGeometry;
|
|
40625
|
+
return closestPointToGeometryFunc(
|
|
40626
|
+
this,
|
|
40627
|
+
otherGeometry,
|
|
40628
|
+
geometryToBvh,
|
|
40629
|
+
target1,
|
|
40630
|
+
target2,
|
|
40631
|
+
minThreshold,
|
|
40632
|
+
maxThreshold
|
|
40633
|
+
);
|
|
40634
|
+
}
|
|
40635
|
+
closestPointToPoint(point, target = {}, minThreshold = 0, maxThreshold = Infinity) {
|
|
40636
|
+
return closestPointToPoint(
|
|
40637
|
+
this,
|
|
40638
|
+
point,
|
|
40639
|
+
target,
|
|
40640
|
+
minThreshold,
|
|
40641
|
+
maxThreshold
|
|
40642
|
+
);
|
|
40643
|
+
}
|
|
40644
|
+
getBoundingBox(target) {
|
|
40645
|
+
target.makeEmpty();
|
|
40646
|
+
const roots = this._roots;
|
|
40647
|
+
roots.forEach((buffer) => {
|
|
40648
|
+
arrayToBox(0, new Float32Array(buffer), tempBox);
|
|
40649
|
+
target.union(tempBox);
|
|
40650
|
+
});
|
|
40651
|
+
return target;
|
|
40652
|
+
}
|
|
40653
|
+
}
|
|
40654
|
+
function countToStringFormat(count) {
|
|
40655
|
+
switch (count) {
|
|
40656
|
+
case 1:
|
|
40657
|
+
return "R";
|
|
40658
|
+
case 2:
|
|
40659
|
+
return "RG";
|
|
40660
|
+
case 3:
|
|
40661
|
+
return "RGBA";
|
|
40662
|
+
case 4:
|
|
40663
|
+
return "RGBA";
|
|
40664
|
+
}
|
|
40665
|
+
throw new Error();
|
|
40666
|
+
}
|
|
40667
|
+
function countToFormat(count) {
|
|
40668
|
+
switch (count) {
|
|
40669
|
+
case 1:
|
|
40670
|
+
return RedFormat;
|
|
40671
|
+
case 2:
|
|
40672
|
+
return RGFormat;
|
|
40673
|
+
case 3:
|
|
40674
|
+
return RGBAFormat;
|
|
40675
|
+
case 4:
|
|
40676
|
+
return RGBAFormat;
|
|
40677
|
+
}
|
|
40678
|
+
}
|
|
40679
|
+
function countToIntFormat(count) {
|
|
40680
|
+
switch (count) {
|
|
40681
|
+
case 1:
|
|
40682
|
+
return RedIntegerFormat;
|
|
40683
|
+
case 2:
|
|
40684
|
+
return RGIntegerFormat;
|
|
40685
|
+
case 3:
|
|
40686
|
+
return RGBAIntegerFormat;
|
|
40687
|
+
case 4:
|
|
40688
|
+
return RGBAIntegerFormat;
|
|
40689
|
+
}
|
|
40690
|
+
}
|
|
40691
|
+
class VertexAttributeTexture extends DataTexture {
|
|
40692
|
+
constructor() {
|
|
40693
|
+
super();
|
|
40694
|
+
this.minFilter = NearestFilter;
|
|
40695
|
+
this.magFilter = NearestFilter;
|
|
40696
|
+
this.generateMipmaps = false;
|
|
40697
|
+
this.overrideItemSize = null;
|
|
40698
|
+
this._forcedType = null;
|
|
40699
|
+
}
|
|
40700
|
+
updateFrom(attr) {
|
|
40701
|
+
const overrideItemSize = this.overrideItemSize;
|
|
40702
|
+
const originalItemSize = attr.itemSize;
|
|
40703
|
+
const originalCount = attr.count;
|
|
40704
|
+
if (overrideItemSize !== null) {
|
|
40705
|
+
if (originalItemSize * originalCount % overrideItemSize !== 0) {
|
|
40706
|
+
throw new Error("VertexAttributeTexture: overrideItemSize must divide evenly into buffer length.");
|
|
40707
|
+
}
|
|
40708
|
+
attr.itemSize = overrideItemSize;
|
|
40709
|
+
attr.count = originalCount * originalItemSize / overrideItemSize;
|
|
40710
|
+
}
|
|
40711
|
+
const itemSize = attr.itemSize;
|
|
40712
|
+
const count = attr.count;
|
|
40713
|
+
const normalized = attr.normalized;
|
|
40714
|
+
const originalBufferCons = attr.array.constructor;
|
|
40715
|
+
const byteCount = originalBufferCons.BYTES_PER_ELEMENT;
|
|
40716
|
+
let targetType = this._forcedType;
|
|
40717
|
+
let finalStride = itemSize;
|
|
40718
|
+
if (targetType === null) {
|
|
40719
|
+
switch (originalBufferCons) {
|
|
40720
|
+
case Float32Array:
|
|
40721
|
+
targetType = FloatType;
|
|
40722
|
+
break;
|
|
40723
|
+
case Uint8Array:
|
|
40724
|
+
case Uint16Array:
|
|
40725
|
+
case Uint32Array:
|
|
40726
|
+
targetType = UnsignedIntType;
|
|
40727
|
+
break;
|
|
40728
|
+
case Int8Array:
|
|
40729
|
+
case Int16Array:
|
|
40730
|
+
case Int32Array:
|
|
40731
|
+
targetType = IntType;
|
|
40732
|
+
break;
|
|
40733
|
+
}
|
|
40734
|
+
}
|
|
40735
|
+
let type, format, normalizeValue, targetBufferCons;
|
|
40736
|
+
let internalFormat = countToStringFormat(itemSize);
|
|
40737
|
+
switch (targetType) {
|
|
40738
|
+
case FloatType:
|
|
40739
|
+
normalizeValue = 1;
|
|
40740
|
+
format = countToFormat(itemSize);
|
|
40741
|
+
if (normalized && byteCount === 1) {
|
|
40742
|
+
targetBufferCons = originalBufferCons;
|
|
40743
|
+
internalFormat += "8";
|
|
40744
|
+
if (originalBufferCons === Uint8Array) {
|
|
40745
|
+
type = UnsignedByteType;
|
|
40746
|
+
} else {
|
|
40747
|
+
type = ByteType;
|
|
40748
|
+
internalFormat += "_SNORM";
|
|
40749
|
+
}
|
|
40750
|
+
} else {
|
|
40751
|
+
targetBufferCons = Float32Array;
|
|
40752
|
+
internalFormat += "32F";
|
|
40753
|
+
type = FloatType;
|
|
40754
|
+
}
|
|
40755
|
+
break;
|
|
40756
|
+
case IntType:
|
|
40757
|
+
internalFormat += byteCount * 8 + "I";
|
|
40758
|
+
normalizeValue = normalized ? Math.pow(2, originalBufferCons.BYTES_PER_ELEMENT * 8 - 1) : 1;
|
|
40759
|
+
format = countToIntFormat(itemSize);
|
|
40760
|
+
if (byteCount === 1) {
|
|
40761
|
+
targetBufferCons = Int8Array;
|
|
40762
|
+
type = ByteType;
|
|
40763
|
+
} else if (byteCount === 2) {
|
|
40764
|
+
targetBufferCons = Int16Array;
|
|
40765
|
+
type = ShortType;
|
|
40766
|
+
} else {
|
|
40767
|
+
targetBufferCons = Int32Array;
|
|
40768
|
+
type = IntType;
|
|
40769
|
+
}
|
|
40770
|
+
break;
|
|
40771
|
+
case UnsignedIntType:
|
|
40772
|
+
internalFormat += byteCount * 8 + "UI";
|
|
40773
|
+
normalizeValue = normalized ? Math.pow(2, originalBufferCons.BYTES_PER_ELEMENT * 8 - 1) : 1;
|
|
40774
|
+
format = countToIntFormat(itemSize);
|
|
40775
|
+
if (byteCount === 1) {
|
|
40776
|
+
targetBufferCons = Uint8Array;
|
|
40777
|
+
type = UnsignedByteType;
|
|
40778
|
+
} else if (byteCount === 2) {
|
|
40779
|
+
targetBufferCons = Uint16Array;
|
|
40780
|
+
type = UnsignedShortType;
|
|
40781
|
+
} else {
|
|
40782
|
+
targetBufferCons = Uint32Array;
|
|
40783
|
+
type = UnsignedIntType;
|
|
40784
|
+
}
|
|
40785
|
+
break;
|
|
40786
|
+
}
|
|
40787
|
+
if (finalStride === 3 && (format === RGBAFormat || format === RGBAIntegerFormat)) {
|
|
40788
|
+
finalStride = 4;
|
|
40789
|
+
}
|
|
40790
|
+
const dimension = Math.ceil(Math.sqrt(count));
|
|
40791
|
+
const length = finalStride * dimension * dimension;
|
|
40792
|
+
const dataArray = new targetBufferCons(length);
|
|
40793
|
+
const originalNormalized = attr.normalized;
|
|
40794
|
+
attr.normalized = false;
|
|
40795
|
+
for (let i = 0; i < count; i++) {
|
|
40796
|
+
const ii = finalStride * i;
|
|
40797
|
+
dataArray[ii] = attr.getX(i) / normalizeValue;
|
|
40798
|
+
if (itemSize >= 2) {
|
|
40799
|
+
dataArray[ii + 1] = attr.getY(i) / normalizeValue;
|
|
40800
|
+
}
|
|
40801
|
+
if (itemSize >= 3) {
|
|
40802
|
+
dataArray[ii + 2] = attr.getZ(i) / normalizeValue;
|
|
40803
|
+
if (finalStride === 4) {
|
|
40804
|
+
dataArray[ii + 3] = 1;
|
|
40805
|
+
}
|
|
40806
|
+
}
|
|
40807
|
+
if (itemSize >= 4) {
|
|
40808
|
+
dataArray[ii + 3] = attr.getW(i) / normalizeValue;
|
|
40809
|
+
}
|
|
40810
|
+
}
|
|
40811
|
+
attr.normalized = originalNormalized;
|
|
40812
|
+
this.internalFormat = internalFormat;
|
|
40813
|
+
this.format = format;
|
|
40814
|
+
this.type = type;
|
|
40815
|
+
this.image.width = dimension;
|
|
40816
|
+
this.image.height = dimension;
|
|
40817
|
+
this.image.data = dataArray;
|
|
40818
|
+
this.needsUpdate = true;
|
|
40819
|
+
this.dispose();
|
|
40820
|
+
attr.itemSize = originalItemSize;
|
|
40821
|
+
attr.count = originalCount;
|
|
40822
|
+
}
|
|
40823
|
+
}
|
|
40824
|
+
class UIntVertexAttributeTexture extends VertexAttributeTexture {
|
|
40825
|
+
constructor() {
|
|
40826
|
+
super();
|
|
40827
|
+
this._forcedType = UnsignedIntType;
|
|
40828
|
+
}
|
|
40829
|
+
}
|
|
40830
|
+
class FloatVertexAttributeTexture extends VertexAttributeTexture {
|
|
40831
|
+
constructor() {
|
|
40832
|
+
super();
|
|
40833
|
+
this._forcedType = FloatType;
|
|
40834
|
+
}
|
|
40835
|
+
}
|
|
40836
|
+
class MeshBVHUniformStruct {
|
|
40837
|
+
constructor() {
|
|
40838
|
+
this.index = new UIntVertexAttributeTexture();
|
|
40839
|
+
this.position = new FloatVertexAttributeTexture();
|
|
40840
|
+
this.bvhBounds = new DataTexture();
|
|
40841
|
+
this.bvhContents = new DataTexture();
|
|
40842
|
+
this._cachedIndexAttr = null;
|
|
40843
|
+
this.index.overrideItemSize = 3;
|
|
40844
|
+
}
|
|
40845
|
+
updateFrom(bvh) {
|
|
40846
|
+
const { geometry } = bvh;
|
|
40847
|
+
bvhToTextures(bvh, this.bvhBounds, this.bvhContents);
|
|
40848
|
+
this.position.updateFrom(geometry.attributes.position);
|
|
40849
|
+
if (bvh.indirect) {
|
|
40850
|
+
const indirectBuffer = bvh._indirectBuffer;
|
|
40851
|
+
if (this._cachedIndexAttr === null || this._cachedIndexAttr.count !== indirectBuffer.length) {
|
|
40852
|
+
if (geometry.index) {
|
|
40853
|
+
this._cachedIndexAttr = geometry.index.clone();
|
|
40854
|
+
} else {
|
|
40855
|
+
const array = getIndexArray(getVertexCount(geometry));
|
|
40856
|
+
this._cachedIndexAttr = new BufferAttribute(array, 1, false);
|
|
40857
|
+
}
|
|
40858
|
+
}
|
|
40859
|
+
dereferenceIndex(geometry, indirectBuffer, this._cachedIndexAttr);
|
|
40860
|
+
this.index.updateFrom(this._cachedIndexAttr);
|
|
40861
|
+
} else {
|
|
40862
|
+
this.index.updateFrom(geometry.index);
|
|
40863
|
+
}
|
|
40864
|
+
}
|
|
40865
|
+
dispose() {
|
|
40866
|
+
const { index, position, bvhBounds, bvhContents } = this;
|
|
40867
|
+
if (index)
|
|
40868
|
+
index.dispose();
|
|
40869
|
+
if (position)
|
|
40870
|
+
position.dispose();
|
|
40871
|
+
if (bvhBounds)
|
|
40872
|
+
bvhBounds.dispose();
|
|
40873
|
+
if (bvhContents)
|
|
40874
|
+
bvhContents.dispose();
|
|
40875
|
+
}
|
|
40876
|
+
}
|
|
40877
|
+
function dereferenceIndex(geometry, indirectBuffer, target) {
|
|
40878
|
+
const unpacked = target.array;
|
|
40879
|
+
const indexArray = geometry.index ? geometry.index.array : null;
|
|
40880
|
+
for (let i = 0, l = indirectBuffer.length; i < l; i++) {
|
|
40881
|
+
const i3 = 3 * i;
|
|
40882
|
+
const v3 = 3 * indirectBuffer[i];
|
|
40883
|
+
for (let c2 = 0; c2 < 3; c2++) {
|
|
40884
|
+
unpacked[i3 + c2] = indexArray ? indexArray[v3 + c2] : v3 + c2;
|
|
40885
|
+
}
|
|
40886
|
+
}
|
|
40887
|
+
}
|
|
40888
|
+
function bvhToTextures(bvh, boundsTexture, contentsTexture) {
|
|
40889
|
+
const roots = bvh._roots;
|
|
40890
|
+
if (roots.length !== 1) {
|
|
40891
|
+
throw new Error("MeshBVHUniformStruct: Multi-root BVHs not supported.");
|
|
40892
|
+
}
|
|
40893
|
+
const root = roots[0];
|
|
40894
|
+
const uint16Array = new Uint16Array(root);
|
|
40895
|
+
const uint32Array = new Uint32Array(root);
|
|
40896
|
+
const float32Array = new Float32Array(root);
|
|
40897
|
+
const nodeCount = root.byteLength / BYTES_PER_NODE;
|
|
40898
|
+
const boundsDimension = 2 * Math.ceil(Math.sqrt(nodeCount / 2));
|
|
40899
|
+
const boundsArray = new Float32Array(4 * boundsDimension * boundsDimension);
|
|
40900
|
+
const contentsDimension = Math.ceil(Math.sqrt(nodeCount));
|
|
40901
|
+
const contentsArray = new Uint32Array(2 * contentsDimension * contentsDimension);
|
|
40902
|
+
for (let i = 0; i < nodeCount; i++) {
|
|
40903
|
+
const nodeIndex32 = i * BYTES_PER_NODE / 4;
|
|
40904
|
+
const nodeIndex16 = nodeIndex32 * 2;
|
|
40905
|
+
const boundsIndex = BOUNDING_DATA_INDEX(nodeIndex32);
|
|
40906
|
+
for (let b = 0; b < 3; b++) {
|
|
40907
|
+
boundsArray[8 * i + 0 + b] = float32Array[boundsIndex + 0 + b];
|
|
40908
|
+
boundsArray[8 * i + 4 + b] = float32Array[boundsIndex + 3 + b];
|
|
40909
|
+
}
|
|
40910
|
+
if (IS_LEAF(nodeIndex16, uint16Array)) {
|
|
40911
|
+
const count = COUNT(nodeIndex16, uint16Array);
|
|
40912
|
+
const offset = OFFSET(nodeIndex32, uint32Array);
|
|
40913
|
+
const mergedLeafCount = 4294901760 | count;
|
|
40914
|
+
contentsArray[i * 2 + 0] = mergedLeafCount;
|
|
40915
|
+
contentsArray[i * 2 + 1] = offset;
|
|
40916
|
+
} else {
|
|
40917
|
+
const rightIndex = 4 * RIGHT_NODE(nodeIndex32, uint32Array) / BYTES_PER_NODE;
|
|
40918
|
+
const splitAxis = SPLIT_AXIS(nodeIndex32, uint32Array);
|
|
40919
|
+
contentsArray[i * 2 + 0] = splitAxis;
|
|
40920
|
+
contentsArray[i * 2 + 1] = rightIndex;
|
|
40921
|
+
}
|
|
40922
|
+
}
|
|
40923
|
+
boundsTexture.image.data = boundsArray;
|
|
40924
|
+
boundsTexture.image.width = boundsDimension;
|
|
40925
|
+
boundsTexture.image.height = boundsDimension;
|
|
40926
|
+
boundsTexture.format = RGBAFormat;
|
|
40927
|
+
boundsTexture.type = FloatType;
|
|
40928
|
+
boundsTexture.internalFormat = "RGBA32F";
|
|
40929
|
+
boundsTexture.minFilter = NearestFilter;
|
|
40930
|
+
boundsTexture.magFilter = NearestFilter;
|
|
40931
|
+
boundsTexture.generateMipmaps = false;
|
|
40932
|
+
boundsTexture.needsUpdate = true;
|
|
40933
|
+
boundsTexture.dispose();
|
|
40934
|
+
contentsTexture.image.data = contentsArray;
|
|
40935
|
+
contentsTexture.image.width = contentsDimension;
|
|
40936
|
+
contentsTexture.image.height = contentsDimension;
|
|
40937
|
+
contentsTexture.format = RGIntegerFormat;
|
|
40938
|
+
contentsTexture.type = UnsignedIntType;
|
|
40939
|
+
contentsTexture.internalFormat = "RG32UI";
|
|
40940
|
+
contentsTexture.minFilter = NearestFilter;
|
|
40941
|
+
contentsTexture.magFilter = NearestFilter;
|
|
40942
|
+
contentsTexture.generateMipmaps = false;
|
|
40943
|
+
contentsTexture.needsUpdate = true;
|
|
40944
|
+
contentsTexture.dispose();
|
|
40945
|
+
}
|
|
40946
|
+
const shaderStructs = (
|
|
40947
|
+
/* glsl */
|
|
40948
|
+
`
|
|
40949
|
+
#ifndef TRI_INTERSECT_EPSILON
|
|
40950
|
+
#define TRI_INTERSECT_EPSILON 1e-5
|
|
40951
|
+
#endif
|
|
40952
|
+
|
|
40953
|
+
#ifndef INFINITY
|
|
40954
|
+
#define INFINITY 1e20
|
|
40955
|
+
#endif
|
|
40956
|
+
|
|
40957
|
+
struct BVH {
|
|
40958
|
+
|
|
40959
|
+
usampler2D index;
|
|
40960
|
+
sampler2D position;
|
|
40961
|
+
|
|
40962
|
+
sampler2D bvhBounds;
|
|
40963
|
+
usampler2D bvhContents;
|
|
40964
|
+
|
|
40965
|
+
};
|
|
40966
|
+
`
|
|
40967
|
+
);
|
|
40968
|
+
const shaderIntersectFunction = (
|
|
40969
|
+
/* glsl */
|
|
40970
|
+
`
|
|
40971
|
+
|
|
40972
|
+
// Utilities
|
|
40973
|
+
uvec4 uTexelFetch1D( usampler2D tex, uint index ) {
|
|
40974
|
+
|
|
40975
|
+
uint width = uint( textureSize( tex, 0 ).x );
|
|
40976
|
+
uvec2 uv;
|
|
40977
|
+
uv.x = index % width;
|
|
40978
|
+
uv.y = index / width;
|
|
40979
|
+
|
|
40980
|
+
return texelFetch( tex, ivec2( uv ), 0 );
|
|
40981
|
+
|
|
40982
|
+
}
|
|
40983
|
+
|
|
40984
|
+
ivec4 iTexelFetch1D( isampler2D tex, uint index ) {
|
|
40985
|
+
|
|
40986
|
+
uint width = uint( textureSize( tex, 0 ).x );
|
|
40987
|
+
uvec2 uv;
|
|
40988
|
+
uv.x = index % width;
|
|
40989
|
+
uv.y = index / width;
|
|
40990
|
+
|
|
40991
|
+
return texelFetch( tex, ivec2( uv ), 0 );
|
|
40992
|
+
|
|
40993
|
+
}
|
|
40994
|
+
|
|
40995
|
+
vec4 texelFetch1D( sampler2D tex, uint index ) {
|
|
40996
|
+
|
|
40997
|
+
uint width = uint( textureSize( tex, 0 ).x );
|
|
40998
|
+
uvec2 uv;
|
|
40999
|
+
uv.x = index % width;
|
|
41000
|
+
uv.y = index / width;
|
|
41001
|
+
|
|
41002
|
+
return texelFetch( tex, ivec2( uv ), 0 );
|
|
41003
|
+
|
|
41004
|
+
}
|
|
41005
|
+
|
|
41006
|
+
vec4 textureSampleBarycoord( sampler2D tex, vec3 barycoord, uvec3 faceIndices ) {
|
|
41007
|
+
|
|
41008
|
+
return
|
|
41009
|
+
barycoord.x * texelFetch1D( tex, faceIndices.x ) +
|
|
41010
|
+
barycoord.y * texelFetch1D( tex, faceIndices.y ) +
|
|
41011
|
+
barycoord.z * texelFetch1D( tex, faceIndices.z );
|
|
41012
|
+
|
|
41013
|
+
}
|
|
41014
|
+
|
|
41015
|
+
void ndcToCameraRay(
|
|
41016
|
+
vec2 coord, mat4 cameraWorld, mat4 invProjectionMatrix,
|
|
41017
|
+
out vec3 rayOrigin, out vec3 rayDirection
|
|
41018
|
+
) {
|
|
41019
|
+
|
|
41020
|
+
// get camera look direction and near plane for camera clipping
|
|
41021
|
+
vec4 lookDirection = cameraWorld * vec4( 0.0, 0.0, - 1.0, 0.0 );
|
|
41022
|
+
vec4 nearVector = invProjectionMatrix * vec4( 0.0, 0.0, - 1.0, 1.0 );
|
|
41023
|
+
float near = abs( nearVector.z / nearVector.w );
|
|
41024
|
+
|
|
41025
|
+
// get the camera direction and position from camera matrices
|
|
41026
|
+
vec4 origin = cameraWorld * vec4( 0.0, 0.0, 0.0, 1.0 );
|
|
41027
|
+
vec4 direction = invProjectionMatrix * vec4( coord, 0.5, 1.0 );
|
|
41028
|
+
direction /= direction.w;
|
|
41029
|
+
direction = cameraWorld * direction - origin;
|
|
41030
|
+
|
|
41031
|
+
// slide the origin along the ray until it sits at the near clip plane position
|
|
41032
|
+
origin.xyz += direction.xyz * near / dot( direction, lookDirection );
|
|
41033
|
+
|
|
41034
|
+
rayOrigin = origin.xyz;
|
|
41035
|
+
rayDirection = direction.xyz;
|
|
41036
|
+
|
|
41037
|
+
}
|
|
41038
|
+
|
|
41039
|
+
// Raycasting
|
|
41040
|
+
float intersectsBounds( vec3 rayOrigin, vec3 rayDirection, vec3 boundsMin, vec3 boundsMax ) {
|
|
41041
|
+
|
|
41042
|
+
// https://www.reddit.com/r/opengl/comments/8ntzz5/fast_glsl_ray_box_intersection/
|
|
41043
|
+
// https://tavianator.com/2011/ray_box.html
|
|
41044
|
+
vec3 invDir = 1.0 / rayDirection;
|
|
41045
|
+
|
|
41046
|
+
// find intersection distances for each plane
|
|
41047
|
+
vec3 tMinPlane = invDir * ( boundsMin - rayOrigin );
|
|
41048
|
+
vec3 tMaxPlane = invDir * ( boundsMax - rayOrigin );
|
|
41049
|
+
|
|
41050
|
+
// get the min and max distances from each intersection
|
|
41051
|
+
vec3 tMinHit = min( tMaxPlane, tMinPlane );
|
|
41052
|
+
vec3 tMaxHit = max( tMaxPlane, tMinPlane );
|
|
41053
|
+
|
|
41054
|
+
// get the furthest hit distance
|
|
41055
|
+
vec2 t = max( tMinHit.xx, tMinHit.yz );
|
|
41056
|
+
float t0 = max( t.x, t.y );
|
|
41057
|
+
|
|
41058
|
+
// get the minimum hit distance
|
|
41059
|
+
t = min( tMaxHit.xx, tMaxHit.yz );
|
|
41060
|
+
float t1 = min( t.x, t.y );
|
|
41061
|
+
|
|
41062
|
+
// set distance to 0.0 if the ray starts inside the box
|
|
41063
|
+
float dist = max( t0, 0.0 );
|
|
41064
|
+
|
|
41065
|
+
return t1 >= dist ? dist : INFINITY;
|
|
41066
|
+
|
|
41067
|
+
}
|
|
41068
|
+
|
|
41069
|
+
bool intersectsTriangle(
|
|
41070
|
+
vec3 rayOrigin, vec3 rayDirection, vec3 a, vec3 b, vec3 c,
|
|
41071
|
+
out vec3 barycoord, out vec3 norm, out float dist, out float side
|
|
41072
|
+
) {
|
|
41073
|
+
|
|
41074
|
+
// https://stackoverflow.com/questions/42740765/intersection-between-line-and-triangle-in-3d
|
|
41075
|
+
vec3 edge1 = b - a;
|
|
41076
|
+
vec3 edge2 = c - a;
|
|
41077
|
+
norm = cross( edge1, edge2 );
|
|
41078
|
+
|
|
41079
|
+
float det = - dot( rayDirection, norm );
|
|
41080
|
+
float invdet = 1.0 / det;
|
|
41081
|
+
|
|
41082
|
+
vec3 AO = rayOrigin - a;
|
|
41083
|
+
vec3 DAO = cross( AO, rayDirection );
|
|
41084
|
+
|
|
41085
|
+
vec4 uvt;
|
|
41086
|
+
uvt.x = dot( edge2, DAO ) * invdet;
|
|
41087
|
+
uvt.y = - dot( edge1, DAO ) * invdet;
|
|
41088
|
+
uvt.z = dot( AO, norm ) * invdet;
|
|
41089
|
+
uvt.w = 1.0 - uvt.x - uvt.y;
|
|
41090
|
+
|
|
41091
|
+
// set the hit information
|
|
41092
|
+
barycoord = uvt.wxy; // arranged in A, B, C order
|
|
41093
|
+
dist = uvt.z;
|
|
41094
|
+
side = sign( det );
|
|
41095
|
+
norm = side * normalize( norm );
|
|
41096
|
+
|
|
41097
|
+
// add an epsilon to avoid misses between triangles
|
|
41098
|
+
uvt += vec4( TRI_INTERSECT_EPSILON );
|
|
41099
|
+
|
|
41100
|
+
return all( greaterThanEqual( uvt, vec4( 0.0 ) ) );
|
|
41101
|
+
|
|
41102
|
+
}
|
|
41103
|
+
|
|
41104
|
+
bool intersectTriangles(
|
|
41105
|
+
BVH bvh, vec3 rayOrigin, vec3 rayDirection, uint offset, uint count,
|
|
41106
|
+
inout float minDistance, inout uvec4 faceIndices, inout vec3 faceNormal, inout vec3 barycoord,
|
|
41107
|
+
inout float side, inout float dist
|
|
41108
|
+
) {
|
|
41109
|
+
|
|
41110
|
+
bool found = false;
|
|
41111
|
+
vec3 localBarycoord, localNormal;
|
|
41112
|
+
float localDist, localSide;
|
|
41113
|
+
for ( uint i = offset, l = offset + count; i < l; i ++ ) {
|
|
41114
|
+
|
|
41115
|
+
uvec3 indices = uTexelFetch1D( bvh.index, i ).xyz;
|
|
41116
|
+
vec3 a = texelFetch1D( bvh.position, indices.x ).rgb;
|
|
41117
|
+
vec3 b = texelFetch1D( bvh.position, indices.y ).rgb;
|
|
41118
|
+
vec3 c = texelFetch1D( bvh.position, indices.z ).rgb;
|
|
41119
|
+
|
|
41120
|
+
if (
|
|
41121
|
+
intersectsTriangle( rayOrigin, rayDirection, a, b, c, localBarycoord, localNormal, localDist, localSide )
|
|
41122
|
+
&& localDist < minDistance
|
|
41123
|
+
) {
|
|
41124
|
+
|
|
41125
|
+
found = true;
|
|
41126
|
+
minDistance = localDist;
|
|
41127
|
+
|
|
41128
|
+
faceIndices = uvec4( indices.xyz, i );
|
|
41129
|
+
faceNormal = localNormal;
|
|
41130
|
+
|
|
41131
|
+
side = localSide;
|
|
41132
|
+
barycoord = localBarycoord;
|
|
41133
|
+
dist = localDist;
|
|
41134
|
+
|
|
41135
|
+
}
|
|
41136
|
+
|
|
41137
|
+
}
|
|
41138
|
+
|
|
41139
|
+
return found;
|
|
41140
|
+
|
|
41141
|
+
}
|
|
41142
|
+
|
|
41143
|
+
float intersectsBVHNodeBounds( vec3 rayOrigin, vec3 rayDirection, BVH bvh, uint currNodeIndex ) {
|
|
41144
|
+
|
|
41145
|
+
vec3 boundsMin = texelFetch1D( bvh.bvhBounds, currNodeIndex * 2u + 0u ).xyz;
|
|
41146
|
+
vec3 boundsMax = texelFetch1D( bvh.bvhBounds, currNodeIndex * 2u + 1u ).xyz;
|
|
41147
|
+
return intersectsBounds( rayOrigin, rayDirection, boundsMin, boundsMax );
|
|
41148
|
+
|
|
41149
|
+
}
|
|
41150
|
+
|
|
41151
|
+
bool bvhIntersectFirstHit(
|
|
41152
|
+
BVH bvh, vec3 rayOrigin, vec3 rayDirection,
|
|
41153
|
+
|
|
41154
|
+
// output variables
|
|
41155
|
+
inout uvec4 faceIndices, inout vec3 faceNormal, inout vec3 barycoord,
|
|
41156
|
+
inout float side, inout float dist
|
|
41157
|
+
) {
|
|
41158
|
+
|
|
41159
|
+
// stack needs to be twice as long as the deepest tree we expect because
|
|
41160
|
+
// we push both the left and right child onto the stack every traversal
|
|
41161
|
+
int ptr = 0;
|
|
41162
|
+
uint stack[ 60 ];
|
|
41163
|
+
stack[ 0 ] = 0u;
|
|
41164
|
+
|
|
41165
|
+
float triangleDistance = 1e20;
|
|
41166
|
+
bool found = false;
|
|
41167
|
+
while ( ptr > - 1 && ptr < 60 ) {
|
|
41168
|
+
|
|
41169
|
+
uint currNodeIndex = stack[ ptr ];
|
|
41170
|
+
ptr --;
|
|
41171
|
+
|
|
41172
|
+
// check if we intersect the current bounds
|
|
41173
|
+
float boundsHitDistance = intersectsBVHNodeBounds( rayOrigin, rayDirection, bvh, currNodeIndex );
|
|
41174
|
+
if ( boundsHitDistance == INFINITY || boundsHitDistance > triangleDistance ) {
|
|
41175
|
+
|
|
41176
|
+
continue;
|
|
41177
|
+
|
|
41178
|
+
}
|
|
41179
|
+
|
|
41180
|
+
uvec2 boundsInfo = uTexelFetch1D( bvh.bvhContents, currNodeIndex ).xy;
|
|
41181
|
+
bool isLeaf = bool( boundsInfo.x & 0xffff0000u );
|
|
41182
|
+
|
|
41183
|
+
if ( isLeaf ) {
|
|
41184
|
+
|
|
41185
|
+
uint count = boundsInfo.x & 0x0000ffffu;
|
|
41186
|
+
uint offset = boundsInfo.y;
|
|
41187
|
+
|
|
41188
|
+
found = intersectTriangles(
|
|
41189
|
+
bvh, rayOrigin, rayDirection, offset, count, triangleDistance,
|
|
41190
|
+
faceIndices, faceNormal, barycoord, side, dist
|
|
41191
|
+
) || found;
|
|
41192
|
+
|
|
41193
|
+
} else {
|
|
41194
|
+
|
|
41195
|
+
uint leftIndex = currNodeIndex + 1u;
|
|
41196
|
+
uint splitAxis = boundsInfo.x & 0x0000ffffu;
|
|
41197
|
+
uint rightIndex = boundsInfo.y;
|
|
41198
|
+
|
|
41199
|
+
bool leftToRight = rayDirection[ splitAxis ] >= 0.0;
|
|
41200
|
+
uint c1 = leftToRight ? leftIndex : rightIndex;
|
|
41201
|
+
uint c2 = leftToRight ? rightIndex : leftIndex;
|
|
41202
|
+
|
|
41203
|
+
// set c2 in the stack so we traverse it later. We need to keep track of a pointer in
|
|
41204
|
+
// the stack while we traverse. The second pointer added is the one that will be
|
|
41205
|
+
// traversed first
|
|
41206
|
+
ptr ++;
|
|
41207
|
+
stack[ ptr ] = c2;
|
|
41208
|
+
|
|
41209
|
+
ptr ++;
|
|
41210
|
+
stack[ ptr ] = c1;
|
|
41211
|
+
|
|
41212
|
+
}
|
|
41213
|
+
|
|
41214
|
+
}
|
|
41215
|
+
|
|
41216
|
+
return found;
|
|
41217
|
+
|
|
41218
|
+
}
|
|
41219
|
+
`
|
|
41220
|
+
);
|
|
41221
|
+
function shaderMaterial(uniforms, vertexShader, fragmentShader, onInit) {
|
|
41222
|
+
const material = class material extends ShaderMaterial {
|
|
41223
|
+
constructor(parameters = {}) {
|
|
41224
|
+
const entries = Object.entries(uniforms);
|
|
41225
|
+
super({
|
|
41226
|
+
uniforms: entries.reduce((acc, [name, value]) => {
|
|
41227
|
+
const uniform = UniformsUtils.clone({
|
|
41228
|
+
[name]: {
|
|
41229
|
+
value
|
|
41230
|
+
}
|
|
41231
|
+
});
|
|
41232
|
+
return {
|
|
41233
|
+
...acc,
|
|
41234
|
+
...uniform
|
|
41235
|
+
};
|
|
41236
|
+
}, {}),
|
|
41237
|
+
vertexShader,
|
|
41238
|
+
fragmentShader
|
|
41239
|
+
});
|
|
41240
|
+
this.key = "";
|
|
41241
|
+
entries.forEach(([name]) => Object.defineProperty(this, name, {
|
|
41242
|
+
get: () => this.uniforms[name].value,
|
|
41243
|
+
set: (v) => this.uniforms[name].value = v
|
|
41244
|
+
}));
|
|
41245
|
+
Object.assign(this, parameters);
|
|
41246
|
+
if (onInit)
|
|
41247
|
+
onInit(this);
|
|
41248
|
+
}
|
|
41249
|
+
};
|
|
41250
|
+
material.key = MathUtils.generateUUID();
|
|
41251
|
+
return material;
|
|
41252
|
+
}
|
|
41253
|
+
const getVersion = () => parseInt(REVISION.replace(/\D+/g, ""));
|
|
41254
|
+
const version = /* @__PURE__ */ getVersion();
|
|
41255
|
+
const MeshRefractionMaterial = /* @__PURE__ */ shaderMaterial(
|
|
41256
|
+
{
|
|
41257
|
+
envMap: null,
|
|
41258
|
+
bounces: 2,
|
|
41259
|
+
ior: 2.5,
|
|
41260
|
+
correctMips: true,
|
|
41261
|
+
aberrationStrength: 0.01,
|
|
41262
|
+
fresnel: 0.4,
|
|
41263
|
+
bvh: /* @__PURE__ */ new MeshBVHUniformStruct(),
|
|
41264
|
+
color: /* @__PURE__ */ new Color("white"),
|
|
41265
|
+
resolution: /* @__PURE__ */ new Vector2(),
|
|
41266
|
+
viewMatrixInverse: /* @__PURE__ */ new Matrix4(),
|
|
41267
|
+
projectionMatrixInverse: /* @__PURE__ */ new Matrix4()
|
|
41268
|
+
},
|
|
41269
|
+
/*glsl*/
|
|
41270
|
+
`
|
|
41271
|
+
uniform mat4 viewMatrixInverse;
|
|
41272
|
+
|
|
41273
|
+
varying vec3 vWorldPosition;
|
|
41274
|
+
varying vec3 vNormal;
|
|
41275
|
+
varying mat4 vModelMatrixInverse;
|
|
41276
|
+
|
|
41277
|
+
#ifdef USE_INSTANCING_COLOR
|
|
41278
|
+
varying vec3 vInstanceColor;
|
|
41279
|
+
#endif
|
|
41280
|
+
|
|
41281
|
+
void main() {
|
|
41282
|
+
vec4 transformedNormal = vec4(normal, 0.0);
|
|
41283
|
+
vec4 transformedPosition = vec4(position, 1.0);
|
|
41284
|
+
#ifdef USE_INSTANCING
|
|
41285
|
+
transformedNormal = instanceMatrix * transformedNormal;
|
|
41286
|
+
transformedPosition = instanceMatrix * transformedPosition;
|
|
41287
|
+
#endif
|
|
41288
|
+
|
|
41289
|
+
#ifdef USE_INSTANCING
|
|
41290
|
+
vModelMatrixInverse = inverse(modelMatrix * instanceMatrix);
|
|
41291
|
+
#else
|
|
41292
|
+
vModelMatrixInverse = inverse(modelMatrix);
|
|
41293
|
+
#endif
|
|
41294
|
+
|
|
41295
|
+
#ifdef USE_INSTANCING_COLOR
|
|
41296
|
+
vInstanceColor = instanceColor.rgb;
|
|
41297
|
+
#endif
|
|
41298
|
+
|
|
41299
|
+
vWorldPosition = (modelMatrix * transformedPosition).xyz;
|
|
41300
|
+
vNormal = normalize((viewMatrixInverse * vec4(normalMatrix * transformedNormal.xyz, 0.0)).xyz);
|
|
41301
|
+
gl_Position = projectionMatrix * viewMatrix * modelMatrix * transformedPosition;
|
|
41302
|
+
}`,
|
|
41303
|
+
/*glsl*/
|
|
41304
|
+
`
|
|
41305
|
+
#define ENVMAP_TYPE_CUBE_UV
|
|
41306
|
+
precision highp isampler2D;
|
|
41307
|
+
precision highp usampler2D;
|
|
41308
|
+
varying vec3 vWorldPosition;
|
|
41309
|
+
varying vec3 vNormal;
|
|
41310
|
+
varying mat4 vModelMatrixInverse;
|
|
41311
|
+
|
|
41312
|
+
#ifdef USE_INSTANCING_COLOR
|
|
41313
|
+
varying vec3 vInstanceColor;
|
|
41314
|
+
#endif
|
|
41315
|
+
|
|
41316
|
+
#ifdef ENVMAP_TYPE_CUBEM
|
|
41317
|
+
uniform samplerCube envMap;
|
|
41318
|
+
#else
|
|
41319
|
+
uniform sampler2D envMap;
|
|
41320
|
+
#endif
|
|
41321
|
+
|
|
41322
|
+
uniform float bounces;
|
|
41323
|
+
${shaderStructs}
|
|
41324
|
+
${shaderIntersectFunction}
|
|
41325
|
+
uniform BVH bvh;
|
|
41326
|
+
uniform float ior;
|
|
41327
|
+
uniform bool correctMips;
|
|
41328
|
+
uniform vec2 resolution;
|
|
41329
|
+
uniform float fresnel;
|
|
41330
|
+
uniform mat4 modelMatrix;
|
|
41331
|
+
uniform mat4 projectionMatrixInverse;
|
|
41332
|
+
uniform mat4 viewMatrixInverse;
|
|
41333
|
+
uniform float aberrationStrength;
|
|
41334
|
+
uniform vec3 color;
|
|
41335
|
+
|
|
41336
|
+
float fresnelFunc(vec3 viewDirection, vec3 worldNormal) {
|
|
41337
|
+
return pow( 1.0 + dot( viewDirection, worldNormal), 10.0 );
|
|
41338
|
+
}
|
|
41339
|
+
|
|
41340
|
+
vec3 totalInternalReflection(vec3 ro, vec3 rd, vec3 normal, float ior, mat4 modelMatrixInverse) {
|
|
41341
|
+
vec3 rayOrigin = ro;
|
|
41342
|
+
vec3 rayDirection = rd;
|
|
41343
|
+
rayDirection = refract(rayDirection, normal, 1.0 / ior);
|
|
41344
|
+
rayOrigin = vWorldPosition + rayDirection * 0.001;
|
|
41345
|
+
rayOrigin = (modelMatrixInverse * vec4(rayOrigin, 1.0)).xyz;
|
|
41346
|
+
rayDirection = normalize((modelMatrixInverse * vec4(rayDirection, 0.0)).xyz);
|
|
41347
|
+
for(float i = 0.0; i < bounces; i++) {
|
|
41348
|
+
uvec4 faceIndices = uvec4( 0u );
|
|
41349
|
+
vec3 faceNormal = vec3( 0.0, 0.0, 1.0 );
|
|
41350
|
+
vec3 barycoord = vec3( 0.0 );
|
|
41351
|
+
float side = 1.0;
|
|
41352
|
+
float dist = 0.0;
|
|
41353
|
+
bvhIntersectFirstHit( bvh, rayOrigin, rayDirection, faceIndices, faceNormal, barycoord, side, dist );
|
|
41354
|
+
vec3 hitPos = rayOrigin + rayDirection * max(dist - 0.001, 0.0);
|
|
41355
|
+
vec3 tempDir = refract(rayDirection, faceNormal, ior);
|
|
41356
|
+
if (length(tempDir) != 0.0) {
|
|
41357
|
+
rayDirection = tempDir;
|
|
41358
|
+
break;
|
|
41359
|
+
}
|
|
41360
|
+
rayDirection = reflect(rayDirection, faceNormal);
|
|
41361
|
+
rayOrigin = hitPos + rayDirection * 0.01;
|
|
41362
|
+
}
|
|
41363
|
+
rayDirection = normalize((modelMatrix * vec4(rayDirection, 0.0)).xyz);
|
|
41364
|
+
return rayDirection;
|
|
41365
|
+
}
|
|
41366
|
+
|
|
41367
|
+
#include <common>
|
|
41368
|
+
#include <cube_uv_reflection_fragment>
|
|
41369
|
+
|
|
41370
|
+
#ifdef ENVMAP_TYPE_CUBEM
|
|
41371
|
+
vec4 textureGradient(samplerCube envMap, vec3 rayDirection, vec3 directionCamPerfect) {
|
|
41372
|
+
return textureGrad(envMap, rayDirection, dFdx(correctMips ? directionCamPerfect: rayDirection), dFdy(correctMips ? directionCamPerfect: rayDirection));
|
|
41373
|
+
}
|
|
41374
|
+
#else
|
|
41375
|
+
vec4 textureGradient(sampler2D envMap, vec3 rayDirection, vec3 directionCamPerfect) {
|
|
41376
|
+
vec2 uvv = equirectUv( rayDirection );
|
|
41377
|
+
vec2 smoothUv = equirectUv( directionCamPerfect );
|
|
41378
|
+
return textureGrad(envMap, uvv, dFdx(correctMips ? smoothUv : uvv), dFdy(correctMips ? smoothUv : uvv));
|
|
41379
|
+
}
|
|
41380
|
+
#endif
|
|
41381
|
+
|
|
41382
|
+
void main() {
|
|
41383
|
+
vec2 uv = gl_FragCoord.xy / resolution;
|
|
41384
|
+
vec3 directionCamPerfect = (projectionMatrixInverse * vec4(uv * 2.0 - 1.0, 0.0, 1.0)).xyz;
|
|
41385
|
+
directionCamPerfect = (viewMatrixInverse * vec4(directionCamPerfect, 0.0)).xyz;
|
|
41386
|
+
directionCamPerfect = normalize(directionCamPerfect);
|
|
41387
|
+
vec3 normal = vNormal;
|
|
41388
|
+
vec3 rayOrigin = cameraPosition;
|
|
41389
|
+
vec3 rayDirection = normalize(vWorldPosition - cameraPosition);
|
|
41390
|
+
vec3 finalColor;
|
|
41391
|
+
#ifdef CHROMATIC_ABERRATIONS
|
|
41392
|
+
vec3 rayDirectionG = totalInternalReflection(rayOrigin, rayDirection, normal, max(ior, 1.0), vModelMatrixInverse);
|
|
41393
|
+
#ifdef FAST_CHROMA
|
|
41394
|
+
vec3 rayDirectionR = normalize(rayDirectionG + 1.0 * vec3(aberrationStrength / 2.0));
|
|
41395
|
+
vec3 rayDirectionB = normalize(rayDirectionG - 1.0 * vec3(aberrationStrength / 2.0));
|
|
41396
|
+
#else
|
|
41397
|
+
vec3 rayDirectionR = totalInternalReflection(rayOrigin, rayDirection, normal, max(ior * (1.0 - aberrationStrength), 1.0), vModelMatrixInverse);
|
|
41398
|
+
vec3 rayDirectionB = totalInternalReflection(rayOrigin, rayDirection, normal, max(ior * (1.0 + aberrationStrength), 1.0), vModelMatrixInverse);
|
|
41399
|
+
#endif
|
|
41400
|
+
float finalColorR = textureGradient(envMap, rayDirectionR, directionCamPerfect).r;
|
|
41401
|
+
float finalColorG = textureGradient(envMap, rayDirectionG, directionCamPerfect).g;
|
|
41402
|
+
float finalColorB = textureGradient(envMap, rayDirectionB, directionCamPerfect).b;
|
|
41403
|
+
finalColor = vec3(finalColorR, finalColorG, finalColorB);
|
|
41404
|
+
#else
|
|
41405
|
+
rayDirection = totalInternalReflection(rayOrigin, rayDirection, normal, max(ior, 1.0), vModelMatrixInverse);
|
|
41406
|
+
finalColor = textureGradient(envMap, rayDirection, directionCamPerfect).rgb;
|
|
41407
|
+
#endif
|
|
41408
|
+
|
|
41409
|
+
finalColor *= color;
|
|
41410
|
+
#ifdef USE_INSTANCING_COLOR
|
|
41411
|
+
finalColor *= vInstanceColor;
|
|
41412
|
+
#endif
|
|
41413
|
+
|
|
41414
|
+
vec3 viewDirection = normalize(vWorldPosition - cameraPosition);
|
|
41415
|
+
float nFresnel = fresnelFunc(viewDirection, normal) * fresnel;
|
|
41416
|
+
gl_FragColor = vec4(mix(finalColor, vec3(1.0), nFresnel), 1.0);
|
|
41417
|
+
#include <tonemapping_fragment>
|
|
41418
|
+
#include <${version >= 154 ? "colorspace_fragment" : "encodings_fragment"}>
|
|
41419
|
+
}`
|
|
41420
|
+
);
|
|
37285
41421
|
let lensMaterial;
|
|
41422
|
+
let envMap;
|
|
37286
41423
|
const positions = [0, 0.4, 0.7, 1];
|
|
37287
41424
|
const opacities = [0.85, 0.62, 0.3, 0];
|
|
37288
41425
|
const colors = [
|
|
@@ -37307,6 +41444,11 @@ var __publicField = (obj, key, value) => {
|
|
|
37307
41444
|
opacities: { value: opacities }
|
|
37308
41445
|
};
|
|
37309
41446
|
document.getElementById("gui-container");
|
|
41447
|
+
const diamondMaterial = new MeshRefractionMaterial();
|
|
41448
|
+
const BLOOM_SCENE = 1;
|
|
41449
|
+
const bloomLayer = new Layers();
|
|
41450
|
+
bloomLayer.set(BLOOM_SCENE);
|
|
41451
|
+
new MeshBasicMaterial({ color: "black" });
|
|
37310
41452
|
class CustomRenderer {
|
|
37311
41453
|
// lensMaterial:THREE.MeshPhysicalMaterial| any
|
|
37312
41454
|
constructor(apiService) {
|
|
@@ -37319,6 +41461,7 @@ var __publicField = (obj, key, value) => {
|
|
|
37319
41461
|
this.scene = new Scene();
|
|
37320
41462
|
}
|
|
37321
41463
|
async intialize() {
|
|
41464
|
+
var _a;
|
|
37322
41465
|
const newWidth = document.querySelector("canvas.sprie-config-webgl").clientWidth;
|
|
37323
41466
|
const newHeight = document.querySelector("canvas.sprie-config-webgl").clientHeight;
|
|
37324
41467
|
this.camera = new PerspectiveCamera(
|
|
@@ -37336,6 +41479,42 @@ var __publicField = (obj, key, value) => {
|
|
|
37336
41479
|
});
|
|
37337
41480
|
this.renderer.setSize(newWidth, newHeight);
|
|
37338
41481
|
this.renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
|
|
41482
|
+
const rgbeLoader = new RGBELoader();
|
|
41483
|
+
rgbeLoader.load(
|
|
41484
|
+
"https://sprie-jarvis-public.s3.eu-west-2.amazonaws.com/environment_desaturated.hdr",
|
|
41485
|
+
(environmentMap) => {
|
|
41486
|
+
environmentMap.mapping = EquirectangularReflectionMapping;
|
|
41487
|
+
this.scene.environment = environmentMap;
|
|
41488
|
+
}
|
|
41489
|
+
);
|
|
41490
|
+
rgbeLoader.load(
|
|
41491
|
+
"https://sprie-jarvis-public.s3.eu-west-2.amazonaws.com/environment_gemstones.hdr",
|
|
41492
|
+
(reflectionMap) => {
|
|
41493
|
+
reflectionMap.mapping = EquirectangularReflectionMapping;
|
|
41494
|
+
diamondMaterial.uniforms.envMap.value = reflectionMap;
|
|
41495
|
+
envMap = reflectionMap;
|
|
41496
|
+
}
|
|
41497
|
+
);
|
|
41498
|
+
const aberrationStrength = 0.01;
|
|
41499
|
+
const isCubeTexture = (def) => def && def.isCubeTexture;
|
|
41500
|
+
diamondMaterial.uniforms.aberrationStrength.value = aberrationStrength;
|
|
41501
|
+
diamondMaterial.uniforms.resolution.value = new Vector2(newWidth, newHeight);
|
|
41502
|
+
const temp5 = {};
|
|
41503
|
+
const isCubeMap = isCubeTexture(envMap);
|
|
41504
|
+
const w2 = (isCubeMap ? (_a = envMap == null ? void 0 : envMap.image[0]) == null ? void 0 : _a.width : envMap == null ? void 0 : envMap.image.width) ?? 1024;
|
|
41505
|
+
const cubeSize = w2 / 4;
|
|
41506
|
+
const _lodMax = Math.floor(Math.log2(cubeSize));
|
|
41507
|
+
const _cubeSize = Math.pow(2, _lodMax);
|
|
41508
|
+
const width = 3 * Math.max(_cubeSize, 16 * 7);
|
|
41509
|
+
const height = 4 * _cubeSize;
|
|
41510
|
+
if (isCubeMap)
|
|
41511
|
+
temp5.ENVMAP_TYPE_CUBEM = "";
|
|
41512
|
+
temp5.CUBEUV_TEXEL_WIDTH = `${1 / width}`;
|
|
41513
|
+
temp5.CUBEUV_TEXEL_HEIGHT = `${1 / height}`;
|
|
41514
|
+
temp5.CUBEUV_MAX_MIP = `${_lodMax}.0`;
|
|
41515
|
+
temp5.CHROMATIC_ABERRATIONS = "";
|
|
41516
|
+
temp5.FAST_CHROMA = "";
|
|
41517
|
+
diamondMaterial.defines = temp5;
|
|
37339
41518
|
}
|
|
37340
41519
|
cleanUp() {
|
|
37341
41520
|
if (this.renderer) {
|
|
@@ -37395,6 +41574,7 @@ var __publicField = (obj, key, value) => {
|
|
|
37395
41574
|
gltf.scene.traverse((node) => {
|
|
37396
41575
|
if (node.isMesh) {
|
|
37397
41576
|
bottom = Math.min(bottom, this.getMinY(node));
|
|
41577
|
+
console.log("node name", node.name);
|
|
37398
41578
|
if (node.material && node.material.name == "Lenses") {
|
|
37399
41579
|
let lowestY = Number.POSITIVE_INFINITY;
|
|
37400
41580
|
let highestY = Number.NEGATIVE_INFINITY;
|
|
@@ -37453,7 +41633,7 @@ var __publicField = (obj, key, value) => {
|
|
|
37453
41633
|
`
|
|
37454
41634
|
)}
|
|
37455
41635
|
`;
|
|
37456
|
-
shader.fragmentShader =
|
|
41636
|
+
shader.fragmentShader = `uniform sampler2D uTexture;
|
|
37457
41637
|
uniform vec2 resolution;
|
|
37458
41638
|
uniform vec3 color;
|
|
37459
41639
|
uniform bool uAlpha;
|
|
@@ -37499,6 +41679,14 @@ var __publicField = (obj, key, value) => {
|
|
|
37499
41679
|
lensMaterial.needsUpdate = true;
|
|
37500
41680
|
}
|
|
37501
41681
|
}
|
|
41682
|
+
if (node.material && node.name === "Diamonds") {
|
|
41683
|
+
console.log("Diamond mesh detected");
|
|
41684
|
+
diamondMaterial.uniforms.bvh.value = new MeshBVHUniformStruct();
|
|
41685
|
+
diamondMaterial.uniforms.bvh.value.updateFrom(
|
|
41686
|
+
new MeshBVH(node.geometry.clone().toNonIndexed(), { strategy: SAH })
|
|
41687
|
+
);
|
|
41688
|
+
node.material = diamondMaterial;
|
|
41689
|
+
}
|
|
37502
41690
|
}
|
|
37503
41691
|
});
|
|
37504
41692
|
let diff = targetY - bottom;
|
|
@@ -37735,7 +41923,6 @@ var __publicField = (obj, key, value) => {
|
|
|
37735
41923
|
}
|
|
37736
41924
|
setupLensMaterial(selectedLens) {
|
|
37737
41925
|
if (lensMaterial) {
|
|
37738
|
-
console.log(selectedLens);
|
|
37739
41926
|
if (selectedLens.direction == "u") {
|
|
37740
41927
|
lensMaterial.color = new Color(selectedLens.color);
|
|
37741
41928
|
lensMaterial.opacity = selectedLens.opacity;
|
|
@@ -37766,17 +41953,6 @@ var __publicField = (obj, key, value) => {
|
|
|
37766
41953
|
}
|
|
37767
41954
|
}
|
|
37768
41955
|
setupAndRenderScene() {
|
|
37769
|
-
const rgbeLoader = new RGBELoader();
|
|
37770
|
-
rgbeLoader.load(
|
|
37771
|
-
"https://sprie-jarvis-public.s3.eu-west-2.amazonaws.com/royal_esplanade_1k_desaturated.hdr",
|
|
37772
|
-
(environmentMap) => {
|
|
37773
|
-
const pmremGenerator = new PMREMGenerator(this.renderer);
|
|
37774
|
-
pmremGenerator.compileCubemapShader();
|
|
37775
|
-
const hdrCubeRenderTarget = pmremGenerator.fromEquirectangular(environmentMap).texture;
|
|
37776
|
-
this.scene.environment = hdrCubeRenderTarget;
|
|
37777
|
-
pmremGenerator.dispose();
|
|
37778
|
-
}
|
|
37779
|
-
);
|
|
37780
41956
|
if (!this.camera || !this.renderer)
|
|
37781
41957
|
return;
|
|
37782
41958
|
this.scene.add(this.camera);
|
|
@@ -37791,8 +41967,8 @@ var __publicField = (obj, key, value) => {
|
|
|
37791
41967
|
2.2,
|
|
37792
41968
|
4
|
|
37793
41969
|
);
|
|
37794
|
-
controls.minDistance =
|
|
37795
|
-
controls.maxDistance =
|
|
41970
|
+
controls.minDistance = 1;
|
|
41971
|
+
controls.maxDistance = 5;
|
|
37796
41972
|
controls.enableDamping = true;
|
|
37797
41973
|
controls.dampingFactor = 0.2;
|
|
37798
41974
|
controls.enablePan = true;
|
|
@@ -37802,6 +41978,7 @@ var __publicField = (obj, key, value) => {
|
|
|
37802
41978
|
this.renderer.toneMapping = ACESFilmicToneMapping;
|
|
37803
41979
|
this.renderer.toneMappingExposure = 1.2;
|
|
37804
41980
|
this.renderer.setClearColor(15724527);
|
|
41981
|
+
this.renderer.outputColorSpace = SRGBColorSpace;
|
|
37805
41982
|
const PLANE_WIDTH = 2.5;
|
|
37806
41983
|
const PLANE_HEIGHT = 2.5;
|
|
37807
41984
|
const CAMERA_HEIGHT = 0.4;
|
|
@@ -37893,11 +42070,11 @@ var __publicField = (obj, key, value) => {
|
|
|
37893
42070
|
shadowCamera.updateProjectionMatrix();
|
|
37894
42071
|
}
|
|
37895
42072
|
const outputPass = new OutputPass();
|
|
37896
|
-
const size = this.renderer.getDrawingBufferSize(new Vector2());
|
|
37897
|
-
const renderTarget2 = new WebGLRenderTarget(size.width, size.height, { samples: 4, type: HalfFloatType });
|
|
37898
42073
|
const renderPass = new RenderPass(this.scene, this.camera);
|
|
37899
42074
|
renderPass.clearAlpha = 0;
|
|
37900
|
-
|
|
42075
|
+
const size = this.renderer.getDrawingBufferSize(new Vector2());
|
|
42076
|
+
const renderTargetAA = new WebGLRenderTarget(size.width, size.height, { samples: 4, type: HalfFloatType });
|
|
42077
|
+
const composer = new EffectComposer(this.renderer, renderTargetAA);
|
|
37901
42078
|
composer.addPass(renderPass);
|
|
37902
42079
|
composer.addPass(outputPass);
|
|
37903
42080
|
const animate = () => {
|
|
@@ -37918,6 +42095,8 @@ var __publicField = (obj, key, value) => {
|
|
|
37918
42095
|
this.renderer.setRenderTarget(null);
|
|
37919
42096
|
this.renderer.setClearAlpha(initialClearAlpha);
|
|
37920
42097
|
this.scene.background = initialBackground;
|
|
42098
|
+
diamondMaterial.uniforms.viewMatrixInverse.value = this.camera.matrixWorld;
|
|
42099
|
+
diamondMaterial.uniforms.projectionMatrixInverse.value = this.camera.projectionMatrixInverse;
|
|
37921
42100
|
requestAnimationFrame(animate);
|
|
37922
42101
|
composer.render();
|
|
37923
42102
|
};
|
|
@@ -46848,7 +51027,7 @@ var __publicField = (obj, key, value) => {
|
|
|
46848
51027
|
log,
|
|
46849
51028
|
logErr,
|
|
46850
51029
|
metaData: {
|
|
46851
|
-
appVersion: version,
|
|
51030
|
+
appVersion: version$1,
|
|
46852
51031
|
previewUrlPrams,
|
|
46853
51032
|
targetClassName: "sprie-embed-element"
|
|
46854
51033
|
}
|