diff --git a/OctreeCSG.extended.js b/OctreeCSG/OctreeCSG.extended.js
similarity index 100%
rename from OctreeCSG.extended.js
rename to OctreeCSG/OctreeCSG.extended.js
diff --git a/OctreeCSG.js b/OctreeCSG/OctreeCSG.js
similarity index 100%
rename from OctreeCSG.js
rename to OctreeCSG/OctreeCSG.js
diff --git a/OctreeCSG.worker.js b/OctreeCSG/OctreeCSG.worker.js
similarity index 100%
rename from OctreeCSG.worker.js
rename to OctreeCSG/OctreeCSG.worker.js
diff --git a/test/OctreeCSG/three-triangle-intersection.js b/OctreeCSG/three-triangle-intersection.js
similarity index 100%
rename from test/OctreeCSG/three-triangle-intersection.js
rename to OctreeCSG/three-triangle-intersection.js
diff --git a/test/OTCSGDemo.html b/test/OTCSGDemo.html
deleted file mode 100644
index 4104b18..0000000
--- a/test/OTCSGDemo.html
+++ /dev/null
@@ -1,32 +0,0 @@
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/test/OTCSGDemo.js b/test/OTCSGDemo.js
deleted file mode 100644
index 0bf6cbd..0000000
--- a/test/OTCSGDemo.js
+++ /dev/null
@@ -1,249 +0,0 @@
-
-import * as THREE from 'three';
-import {OrbitControls} from 'threeModules/controls/OrbitControls.js';
-//import {TorusKnotGeometry} from 'threeModules/geometries/TorusKnotGeometry.js';
-import CSG from "./three-csg.js"
-import app from "./app3.js"
-import OctreeCSG from "OctreeCSG/OctreeCSG.js"
-import { computeBoundsTree, disposeBoundsTree, acceleratedRaycast } from './three-mesh-bvh.module.js';
-
-const computeBoundsTree_original = THREE.BufferGeometry.prototype.computeBoundsTree;
-const disposeBoundsTree_original = THREE.BufferGeometry.prototype.disposeBoundsTree;
-const raycast_original = THREE.Mesh.prototype.raycast;
-window.OctreeCSG = OctreeCSG;
-let {renderer,scene,camera} = app;
-
-//UI(app);
-let tx = app.environment.makeProceduralTexture(256,(u,v)=>{
- let rb = ((Math.random()*128)|0) * (((((u*2)&1)^((v*2)&1))|0)?1:2)
- return (rb*256)|(rb*256*256)|(rb*256*256*256)|0x000000ff
-})
-tx.repeat.set(2,2);
-tx.wrapS = tx.wrapT = THREE.RepeatWrapping
-
-let mkMat=(color) => new THREE.MeshStandardMaterial({color:color,roughness:1,metalness:0.8,map:tx});
-let rnd=(rng)=>((Math.random()*2)-1)*(rng||1)
-
-let testMeshes = {
- sphere:new THREE.Mesh(new THREE.SphereGeometry(1.2,8,8),mkMat('grey')),
- box: new THREE.Mesh(new THREE.BoxGeometry(2,2,2),mkMat('grey')),
- torusknot: new THREE.Mesh(new THREE.TorusKnotGeometry(1, .4, 30, 4),mkMat('grey')),
-}
-let meshNames=Object.keys(testMeshes)
-let objA = 0;
-let objB = 1;
-
-
-let animating = true
-let stepping = false
-let logPositionsFlag = false;
-
-let meshA = testMeshes[meshNames[objA]].clone();
-scene.add(meshA)
-
-let meshB = testMeshes[meshNames[objB]].clone();
-scene.add(meshB)
-
-
-function doCSGbrute(a,b,op,mat){
- let bspA = CSG.fromMesh( a );
- let bspB = CSG.fromMesh( b );
- let bspC = bspA[op]( bspB );
- let result = CSG.toMesh( bspC, a.matrix );
- result.material = mat;
- result.castShadow = result.receiveShadow = true;
- result.csgOp = op;
- return result;
-}
-function doCSGoctree(a,b,op,mat){
- let bspA = OctreeCSG.fromMesh( a );
- let bspB = OctreeCSG.fromMesh( b );
- let bspC = OctreeCSG[op]( bspA,bspB );
- let result = OctreeCSG.toMesh( bspC , a.material);//, a.matrix );
- result.material = mat;
- result.castShadow = result.receiveShadow = true;
- result.csgOp = op;
- return result;
-}
-function doCSGoctreeBVH(a,b,op,mat){
- a.geometry.computeBoundsTree();
- b.geometry.computeBoundsTree();
- let bspA = OctreeCSG.fromMesh( a );
- let bspB = OctreeCSG.fromMesh( b );
- let bspC = OctreeCSG[op]( bspA,bspB );
- let result = OctreeCSG.toMesh( bspC , a.material);//, a.matrix );
- result.material = mat;
- result.castShadow = result.receiveShadow = true;
- a.geometry.disposeBoundsTree();
- b.geometry.disposeBoundsTree();
- result.csgOp = op;
- return result;
-}
-
-let subMaterial = mkMat('red')
-let intersectMaterial = mkMat('green')
-let unionMaterial = mkMat('blue');
-let results = []
-
-let mats=[subMaterial,intersectMaterial,unionMaterial]
-
-let csgMethods={
- 'brute':doCSGbrute,
- 'octree':doCSGoctree,
- 'octree + mesh-bvh':doCSGoctreeBVH
-}
-let csgMethodsNames = Object.keys(csgMethods);
-
-let curCSGMethod = 1;
-let csgMethod = csgMethods[csgMethodsNames[curCSGMethod]]
-
-let info = document.createElement('span')
-
-Object.assign(info.style,{
- position: 'absolute',
- zIndex: 10,
- left: '10px',
- top: '10px',
- fontFamily: 'Arial, Helvetica, sans-serif',
- color: 'white',
- background: 'rgba(50,50,50,.5)'})
-document.body.appendChild(info)
-
-let timeTaken=0;
-let heap = 0;
-let heapLow = 0;
-let heapHigh = 0;
-let heapChange = 0;
-let mb=v=>(v/1000000)|0
-let updateInfo=()=>{
- let ntris=0;
- results.forEach(m=>ntris+=m.geometry.attributes.position.count)
- info.innerHTML = `[W] - wireframe
-[Space] - change method
-[Q] - objA:${meshNames[objA]}
-[E] - objB:${meshNames[objB]}
-[A] - animate
-[D] - step
-current method:${csgMethodsNames[curCSGMethod]}
-time taken: ${timeTaken.toFixed(2)}
-triangles: ${ntris}
-heap low (mb) : ${mb(heapLow)}
-heap high (mb): ${mb(heapHigh)}
-heap (mb) : ${mb(heap)}
-used
-`
-}
-
-let step = 0;
-window.addEventListener("keydown", (e)=>{
-if(e.code=='KeyW'){
- scene.traverse(e=>e.isMesh&&((e.material.length&&(e.material.forEach(m=>m.wireframe=!m.wireframe)))||(e.material.wireframe = !e.material.wireframe)))
- mats.forEach(m=>m.wireframe=!m.wireframe)
-}else if(e.code=='Space'){
- curCSGMethod = (curCSGMethod + 1) % csgMethodsNames.length;
- csgMethod = csgMethods[csgMethodsNames[curCSGMethod]];
- if (curCSGMethod == 2) { // octree + mesh-bvh
- THREE.BufferGeometry.prototype.computeBoundsTree = computeBoundsTree;
- THREE.BufferGeometry.prototype.disposeBoundsTree = disposeBoundsTree;
- THREE.Mesh.prototype.raycast = acceleratedRaycast;
- meshA.geometry.computeBoundsTree = computeBoundsTree;
- meshA.geometry.disposeBoundsTree = disposeBoundsTree;
- meshA.raycast = acceleratedRaycast;
- meshB.geometry.computeBoundsTree = computeBoundsTree;
- meshB.geometry.disposeBoundsTree = disposeBoundsTree;
- meshB.raycast = acceleratedRaycast;
- }
- else {
- THREE.BufferGeometry.prototype.computeBoundsTree = computeBoundsTree_original;
- THREE.BufferGeometry.prototype.disposeBoundsTree = disposeBoundsTree_original;
- THREE.Mesh.prototype.raycast = raycast_original;
- meshA.geometry.computeBoundsTree = computeBoundsTree_original;
- meshA.geometry.disposeBoundsTree = disposeBoundsTree_original;
- meshA.raycast = raycast_original;
- meshB.geometry.computeBoundsTree = computeBoundsTree_original;
- meshB.geometry.disposeBoundsTree = disposeBoundsTree_original;
- meshB.raycast = raycast_original;
- }
-
-
-}else if(e.code=='KeyQ'){
- objA=(objA+1)%meshNames.length;
- meshA.geometry=testMeshes[meshNames[objA]].geometry;
-}else if(e.code=='KeyE'){
- objB=(objB+1)%meshNames.length;
- meshB.geometry=testMeshes[meshNames[objB]].geometry;
-}else if(e.code=='KeyA'){
- animating = true;
- stepping = false;
-}else if(e.code=='KeyD'){
- animating = false;
- stepping = true;
- step+=16;
- logPositionsFlag = true;
-}
-
-}, false);
-
-function recompute(){
- heapChange = performance.memory.usedJSHeapSize;
- timeTaken = performance.now();
- for(let i=0;i{
- //let time = performance.now()
-
- meshA.position.x=Math.sin(step*0.001)*2;
- meshA.position.z=Math.cos(step*0.0011)*0.5;
- if(animating){
- step+=16
- recompute();
- }
- else if (stepping) {
- recompute();
- console.log("meshA position:", meshA.position);
- console.log("meshB position:", meshB.position);
- stepping = false;
- }
- //meshA.position.t=Math.sin(time*-0.0012)*0.5;
- // if (logPositionsFlag) {
- // console.log("meshA position:", meshA.position);
- // console.log("meshB position:", meshB.position);
- // logPositionsFlag = false;
- // }
-})
diff --git a/test/OctreeCSG/OctreeCSG.js b/test/OctreeCSG/OctreeCSG.js
deleted file mode 100644
index 32f7095..0000000
--- a/test/OctreeCSG/OctreeCSG.js
+++ /dev/null
@@ -1,3305 +0,0 @@
-// import * as THREE from 'three';
-// const { Vector2, Vector3, Box3, BackSide, DoubleSide, FrontSide, Matrix3, Matrix4, Ray, Triangle, BufferGeometry, BufferAttribute, Mesh, Raycaster } = THREE;
-import { Vector2, Vector3, Box3, BackSide, DoubleSide, FrontSide, Matrix3, Matrix4, Ray, Triangle, BufferGeometry, BufferAttribute, Mesh, Raycaster } from 'three';
-import { triangleIntersectsTriangle, checkTrianglesIntersection } from './three-triangle-intersection.js';
-const _v1 = new Vector3();
-const _v2 = new Vector3();
-const _v3 = new Vector3();
-const tmpInverseMatrix = new Matrix4();
-// import * as BVH from '/js/three-mesh-bvh.module.js';
-// console.log("BVH TEST:", BVH);
-
-const tv0 = new Vector3();
-const tv1 = new Vector3();
-const _raycaster1 = new Raycaster();
-const _ray = new Ray();
-const _ray2 = new Ray();
-const _rayDirection = new Vector3(0, 0, 1);
-
-// const _raycastDirections = [
-// new Vector3(0, 0, 1),
-// new Vector3(0, 1, 0),
-// new Vector3(1, 0, 0)
-// ];
-// const _raycastDirectionsCount = _raycastDirections.length;
-
-
-let _octreeID = 0;
-let _triangleID = 0;
-let _polygonID = 0;
-const EPSILON = 1e-5;
-const COPLANAR = 0;
-const FRONT = 1;
-const BACK = 2;
-const SPANNING = 3;
-let testvar = 0;
-// const trianglesMap = new Map();
-//const polygonMaps = new Map();
-
-class OctreeCSG {
- constructor(box, parent) {
- // this.octreeMap = new Map();
- // this.isOctree = true;
- // this.triangles = [];
- this.polygons = [];
- // this.polygonMap;
- this.mesh;
- this.originalMatrixWorld;
- // this.bspNode;
- this.box = box;
- this.subTrees = [];
- this.parent = parent;
- this.level = 0;
- Object.defineProperties(this, {
- id: {
- value: _octreeID++
- },
- isOctree: {
- value: true
- }
- });
-
- }
- clone() {
- return new this.constructor().copy(this);
- }
-
- copy(source) {
- this.polygons = source.polygons.map(p => p.clone());
- if (source.mesh) {
- this.mesh = source.mesh;
- }
- if (source.originalMatrixWorld) {
- this.originalMatrixWorld = source.originalMatrixWorld.clone();
- }
- this.box = source.box.clone();
- this.level = source.level;
-
- for (let i = 0; i < source.subTrees.length; i++) {
- let subTree = new this.constructor(undefined, this).copy(source.subTrees[i]);
- this.subTrees.push(subTree);
- }
-
- return this;
- }
- testget() {
- return testvar;
- }
- testset() {
- testvar++;
- }
- isEmpty() {
- return this.polygons.length === 0;
- }
- addPolygon(polygon) {
- if (!this.bounds) {
- this.bounds = new Box3();
- }
- let triangle = polygon.triangle;
- this.bounds.min.x = Math.min(this.bounds.min.x, triangle.a.x, triangle.b.x, triangle.c.x);
- this.bounds.min.y = Math.min(this.bounds.min.y, triangle.a.y, triangle.b.y, triangle.c.y);
- this.bounds.min.z = Math.min(this.bounds.min.z, triangle.a.z, triangle.b.z, triangle.c.z);
- this.bounds.max.x = Math.max(this.bounds.max.x, triangle.a.x, triangle.b.x, triangle.c.x);
- this.bounds.max.y = Math.max(this.bounds.max.y, triangle.a.y, triangle.b.y, triangle.c.y);
- this.bounds.max.z = Math.max(this.bounds.max.z, triangle.a.z, triangle.b.z, triangle.c.z);
-
- this.polygons.push(polygon);
- return this;
- }
-
- calcBox() {
- if (!this.bounds) {
- this.bounds = new Box3();
- }
- this.box = this.bounds.clone();
-
- // offset small ammount to account for regular grid
- this.box.min.x -= 0.01;
- this.box.min.y -= 0.01;
- this.box.min.z -= 0.01;
-
- return this;
-
- }
-
- split(level) {
-
- if (!this.box) return;
-
- const subTrees = [];
- const halfsize = _v2.copy(this.box.max).sub(this.box.min).multiplyScalar(0.5);
- for (let x = 0; x < 2; x++) {
- for (let y = 0; y < 2; y++) {
- for (let z = 0; z < 2; z++) {
- const box = new Box3();
- const v = _v1.set(x, y, z);
-
- box.min.copy(this.box.min).add(v.multiply(halfsize));
- box.max.copy(box.min).add(halfsize);
- box.expandByScalar(EPSILON);
- subTrees.push(new OctreeCSG(box, this));
- }
- }
- }
- // console.log(`Octree (${this.id}) suggested subTrees:`, subTrees);
- // let triangle;
- let polygon;
- // while (triangle = this.triangles.pop()) {
- while (polygon = this.polygons.pop()) {
- let triangle = polygon.triangle;
- let found = false;
- for (let i = 0; i < subTrees.length; i++) {
- // let triangleMidPoint = Vector3();
-
- if (subTrees[i].box.containsPoint(triangle.midPoint)) {
- // if (subTrees[i].box.containsPoint(triangle.getMidpoint(_v1))) {
- // if (subTrees[i].box.intersectsTriangle(triangle)) {
-
- // subTrees[i].triangles.push(triangle);
- subTrees[i].polygons.push(polygon);
- found = true;
- }
-
- }
- if (!found) {
- console.error("ERROR: unable to find subtree for:", triangle, triangle.getMidpoint(_v1), this, subTrees);
- throw new Error(`Unable to find subtree for triangle at level ${level}`);
- }
-
- }
- // if (level >= OctreeCSG.maxLevel) {
- // console.log(`Warning: Octree reached max level (${level})`);
- // }
- for (let i = 0; i < subTrees.length; i++) {
- subTrees[i].level = level + 1;
- const len = subTrees[i].polygons.length;
-
- if (len > OctreeCSG.polygonsPerTree && level < OctreeCSG.maxLevel) {
-
- subTrees[i].split(level + 1);
-
- }
-
- // if (len !== 0) {
-
- this.subTrees.push(subTrees[i]);
-
- // }
-
- }
-
- return this;
-
- }
-
- buildTree() {
- // this.setPolygonMap(new Map());
- // octree.setPolygonMap();
- this.calcBox();
- this.split(0);
- this.processTree();
- // console.log("trianglesMap", trianglesMap);
- return this;
-
- }
- processTree() {
- // this.octreeMap.set(this.id, this);
- if (!this.isEmpty()) {
- // console.log("triangles in level", this.level, "Octree ID:", this.id);
- // let currentBox = this.box.clone();
- // for (let i = 0; i < this.triangles.length; i++) {
- for (let i = 0; i < this.polygons.length; i++) {
- // OctreeCSG.addPolygonToMap(this.polygonMap, this.polygons[i], this);
- // OctreeCSG.addTriangleToMap(trianglesMap, this.triangles[i], this);
- this.box.expandByPoint(this.polygons[i].triangle.a);
- this.box.expandByPoint(this.polygons[i].triangle.b);
- this.box.expandByPoint(this.polygons[i].triangle.c);
- // currentBox.expandByPoint(this.triangles[i].a);
- // currentBox.expandByPoint(this.triangles[i].b);
- // currentBox.expandByPoint(this.triangles[i].c);
-
- // if (this.polygons[i].source === "a") {
- // this.aPolygons.push(this.polygons[i]);
- // }
- // else if (this.polygons[i].source === "b") {
- // this.bPolygons.push(this.polygons[i]);
- // }
- }
- this.expandParentBox();
- // if (!this.box.equals(currentBox)) {
- // console.log("bound box changed in tree id", this.id, this.box, currentBox);
- // }
- }
- for (let i = 0; i < this.subTrees.length; i++) {
- // this.subTrees[i].setPolygonMap(this.polygonMap);
- this.subTrees[i].processTree();
- }
- }
- expandParentBox() {
- if (this.parent) {
- this.parent.box.expandByPoint(this.box.min);
- this.parent.box.expandByPoint(this.box.max);
- this.parent.expandParentBox();
- }
- }
- // setPolygonMap(map) {
- // this.polygonMap = map;
- // }
-
- // Not used
- // getRayTriangles(ray, triangles) {
- // // console.log("triangles:", triangles);
- // for (let i = 0; i < this.subTrees.length; i++) {
-
- // const subTree = this.subTrees[i];
- // if (!ray.intersectsBox(subTree.box)) {
- // // console.log(i, "ray not intersecting", subTree.box);
- // continue;
- // }
- // // console.log(i, "poly count:", subTree.polygons.length);
- // // if (subTree.triangles.length > 0) {
- // if (subTree.polygons.length > 0) {
- // // for (let j = 0; j < subTree.triangles.length; j++) {
- // for (let j = 0; j < subTree.polygons.length; j++) {
-
- // // if (triangles.indexOf(subTree.triangles[j]) === - 1) triangles.push(subTree.triangles[j]);
- // if (triangles.indexOf(subTree.polygons[j].triangle) === - 1) {
- // // console.log("adding triangle", subTree.polygons[j].triangle);
- // triangles.push(subTree.polygons[j].triangle);
- // }
- // // else {
- // // console.log("skipping triangle", subTree.polygons[j].triangle, "all triangles:", triangles);
- // // }
-
- // }
-
- // } else {
-
- // subTree.getRayTriangles(ray, triangles);
-
- // }
-
- // }
-
- // return triangles;
-
- // }
-
-
- // Not used
- // increaseTriangleSize(triangle, targetTriangle = new Triangle()) {
- // let EPSILON = 0;
- // targetTriangle.copy(triangle);
- // targetTriangle.a.x += triangle.a.x < 0 ? -EPSILON : EPSILON;
- // targetTriangle.a.y += triangle.a.y < 0 ? -EPSILON : EPSILON;
- // targetTriangle.a.z += triangle.a.z < 0 ? -EPSILON : EPSILON;
- // targetTriangle.b.x += triangle.b.x < 0 ? -EPSILON : EPSILON;
- // targetTriangle.b.y += triangle.b.y < 0 ? -EPSILON : EPSILON;
- // targetTriangle.b.z += triangle.b.z < 0 ? -EPSILON : EPSILON;
- // targetTriangle.c.x += triangle.c.x < 0 ? -EPSILON : EPSILON;
- // targetTriangle.c.y += triangle.c.y < 0 ? -EPSILON : EPSILON;
- // targetTriangle.c.z += triangle.c.z < 0 ? -EPSILON : EPSILON;
- // return targetTriangle;
- // }
- getPolygonsOnlyIntersectingPolygon(targetPolygon, polygons = []) {
- if (targetPolygon.triangle === undefined) {
- console.log("UNDEFINED", targetPolygon);
- return polygons;
- }
- if (this.box.intersectsTriangle(targetPolygon.triangle)) {
- if (this.polygons.length > 0) {
- polygons.push(...this.polygons.filter(p => p.valid));
- }
- for (let i = 0; i < this.subTrees.length; i++) {
- this.subTrees[i].getPolygonsOnlyIntersectingPolygon(targetPolygon, polygons);
- }
- }
-
- return polygons;
- }
-
-
- getPolygonsIntersectingPolygon(targetPolygon, debug = false, polygons = []) {
- let found = false;
- if (this.polygons.length > 0) {
- if (targetPolygon.triangle === undefined) {
- console.log("UNDEFINED", targetPolygon);
- }
- // let targetTriangle = this.increaseTriangleSize(targetPolygon.triangle);
- let targetTriangle = targetPolygon.triangle;
- // let bvhTriangle1 = new BVH.SeparatingAxisTriangle(targetTriangle.a, targetTriangle.b, targetTriangle.c);
- if (this.box.intersectsTriangle(targetTriangle)) {
- for (let i = 0; i < this.polygons.length; i++) {
- let polygon = this.polygons[i];
- // }
- // this.polygons.forEach(polygon => {
- if (!polygon.valid || !polygon.intersects) {
- continue;
- }
- if (debug) {
- // if (((polygon.triangle.a.z == 5) || (polygon.triangle.b.z == 5) || (polygon.triangle.c.z == 5)) && ((polygon.triangle.a.x >= 1) || (polygon.triangle.b.x >= 1) || (polygon.triangle.c.x >= 1))) {
- let additionsObj = {
- coplanar: false,
- source: new Vector3(),
- target: new Vector3()
- };
- console.log("Testing intersection with polygon:", targetPolygon.id, targetPolygon, polygon, polygon.triangle);
- if ((targetTriangle === undefined) || (polygon.triangle === undefined)) {
- console.log("UNDEFINED!!!!!", targetPolygon, polygon);
- }
- // if (triangleIntersectsTriangle(targetTriangle, polygon.triangle, additionsObj)) {
-
-
- // let bvhTriangle2 = new BVH.SeparatingAxisTriangle(polygon.triangle.a, polygon.triangle.b, polygon.triangle.c);
- // console.log("BVH Intersect", bvhTriangle1.intersectsTriangle(bvhTriangle2));
- // if (bvhTriangle1.intersectsTriangle(bvhTriangle2)) {
- // console.log("found intersecting polygon", polygon);
- if (checkTrianglesIntersection(targetTriangle, polygon.triangle, additionsObj)) {
- console.log("intersects", additionsObj.triangleCheck, additionsObj);
- polygons.push(polygon);
- found = true;
- }
- // else {
- // console.log("nope", additionsObj.triangleCheck);
- // }
-
- }
- else {
- if ((targetTriangle === undefined) || (polygon.triangle === undefined)) {
- console.log("UNDEFINED!!!!!", targetPolygon, polygon);
- }
- // if (triangleIntersectsTriangle(targetTriangle, polygon.triangle)) {
- if (checkTrianglesIntersection(targetTriangle, polygon.triangle)) {
- polygons.push(polygon);
- }
-
- }
- };
- }
- }
- debug && console.warn("[getPolygonsIntersectingPolygon] FOUND?", found);
-
- for (let i = 0; i < this.subTrees.length; i++) {
- this.subTrees[i].getPolygonsIntersectingPolygon(targetPolygon, debug, polygons);
- }
-
- return polygons;
- }
-
-
- // Testing
- populatePolygonWithOctree() {
- if (this.polygons.length > 0) {
- this.polygons.forEach(p => p.octree = this);
- }
- for (let i = 0; i < this.subTrees.length; i++) {
- this.subTrees[i].populatePolygonWithOctree();
- }
- }
- getRayPolygons(ray, polygons = []) {
- // console.log("[getRayPolygons] checking octree", this, this.polygons.length);
- if (this.polygons.length > 0) {
- for (let i = 0; i < this.polygons.length; i++) {
- if (this.polygons[i].valid) {
- if (polygons.indexOf(this.polygons[i]) === -1) {
- polygons.push(this.polygons[i]);
- }
- }
- }
- }
- for (let i = 0; i < this.subTrees.length; i++) {
- // if (ray.triangle ? this.subTrees[i].box.intersectsTriangle(ray.triangle) : ray.intersectsBox(this.subTrees[i].box)) {
- if (ray.intersectsBox(this.subTrees[i].box)) {
- this.subTrees[i].getRayPolygons(ray, polygons);
- }
- }
-
- return polygons;
- }
-
- // Testing
- rayIntersect(ray, matrixWorld, intersects = []) {
-
- if (ray.direction.length() === 0) return;
- if (matrixWorld) {
- tmpInverseMatrix.copy(matrixWorld).invert();
- _ray2.copy(ray).applyMatrix4(tmpInverseMatrix);
- }
-
- // three-mesh-bvh
- // const distance = ray.origin.distanceTo( point );
- // hit.point.applyMatrix4( object.matrixWorld );
- // hit.distance = hit.point.distanceTo( raycaster.ray.origin );
- // hit.object = object;
- // if ( hit.distance < raycaster.near || hit.distance > raycaster.far ) {
- // return null;
- // } else {
- // return hit;
-
-
- // three.js
- // _intersectionPointWorld.copy(point);
- // _intersectionPointWorld.applyMatrix4(object.matrixWorld);
- // const distance = raycaster.ray.origin.distanceTo(_intersectionPointWorld);
- // if (distance < raycaster.near || distance > raycaster.far) return null;
- // return {
- // distance: distance,
- // point: _intersectionPointWorld.clone(),
- // object: object
- // };
-
-
-
-
- // const polygons = [];
- let polygon, position, distance = 1e100;
-
- // this.getRayTriangles(ray, triangles);
-
- // let polygons = this.getRayPolygons(ray);
- // let polygons = this.getPolygons();
- let polygons = OctreeCSG.getRayPolys ? this.getRayPolygons(ray) : this.getPolygons();
-
- OctreeCSG.debugPoly && console.log("[rayIntersect] polygons", polygons, "OctreeCSG.testSide", OctreeCSG.testSide);
- for (let i = 0; i < polygons.length; i++) {
- let result;
- switch (OctreeCSG.rayIntersectTriangleType) {
- case "MollerTrumbore":
- result = rayIntersectsTriangle(ray, polygons[i].triangle, _v1);
- if (result) {
- const newdistance = result.clone().sub(ray.origin).length();
- if (distance > newdistance) {
- distance = newdistance;
- }
- if (distance < 1e100) {
- // if (distance !== newdistance) {
- // console.log("DISTANCE CHECK:", distance, newdistance);
- // }
- // intersects.push({ distance: newdistance, polygon: polygons[i], position: result.clone().add(ray.origin) });
- intersects.push({ distance: distance, polygon: polygons[i], position: result.clone().add(ray.origin) });
- }
- else {
- console.log("BIG DISTANCE:", { distance: distance, polygon: polygons[i], position: result.clone().add(ray.origin) });
- }
- }
- break;
- case "regular":
- default:
- // ray.direction = polygons[i].vertices[0].normal;
- // let result = ray.intersectTriangle(polygons[i].triangle.c, polygons[i].triangle.b, polygons[i].triangle.a, true, _v1); // back
- result = ray.intersectTriangle(polygons[i].triangle.a, polygons[i].triangle.b, polygons[i].triangle.c, false, _v1); //double
-
-
- // let result = _ray2.intersectTriangle(polygons[i].triangle.a, polygons[i].triangle.b, polygons[i].triangle.c, false, _v1); //double
- if (result) {
- _v1.applyMatrix4(matrixWorld);
- // distance = ray.origin.distanceTo(_v1);
- distance = _v1.distanceTo(ray.origin);
- // if (distance > 0 && distance < Infinity) {
- if (distance < 0 || distance > Infinity) {
- console.warn("[rayIntersect] Failed ray distance check", ray);
- }
- else {
- intersects.push({ distance: distance, polygon: polygons[i], position: _v1.clone() });
- }
-
-
- // const newdistance = result.sub(ray.origin).length();
- // if (distance > newdistance) {
- // position = result.clone().add(ray.origin);
- // distance = newdistance;
- // polygon = polygons[i];
- // }
- // if (distance < 1e100) {
- // intersects.push({ distance: newdistance, polygon: polygons[i], position: result.clone().add(ray.origin) });
- // }
- // else {
- // console.log("BIG DISTANCE:", { distance: distance, polygon: polygon, position: position });
- // }
-
- }
- break;
- }
-
- OctreeCSG.debugPoly && console.log("[rayIntersect]", i, result);
- // Not required since always using DoubleSide check (?)
- /*
- if (OctreeCSG.testSide == BackSide) { // backside
- // console.log("ray testing back");
- result = ray.intersectTriangle(polygons[i].triangle.c, polygons[i].triangle.b, polygons[i].triangle.a, true, _v1);
- }
- else if (OctreeCSG.testSide == DoubleSide) { // doubleside
- // console.log("ray testing double");
- // console.log("OctreeCSG.testSide !== DoubleSide", OctreeCSG.testSide !== DoubleSide, OctreeCSG.testSide);
- result = ray.intersectTriangle(polygons[i].triangle.a, polygons[i].triangle.b, polygons[i].triangle.c, false, _v1);
- }
- else if (OctreeCSG.testSide == FrontSide) { // frontside
- // console.log("ray testing front");
- // console.log("OctreeCSG.testSide !== DoubleSide", OctreeCSG.testSide !== DoubleSide, OctreeCSG.testSide);
- result = ray.intersectTriangle(polygons[i].triangle.a, polygons[i].triangle.b, polygons[i].triangle.c, true, _v1);
- }
- // result = ray.intersectTriangle(triangles[i].a, triangles[i].b, triangles[i].c, false, _v1);
- */
-
- // const result = ray.intersectTriangle(triangles[i].a, triangles[i].b, triangles[i].c, true, _v1);
-
- // else {
- // console.log(i, "nope", result);
- // }
-
- }
- // intersectObject(object, recursive = true, intersects = []) {
- // intersectObject(object, this, intersects, recursive);
- // intersects.sort(ascSort);
- // return intersects;
- // }
- intersects.length && intersects.sort(raycastIntersectAscSort);
- return intersects;
- // return distance < 1e100 ? { distance: distance, triangle: triangle, position: position } : false;
-
- }
-
- getIntersectingPolygons(polygons = []) {
- if (this.polygons.length) {
- for (let i = 0; i < this.polygons.length; i++) {
- if (this.polygons[i].valid && this.polygons[i].intersects) {
- polygons.push(this.polygons[i]);
- }
- }
- }
- for (let i = 0; i < this.subTrees.length; i++) {
- this.subTrees[i].getIntersectingPolygons(polygons);
- }
- return polygons;
- }
- getPolygons(polygons = []) {
- if (this.polygons.length) {
- for (let i = 0; i < this.polygons.length; i++) {
- if (this.polygons[i].valid) {
- polygons.push(this.polygons[i]);
- }
- }
- }
- for (let i = 0; i < this.subTrees.length; i++) {
- this.subTrees[i].getPolygons(polygons);
- }
- return polygons;
- }
- getInvalidPolygons(polygons = []) {
- polygons.push(...this.polygons.filter(p => !p.valid));
- for (let i = 0; i < this.subTrees.length; i++) {
- this.subTrees[i].getInvalidPolygons(polygons);
- }
-
- return polygons;
- }
- invert() {
- if (this.polygons.length > 0) {
- this.polygons.forEach(p => p.flip());
- }
- for (let i = 0; i < this.subTrees.length; i++) {
- this.subTrees[i].invert();
- }
- }
- getMesh() {
- if (this.parent) {
- return this.parent.getMesh();
- }
- return this.mesh;
- }
-
- replacePolygon(polygon, newPolygons, firstRun = true) {
- if (!Array.isArray(newPolygons)) {
- newPolygons = [newPolygons];
- }
- if (this.polygons.length > 0) {
- let polygonIndex = this.polygons.indexOf(polygon);
- if (polygonIndex > -1) {
- // console.log("replacing polygons in tree id", this.id, "old polygon:", polygon, "new polygons:", newPolygons);
- polygon.setInvalid();
- this.polygons.splice(polygonIndex, 1, ...newPolygons);
- // polygon.delete();
- }
- }
- for (let i = 0; i < this.subTrees.length; i++) {
- this.subTrees[i].replacePolygon(polygon, newPolygons, false);
- }
- if (firstRun) {
- polygon.delete();
- }
- }
-
-
- deletePolygonsByStateRules(rulesArr, debug = false, firstRun = true) {
- if (this.polygons.length > 0) {
- // let polygonArr = this.polygons.slice();
- let polygonArr = this.polygons.filter(polygon => (polygon.valid == true) && (polygon.intersects == true));
- polygonArr.forEach(polygon => {
- let found = false;
- for (let j = 0; j < rulesArr.length; j++) {
- if (rulesArr[j].array) {
- let states = rulesArr[j].rule;
- if ((states.includes(polygon.state)) && (((polygon.previousState !== "undecided") && (states.includes(polygon.previousState))) || (polygon.previousState == "undecided"))) {
- debug && console.log("deletePolygonsByStates A");
- found = true;
- let statesObj = {};
- let mainStatesObj = {};
- states.forEach(state => statesObj[state] = false);
- states.forEach(state => mainStatesObj[state] = false);
- statesObj[polygon.state] = true;
- for (let i = 0; i < polygon.previousStates.length; i++) {
- if (!states.includes(polygon.previousStates[i])) { // if previous state not one of provided states (not included in states array), break
- debug && console.log("deletePolygonsByStates B", polygon.previousStates[i]);
- found = false;
- break;
- }
- else {
- statesObj[polygon.previousStates[i]] = true;
- }
- }
- debug && console.log("deletePolygonsByStates C");
- if (found) {
- debug && console.log("deletePolygonsByStates D");
- // if (polygon.previousState !== "undecided") { // <- NOT TESTED
- for (let state in statesObj) {
- if (statesObj[state] === false) {
- // if (!mainSatisfied) {
- debug && console.log("deletePolygonsByStates D2");
- found = false;
- // }
- break;
- }
- }
- // }
-
- if (found) {
- break;
- }
- }
- }
- }
- else {
- if (polygon.checkAllStates(rulesArr[j].rule)) {
- found = true;
- break;
- }
- }
- }
- if (found) {
- debug && console.log("deletePolygonsByStates E");
- let polygonIndex = this.polygons.indexOf(polygon);
- if (polygonIndex > -1) {
- debug && console.log("deletePolygonsByStates F", polygon);
- polygon.setInvalid();
- this.polygons.splice(polygonIndex, 1);
- // polygon.delete();
- }
- // else {
- // polygon.setInvalid();
- // }
- if (firstRun) {
- polygon.delete();
- }
- }
- });
- }
- for (let i = 0; i < this.subTrees.length; i++) {
- this.subTrees[i].deletePolygonsByStateRules(rulesArr, debug, false);
- }
- }
-
- deletePolygonsByIntersection(intersects, firstRun = true) {
- if (intersects == undefined) {
- return;
- }
- if (this.polygons.length > 0) {
- let polygonArr = this.polygons.slice();
- polygonArr.forEach(polygon => {
- if (polygon.valid) {
- if (polygon.intersects === intersects) {
- let polygonIndex = this.polygons.indexOf(polygon);
- if (polygonIndex > -1) {
- polygon.setInvalid();
- this.polygons.splice(polygonIndex, 1);
- // polygon.delete();
- }
- // else {
- // polygon.setInvalid();
- // }
- if (firstRun) {
- polygon.delete();
- }
- }
- }
- });
- }
- for (let i = 0; i < this.subTrees.length; i++) {
- this.subTrees[i].deletePolygonsByIntersection(intersects, false);
- }
- }
-
- isPolygonIntersecting(polygon) {
- if (!this.box.intersectsTriangle(polygon.triangle)) {
- return false;
- }
-
- // Changing to return true if intersecting with box, if looking only for octrees with polygons that intersects it can lead to incorrectly identifying intersecting polygons
- return true;
- // if (this.polygons.length > 0) {
- // return true;
- // }
- // let isIntersecting = false;
- // if (this.subTrees.length > 0) {
- // for (let i = 0; i < this.subTrees.length; i++) {
- // isIntersecting = this.subTrees[i].isPolygonIntersecting(polygon);
- // if (isIntersecting) {
- // break;
- // }
- // }
- // }
- // return isIntersecting;
- }
- markIntesectingPolygons(targetOctree) {
- if (this.polygons.length > 0) {
- this.polygons.forEach(polygon => {
- // polygon.intersects = boundingBox.intersectsTriangle(polygon.triangle);
- polygon.intersects = targetOctree.isPolygonIntersecting(polygon);
- // polygon.intersects = targetOctree.box.intersectsTriangle(polygon.triangle);
- });
- }
- for (let i = 0; i < this.subTrees.length; i++) {
- this.subTrees[i].markIntesectingPolygons(targetOctree);
- }
-
- }
-
- resetPolygonsByState(state) {
- if (this.polygons.length > 0) {
- this.polygons.forEach(polygon => {
- if (polygon.valid && polygon.intersects) {
- if (polygon.state == state && polygon.previousState == "undecided") {
- polygon.state = "undecided";
- polygon.checkAll = true;
- }
- }
- // polygon.reset();
- });
- }
- for (let i = 0; i < this.subTrees.length; i++) {
- this.subTrees[i].resetPolygonsByState(state);
- }
- }
- resetPolygons() {
- if (this.polygons.length > 0) {
- this.polygons.forEach(polygon => {
- polygon.reset();
- });
- }
- for (let i = 0; i < this.subTrees.length; i++) {
- this.subTrees[i].resetPolygons();
- }
- }
- handleIntersectingPolygons(targetOctree, targetOctreeBuffer) {
- if (this.polygons.length > 0) {
- let polygonStack = this.polygons.filter(polygon => (polygon.valid == true) && (polygon.intersects == true) && (polygon.state == "undecided"));
- let currentPolygon = polygonStack.pop();
- while (currentPolygon) {
- if (currentPolygon.state !== "undecided") {
- continue;
- }
- if (!currentPolygon.valid) {
- continue;
- }
-
- let debugPoly = false;
- // let testTriangle = new THREE.Triangle(new THREE.Vector3(0.29171404242515564, -4.110300540924072, 2.832019329071045), new THREE.Vector3(-0.29171404242515564, -4.110300540924072, 2.832019329071045), new THREE.Vector3(0, -4.3809967041015625, 2.4097442626953125));
- // if ((OctreeCSG.returnType == -1) && (currentPolygon.triangle.equals(testTriangle))) {
- // debugPoly = true;
- // console.warn("STARTING DEBUG");
- // }
- OctreeCSG.debugPoly = debugPoly;
- let targetPolygons = targetOctree.getPolygonsIntersectingPolygon(currentPolygon, debugPoly);
-
- if (targetPolygons.length > 0) {
- if (debugPoly) {
- console.log("BLA POLYGON TARGET COUNT", targetPolygons.length);
- }
- // let needsBreak = false;
- for (let j = 0; j < targetPolygons.length; j++) {
- let target = targetPolygons[j];
- if (debugPoly) {
- console.log("BLA POLYGON", currentPolygon, target);
- }
- // console.log("needsBreak", needsBreak);
- let splitResults = splitPolygonByPlane(currentPolygon, target.plane);
- debugPoly && console.log("splitResults", splitResults)
- if (splitResults.length > 1) {
- // let newPolygons = [];
- for (let i = 0; i < splitResults.length; i++) {
- let polygon = splitResults[i].polygon;
- polygon.intersects = currentPolygon.intersects;
- polygon.splitState1 = splitResults[i].type;
- // if (splitResults[i].type == "back") {
- polygonStack.push(polygon);
- // }
- // else {
- // polygon.setState(splitResults[i].type);
- // }
-
- }
- this.replacePolygon(currentPolygon, splitResults.map(result => result.polygon));
- // needsBreak = true;
- break;
- }
- else {
- if (currentPolygon.id !== splitResults[0].polygon.id) {
- splitResults[0].polygon.intersects = currentPolygon.intersects;
- splitResults[0].polygon.splitState2 = splitResults[0].type;
- // if (splitResults[0].type == "back") {
- polygonStack.push(splitResults[0].polygon);
- // }
- // else {
- // splitResults[0].polygon.setState(splitResults[0].type);
- // }
- this.replacePolygon(currentPolygon, splitResults[0].polygon);
- break;
- }
- else {
- if ((splitResults[0].type == "coplanar-front") || (splitResults[0].type == "coplanar-back")) {
- currentPolygon.setState(splitResults[0].type);
- currentPolygon.coplanar = true;
- }
- }
- }
- // if (needsBreak) {
- // break;
- // }
- // console.log(j, currentPolygon, target, splitResults);
-
- // let polyType = getPolygonType(currentPolygon, target.plane);
- // // console.log(i, currentPolygon, target, polyType);
- // let polyType2 = getRayIntersectionType(currentPolygon, target, aMatrixWorld);
- // console.log(i, "getRayIntersectionType", polyType2);
- }
- }
- else {
- debugPoly && console.log("[handleIntersectingPolygons] Not intersecting with any target polygons", currentPolygon);
- }
-
- // if (iteration >= 100) {
- // break;
- // }
- // console.log("--------------------");
- currentPolygon = polygonStack.pop();
- }
-
- // console.log("ASDADASD", this.polygons);
- // if (OctreeCSG.useWindingNumber === true && targetOctreeAllPolygons === undefined) {
- // console.log("[handleIntersectingPolygons] targetOctreeAllPolygons === undefined");
- // targetOctreeAllPolygons = targetOctree.getPolygons();
- // }
- polygonStack = this.polygons.filter(polygon => (polygon.valid == true) && (polygon.intersects == true));
- currentPolygon = polygonStack.pop();
- while (currentPolygon) {
- // if (currentPolygon.state !== "undecided") {
- // continue;
- // }
- if (!currentPolygon.valid) {
- continue;
- }
-
- let debugPoly = false;
-
- // let testTriangle = new THREE.Triangle(new THREE.Vector3(0.29171404242515564, -4.110300540924072, 2.832019329071045), new THREE.Vector3(-0.29171404242515564, -4.110300540924072, 2.832019329071045), new THREE.Vector3(0, -4.3809967041015625, 2.4097442626953125));
- // if ((OctreeCSG.returnType == -1) && (currentPolygon.triangle.equals(testTriangle))) {
- // debugPoly = true;
- // console.warn("STARTING DEBUG");
- // }
- OctreeCSG.debugPoly = debugPoly;
- let inside = false;
- if (targetOctree.box.containsPoint(currentPolygon.triangle.midPoint)) {
- if (OctreeCSG.useWindingNumber === true) {
- inside = polyInside_WindingNumber_buffer(targetOctreeBuffer, currentPolygon.triangle.midPoint, currentPolygon.coplanar);
- }
- else {
- let point = pointRounding(_v2.copy(currentPolygon.triangle.midPoint));
- // let point = currentPolygon.triangle.midPoint;
-
- // let point = pointRounding(currentPolygon.triangle.getMidpoint(_v2));
- debugPoly && console.log("point for currentPolygon", point.clone(), currentPolygon);
- // let point = currentPolygon.triangle.getMidpoint(_v2);
- // _rayDirection.copy(currentPolygon.plane.normal).normalize();
-
-
-
- if (OctreeCSG.useOctreeRay !== true) {
- // _ray.origin.copy(point);
- _rayDirection.copy(currentPolygon.plane.normal);
- // _raycaster1.ray.origin.copy(point);
- // _raycaster1.set(point, _rayDirection);
- // for (let i = 0; i < _raycastDirectionsCount; i++) {
- // _raycaster1.ray.direction.copy(_raycastDirections[i]);
- // let intersects = _raycaster1.intersectObject(targetOctree.mesh);
- // // console.log(i, "Intersects?", intersects);
- // if (debugPoly) {
- // console.log("RAY CHECK intersects.length", intersects.length, point, _raycastDirections[i]);
- // }
- // if (intersects.length) {
-
- // if (_raycastDirections[i].dot(intersects[0].face.normal) > 0) {
- // debugPoly && console.log(i, "Point is inside the object", _raycastDirections[i].dot(intersects[0].face.normal));
- // inside = true;
- // break;
- // }
- // else {
- // debugPoly && console.log(i, "Point is outside the object", _raycastDirections[i].dot(intersects[0].face.normal));
- // }
- // }
- // }
- _raycaster1.set(point, _rayDirection);
- let intersects = _raycaster1.intersectObject(targetOctree.mesh);
- // console.log(i, "Intersects?", intersects);
- if (debugPoly) {
- console.log("RAY CHECK intersects.length", intersects.length, point, _rayDirection);
- }
- if (intersects.length) {
-
- if (_rayDirection.dot(intersects[0].face.normal) > 0) {
- debugPoly && console.log("Point is inside the object", _rayDirection.dot(intersects[0].face.normal));
- inside = true;
- }
- else {
- debugPoly && console.log("Point is outside the object", _rayDirection.dot(intersects[0].face.normal));
- }
-
- }
- if (!inside && currentPolygon.coplanar) {
- // let coplanarFound = false;
- // console.log("POLYGON IS COPLANAR");
- for (let j = 0; j < _wP_EPS_ARR_COUNT; j++) {
- // console.warn("DOES IT GET HERE?");
- _raycaster1.ray.origin.copy(point).add(_wP_EPS_ARR[j]);
- // let intersects = targetOctree.rayIntersect(_ray, targetOctree.mesh.matrixWorld);
- let intersects = _raycaster1.intersectObject(targetOctree.mesh);
- // console.log(i, "Intersects?", intersects);
- if (debugPoly) {
- console.log("RAY CHECK intersects.length", intersects.length, point, _rayDirection);
- }
- if (intersects.length) {
-
- if (_rayDirection.dot(intersects[0].face.normal) > 0) {
- debugPoly && console.log("Point is inside the object", _rayDirection.dot(intersects[0].face.normal));
- inside = true;
- break;
- }
- else {
- debugPoly && console.log("Point is outside the object", _rayDirection.dot(intersects[0].face.normal));
- }
-
- }
- }
- // if (coplanarFound) {
- // console.log("Found as coplanar", _ray.clone());
- // }
- }
- }
- else {
- // let ray = new Ray(point, _rayDirection);
- _ray.origin.copy(point);
- _rayDirection.copy(currentPolygon.plane.normal);
- // _ray.direction.copy(_rayDirection);
- _ray.direction.copy(currentPolygon.plane.normal);
- // let intersects = targetOctree.rayIntersect(_ray, targetOctree.mesh.matrixWorld);
- let intersects = targetOctree.rayIntersect(_ray, targetOctree.originalMatrixWorld);
- if (debugPoly) {
- console.log("RAY CHECK intersects.length", intersects.length, point, _rayDirection);
- }
- if (intersects.length) {
- if (_rayDirection.dot(intersects[0].polygon.plane.normal) > 0) {
- debugPoly && console.log("Point is inside the object", _rayDirection.dot(intersects[0].polygon.plane.normal));
- inside = true;
- // break;
- }
- else {
- debugPoly && console.log("Point is outside the object", _rayDirection.dot(intersects[0].polygon.plane.normal));
- }
-
- }
- if (!inside && currentPolygon.coplanar) {
- // let coplanarFound = false;
- // console.log("POLYGON IS COPLANAR");
- for (let j = 0; j < _wP_EPS_ARR_COUNT; j++) {
- // console.warn("DOES IT GET HERE?");
- _ray.origin.copy(point).add(_wP_EPS_ARR[j]);
- _rayDirection.copy(currentPolygon.plane.normal);
- _ray.direction.copy(currentPolygon.plane.normal);
- // let intersects = targetOctree.rayIntersect(_ray, targetOctree.mesh.matrixWorld);
- let intersects = targetOctree.rayIntersect(_ray, targetOctree.originalMatrixWorld);
- if (debugPoly) {
- console.log("RAY CHECK intersects.length", intersects.length, point, _rayDirection);
- }
- if (intersects.length) {
- if (_rayDirection.dot(intersects[0].polygon.plane.normal) > 0) {
- debugPoly && console.log("Point is inside the object", _rayDirection.dot(intersects[0].polygon.plane.normal));
- inside = true;
- // coplanarFound = true;
- break;
- }
- else {
- debugPoly && console.log("Point is outside the object", _rayDirection.dot(intersects[0].polygon.plane.normal));
- }
-
- }
- }
- // if (coplanarFound) {
- // console.log("Found as coplanar", _ray.clone());
- // }
- }
- /*
- for (let i = 0; i < _raycastDirectionsCount; i++) {
- _ray.direction.copy(_raycastDirections[i]);
- let intersects = targetOctree.rayIntersect(_ray, targetOctree.mesh.matrixWorld);
- // let intersects = targetOctree.rayIntersect(_ray, targetOctree.originalMatrixWorld);
- if (debugPoly) {
- console.log("RAY CHECK intersects.length", intersects.length, point, _raycastDirections[i]);
- }
- if (intersects.length) {
- if (_raycastDirections[i].dot(intersects[0].polygon.plane.normal) > 0) {
- debugPoly && console.log(i, "Point is inside the object", _raycastDirections[i].dot(intersects[0].polygon.plane.normal));
- inside = true;
- break;
- }
- else {
- debugPoly && console.log(i, "Point is outside the object", _raycastDirections[i].dot(intersects[0].polygon.plane.normal));
- }
-
- }
- }
- */
-
- /*
- // let ray = new Ray(point, _rayDirection);
- let intersects = targetOctree.rayIntersect(ray);
- // console.log("octree ray test", intersects);
- if (debugPoly) {
- console.log("RAY CHECK intersects.length", intersects.length, point, _rayDirection);
- }
- if (intersects.length) {
- for (let i = 0; i < intersects.length; i++) {
- if (_rayDirection.dot(intersects[i].polygon.plane.normal) > 0) {
- debugPoly && console.log(i, "Point is inside the object", _rayDirection.dot(intersects[i].polygon.plane.normal));
- inside = true;
- break;
- }
- else {
- debugPoly && console.log(i, "Point is outside the object", _rayDirection.dot(intersects[i].polygon.plane.normal));
- }
- }
- }
- */
- }
- }
- }
-
- if (debugPoly) {
- console.log("CHECK INSIDE", inside);
- }
- if (inside === true) {
- currentPolygon.setState("inside");
- }
- else {
- currentPolygon.setState("outside");
- }
-
- currentPolygon = polygonStack.pop();
- }
-
- }
- for (let i = 0; i < this.subTrees.length; i++) {
- this.subTrees[i].handleIntersectingPolygons(targetOctree, targetOctreeBuffer);
- }
- }
-
- handleIntersectingPolygons_reduced(targetOctree, targetOctreeBuffer) { // used in async functions
- // async handleIntersectingPolygons_async(targetOctree, targetOctreeBuffer) {
- // return new Promise(async (resolve, reject) => {
- // try {
- if (this.polygons.length > 0) {
- // testvar++;
- // this.polygons.forEach(polygon => {
- // polygon.reset();
- // });
-
- // TESTING NEW METHOD
- let polygonStack = this.polygons.filter(polygon => (polygon.valid == true) && (polygon.intersects == true) && (polygon.state == "undecided"));
- let currentPolygon = polygonStack.pop();
- while (currentPolygon) {
- if (currentPolygon.state !== "undecided") {
- continue;
- }
- if (!currentPolygon.valid) {
- continue;
- }
-
- let debugPoly = false;
- // let testTriangle = new THREE.Triangle(new THREE.Vector3(0.29171404242515564, -4.110300540924072, 2.832019329071045), new THREE.Vector3(-0.29171404242515564, -4.110300540924072, 2.832019329071045), new THREE.Vector3(0, -4.3809967041015625, 2.4097442626953125));
- // if ((OctreeCSG.returnType == -1) && (currentPolygon.triangle.equals(testTriangle))) {
- // debugPoly = true;
- // console.warn("STARTING DEBUG");
- // }
- OctreeCSG.debugPoly = debugPoly;
- let targetPolygons = targetOctree.getPolygonsIntersectingPolygon(currentPolygon, debugPoly);
-
- if (targetPolygons.length > 0) {
- if (debugPoly) {
- console.log("BLA POLYGON TARGET COUNT", targetPolygons.length);
- }
- // let needsBreak = false;
- for (let j = 0; j < targetPolygons.length; j++) {
- let target = targetPolygons[j];
- if (debugPoly) {
- console.log("BLA POLYGON", currentPolygon, target);
- }
- // console.log("needsBreak", needsBreak);
- let splitResults = splitPolygonByPlane(currentPolygon, target.plane);
- debugPoly && console.log("splitResults", splitResults)
- if (splitResults.length > 1) {
- // let newPolygons = [];
- for (let i = 0; i < splitResults.length; i++) {
- let polygon = splitResults[i].polygon;
- polygon.intersects = currentPolygon.intersects;
- polygon.splitState1 = splitResults[i].type;
- polygonStack.push(polygon);
- }
- this.replacePolygon(currentPolygon, splitResults.map(result => result.polygon));
- break;
- }
- else {
- if (currentPolygon.id !== splitResults[0].polygon.id) {
- splitResults[0].polygon.intersects = currentPolygon.intersects;
- splitResults[0].polygon.splitState2 = splitResults[0].type;
- polygonStack.push(splitResults[0].polygon);
- this.replacePolygon(currentPolygon, splitResults[0].polygon);
- break;
- }
- else {
- if ((splitResults[0].type == "coplanar-front") || (splitResults[0].type == "coplanar-back")) {
- currentPolygon.setState(splitResults[0].type);
- currentPolygon.coplanar = true;
- }
- }
- }
- }
- }
- else {
- debugPoly && console.log("[handleIntersectingPolygons] Not intersecting with any target polygons", currentPolygon);
- }
-
- currentPolygon = polygonStack.pop();
- }
-
- /*
- polygonStack = this.polygons.filter(polygon => (polygon.valid == true) && (polygon.intersects == true));
- let runningWebWorkers = [];
- currentPolygon = polygonStack.pop();
- while (currentPolygon) {
- // console.warn("Checking loop polygon id", currentPolygon.id);
- if (!currentPolygon.valid) {
- continue;
- }
-
- let debugPoly = false;
-
- // let testTriangle = new THREE.Triangle(new THREE.Vector3(0.29171404242515564, -4.110300540924072, 2.832019329071045), new THREE.Vector3(-0.29171404242515564, -4.110300540924072, 2.832019329071045), new THREE.Vector3(0, -4.3809967041015625, 2.4097442626953125));
- // if ((OctreeCSG.returnType == -1) && (currentPolygon.triangle.equals(testTriangle))) {
- // debugPoly = true;
- // console.warn("STARTING DEBUG");
- // }
- OctreeCSG.debugPoly = debugPoly;
- let inside = false;
- if (targetOctree.box.containsPoint(currentPolygon.triangle.midPoint)) {
- // if (OctreeCSG.useWindingNumber === true) {
- // let responses = [];
- // // let result1 = OctreeCSG.testWorker(1);
- // // let result2 = OctreeCSG.testWorker(2);
- let worker = getAvailableWorker();
- while (!worker) {
- // console.log("Waiting for worker");
- await sleep(1);
- worker = getAvailableWorker();
- }
-
- worker.checkWindingNumber({
- type: 'windingNumber',
- point: currentPolygon.triangle.midPoint,
- coplanar: currentPolygon.coplanar,
- polygonID: currentPolygon.id,
- triangles: targetOctreeBuffer
- }, currentPolygon).then(worker => {
- // console.log("Worker finished", worker.id);
- let workerIndex = runningWebWorkers.indexOf(worker);
- if (workerIndex > -1) {
- runningWebWorkers.splice(workerIndex, 1);
- }
- });
- runningWebWorkers.push(worker);
-
- }
- else {
- currentPolygon.setState("outside");
- }
-
- // if (debugPoly) {
- // console.log("CHECK INSIDE", inside);
- // }
- // if (inside === true) {
- // currentPolygon.setState("inside");
- // }
- // else {
- // currentPolygon.setState("outside");
- // }
-
- currentPolygon = polygonStack.pop();
- }
- // console.log("START WAITING", runningWebWorkers.length);
- while (runningWebWorkers.length) {
- // console.log("Waiting to finish");
- await sleep(1);
- }
- // console.log("FINISHED WAITING", runningWebWorkers.length);
- */
-
- }
- for (let i = 0; i < this.subTrees.length; i++) {
- // await this.subTrees[i].handleIntersectingPolygons_async(targetOctree, targetOctreeBuffer);
- this.subTrees[i].handleIntersectingPolygons_reduced(targetOctree, targetOctreeBuffer);
- }
- // resolve();
- // }
- // catch (e) {
- // reject(e);
- // }
- // });
- }
-
- delete() {
- if (this.polygons.length > 0) {
- this.polygons.forEach(p => p.delete());
- this.polygons.length = 0;
- }
- if (this.subTrees.length) {
- for (let i = 0; i < this.subTrees.length; i++) {
- this.subTrees[i].delete(false);
- }
- this.subTrees.length = 0;
- }
- this.mesh = undefined;
- this.originalMatrixWorld = undefined;
- this.box = undefined;
- this.parent = undefined;
- }
- getPolygonCallback(cbFunc) {
- if (this.polygons.length > 0) {
- for (let i = 0; i < this.polygons.length; i++) {
- if (this.polygons[i].valid) {
- cbFunc(this.polygons[i]);
- }
- }
- }
- for (let i = 0; i < this.subTrees.length; i++) {
- this.subTrees[i].getPolygonCallback(cbFunc);
- }
- }
-}
-
-
-function raycastIntersectAscSort(a, b) {
- return a.distance - b.distance;
-}
-
-function pointRounding(point, num = 15) {
- point.x = +point.x.toFixed(num);
- point.y = +point.y.toFixed(num);
- point.z = +point.z.toFixed(num);
- return point;
-}
-
-function splitPolygonByPlane(polygon, plane, result = []) {
- let returnPolygon = {
- polygon: polygon,
- type: "undecided"
- };
- let polygonType = 0;
- let types = [];
- for (let i = 0; i < polygon.vertices.length; i++) {
- let t = plane.normal.dot(polygon.vertices[i].pos) - plane.w;
- let type = (t < -EPSILON) ? BACK : (t > EPSILON) ? FRONT : COPLANAR;
- polygonType |= type;
- types.push(type);
- }
- switch (polygonType) {
- case COPLANAR:
- returnPolygon.type = plane.normal.dot(polygon.plane.normal) > 0 ? "coplanar-front" : "coplanar-back";
- result.push(returnPolygon);
- break;
- case FRONT:
- returnPolygon.type = "front";
- result.push(returnPolygon);
- break;
- case BACK:
- returnPolygon.type = "back";
- result.push(returnPolygon);
- break;
- case SPANNING:
- let f = [];
- let b = [];
- for (let i = 0; i < polygon.vertices.length; i++) {
- let j = (i + 1) % polygon.vertices.length;
- let ti = types[i];
- let tj = types[j];
- let vi = polygon.vertices[i];
- let vj = polygon.vertices[j];
- if (ti != BACK) {
- f.push(vi);
- }
- if (ti != FRONT) {
- b.push(ti != BACK ? vi.clone() : vi);
- }
- if ((ti | tj) == SPANNING) {
- let t = (plane.w - plane.normal.dot(vi.pos)) / plane.normal.dot(tv0.copy(vj.pos).sub(vi.pos));
- let v = vi.interpolate(vj, t);
- f.push(v);
- b.push(v.clone());
- }
- }
- if (f.length >= 3) {
- if (f.length > 3) {
- let newPolys = splitPolygonArr(f);
- for (let npI = 0; npI < newPolys.length; npI++) {
- result.push({
- polygon: new Polygon(newPolys[npI], polygon.shared),
- type: "front"
- });
- }
- }
- else {
- result.push({
- polygon: new Polygon(f, polygon.shared),
- type: "front"
- });
- }
- }
- if (b.length >= 3) {
- if (b.length > 3) {
- let newPolys = splitPolygonArr(b);
- for (let npI = 0; npI < newPolys.length; npI++) {
- result.push({
- polygon: new Polygon(newPolys[npI], polygon.shared),
- type: "back"
- });
- }
- }
- else {
- result.push({
- polygon: new Polygon(b, polygon.shared),
- type: "back"
- });
- }
- }
- break;
- }
- if (result.length == 0) {
- result.push(returnPolygon);
- }
- return result;
-}
-
-function splitPolygonArr(arr) {
- let resultArr = [];
-
-
- if (arr.length > 4) {
- console.warn("[splitPolygonArr] arr.length > 4", arr.length);
- for (let j = 3; j <= arr.length; j++) {
- let result = [];
- result.push(arr[0].clone());
- result.push(arr[j - 2].clone());
- result.push(arr[j - 1].clone());
- resultArr.push(result);
- }
- }
- else {
- if (arr[0].pos.distanceTo(arr[2].pos) <= arr[1].pos.distanceTo(arr[3].pos)) {
- resultArr.push([arr[0].clone(), arr[1].clone(), arr[2].clone()],
- [arr[0].clone(), arr[2].clone(), arr[3].clone()]);
- }
- else {
- resultArr.push([arr[0].clone(), arr[1].clone(), arr[3].clone()],
- [arr[1].clone(), arr[2].clone(), arr[3].clone()]);
- }
- return resultArr;
-
- }
-
- return resultArr;
-}
-
-/*
-Union:
-1. Delete all polygons in A that are:
- a. inside and coplanar-back
- b. inside
-2. Delete all polygons in B that are:
- a. inside and coplanar-back
- b. inside and coplanar-front
- c. inside
-*/
-OctreeCSG.union = function (octreeA, octreeB, buildTargetOctree = true) {
- let octree = new OctreeCSG();
-
- if (octreeA.box.intersectsBox(octreeB.box)) {
- let currentMeshSideA;
- let currentMeshSideB;
- if (octreeA.mesh) {
- currentMeshSideA = octreeA.mesh.material.side;
- octreeA.mesh.material.side = OctreeCSG.testSide;
- }
- if (octreeB.mesh) {
- currentMeshSideB = octreeB.mesh.material.side;
- octreeB.mesh.material.side = OctreeCSG.testSide;
- }
-
- octreeA.resetPolygons();
- octreeB.resetPolygons();
-
- octreeA.markIntesectingPolygons(octreeB);
- octreeB.markIntesectingPolygons(octreeA);
-
- handleIntersectingOctrees(octreeA, octreeB);
- octreeA.deletePolygonsByStateRules([
- {
- array: true,
- rule: ["inside", "coplanar-back"]
- },
- {
- array: false,
- rule: "inside"
- }
- ]);
-
- octreeB.deletePolygonsByStateRules([
- {
- array: true,
- rule: ["inside", "coplanar-back"]
- },
- {
- array: true,
- rule: ["inside", "coplanar-front"]
- },
- {
- array: false,
- rule: "inside"
- }
- ]);
-
- if (OctreeCSG.returnType == 0) {
- octreeA.getPolygonCallback(octree.addPolygon.bind(octree));
- octreeB.getPolygonCallback(octree.addPolygon.bind(octree));
- }
- else if (OctreeCSG.returnType == -1) {
- console.log("OctreeA");
- let polys_test = octreeA.getPolygons();
- let limit = Math.min(polys_test.length, 50000);
- console.log(`[octreeA] polys_test`, polys_test.length, limit);
- let count = 0;
- for (let i = 0; i < limit; i++) {
- if (polys_test[i].intersects) {
- let t = polys_test[i].triangle;
- // if ((t.a.x <= 1) && (t.b.x <= 1) && (t.c.x <= 1)) {
- // if ((t.a.x >= -4) && (t.b.x >= -4) && (t.c.x >= -4)) {
- // if ((t.a.y == -1) && (t.b.y == -1) && (t.c.y == -1)) {
- // if ((t.a.z <= 4) && (t.b.z <= 4) && (t.c.z <= 4)) {
- // if ((t.a.z > -5) && (t.b.z > -5) && (t.c.z > -5)) {
- // console.log("AAAA", i, t, polys_test[i]);
- octree.addPolygon(polys_test[i]);
- count++;
- // }
- // }
- // }
- // }
- // }
- }
- // else {
- // octree.addPolygon(polys_test[i]);
- // }
- }
- console.log("AAAA ADDED COUNT", count);
- }
- else {
- console.log("OctreeB");
- let polys_test = octreeB.getPolygons();
- let limit = Math.min(polys_test.length, 50000);
- console.log(`[octreeB] polys_test`, polys_test.length, limit);
- let count = 0;
- for (let i = 0; i < limit; i++) {
- if (polys_test[i].intersects) {
- // console.log(i, polys_test[i]);
- let t = polys_test[i].triangle;
- // if ((t.a.x <= 1) && (t.b.x <= 1) && (t.c.x <= 1)) {
- // if ((t.a.x >= -2) && (t.b.x >= -2) && (t.c.x >= -2)) {
- // if ((t.a.y >= 3) && (t.b.y >= 3) && (t.c.y >= 3)) {
- // if ((t.a.z <= 1) && (t.b.z <= 1) && (t.c.z <= 1)) {
- // if ((t.a.z >= -2) && (t.b.z >= -2) && (t.c.z >= -2)) {
- // if (polys_test[i].checkAllStates("back")) {
-
-
- // console.log("BBBB", i, t, polys_test[i]);
- octree.addPolygon(polys_test[i]);
- count++;
- // }
- // }
- // }
- // }
- }
- // else {
- // octree.addPolygon(polys_test[i]);
- // }
- }
- console.log("BBBB ADDED COUNT", count);
- }
-
- buildTargetOctree && octree.buildTree();
- if (octreeA.mesh) {
- if (octreeA.mesh.material.side !== currentMeshSideA) {
- octreeA.mesh.material.side = currentMeshSideA;
- }
- }
- if (octreeB.mesh) {
- if (octreeB.mesh.material.side !== currentMeshSideB) {
- octreeB.mesh.material.side = currentMeshSideB;
- }
- }
-
- }
- else {
- octreeA.getPolygonCallback(octree.addPolygon.bind(octree));
- octreeB.getPolygonCallback(octree.addPolygon.bind(octree));
- buildTargetOctree && octree.buildTree();
- }
-
- return octree;
-}
-
-/*
-Subtract:
-1. Delete all polygons in A that are:
- a. inside and coplanar-back
- b. inside and coplanar-front
- c. inside
-2. Delete all polygons in B that are:
- a. outside and coplanar-back
- b. outside and coplanar-front
- c. inside and coplanar-front
- d. outside
-*/
-OctreeCSG.subtract = function (octreeA, octreeB, buildTargetOctree = true) {
- let octree = new OctreeCSG();
- if (octreeA.box.intersectsBox(octreeB.box)) {
- let currentMeshSideA;
- let currentMeshSideB;
- if (octreeA.mesh) {
- currentMeshSideA = octreeA.mesh.material.side;
- octreeA.mesh.material.side = OctreeCSG.testSide;
- }
- if (octreeB.mesh) {
- currentMeshSideB = octreeB.mesh.material.side;
- octreeB.mesh.material.side = OctreeCSG.testSide;
- }
-
- octreeA.resetPolygons();
- octreeB.resetPolygons();
- octreeA.markIntesectingPolygons(octreeB);
- octreeB.markIntesectingPolygons(octreeA);
-
-
- handleIntersectingOctrees(octreeA, octreeB);
-
- octreeA.deletePolygonsByStateRules([
- {
- array: true,
- rule: ["inside", "coplanar-back"]
- },
- {
- array: true,
- rule: ["inside", "coplanar-front"]
- },
- {
- array: false,
- rule: "inside"
- }
- ]);
- octreeB.deletePolygonsByStateRules([
- {
- array: true,
- rule: ["outside", "coplanar-back"]
- },
- {
- array: true,
- rule: ["outside", "coplanar-front"]
- },
- {
- array: true,
- rule: ["inside", "coplanar-front"]
- },
- {
- array: false,
- rule: "outside"
- }
- ]);
-
-
- octreeB.deletePolygonsByIntersection(false);
-
-
- octreeB.invert();
-
-
- if (OctreeCSG.returnType == 0) {
- octreeA.getPolygonCallback(octree.addPolygon.bind(octree));
- octreeB.getPolygonCallback(octree.addPolygon.bind(octree));
- }
- else if (OctreeCSG.returnType == -1) {
- console.log("OctreeA");
- let polys_test = octreeA.getPolygons();
- let limit = Math.min(polys_test.length, 50000);
- console.log(`[octreeA] polys_test`, polys_test.length, limit);
- for (let i = 0; i < limit; i++) {
- if (polys_test[i].intersects) {
- let t = polys_test[i].triangle;
- if (((t.a.y < -3) && (t.b.y < -3) && (t.c.y < -3))) {
- // if (((t.a.x >= 0.8) && (t.b.x >= 0.8) && (t.c.x >= 0.8))) {
- console.log("AAAA", i, t, polys_test[i]);
- octree.addPolygon(polys_test[i]);
- }
- }
- // else {
- // octree.addPolygon(polys_test[i]);
- // }
- }
- }
- else {
- console.log("OctreeB");
- let polys_test = octreeB.getPolygons();
- let limit = Math.min(polys_test.length, 50000);
- console.log(`[octreeB] polys_test`, polys_test.length, limit);
- for (let i = 0; i < limit; i++) {
- if (polys_test[i].intersects) {
- let t = polys_test[i].triangle;
- // if ((t.a.x <= 1) && (t.b.x <= 1) && (t.c.x <= 1)) {
- // if (((t.a.y === -5) && (t.b.y === -5) && (t.c.y === -5))) {
- // console.log("BBBB", i, t, polys_test[i]);
- octree.addPolygon(polys_test[i]);
- // }
- }
- // else {
- // octree.addPolygon(polys_test[i]);
- // }
- }
- }
-
- if (octreeA.mesh) {
- if (octreeA.mesh.material.side !== currentMeshSideA) {
- octreeA.mesh.material.side = currentMeshSideA;
- }
- }
- if (octreeB.mesh) {
- if (octreeB.mesh.material.side !== currentMeshSideB) {
- octreeB.mesh.material.side = currentMeshSideB;
- }
- }
- }
- else {
- octreeA.getPolygonCallback(octree.addPolygon.bind(octree));
- }
-
- buildTargetOctree && octree.buildTree();
- // octree.invert();
- return octree;
-}
-
-/*
-Intersect:
-1. Delete all polygons in A that are:
- a. inside and coplanar-back
- b. outside and coplanar-front
- c. outside and coplanar-back
- d. outside
-2. Delete all polygons in B that are:
- a. inside and coplanar-front
- b. inside and coplanar-back
- c. outside and coplanar-front
- d. outside and coplanar-back
- e. outside
-*/
-OctreeCSG.intersect = function (octreeA, octreeB, buildTargetOctree = true) {
- let octree = new OctreeCSG();
- if (octreeA.box.intersectsBox(octreeB.box)) {
- let currentMeshSideA;
- let currentMeshSideB;
- if (octreeA.mesh) {
- currentMeshSideA = octreeA.mesh.material.side;
- octreeA.mesh.material.side = OctreeCSG.testSide;
- }
- if (octreeB.mesh) {
- currentMeshSideB = octreeB.mesh.material.side;
- octreeB.mesh.material.side = OctreeCSG.testSide;
- }
-
- octreeA.resetPolygons();
- octreeB.resetPolygons();
-
- octreeA.markIntesectingPolygons(octreeB);
- octreeB.markIntesectingPolygons(octreeA);
-
- handleIntersectingOctrees(octreeA, octreeB);
-
- octreeA.deletePolygonsByStateRules([
- {
- array: true,
- rule: ["inside", "coplanar-back"]
- },
- {
- array: true,
- rule: ["outside", "coplanar-front"]
- },
- {
- array: true,
- rule: ["outside", "coplanar-back"]
- },
- {
- array: false,
- rule: "outside"
- }
- ]);
-
- octreeB.deletePolygonsByStateRules([
- {
- array: true,
- rule: ["inside", "coplanar-front"]
- },
- {
- array: true,
- rule: ["inside", "coplanar-back"]
- },
- {
- array: true,
- rule: ["outside", "coplanar-front"]
- },
- {
- array: true,
- rule: ["outside", "coplanar-back"]
- },
- {
- array: false,
- rule: "outside"
- }
- ]);
- octreeA.deletePolygonsByIntersection(false);
- octreeB.deletePolygonsByIntersection(false);
-
- if (OctreeCSG.returnType == 0) {
- octreeA.getPolygonCallback(octree.addPolygon.bind(octree));
- octreeB.getPolygonCallback(octree.addPolygon.bind(octree));
- }
- else if (OctreeCSG.returnType == -1) {
- console.log("OctreeA");
- let polys_test = octreeA.getPolygons();
- let limit = Math.min(polys_test.length, 50000);
- console.log(`[octreeA] polys_test`, polys_test.length, limit);
- for (let i = 0; i < limit; i++) {
- if (polys_test[i].intersects) {
- let t = polys_test[i].triangle;
- // if (((t.a.y < -3) && (t.b.y < -3) && (t.c.y < -3))) {
- // if (((t.a.x >= 0.8) && (t.b.x >= 0.8) && (t.c.x >= 0.8))) {
- // console.log("AAAA", i, t, polys_test[i]);
- octree.addPolygon(polys_test[i]);
- // }
- }
- // else {
- // octree.addPolygon(polys_test[i]);
- // }
- }
- }
- else {
- console.log("OctreeB");
- let polys_test = octreeB.getPolygons();
- let limit = Math.min(polys_test.length, 50000);
- console.log(`[octreeB] polys_test`, polys_test.length, limit);
- for (let i = 0; i < limit; i++) {
- if (polys_test[i].intersects) {
- let t = polys_test[i].triangle;
- // if ((t.a.x <= 1) && (t.b.x <= 1) && (t.c.x <= 1)) {
- // if (((t.a.y === -5) && (t.b.y === -5) && (t.c.y === -5))) {
- // console.log("BBBB", i, t, polys_test[i]);
- octree.addPolygon(polys_test[i]);
- // }
- }
- // else {
- // octree.addPolygon(polys_test[i]);
- // }
- }
- }
-
- // let polys_test = octreeB.getPolygons();
- // let limit = Math.min(polys_test.length, 50);
- // for (let i = 0; i < limit; i++) {
- // console.log(i, polys_test[i]);
- // octree.addPolygon(polys_test[i]);
- // }
-
- if (octreeA.mesh) {
- if (octreeA.mesh.material.side !== currentMeshSideA) {
- octreeA.mesh.material.side = currentMeshSideA;
- }
- }
- if (octreeB.mesh) {
- if (octreeB.mesh.material.side !== currentMeshSideB) {
- octreeB.mesh.material.side = currentMeshSideB;
- }
- }
- }
- // else {
- // octreeA.getPolygonCallback(octree.addPolygon.bind(octree));
- // }
- buildTargetOctree && octree.buildTree();
- // octree.invert();
- return octree;
-}
-
-OctreeCSG.operation = function (obj, returnOctrees = false, buildTargetOctree = true, options = { objCounter: 0 }, firstRun = true) {
- // console.log("OctreeCSG.operation", obj);
- let octreeA, octreeB, resultOctree, material;
- if (obj.material) {
- material = obj.material;
- }
- if (obj.objA) {
- octreeA = handleObjectForOp(obj.objA, returnOctrees, buildTargetOctree, options);
- if (returnOctrees == true) {
- obj.objA = octreeA.original;
- octreeA = octreeA.result;
- }
- }
- if (obj.objB) {
- octreeB = handleObjectForOp(obj.objB, returnOctrees, buildTargetOctree, options);
- if (returnOctrees == true) {
- obj.objB = octreeB.original;
- octreeB = octreeB.result;
- }
- }
- switch (obj.op) {
- case 'union':
- resultOctree = OctreeCSG.union(octreeA, octreeB, buildTargetOctree);
- break;
- case 'subtract':
- resultOctree = OctreeCSG.subtract(octreeA, octreeB, buildTargetOctree);
- break;
- case 'intersect':
- resultOctree = OctreeCSG.intersect(octreeA, octreeB, buildTargetOctree);
- break;
- }
- if (firstRun && material) {
- let mesh = OctreeCSG.toMesh(resultOctree, material);
- return returnOctrees ? { result: mesh, operationTree: obj } : mesh;
- }
- if (firstRun && returnOctrees) {
- return { result: resultOctree, operationTree: obj };
- }
- return resultOctree;
-}
-
-// Work in progress
-function handleObjectForOp(obj, returnOctrees, buildTargetOctree, options) {
- let returnObj;
- if (obj.isMesh) {
- returnObj = OctreeCSG.fromMesh(obj, options.objCounter++);
- if (returnOctrees) {
- returnObj = { result: returnObj, original: returnObj.clone() };
- }
- }
- else if (obj.isOctree) {
- returnObj = obj;
- if (returnOctrees) {
- returnObj = { result: obj, original: obj.clone() };
- }
- }
- else if (obj.op) {
- returnObj = OctreeCSG.operation(obj, returnOctrees, buildTargetOctree, options, false);
- if (returnOctrees) {
- returnObj = { result: returnObj, original: obj };
- }
- }
-
- return returnObj;
-}
-
-/*
-// Work in progress
-OctreeCSG.unionArray = function (objArr, buildTargetOctree = true) {
- // console.log("OctreeCSG.getRayPolys", OctreeCSG.getRayPolys);
- // console.log("OctreeCSG.useOctreeRay", OctreeCSG.useOctreeRay);
- // let polys = [];
- let octrees = [];
- for (let i = 0; i < objArr.length; i++) {
- let tempOctree = OctreeCSG.fromMesh(objArr[i]);
- tempOctree.octreeIndex = i;
- octrees.push(tempOctree);
- }
- let octree = new OctreeCSG();
-
-
-
-
- // let aPolygons = octreeA.getPolygons();
- // let bPolygons = octreeB.getPolygons();
- // let filterResults;
- if (octreeA.box.intersectsBox(octreeB.box)) {
- let trianglesSet = new Set();
- let currentMeshSideA;
- let currentMeshSideB;
- if (octreeA.mesh) {
- currentMeshSideA = octreeA.mesh.material.side;
- octreeA.mesh.material.side = OctreeCSG.testSide;
- }
- if (octreeB.mesh) {
- currentMeshSideB = octreeB.mesh.material.side;
- octreeB.mesh.material.side = OctreeCSG.testSide;
- }
-
- octreeA.resetPolygons();
- octreeB.resetPolygons();
-
- octreeA.markIntesectingPolygons(octreeB);
- octreeB.markIntesectingPolygons(octreeA);
-
-
- handleIntersectingOctrees(octreeA, octreeB);
-
- octreeA.deletePolygonsByStateRules([
- {
- array: true,
- rule: ["inside", "coplanar-back"]
- },
- {
- array: false,
- rule: "inside"
- }
- ]);
-
- // }
-
- octreeB.deletePolygonsByStateRules([
- {
- array: true,
- rule: ["inside", "coplanar-back"]
- },
- {
- array: true,
- rule: ["inside", "coplanar-front"]
- },
- {
- array: false,
- rule: "inside"
- }
- ]);
-
- octreeA.getPolygonCallback(octree.addPolygon.bind(octree));
- octreeB.getPolygonCallback(octree.addPolygon.bind(octree));
-
-
- buildTargetOctree && octree.buildTree();
- if (octreeA.mesh) {
- if (octreeA.mesh.material.side !== currentMeshSideA) {
- octreeA.mesh.material.side = currentMeshSideA;
- }
- }
- if (octreeB.mesh) {
- if (octreeB.mesh.material.side !== currentMeshSideB) {
- octreeB.mesh.material.side = currentMeshSideB;
- }
- }
-
- }
- else {
- octreeA.getPolygonCallback(octree.addPolygon.bind(octree));
- octreeB.getPolygonCallback(octree.addPolygon.bind(octree));
- buildTargetOctree && octree.buildTree();
- }
-
- return octree;
-}
-*/
-
-OctreeCSG.isUniqueTriangle = function (triangle, set, map) {
- const hash1 = `{${triangle.a.x},${triangle.a.y},${triangle.a.z}}-{${triangle.b.x},${triangle.b.y},${triangle.b.z}}-{${triangle.c.x},${triangle.c.y},${triangle.c.z}}`;
-
- if (set.has(hash1) === true) {
- return false;
- }
- else {
- set.add(hash1);
- if (map) {
- map.set(triangle, triangle);
- }
- return true;
- }
-}
-
-const nbuf3 = (ct) => {
- return {
- top: 0,
- array: new Float32Array(ct),
- write: function (v) {
- this.array[this.top++] = v.x;
- this.array[this.top++] = v.y;
- this.array[this.top++] = v.z;
- }
- }
-}
-const nbuf2 = (ct) => {
- return {
- top: 0,
- array: new Float32Array(ct),
- write: function (v) {
- this.array[this.top++] = v.x;
- this.array[this.top++] = v.y;
- }
- }
-}
-const _normal1 = new Vector3();
-const tmpm3 = new Matrix3();
-const ttvv0 = new Vector3()
-
-OctreeCSG.toGeometry = function (octree) {
- let polygons = octree.getPolygons();
- let validPolygons = [];
- let trianglesSet = new Set();
- let duplicateCount = 0;
-
- let triangleCount = 0;
- polygons.forEach(polygon => {
- if (OctreeCSG.isUniqueTriangle(polygon.triangle, trianglesSet)) {
- triangleCount += (polygon.vertices.length - 2);
- validPolygons.push(polygon);
- }
- // else {
- // duplicateCount++;
- // let a = triangleMap.get(polygon.triangle);
- // console.log("DUPLICATE!!", polygon.id == a.polygon.id);
- // }
- });
- trianglesSet.clear();
- trianglesSet = undefined;
-
- let positions = nbuf3(triangleCount * 3 * 3);
- let normals = nbuf3(triangleCount * 3 * 3);
- let uvs;
- let colors;
- let groups = [];
- let defaultGroup = [];
-
- validPolygons.forEach(polygon => {
- let vertices = polygon.vertices;
- let verticesLen = vertices.length;
- if (polygon.shared !== undefined) {
- if (!groups[polygon.shared]) {
- groups[polygon.shared] = [];
- }
- }
- if (verticesLen > 0) {
- if (vertices[0].uv !== undefined) {
- !uvs && (uvs = nbuf2(triangleCount * 2 * 3));
- }
- if (vertices[0].color !== undefined) {
- !colors && (colors = nbuf3(triangleCount * 3 * 3));
- }
- }
- for (let i = 3; i <= verticesLen; i++) {
- (polygon.shared === undefined ? defaultGroup : groups[polygon.shared]).push(positions.top / 3, (positions.top / 3) + 1, (positions.top / 3) + 2);
- positions.write(vertices[0].pos);
- positions.write(vertices[i - 2].pos);
- positions.write(vertices[i - 1].pos);
- normals.write(vertices[0].normal);
- normals.write(vertices[i - 2].normal);
- normals.write(vertices[i - 1].normal);
- if (uvs !== undefined) {
- uvs.write(vertices[0].uv);
- uvs.write(vertices[i - 2].uv);
- uvs.write(vertices[i - 1].uv);
- }
- if (colors !== undefined) {
- colors.write(vertices[0].color);
- colors.write(vertices[i - 2].color);
- colors.write(vertices[i - 1].color);
- }
- }
- });
-
- let geometry = new BufferGeometry();
- geometry.setAttribute('position', new BufferAttribute(positions.array, 3));
- geometry.setAttribute('normal', new BufferAttribute(normals.array, 3));
- uvs && geometry.setAttribute('uv', new BufferAttribute(uvs.array, 2));
- colors && geometry.setAttribute('color', new BufferAttribute(colors.array, 3));
-
- if (groups.length > 0) {
- let index = [];
- let groupBase = 0;
- for (let i = 0; i < groups.length; i++) {
- if (groups[i] === undefined) {
- groups[i] = [];
- }
- geometry.addGroup(groupBase, groups[i].length, i);
- groupBase += groups[i].length;
- index = index.concat(groups[i]);
- }
- if (defaultGroup.length) {
- geometry.addGroup(groupBase, defaultGroup.length, groups.length);
- index = index.concat(defaultGroup);
- }
- geometry.setIndex(index);
- }
- // console.log("duplicateCount", duplicateCount);
- return geometry;
-}
-
-OctreeCSG.toMesh = function (octree, toMaterial) {
- let geometry = OctreeCSG.toGeometry(octree);
- // geometry = BufferGeometryUtils.mergeVertices(geometry);
- // geometry = geometry.toNonIndexed();
- return new Mesh(geometry, toMaterial);
-}
-
-OctreeCSG.fromMesh = function (obj, objectIndex) {
- let octree = new OctreeCSG();
- octree.originalMatrixWorld = obj.matrixWorld.clone();
- obj.updateWorldMatrix(true, true);
- // obj.updateMatrixWorld();
- // obj.updateMatrix();
- let geometry = obj.geometry;
- tmpm3.getNormalMatrix(obj.matrix);
- let posattr = geometry.attributes.position;
- let normalattr = geometry.attributes.normal;
- let uvattr = geometry.attributes.uv;
- let colorattr = geometry.attributes.color;
- let groups = geometry.groups;
- let index;
- if (geometry.index)
- index = geometry.index.array;
- else {
- index = new Array((posattr.array.length / posattr.itemSize) | 0);
- for (let i = 0; i < index.length; i++)
- index[i] = i;
- }
- // let triCount = (index.length / 3) | 0;
- let polys = [];
- // polys = new Array(triCount)
- for (let i = 0, pli = 0, l = index.length; i < l; i += 3, pli++) {
- let vertices = [];
- for (let j = 0; j < 3; j++) {
- let vi = index[i + j];
- let vp = vi * 3;
- let vt = vi * 2;
- let pos = new Vector3(posattr.array[vp], posattr.array[vp + 1], posattr.array[vp + 2]);
- let normal = new Vector3(normalattr.array[vp], normalattr.array[vp + 1], normalattr.array[vp + 2]);
- pos.applyMatrix4(obj.matrix);
- normal.applyMatrix3(tmpm3);
-
- vertices.push(new Vertex(pos, normal, uvattr && { // uv
- x: uvattr.array[vt],
- y: uvattr.array[vt + 1]
- }, colorattr && { x: colorattr.array[vt], y: colorattr.array[vt + 1], z: colorattr.array[vt + 2] }));
- }
- if ((objectIndex === undefined) && groups && groups.length > 0) {
- let polygon;
- for (let group of groups) {
- if ((index[i] >= group.start) && (index[i] < (group.start + group.count))) {
- polygon = new Polygon(vertices, group.materialIndex);
- }
- }
- if (polygon) {
- polys.push(polygon);
- }
-
- }
- else {
- polys.push(new Polygon(vertices, objectIndex));
- }
- }
-
- for (let i = 0; i < polys.length; i++) {
- if (isValidTriangle(polys[i].triangle)) {
- if (isNaN(polys[i].plane.normal.x)) {
- console.warn("polygon", i, "is NaN!!!!");
- }
-
- octree.addPolygon(polys[i]);
- }
- else {
- // console.log("polygon", i, "has two points at same place", polys[i]);
- polys[i].delete();
- }
- }
- // octree.addTriangle(newTriangle(v1, v2, v3));
-
-
- octree.buildTree();
- // return CSG.fromPolygons(polys.filter(p => !isNaN(p.plane.normal.x)));
- octree.mesh = obj;
- return octree;
-
-};
-
-function isValidTriangle(triangle) {
- if (triangle.a.equals(triangle.b)) return false;
- if (triangle.a.equals(triangle.c)) return false;
- if (triangle.b.equals(triangle.c)) return false;
- return true;
-}
-
-// OctreeCSG.meshToBuffers = function (obj, objectIndex) {
-// obj.updateWorldMatrix(true, true);
-// // let octree = new OctreeCSG();
-// let geometry = obj.geometry;
-// tmpm3.getNormalMatrix(obj.matrix);
-// let posattr = geometry.attributes.position;
-// let normalattr = geometry.attributes.normal;
-// let uvattr = geometry.attributes.uv;
-// let colorattr = geometry.attributes.color;
-// let groups = geometry.groups;
-// let index;
-// if (geometry.index)
-// index = geometry.index.array;
-// else {
-// index = new Array((posattr.array.length / posattr.itemSize) | 0);
-// for (let i = 0; i < index.length; i++)
-// index[i] = i;
-// }
-// // let triCount = (index.length / 3) | 0;
-// let polys = [];
-// // polys = new Array(triCount)
-// for (let i = 0, pli = 0, l = index.length; i < l; i += 3, pli++) {
-// let vertices = [];
-// for (let j = 0; j < 3; j++) {
-// let vi = index[i + j]
-// let vp = vi * 3;
-// let vt = vi * 2;
-// let pos = new Vector3(posattr.array[vp], posattr.array[vp + 1], posattr.array[vp + 2]);
-// let normal = new Vector3(normalattr.array[vp], normalattr.array[vp + 1], normalattr.array[vp + 2]);
-// pos.applyMatrix4(obj.matrix);
-// normal.applyMatrix3(tmpm3);
-// // v.applyMatrix4(obj.matrixWorld);
-// // vertices.push(v);
-// // v2.applyMatrix4(obj.matrixWorld);
-// // v3.applyMatrix4(obj.matrixWorld);
-// vertices.push(new Vertex(pos, normal, uvattr && { // uv
-// x: uvattr.array[vt],
-// y: uvattr.array[vt + 1]
-// }, colorattr && { x: colorattr.array[vt], y: colorattr.array[vt + 1], z: colorattr.array[vt + 2] }));
-// }
-// if ((objectIndex === undefined) && groups && groups.length > 0) {
-// let polygon;
-// for (let group of groups) {
-// if ((index[i] >= group.start) && (index[i] < (group.start + group.count))) {
-// polygon = new Polygon(vertices, group.materialIndex);
-// }
-// }
-// if (polygon) {
-// polys.push(polygon);
-// }
-
-// }
-// else {
-// polys.push(new Polygon(vertices, objectIndex));
-// }
-// }
-// return polys;
-// // for (let i = 0; i < polys.length; i++) {
-// // octree.addPolygon(polys[i]);
-// // }
-// // // octree.addTriangle(newTriangle(v1, v2, v3));
-
-// // octree.buildTree();
-// // // return CSG.fromPolygons(polys.filter(p => !isNaN(p.plane.normal.x)));
-// // return octree;
-
-// };
-
-OctreeCSG.meshToPolygons = function (obj, objectIndex) {
- obj.updateWorldMatrix(true, true);
- // let octree = new OctreeCSG();
- let geometry = obj.geometry;
- tmpm3.getNormalMatrix(obj.matrix);
- let posattr = geometry.attributes.position;
- let normalattr = geometry.attributes.normal;
- let uvattr = geometry.attributes.uv;
- let colorattr = geometry.attributes.color;
- let groups = geometry.groups;
- let index;
- if (geometry.index)
- index = geometry.index.array;
- else {
- index = new Array((posattr.array.length / posattr.itemSize) | 0);
- for (let i = 0; i < index.length; i++)
- index[i] = i;
- }
- // let triCount = (index.length / 3) | 0;
- let polys = [];
- // polys = new Array(triCount)
- for (let i = 0, pli = 0, l = index.length; i < l; i += 3, pli++) {
- let vertices = [];
- for (let j = 0; j < 3; j++) {
- let vi = index[i + j]
- let vp = vi * 3;
- let vt = vi * 2;
- let pos = new Vector3(posattr.array[vp], posattr.array[vp + 1], posattr.array[vp + 2]);
- let normal = new Vector3(normalattr.array[vp], normalattr.array[vp + 1], normalattr.array[vp + 2]);
- pos.applyMatrix4(obj.matrix);
- normal.applyMatrix3(tmpm3);
- // v.applyMatrix4(obj.matrixWorld);
- // vertices.push(v);
- // v2.applyMatrix4(obj.matrixWorld);
- // v3.applyMatrix4(obj.matrixWorld);
- vertices.push(new Vertex(pos, normal, uvattr && { // uv
- x: uvattr.array[vt],
- y: uvattr.array[vt + 1]
- }, colorattr && { x: colorattr.array[vt], y: colorattr.array[vt + 1], z: colorattr.array[vt + 2] }));
- }
- if ((objectIndex === undefined) && groups && groups.length > 0) {
- let polygon;
- for (let group of groups) {
- if ((index[i] >= group.start) && (index[i] < (group.start + group.count))) {
- polygon = new Polygon(vertices, group.materialIndex);
- }
- }
- if (polygon) {
- polys.push(polygon);
- }
-
- }
- else {
- polys.push(new Polygon(vertices, objectIndex));
- }
- }
- return polys;
- // for (let i = 0; i < polys.length; i++) {
- // octree.addPolygon(polys[i]);
- // }
- // // octree.addTriangle(newTriangle(v1, v2, v3));
-
- // octree.buildTree();
- // // return CSG.fromPolygons(polys.filter(p => !isNaN(p.plane.normal.x)));
- // return octree;
-
-};
-
-
-
-
-
-
-// OctreeCSG.addPolygonToMap = function (map, polygon, value) {
-// let mapValue = map.get(polygon) || [];
-// mapValue.push(value);
-// map.set(polygon, mapValue);
-// }
-
-
-
-// class Vertex
-
-class Vertex {
-
- constructor(pos, normal, uv, color) {
- this.pos = new Vector3().copy(pos);
- this.normal = new Vector3().copy(normal);
- uv && (this.uv = new Vector2().copy(uv));
- color && (this.color = new Vector3().copy(color));
- }
-
- clone() {
- return new Vertex(this.pos.clone(), this.normal.clone(), this.uv && this.uv.clone(), this.color && this.color.clone());
- }
-
- // Invert all orientation-specific data (e.g. vertex normal). Called when the
- // orientation of a polygon is flipped.
- flip() {
- this.normal.negate();
- }
- delete() {
- this.pos = undefined;
- this.normal = undefined;
- this.uv && (this.uv = undefined);
- this.color && (this.color = undefined);
- }
- // Create a new vertex between this vertex and `other` by linearly
- // interpolating all properties using a parameter of `t`. Subclasses should
- // override this to interpolate additional properties.
- interpolate(other, t) {
- return new Vertex(this.pos.clone().lerp(other.pos, t), this.normal.clone().lerp(other.normal, t), this.uv && other.uv && this.uv.clone().lerp(other.uv, t), this.color && other.color && this.color.clone().lerp(other.color, t));
- }
-}
-
-// class Plane
-
-class Plane {
- constructor(normal, w) {
- this.normal = normal;
- this.w = w;
- // this.constant;
- }
-
- clone() {
- return new Plane(this.normal.clone(), this.w);
- }
-
- flip() {
- this.normal.negate();
- this.w = -this.w;
- }
- delete() {
- this.normal = undefined;
- this.w = undefined;
- }
-
- equals(p) {
- if (this.normal.equals(p.normal) && this.w === p.w) {
- return true;
- }
- return false;
- }
- // distanceToPoint(point) {
- // return this.normal.dot(point) - this.constant;
- // }
-
-}
-
-Plane.fromPoints = function (a, b, c) {
- let n = tv0.copy(b).sub(a).cross(tv1.copy(c).sub(a)).normalize().clone();
- return new Plane(n, n.dot(a));
-}
-
-
-// class Polygon
-
-class Polygon {
- constructor(vertices, shared) {
- this.vertices = vertices.map(v => v.clone());
- this.shared = shared;
- this.plane = Plane.fromPoints(this.vertices[0].pos, this.vertices[1].pos, this.vertices[2].pos);
- this.triangle = new Triangle(this.vertices[0].pos, this.vertices[1].pos, this.vertices[2].pos);
- this.triangle.midPoint = this.triangle.getMidpoint(new Vector3());
-
- // this.triangle.polygon = this;
- // this.plane.constant = this.plane.normal.dot(this.triangle.midPoint);
- // this.box = new Box3();
- // this.box.expandByPoint(this.triangle.a);
- // this.box.expandByPoint(this.triangle.b);
- // this.box.expandByPoint(this.triangle.c);
- // this.box.expandByScalar(EPSILON);
-
- // this.source = "new";
- this.intersects = false;
- this.state = "undecided";
- this.previousState = "undecided";
- this.previousStates = [];
- this.valid = true;
- this.coplanar = false;
- // this.original = true;
- Object.defineProperty(this, 'id', {
- value: _polygonID++
- });
- }
- reset() {
- this.intersects = false;
- this.state = "undecided";
- this.previousState = "undecided";
- this.previousStates.length = 0;
- this.valid = true;
- }
- setState(state, keepState) {
- if (this.state === keepState) {
- return;
- }
- this.previousState = this.state;
- this.state !== "undecided" && this.previousStates.push(this.state);
- this.state = state;
- }
- checkAllStates(state) {
- if ((this.state !== state) || ((this.previousState !== state) && (this.previousState !== "undecided"))) {
- // if ( || ) {
- return false;
- }
- for (let i = 0; i < this.previousStates.length; i++) {
- if (this.previousStates[i] !== state) {
- return false;
- }
- }
- return true;
- }
- setInvalid() {
- this.valid = false;
- }
- setValid() {
- this.valid = true;
- }
- clone() {
- let polygon = new Polygon(this.vertices.map(v => v.clone()), this.shared);
- polygon.intersects = this.intersects;
- polygon.valid = this.valid;
- return polygon;
- }
- flip() {
- this.vertices.reverse().forEach(v => v.flip());
- // _v3.copy(this.triangle.a);
- // this.triangle.a.copy(this.triangle.c);
- // this.triangle.c.copy(_v3);
- let tmp = this.triangle.a;
- this.triangle.a = this.triangle.c;
- this.triangle.c = tmp;
- this.plane.flip();
- }
- delete() {
- this.vertices.forEach(v => v.delete());
- this.vertices.length = 0;
- this.plane.delete();
- this.plane = undefined;
- this.triangle = undefined;
- this.shared = undefined;
- this.setInvalid();
- }
-}
-
-
-
-
-////
-// Winding Number algorithm adapted from https://github.com/grame-cncm/faust/blob/master-dev/tools/physicalModeling/mesh2faust/vega/libraries/windingNumber/windingNumber.cpp
-const _wV1 = new Vector3();
-const _wV2 = new Vector3();
-const _wV3 = new Vector3();
-const _wP = new Vector3();
-const _wP_EPS_ARR = [
- new Vector3(EPSILON, 0, 0),
- new Vector3(0, EPSILON, 0),
- new Vector3(0, 0, EPSILON),
- new Vector3(-EPSILON, 0, 0),
- new Vector3(0, -EPSILON, 0),
- new Vector3(0, 0, -EPSILON)
-];
-const _wP_EPS_ARR_COUNT = _wP_EPS_ARR.length;
-const _matrix3 = new Matrix3();
-const wNPI = 4 * Math.PI;
-
-/*
-// Replaced with buffer functions below
-function calcWindingNumber(polygons, point) {
- let wN = 0;
- for (let i = 0; i < polygons.length; i++) {
- let pT = polygons[i].triangle;
- _wV1.subVectors(pT.a, point);
- _wV2.subVectors(pT.b, point);
- _wV3.subVectors(pT.c, point);
- let lenA = _wV1.length();
- let lenB = _wV2.length();
- let lenC = _wV3.length();
- _matrix3.set(_wV1.x, _wV1.y, _wV1.z, _wV2.x, _wV2.y, _wV2.z, _wV3.x, _wV3.y, _wV3.z);
- let omega = 2 * Math.atan2(_matrix3.determinant(), (lenA * lenB * lenC + _wV1.dot(_wV2) * lenC + _wV2.dot(_wV3) * lenA + _wV3.dot(_wV1) * lenB));
- wN += omega;
- }
-
- wN = Math.round(wN / wNPI);
- return wN;
-}
-function polyInside_WindingNumber(polygons, polygon, boundingBox) {
- let result = false;
- let point = polygon.triangle.midPoint;
- _wP.copy(point);
- let wN = calcWindingNumber(polygons, _wP);
- if (wN === 0) {
- if (polygon.coplanar) {
- for (let j = 0; j < _wP_EPS_ARR_COUNT; j++) {
- _wP.copy(point).add(_wP_EPS_ARR[j]);
- wN = calcWindingNumber(polygons, _wP);
- if (wN !== 0) {
- result = true;
- break;
- }
- }
- }
- }
- else {
- result = true;
- }
-
- return result;
-
-}
-*/
-
-
-function returnXYZ(arr, index) {
- return { x: arr[index], y: arr[index + 1], z: arr[index + 2] };
-}
-function calcWindingNumber_buffer(trianglesArr, point) {
- let wN = 0;
- for (let i = 0; i < trianglesArr.length; i += 9) {
- _wV1.subVectors(returnXYZ(trianglesArr, i), point);
- _wV2.subVectors(returnXYZ(trianglesArr, i + 3), point);
- _wV3.subVectors(returnXYZ(trianglesArr, i + 6), point);
- let lenA = _wV1.length();
- let lenB = _wV2.length();
- let lenC = _wV3.length();
- _matrix3.set(_wV1.x, _wV1.y, _wV1.z, _wV2.x, _wV2.y, _wV2.z, _wV3.x, _wV3.y, _wV3.z);
- let omega = 2 * Math.atan2(_matrix3.determinant(), (lenA * lenB * lenC + _wV1.dot(_wV2) * lenC + _wV2.dot(_wV3) * lenA + _wV3.dot(_wV1) * lenB));
- wN += omega;
- }
- wN = Math.round(wN / wNPI);
- return wN;
-}
-function polyInside_WindingNumber_buffer(trianglesArr, point, coplanar) {
- let result = false;
- _wP.copy(point);
- let wN = calcWindingNumber_buffer(trianglesArr, _wP);
- if (wN === 0) {
- if (coplanar) {
- for (let j = 0; j < _wP_EPS_ARR_COUNT; j++) {
- _wP.copy(point).add(_wP_EPS_ARR[j]);
- wN = calcWindingNumber_buffer(trianglesArr, _wP);
- if (wN !== 0) {
- result = true;
- break;
- }
- }
- }
- }
- else {
- result = true;
- }
-
- return result;
-
-}
-
-/////
-
-
-
-function handleIntersectingOctrees(octreeA, octreeB) {
- let octreeA_clone = octreeA.clone();
- let octreeA_buffer;
- let octreeB_buffer;
- if (OctreeCSG.useWindingNumber === true) {
- octreeA_buffer = prepareTriangleBuffer(octreeA_clone.getPolygons());
- octreeB_buffer = prepareTriangleBuffer(octreeB.getPolygons());
- }
- octreeA.handleIntersectingPolygons(octreeB, octreeB_buffer);
- octreeB.handleIntersectingPolygons(octreeA_clone, octreeA_buffer);
- octreeA_clone.delete();
- octreeA_clone = undefined;
- if (octreeA_buffer !== undefined) {
- octreeA_buffer = undefined;
- octreeB_buffer = undefined;
- }
-}
-
-OctreeCSG.subtract_async = async function (octreeA, octreeB, buildTargetOctree = true) {
- return new Promise(async (resolve, reject) => {
- try {
- if (workerPool.length < OctreeCSG.maxWebWorkers) {
- OctreeCSG.createWorkers();
- }
- let octree = new OctreeCSG();
- if (octreeA.box.intersectsBox(octreeB.box)) {
- let currentMeshSideA;
- let currentMeshSideB;
- if (octreeA.mesh) {
- currentMeshSideA = octreeA.mesh.material.side;
- octreeA.mesh.material.side = OctreeCSG.testSide;
- }
- if (octreeB.mesh) {
- currentMeshSideB = octreeB.mesh.material.side;
- octreeB.mesh.material.side = OctreeCSG.testSide;
- }
-
- octreeA.resetPolygons();
- octreeB.resetPolygons();
- octreeA.markIntesectingPolygons(octreeB);
- octreeB.markIntesectingPolygons(octreeA);
- let before = performance.now();
- console.log("[OctreeCSG.subtract_async] before", performance.now());
- // console.log("before sleep");
- // await sleep(1000);
- // console.log("after sleep");
- await handleIntersectingOctrees_async(octreeA, octreeB);
- console.log("[OctreeCSG.subtract_async] after", performance.now());
-
- octreeA.deletePolygonsByStateRules([
- {
- array: true,
- rule: ["inside", "coplanar-back"]
- },
- {
- array: true,
- rule: ["inside", "coplanar-front"]
- },
- {
- array: false,
- rule: "inside"
- }
- ]);
- octreeB.deletePolygonsByStateRules([
- {
- array: true,
- rule: ["outside", "coplanar-back"]
- },
- {
- array: true,
- rule: ["outside", "coplanar-front"]
- },
- {
- array: true,
- rule: ["inside", "coplanar-front"]
- },
- {
- array: false,
- rule: "outside"
- }
- ]);
-
-
- octreeB.deletePolygonsByIntersection(false);
-
-
- octreeB.invert();
-
- if (OctreeCSG.returnType == 0) {
- octreeA.getPolygonCallback(octree.addPolygon.bind(octree));
- octreeB.getPolygonCallback(octree.addPolygon.bind(octree));
- }
- else if (OctreeCSG.returnType == -1) {
- console.log("OctreeA");
- let polys_test = octreeA.getPolygons();
- let limit = Math.min(polys_test.length, 50000);
- console.log(`[octreeA] polys_test`, polys_test.length, limit);
- for (let i = 0; i < limit; i++) {
- if (polys_test[i].intersects) {
- let t = polys_test[i].triangle;
- // if (((t.a.y < -3) && (t.b.y < -3) && (t.c.y < -3))) {
- // if (((t.a.x >= 0.8) && (t.b.x >= 0.8) && (t.c.x >= 0.8))) {
- // console.log("AAAA", i, t, polys_test[i]);
- octree.addPolygon(polys_test[i]);
- // }
- }
- // else {
- // octree.addPolygon(polys_test[i]);
- // }
- }
- }
- else {
- console.log("OctreeB");
- let polys_test = octreeB.getPolygons();
- let limit = Math.min(polys_test.length, 50000);
- console.log(`[octreeB] polys_test`, polys_test.length, limit);
- for (let i = 0; i < limit; i++) {
- if (polys_test[i].intersects) {
- let t = polys_test[i].triangle;
- // if ((t.a.x <= 1) && (t.b.x <= 1) && (t.c.x <= 1)) {
- // if (((t.a.y === -5) && (t.b.y === -5) && (t.c.y === -5))) {
- // console.log("BBBB", i, t, polys_test[i]);
- octree.addPolygon(polys_test[i]);
- // }
- }
- // else {
- // octree.addPolygon(polys_test[i]);
- // }
- }
- }
-
- if (octreeA.mesh) {
- if (octreeA.mesh.material.side !== currentMeshSideA) {
- octreeA.mesh.material.side = currentMeshSideA;
- }
- }
- if (octreeB.mesh) {
- if (octreeB.mesh.material.side !== currentMeshSideB) {
- octreeB.mesh.material.side = currentMeshSideB;
- }
- }
- }
- else {
- octreeA.getPolygonCallback(octree.addPolygon.bind(octree));
- }
-
- buildTargetOctree && octree.buildTree();
- // octree.invert();
- resolve(octree);
- }
- catch (e) {
- reject(e);
- }
- });
-}
-
-async function handleIntersectingOctrees_async(octreeA, octreeB) {
- return new Promise(async (resolve, reject) => {
- try {
- const original_useWindingNumber = OctreeCSG.useWindingNumber;
- OctreeCSG.useWindingNumber = true;
- let octreeA_clone = octreeA.clone();
- // let octreeA_polygons;
- // let octreeB_polygons;
- let octreeA_buffer;
- let octreeB_buffer;
- if (OctreeCSG.useWindingNumber === true) {
- octreeA_buffer = prepareTriangleBuffer(octreeA_clone.getPolygons());
- octreeB_buffer = prepareTriangleBuffer(octreeB.getPolygons());
- }
- // console.log("[handleIntersectingOctrees_async] before");
- // await octreeA.handleIntersectingPolygons_async(octreeB, octreeB_buffer);
- octreeA.handleIntersectingPolygons_reduced(octreeB, octreeB_buffer);
- // console.log("[handleIntersectingOctrees_async] before 2");
- await handleInsideOutsidePolygons_async(octreeA, octreeB, octreeB_buffer);
- // console.log("[handleIntersectingOctrees_async] before 3");
- // await octreeB.handleIntersectingPolygons_async(octreeA_clone, octreeA_buffer);
- octreeB.handleIntersectingPolygons_reduced(octreeA_clone, octreeA_buffer);
- // console.log("[handleIntersectingOctrees_async] before 4");
- await handleInsideOutsidePolygons_async(octreeB, octreeA_clone, octreeA_buffer);
- // console.log("[handleIntersectingOctrees_async] after");
- octreeA_clone.delete();
- octreeA_clone = undefined;
-
- if (octreeA_buffer !== undefined) {
- octreeA_buffer = undefined;
- octreeB_buffer = undefined;
- }
- OctreeCSG.useWindingNumber = original_useWindingNumber;
- resolve();
- }
- catch (e) {
- reject(e)
- }
- });
-}
-
-async function handleInsideOutsidePolygons_async(octree, targetOctree, targetOctreeBuffer) {
- return new Promise(async (resolve, reject) => {
- try {
- // polygonStack = this.polygons.filter(polygon => (polygon.valid == true) && (polygon.intersects == true));
- let polygonStack = octree.getIntersectingPolygons();
- let runningWebWorkers = [];
- let currentPolygon = polygonStack.pop();
- while (currentPolygon) {
- // console.warn("Checking loop polygon id", currentPolygon.id);
- if (!currentPolygon.valid) {
- continue;
- }
-
- let debugPoly = false;
-
- // let testTriangle = new THREE.Triangle(new THREE.Vector3(0.29171404242515564, -4.110300540924072, 2.832019329071045), new THREE.Vector3(-0.29171404242515564, -4.110300540924072, 2.832019329071045), new THREE.Vector3(0, -4.3809967041015625, 2.4097442626953125));
- // if ((OctreeCSG.returnType == -1) && (currentPolygon.triangle.equals(testTriangle))) {
- // debugPoly = true;
- // console.warn("STARTING DEBUG");
- // }
- OctreeCSG.debugPoly = debugPoly;
- let inside = false;
- if (targetOctree.box.containsPoint(currentPolygon.triangle.midPoint)) {
- // if (OctreeCSG.useWindingNumber === true) {
- // let responses = [];
- // // let result1 = OctreeCSG.testWorker(1);
- // // let result2 = OctreeCSG.testWorker(2);
- let worker = getAvailableWorker();
- while (!worker) {
- // console.log("Waiting for worker");
- await sleep(1);
- worker = getAvailableWorker();
- }
-
- worker.checkWindingNumber({
- type: 'windingNumber',
- point: currentPolygon.triangle.midPoint,
- coplanar: currentPolygon.coplanar,
- polygonID: currentPolygon.id,
- triangles: targetOctreeBuffer
- }, currentPolygon).then(worker => {
- // console.log("Worker finished", worker.id);
- let workerIndex = runningWebWorkers.indexOf(worker);
- if (workerIndex > -1) {
- runningWebWorkers.splice(workerIndex, 1);
- }
- });
- runningWebWorkers.push(worker);
-
- }
- else {
- currentPolygon.setState("outside");
- }
-
- // if (debugPoly) {
- // console.log("CHECK INSIDE", inside);
- // }
- // if (inside === true) {
- // currentPolygon.setState("inside");
- // }
- // else {
- // currentPolygon.setState("outside");
- // }
-
- currentPolygon = polygonStack.pop();
- }
- // console.log("START WAITING", runningWebWorkers.length);
- while (runningWebWorkers.length) {
- // console.log("Waiting to finish");
- await sleep(1);
- }
- resolve();
- }
- catch (e) {
- reject(e);
- }
- });
-}
-
-// OctreeCSG.prepareTriangleBuffer = function (polygons) {
-// return prepareTriangleBuffer(polygons);
-// }
-
-// {message: data, data: buff}
-// OctreeCSG.runWorker = async function (data, transferables) {
-
-function prepareTriangleBuffer(polygons) {
- let numOfTriangles = polygons.length;
- // let buffer = new ArrayBuffer(numOfTriangles * 3 * 3 * 4);
- // let array = new Float32Array(buffer);
- let array = new Float32Array(numOfTriangles * 3 * 3);
- let bufferIndex = 0;
- for (let i = 0; i < numOfTriangles; i++) {
- let triangle = polygons[i].triangle;
- array[bufferIndex++] = triangle.a.x;
- array[bufferIndex++] = triangle.a.y;
- array[bufferIndex++] = triangle.a.z;
- array[bufferIndex++] = triangle.b.x;
- array[bufferIndex++] = triangle.b.y;
- array[bufferIndex++] = triangle.b.z;
- array[bufferIndex++] = triangle.c.x;
- array[bufferIndex++] = triangle.c.y;
- array[bufferIndex++] = triangle.c.z;
- }
- // return buffer;
- return array;
-}
-OctreeCSG.prepareTriangleBuffer = prepareTriangleBuffer;
-const workerPool = [];
-OctreeCSG.useWebWorkers = false;
-OctreeCSG.useWebWorkersSync = true;
-OctreeCSG.maxWebWorkers = navigator.hardwareConcurrency || 4;
-OctreeCSG.createWorkers = function () {
- let max = OctreeCSG.maxWebWorkers - workerPool.length;
- for (let i = 0; i < max; i++) {
- OctreeCSG.createWorker();
- }
-}
-OctreeCSG.getWorkerPool = function () { // FOR TESTING ONLY - WILL BE DELETED BEFORE PROD
- return workerPool;
-}
-function getAvailableWorker() {
- for (let i = 0; i < workerPool.length; i++) {
- if (!workerPool[i].running) {
- return workerPool[i];
- }
- }
- return;
-}
-OctreeCSG.createWorker = function () {
- let worker = new GenerateWebWorker();
- workerPool.push(worker);
- return worker;
-}
-OctreeCSG.testWorker2 = function (data) {
- console.log("OctreeCSG.testWorker2");
- let result = OctreeCSG.testWorker4(data);
- console.log("OctreeCSG.testWorker2", result);
- return result;
- // // let worker = new Worker('./js/OctreeCSG/OctreeCSG.worker.js');
- // let worker = new Worker(new URL('./OctreeCSG.worker.js', import.meta.url), { type: 'module' });
- // worker.onerror = (e) => {
- // console.log(e);
- // }
- // worker.onmessage = (e) => {
- // console.log("INC DATA:", e.data);
- // }
- // worker.postMessage("A");
-
-}
-OctreeCSG.testWorker4 = function (data) {
- console.log("OctreeCSG.testWorker4");
- let result = OctreeCSG.testWorker3(data);
- console.log("OctreeCSG.testWorker4", result);
- return result;
-}
-async function sleep(ms) {
- return new Promise(resolve => setTimeout(resolve, ms));
-}
-OctreeCSG.testWorker3 = async function (data) {
- console.log("OctreeCSG.testWorker3");
- let responses = [];
- // let result1 = OctreeCSG.testWorker(1);
- // let result2 = OctreeCSG.testWorker(2);
- let worker = getAvailableWorker();
- if (!worker) {
- console.warn("no available workers");
- return;
- }
- console.log("testing worker");
- worker.sendMessage(data).then(data => responses.push(data));
- let worker2 = getAvailableWorker();
- if (!worker2) {
- console.warn("no available workers");
- return;
- }
- console.log("testing worker 2");
- worker2.sendMessage(data).then(data => responses.push(data));
- while (responses.length < 2) {
- console.log("responses not received", responses.length, performance.now());
- await sleep(500);
- }
- console.log("got response:", responses);
- return responses;
-}
-// OctreeCSG.sendToWorker = async function (data) {
-OctreeCSG.testWorker = async function (data) {
- console.log("OctreeCSG.testWorker");
- let worker = getAvailableWorker();
- if (!worker) {
- console.warn("no available workers");
- return;
- }
- console.log("testing worker");
- let result = await worker.sendMessage(data);
- console.log("got response:", result);
- // worker.sendMessage(data).then(workerCB, (msg) => {
- // console.log("ERR", msg);
- // });
- return result;
-}
-OctreeCSG.runWorker = async function (data, transferables) {
- let worker = getAvailableWorker();
- if (!worker) {
- console.warn("no available workers");
- return;
- }
- // console.log("testing worker");
- let result = await worker.sendMessage(data, transferables);
- // console.log("got response:", result);
- // worker.sendMessage(data).then(workerCB, (msg) => {
- // console.log("ERR", msg);
- // });
- return result;
-}
-function workerCB() {
- console.log("CALLBACK", arguments);
-}
-
-let webWorker_ID = 0;
-class GenerateWebWorker {
- constructor() {
- this.running = false;
- this.worker = new Worker(new URL('./OctreeCSG.worker.js', import.meta.url), { type: 'module' });
- this.worker.onerror = (e) => {
- if (e.message) {
- throw new Error(`[OctreeCSG] GenerateWebWorker: Could not create a web worker with the error "${e.message}"`);
- }
- else {
- throw new Error(`[OctreeCSG] GenerateWebWorker: Could not create a web worker, no error message was provided.`);
- }
- }
- this.id = webWorker_ID++;
- }
- checkWindingNumber(data, currentPolygon) {
- // worker.checkWindingNumber({
- // type: windingNumber,
- // point: currentPolygon.triangle.midPoint,
- // coplanar: currentPolygon.coplanar,
- // polygonID: currentPolygon.id,
- // triangles: targetOctreeBuffer
- // }, currentPolygon)
- if (this.running) {
- throw new Error(`[GenerateWebWorker] checkWindingNumber: Worker is already running`);
- }
- if (this.worker === null) {
- throw new Error(`[GenerateWebWorker] checkWindingNumber: Worker has beein disposed`);
- }
- this.running = true;
- const { worker } = this;
- return new Promise((resolve, reject) => {
- try {
- worker.onerror = (e) => {
- reject(new Error(`[GenerateWebWorker] checkWindingNumber: ${e.message}`));
- this.running = false;
- worker.onmessage = null;
- }
- worker.onmessage = (e) => {
- const { data } = e;
- if (data.error) {
- reject(new Error(data.error));
- worker.onmessage = null;
- }
- if ((data.type === 'windingNumber') && currentPolygon) {
- if (data.result === true) {
- currentPolygon.setState("inside");
- }
- else {
- currentPolygon.setState("outside");
- }
- resolve(this);
- }
- else {
- resolve(data);
- }
- this.running = false;
- worker.onmessage = null;
- }
- // console.log("GOT HERE?", worker);
- // let numOfObjects = 1;
- // let buff = new ArrayBuffer(numOfObjects * 4);
- // let test = new Float32Array(buff);
- // test[0] = 7;
- // {message: data, data: buff}
- worker.postMessage(data);
- }
- catch (e) {
- reject(e);
- worker.onmessage = null;
- }
-
- });
- }
- sendMessage(data, transferables, currentPolygon) {
- if (this.running) {
- throw new Error(`[GenerateWebWorker] sendMessage: Worker is already running`);
- }
- if (this.worker === null) {
- throw new Error(`[GenerateWebWorker] sendMessage: Worker has beein disposed`);
- }
- this.running = true;
- const { worker } = this;
- return new Promise((resolve, reject) => {
- try {
- worker.onerror = (e) => {
- reject(new Error(`[GenerateWebWorker] sendMessage: ${e.message}`));
- // reject(e);
- this.running = false;
- worker.onmessage = null;
- }
- worker.onmessage = (e) => {
- // console.log("INC DATA:", e);
- const { data } = e;
- if (data.error) {
- reject(new Error(data.error));
- worker.onmessage = null;
- }
- resolve(data);
- this.running = false;
- worker.onmessage = null;
- }
- // console.log("GOT HERE?", worker);
- // let numOfObjects = 1;
- // let buff = new ArrayBuffer(numOfObjects * 4);
- // let test = new Float32Array(buff);
- // test[0] = 7;
- // {message: data, data: buff}
- worker.postMessage(data, transferables);
- }
- catch (e) {
- reject(e);
- worker.onmessage = null;
- }
-
- });
- }
- dispose() {
- if (this.worker) {
- this.worker.terminate();
- this.worker = undefined;
- let workerIndex = workerPool.indexOf(this);
- if (workerIndex > -1) {
- workerPool.splice(workerIndex, 1);
- }
- }
- }
-}
-
-
-
-////////
-// https://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm
-const edge1 = new Vector3();
-const edge2 = new Vector3();
-const h = new Vector3();
-const s = new Vector3();
-const q = new Vector3();
-function rayIntersectsTriangle(ray, triangle, target = new Vector3()) {
-
-
- const EPSILON = 0.0000001;
- edge1.subVectors(triangle.b, triangle.a);
- edge2.subVectors(triangle.c, triangle.a);
- h.crossVectors(ray.direction, edge2);
- let a = edge1.dot(h);
- if (a > -EPSILON && a < EPSILON) {
- return null; // Ray is parallel to the triangle
- }
- let f = 1 / a;
- s.subVectors(ray.origin, triangle.a);
- let u = f * s.dot(h);
- if (u < 0 || u > 1) {
- return null;
- }
- q.crossVectors(s, edge1);
- let v = f * ray.direction.dot(q);
- if (v < 0 || u + v > 1) {
- return null;
- }
- // Check where intersection is
- let t = f * edge2.dot(q);
- if (t > EPSILON) {
- return target.copy(ray.direction).multiplyScalar(t).add(ray.origin);
- }
- // else {
- return null;
- // }
-}
-OctreeCSG.rayIntersectsTriangle = rayIntersectsTriangle;
-////////
-OctreeCSG.returnType = 0;
-
-OctreeCSG.testSide = DoubleSide;
-OctreeCSG.useOctreeRay = true;
-OctreeCSG.getRayPolys = true;
-OctreeCSG.useWindingNumber = false;
-OctreeCSG.rayIntersectTriangleType = "MollerTrumbore"; // "regular" (three.js' ray.intersectTriangle; "MollerTrumbore" (Moller Trumbore algorithm);
-
-
-OctreeCSG.debugPoly = false;
-OctreeCSG.useWindingNumberTurbo = false;
-OctreeCSG.useGDTest = false;
-
-////
-
-
-
-// TODO: test max level 10 and (min) polys per tree 100 or 200
-OctreeCSG.maxLevel = 16;
-OctreeCSG.polygonsPerTree = 100;
-
-OctreeCSG.Polygon = Polygon;
-export default OctreeCSG;
\ No newline at end of file
diff --git a/test/OctreeCSG/OctreeCSG.worker.js b/test/OctreeCSG/OctreeCSG.worker.js
deleted file mode 100644
index 5f46637..0000000
--- a/test/OctreeCSG/OctreeCSG.worker.js
+++ /dev/null
@@ -1,107 +0,0 @@
-import * as THREE from '../threejs/three.module.js';
-// console.log("GOT HERE");
-onmessage = function (e) {
- // let randLimit = Math.round(Math.random() * 1000000000);
- // console.log("[WORKER]", randLimit, e);
- // let worker_data = {
- // type: 'windingNumber',
- // point: point,
- // triangles: buffer
- // }
- const { type, point, coplanar, polygonID, triangles } = e.data;
- let trianglesArr = new Float32Array(triangles);
- // console.log("[WORKER] Checking Polygon ID:", polygonID, point);
- if (type === 'windingNumber') {
- postMessage({
- type,
- result: polyInside_WindingNumber_buffer(trianglesArr, point, coplanar)
- });
- }
- else {
- let a = 0;
- // for (let i = 0; i < randLimit; i++) {
- // a++;
- // }
- postMessage("[From Worker] Aloha " + a);
- }
-}
-
-////
-const EPSILON = 1e-5;
-// Winding Number algorithm adapted from https://github.com/grame-cncm/faust/blob/master-dev/tools/physicalModeling/mesh2faust/vega/libraries/windingNumber/windingNumber.cpp
-const _wV1 = new THREE.Vector3();
-const _wV2 = new THREE.Vector3();
-const _wV3 = new THREE.Vector3();
-const _wP = new THREE.Vector3();
-const _wP_EPS_ARR = [
- new THREE.Vector3(EPSILON, 0, 0),
- new THREE.Vector3(0, EPSILON, 0),
- new THREE.Vector3(0, 0, EPSILON),
- new THREE.Vector3(-EPSILON, 0, 0),
- new THREE.Vector3(0, -EPSILON, 0),
- new THREE.Vector3(0, 0, -EPSILON)
-];
-const _wP_EPS_ARR_COUNT = _wP_EPS_ARR.length;
-const _matrix3 = new THREE.Matrix3();
-const wNPI = 4 * Math.PI;
-
-// function calcDet(a, b, c) {
-// return (-a.z * b.y * c.x +
-// a.y * b.z * c.x +
-// a.z * b.x * c.y +
-// a.x * b.z * c.y +
-// a.y * b.x * c.z +
-// a.x * b.y * c.z );
-// }
-function returnXYZ(arr, index) {
- return { x: arr[index], y: arr[index + 1], z: arr[index + 2] };
-}
-function calcWindingNumber_buffer(trianglesArr, point) {
- let wN = 0;
- for (let i = 0; i < trianglesArr.length; i += 9) {
- _wV1.subVectors(returnXYZ(trianglesArr, i), point);
- _wV2.subVectors(returnXYZ(trianglesArr, i + 3), point);
- _wV3.subVectors(returnXYZ(trianglesArr, i + 6), point);
- let lenA = _wV1.length();
- let lenB = _wV2.length();
- let lenC = _wV3.length();
- _matrix3.set(_wV1.x, _wV1.y, _wV1.z, _wV2.x, _wV2.y, _wV2.z, _wV3.x, _wV3.y, _wV3.z);
- let omega = 2 * Math.atan2(_matrix3.determinant(), (lenA * lenB * lenC + _wV1.dot(_wV2) * lenC + _wV2.dot(_wV3) * lenA + _wV3.dot(_wV1) * lenB));
- wN += omega;
- }
- wN = Math.round(wN / wNPI);
- return wN;
-}
-function polyInside_WindingNumber_buffer(trianglesArr, point, coplanar) {
- let result = false;
- _wP.copy(point);
- let wN = calcWindingNumber_buffer(trianglesArr, _wP);
- let coplanarFound = false;
- if (wN === 0) {
- if (coplanar) {
- // console.log("POLYGON IS COPLANAR");
- for (let j = 0; j < _wP_EPS_ARR_COUNT; j++) {
- // console.warn("DOES IT GET HERE?");
- _wP.copy(point).add(_wP_EPS_ARR[j]);
- wN = calcWindingNumber_buffer(trianglesArr, _wP);
- if (wN !== 0) {
- // console.warn("GOT HERE");
- result = true;
- coplanarFound = true;
- break;
- }
- }
- }
- }
- else {
- result = true;
- }
- // if (result && polygon.coplanar) {
- // console.log(`[polyInside_WindingNumber] coplanar polygon found ${coplanarFound ? "IN" : "NOT IN"} coplanar test`);
- // }
-
- return result;
-
-}
-
-// export {};
\ No newline at end of file
diff --git a/test/app3.css b/test/app3.css
deleted file mode 100644
index 6f78b3e..0000000
--- a/test/app3.css
+++ /dev/null
@@ -1,25 +0,0 @@
-body {
- margin: 0;
- overflow: hidden;
-}
-
-canvas {
- display: block;
-}
-
-button {
- background: black;
- opacity: .5;
- border: none;
- color: white;
-}
-
-#mainDiv {
- position: absolute;
- z-index: 10;
- left: 10px;
- top: 50px;
- font-family: Arial, Helvetica, sans-serif;
- color: white;
- background: rgba(50,50,50,.5);
-}
diff --git a/test/app3.js b/test/app3.js
deleted file mode 100644
index bf74889..0000000
--- a/test/app3.js
+++ /dev/null
@@ -1,329 +0,0 @@
-import*as THREE from "three";
-import {OrbitControls} from "threeModules/controls/OrbitControls.js";
-import {TransformControls} from "threeModules/controls/TransformControls.js";
-
-//import*as THREE from "https://threejs.org/build/three.module.js";
-
-//import { ConvexHull } from "../three.js-dev/examples/jsm/math/ConvexHull.js";
-//import GridMaterial from "./grid-material.js";
-import Environment from "./cool-env.js"
-
-class App3 {
-
- constructor() {
- let camera, scene, renderer, ocontrols;
-
- renderer = new THREE.WebGLRenderer({
- antialias: true,
- alpha: true
- });
- renderer.setClearColor(0x101010);
- renderer.outputEncoding = THREE.sRGBEncoding;
- //renderer.shadowMap.type = THREE.VSMShadowMap;
- renderer.shadowMap.type = THREE.PCFSoftShadowMap;
- renderer.shadowMap.enabled = true;
- document.body.appendChild(renderer.domElement);
-
- scene = new THREE.Scene();
-
- let aspect = window.innerWidth / window.innerHeight;
- camera = this.camera = new THREE.PerspectiveCamera(75,aspect,0.1,1000);
- scene.add(camera);
-
-
- let environment = this.environment = new Environment(renderer,scene,camera)
-
- var raycaster = new THREE.Raycaster();
- var mouse = new THREE.Vector2();
-
- let lastSavedPosition = new THREE.Vector3(0,1.5,2)
-
- ocontrols = this.orbitControls = new OrbitControls(camera,renderer.domElement);
- ocontrols.enabled = true;
- ocontrols.minZoom = ocontrols.minDistance = 1;
- try {
- camera.position.copy(JSON.parse(localStorage.cameraPosition))
- ocontrols.target.copy(JSON.parse(localStorage.controlsTarget))
- } catch {
- camera.position.copy(lastSavedPosition);
- ocontrols.target.set(0, 0, 0)
- }
- // camera.lookAt(0, 0, 0);
- let frontMaterial = Environment.mkMat('yellow')
- frontMaterial.transparent = true;
- frontMaterial.opacity = .25;
-
- let transformControls = this.transformControls = new TransformControls(camera,renderer.domElement);
- transformControls.translationSnap = 0.05;
- transformControls.rotationSnap = Math.PI / 16;
- scene.add(transformControls);
- /*
- let gridmat = Environment.mkMat(0x404040)
- gridmat.transparent = true;
- let grid = GridMaterial.makeGrid(gridmat)
- scene.add(grid);
-*/
-
- let selectionMaterial = Environment.mkMat(0x404040);
- //grid.material.clone();
- //new GridMaterial(frontMaterial.clone());
- selectionMaterial.color.set('blue');
- selectionMaterial.emissive.set(0x202020)
- selectionMaterial.transparent = true
- selectionMaterial.opacity = .5
-
- let transformGroup = this.transformGroup = new THREE.Group();
- scene.add(transformGroup);
- transformControls.attach(transformGroup);
-
- let tv30 = new THREE.Vector3();
- class Elements {
- constructor() {
- this.selected = {};
- this.selection = [];
- this.elements = [];
- }
- get selectedCount() {
- return this.selection.length;
- }
- forEach(fn) {
- this.elements.slice(0).forEach(fn);
- }
- forSelected(fn) {
- this.selection.slice(0).forEach(fn);
- }
- setMaterial(m, mat) {
- if (!m.userData.saveMaterial && m.userData.material !== m.material)
- m.userData.saveMaterial = m.material;
- m.material = mat;
- }
- clearSelection() {
- this.forSelected((e)=>{
- scene.attach(e);
- if (e.userData.saveMaterial)
- e.material = e.userData.saveMaterial
- }
- )
- this.selected = {};
- this.selection = [];
- }
-
- deselect(idx) {
- let e = this.selected[idx];
- if (e) {
- delete this.selected[idx];
- scene.attach(e);
- this.selection = []
- this.forEach((e,i)=>this.selected[i] && this.selection.push(e) && ((e.userData.saveMaterial) && (e.material = e.userData.saveMaterial)))
- this.update();
- }
- }
-
- update() {
- if (this.selectedCount) {
- if (this.lastSelectedId != this.selection[0].uuid) {
- this.lastSelectedId = this.selection[0].uuid
- if (!this.selectionChangedEvent)
- this.selectionChangedEvent = new Event('selectionChanged')
- this.selectionChangedEvent.app = this;
- document.dispatchEvent(this.selectionChangedEvent)
- }
- this.forSelected(e=>scene.attach(e))
- transformGroup.position.set(0, 0, 0);
- this.forSelected(e=>transformGroup.position.add(e.position));
- transformGroup.position.multiplyScalar(1 / this.selectedCount);
- transformGroup.updateMatrixWorld()
- this.forSelected(e=>transformGroup.attach(e))
-
- }
- }
- select(idx) {
- let e = this.elements[idx];
- this.selected[idx] = e;
- this.selection.push(e);
- this.setMaterial(e, selectionMaterial);
- transformGroup.attach(e);
- this.update();
- }
- set(e) {
- this.forEach(s=>s.parent.remove(s));
- this.elements = e.slice(0);
- this.selection = [];
-
- this.forEach((s,i)=>{
- scene.attach(s);
- if (this.selected[i])
- this.select(i);
- }
- );
- this.update();
- }
- }
-
- let elements = new Elements();
-
- let wasDragged = false;
-
- let transpMat = (color,opacity)=>{
- let m = Environment.mkMat(color)
- if ((m.opacity = opacity) === 1)
- m.transparent = true;
- return m
- }
-
- let materials = this.materials = [transpMat('gray', 1.), transpMat('red', .7), transpMat('green', .7), transpMat('purple', .7), transpMat('teal', .7), transpMat('orange', .7), ]
-
- transformControls.addEventListener("dragging-changed", event=>{
- ocontrols.enabled = !event.value;
- wasDragged = event.value;
- if (!wasDragged) {//console.log("Dragging");
- } else {//console.log("Drag");
- //setElements(fc.update())
- }
- }
- );
-
- this.scene = scene;
- this.elements = elements;
-
- this.mouseWorld = new THREE.Vector3(0,0,0)
- this.smoothMouseWorld = new THREE.Vector3(0,0,0)
-
- this.mouse = {
- mouseWorld: this.mouseWorld,
- smoothMouseWorld: this.smoothMouseWorld,
- buttons: 0
- }
-
- let groundProxy = new THREE.Mesh(new THREE.PlaneBufferGeometry(1000,1000))
- groundProxy.rotation.x = Math.PI * -.5
- groundProxy.updateMatrixWorld()
-
- let v0 = new THREE.Vector3();
-
- let mouseChangeEvent = new Event('mouseChange')
- let mouseEvent = event=>{
- mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
- mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
- raycaster.setFromCamera(mouse, camera);
- // calculate objects intersecting the picking ray
- var intersects = raycaster.intersectObjects(elements.elements);
- this.mouse.buttons = event.buttons;
- // scene.children );
- if (!intersects.length) {
- if ((!event.buttons) && !(event.ctrlKey || event.shiftKey || event.altKey)) {
- ocontrols.enabled = true;
- transformControls.enabled = false;
- }
- let gndintersects = raycaster.intersectObjects([groundProxy]);
- if (gndintersects.length) {
- this.mouseWorld.copy(gndintersects[0].point)
- return
- }
- }
- if (event.type === "pointerdown") {
- if (event.target !== renderer.domElement)
- return;
- if (wasDragged)
- return;
-
- if (intersects.length) {
- ocontrols.enabled = false;
- transformControls.enabled = true;
-
- if (!event.shiftKey)
- elements.clearSelection()
- let o = intersects[0].object;
- elements.forEach((e,i)=>e === o && ((!elements.selected[i]) ? elements.select(i) : elements.deselect(i)));
- } else if (!wasDragged) {
- if (event.buttons === 1)
- elements.clearSelection();
- }
- } else if (event.type === "pointerup") {//updateCSG()
- } else if (event.type === "pointermove") {}
-
- mouseChangeEvent.event = event;
- document.dispatchEvent(mouseChangeEvent)
-
- transformControls.enabled = transformControls.visible = elements.selectedCount ? true : false;
- }
- ;
-
- window.addEventListener("keyup", ()=>transformControls.setMode("translate"), false);
- window.addEventListener("pointermove", mouseEvent, false);
- window.addEventListener("pointerdown", mouseEvent, false);
- window.addEventListener("pointerup", mouseEvent, false);
-
- let resizeFn = event=>{
- let width = window.innerWidth;
- let height = window.innerHeight;
- camera.aspect = width / height;
- camera.updateProjectionMatrix();
-
- renderer.setSize(width, height);
- if (environment && environment.composer)
- environment.resize(width, height)
- }
- ;
-
- resizeFn();
- window.addEventListener("resize", resizeFn, false)
-
- let clamp = (v,n,p)=>v < n ? n : v > p ? p : v
- let clampPoint = (pt,mdist)=>{
- pt.set(clamp(pt.x, -mdist, mdist), clamp(pt.y, -mdist, mdist), clamp(pt.z, -mdist, mdist))
- }
-
- let constrainView = ()=>{
-
- if (ocontrols.target.y < 1) {
- camera.position.y += 1 - ocontrols.target.y;
- ocontrols.target.y += 1 - ocontrols.target.y;
- }
- if (camera.position.y < 1) {
- ocontrols.target.y += 1 - camera.position.y;
- camera.position.y += 1 - camera.position.y;
- }
- ocontrols.maxDistance = 1000;
- if (ocontrols.target.y < 1) {
- //camera.position.y += 1-ocontrols.target.y;
- ocontrols.target.y += 1 - ocontrols.target.y;
- }
- //ocontrols.target.set(0,0,0)
- clampPoint(ocontrols.target, 1000)
- clampPoint(camera.position, 1000)
- //clampPoint(camera.position,100)
- }
-
- let beforeRenderEvent = new Event('beforeRender')
- let afterRenderEvent = new Event('afterRender')
- renderer.setAnimationLoop(()=>{
- this.smoothMouseWorld.add(v0.copy(this.mouseWorld).sub(this.smoothMouseWorld).multiplyScalar(0.1))
- // Mouse smoothing...
- ocontrols.update();
- if (!lastSavedPosition.equals(camera.position)) {
- lastSavedPosition.copy(camera.position)
- localStorage.cameraPosition = JSON.stringify(camera.position)
- localStorage.controlsTarget = JSON.stringify(ocontrols.target)
- }
-
- constrainView()
-
- document.dispatchEvent(beforeRenderEvent)
- if (environment && environment.composer && false)
- environment.composer.render();
- else
- renderer.render(scene, camera);
- document.dispatchEvent(afterRenderEvent)
-
- }
- );
-
- this.renderer = renderer;
- let initEvt = new Event('init')
- initEvt.app = this;
- document.dispatchEvent(initEvt);
- }
-}
-
-export default new App3();
diff --git a/test/cool-env.js b/test/cool-env.js
deleted file mode 100644
index ba6d927..0000000
--- a/test/cool-env.js
+++ /dev/null
@@ -1,219 +0,0 @@
-
-import*as THREE from "three";
-//import { CSS3DRenderer } from "../../../three.js-dev/examples/jsm/renderers/CSS3DRenderer.js";
-
-import {HDRCubeTextureLoader} from "threeModules/loaders/HDRCubeTextureLoader.js";
-import {RGBELoader} from "threeModules/loaders/RGBELoader.js";
-//import {RoughnessMipmapper} from 'threeModules/utils/RoughnessMipmapper.js';
-//import {PMREMGenerator} from "../three.js-dev/examples/jsm/pmrem/PMREMGenerator.js";
-//import {PMREMCubeUVPacker} from "../three.js-dev/examples/jsm/pmrem/PMREMCubeUVPacker.js";
-
-import {EffectComposer} from "threeModules/postprocessing/EffectComposer.js";
-import {RenderPass} from "threeModules/postprocessing/RenderPass.js";
-import {ShaderPass} from "threeModules/postprocessing/ShaderPass.js";
-import {CopyShader} from "threeModules/shaders/CopyShader.js";
-import {LuminosityHighPassShader} from "threeModules/shaders/LuminosityHighPassShader.js";
-import {UnrealBloomPass} from "threeModules/postprocessing/UnrealBloomPass.js";
-import {FXAAShader} from "threeModules/shaders/FXAAShader.js";
-
-import {SSAOShader} from "threeModules/shaders/SSAOShader.js";
-import {SSAOPass} from "threeModules/postprocessing/SSAOPass.js";
-
-import {SimplexNoise} from "threeModules/math/SimplexNoise.js";
-
-class Environment {
- constructor(renderer, scene, camera) {
- let ssaoPass;
- let fxaaPass;
- let self = this;
- function setupPostProcessing() {
- var bloomPass = new UnrealBloomPass(new THREE.Vector2(window.innerWidth,window.innerHeight),1.5,0.4,0.85);
- bloomPass.threshold = 0.99;
- //0.85; 0,1.5,0
- bloomPass.strength = 1.2;
- bloomPass.radius = 0.0;
- //0.02;
-
- //renderer.toneMapping = THREE.ACESFilmicToneMapping;
- //renderer.toneMapping = THREE.ReinhardToneMapping;
- renderer.toneMapping = THREE.LinearToneMapping;
- //renderer.toneMapping = THREE.CineonToneMapping;
- renderer.toneMappingExposure = .8;
- //0.5;//2.3;
-
- var renderScene = new RenderPass(scene,camera);
-
- let composer = new EffectComposer(renderer);
- let width = window.innerWidth;
- let height = window.innerHeight;
-
- composer.addPass(renderScene);
-
- fxaaPass = new ShaderPass(FXAAShader);
-
- renderer.setPixelRatio(1);
-
- var pixelRatio = renderer.getPixelRatio();
-
- let copyPass = new ShaderPass(THREE.CopyShader);
-
- ssaoPass = new SSAOPass(scene,camera,width,height);
- ssaoPass.minDistance = 0.005;
- ssaoPass.maxDistance = 0.28;
- ssaoPass.kernelRadius = 10.1;
-
- self.resize = (width,height)=>{
-
- composer.setSize(width, height);
-
- fxaaPass.material.uniforms["resolution"].value.x = 1 / (width * pixelRatio);
- fxaaPass.material.uniforms["resolution"].value.y = 1 / (height * pixelRatio);
- ssaoPass.setSize(width, height)
-
- }
- self.resize(window.innerWidth, window.innerHeight);
- //bloomPass.renderToScreen = false;
-
- composer.addPass(fxaaPass);
-
- //ssaoPass.clear = false;
- //composer.addPass( ssaoPass );
-
- //composer.addPass( copyPass );
-
- composer.addPass(bloomPass);
-
- //renderer.toneMapping = THREE.ReinhardToneMapping;
- return composer;
- }
-
- let composer = this.composer = setupPostProcessing();
-
- // use of RoughnessMipmapper is optional
- //var roughnessMipmapper = new RoughnessMipmapper(renderer);
-
- function loadHDREquirect(path) {
- var pmremGenerator = new THREE.PMREMGenerator(renderer);
- pmremGenerator.compileEquirectangularShader();
- new RGBELoader()//.setDataType(THREE.UnsignedByteType)// .setPath( '../three.js-dev/examples/textures/equirectangular/' )
- // .load( 'royal_esplanade_1k.hdr',
- .setPath('')
- .load( 'https://threejs.org/examples/textures/equirectangular/venice_sunset_1k.hdr',//'./venice_sunset_1k.hdr',
- //.load('../assets/san_giuseppe_bridge_4k.hdr',
- function(texture) {
- var envMap = pmremGenerator.fromEquirectangular(texture).texture;
- scene.background = envMap;
- scene.environment = envMap;
- texture.dispose();
- pmremGenerator.dispose();
- })
-
- }
-
- function loadHDRCubeMap(dir) {
- var hdrCubeRenderTarget;
- var hdrCubeMap;
- var NhdrUrls = ["px.hdr", "nx.hdr", "py.hdr", "ny.hdr", "pz.hdr", "nz.hdr"];
- var hdrUrls = ["https://cdn.glitch.com/02b1773f-db1a-411a-bc71-ff25644e8e51%2Fpx.hdr?v=1594535462236", "https://cdn.glitch.com/02b1773f-db1a-411a-bc71-ff25644e8e51%2Fnx.hdr?v=1594535462924", "https://cdn.glitch.com/02b1773f-db1a-411a-bc71-ff25644e8e51%2Fpy.hdr?v=1594535455937", "https://cdn.glitch.com/02b1773f-db1a-411a-bc71-ff25644e8e51%2Fny.hdr?v=1594535464928", "https://cdn.glitch.com/02b1773f-db1a-411a-bc71-ff25644e8e51%2Fpz.hdr?v=1594535459665", "https://cdn.glitch.com/02b1773f-db1a-411a-bc71-ff25644e8e51%2Fnz.hdr?v=1594535458938"];
- dir = dir || "";
- //"san_guiseppe_bridge";
- hdrCubeMap = new HDRCubeTextureLoader().setDataType(THREE.UnsignedByteType).load(hdrUrls, function() {
- var pmremGenerator = new THREE.PMREMGenerator(renderer);
-
- hdrCubeRenderTarget = pmremGenerator.fromCubemap(hdrCubeMap);
- pmremGenerator.dispose();
-
- hdrCubeMap.magFilter = THREE.LinearFilter;
- hdrCubeMap.needsUpdate = true;
-
- scene.background = hdrCubeMap;
-
- var newEnvMap = hdrCubeRenderTarget ? hdrCubeRenderTarget.texture : null;
-
- scene.environment = newEnvMap
- });
- return {
- cubeMap: hdrCubeMap,
- cubeRenderTarget: hdrCubeRenderTarget
- };
- }
-
- let hdr = loadHDREquirect();
- //loadHDR();
-
- function mkCanvas(dim) {
- var canvas = document.createElement("canvas");
- canvas.width = canvas.height = dim;
- return canvas;
- }
- this.mkCanvas = mkCanvas;
- function makeProceduralTexture(dim, fn) {
- var canv = mkCanvas(dim);
- var ctx = canv.getContext("2d");
- var pix = ctx.getImageData(0, 0, dim, dim);
- var u32view = new DataView(pix.data.buffer);
- var idx = -4;
- for (var j = 0; j < dim; j++)
- for (var i = 0; i < dim; i++)
- u32view.setUint32((idx += 4), fn(j / dim, i / dim) | 0);
- ctx.putImageData(pix, 0, 0);
- var tex = new THREE.Texture(canv);
- tex.needsUpdate = true;
- return tex;
- }
- var tx = makeProceduralTexture(1024, (u,v)=>{
- var rb = ((Math.random() * 128) | 0) * ((((u * 2) & 1) ^ ((v * 2) & 1)) | 0 ? 1 : 2);
- return ((rb * 256) | (rb * 256 * 256) | (rb * 256 * 256 * 256) | 0x000000ff);
- }
- );
- tx.repeat.set(2, 2);
- tx.wrapS = tx.wrapT = THREE.RepeatWrapping;
- this.makeProceduralTexture = makeProceduralTexture
-
- let mkMat = (color='white')=>new THREE.MeshStandardMaterial({
- color: color,
- roughness: 0.51,
- metalness: 0.7,
- roughnessMap: tx
- });
-
- this.mkMat = Environment.mkMat = mkMat;
-
- let rnd = rng=>(Math.random() * 2 - 1) * (rng || 1);
-
-
- let light1 = new THREE.DirectionalLight();
- light1.position.set(2.8, 12, -15);
- light1.position.set(10, 12, 10);
- light1.castShadow = true;
- var setShadowSize = (sz,mapSz)=>{
- light1.shadow.camera.left = sz;
- light1.shadow.camera.bottom = sz;
- light1.shadow.camera.right = -sz;
- light1.shadow.camera.top = -sz;
- if (mapSz) {
- light1.shadow.mapSize.set(mapSz, mapSz);
- }
- }
- ;
- setShadowSize(20, 2048);
- scene.add(light1);
- light1.shadow.bias = -.0001
-
- //light1.shadow.bias=-0.0001
- let ground = new THREE.Mesh(new THREE.BoxGeometry(2000,1,2000),mkMat("grey"));
- scene.add(ground);
- ground.position.y -= 2.;
- ground.name = "ground";
- ground.receiveShadow = true;
- ground.material.roughnessMap = ground.material.roughnessMap.clone();
- ground.material.roughnessMap.repeat.set(80, 80);
- ground.material.roughnessMap.needsUpdate = true;
- ground.material.color.set(0x101010)
- ground.material.metalness = 0.2;
- ground.material.roughness = .9;
-
- }
-}
-
-export default Environment;
diff --git a/test/csg-lib.js b/test/csg-lib.js
deleted file mode 100644
index c9fb043..0000000
--- a/test/csg-lib.js
+++ /dev/null
@@ -1,482 +0,0 @@
-
-// ## License
-//
-// Copyright (c) 2011 Evan Wallace (http://madebyevan.com/), under the MIT license.
-// THREE.js rework by thrax
-
-// # class CSG
-// Holds a binary space partition tree representing a 3D solid. Two solids can
-// be combined using the `union()`, `subtract()`, and `intersect()` methods.
-
-
-class CSG {
- constructor() {
- this.polygons = [];
- }
- clone() {
- let csg = new CSG();
- csg.polygons = this.polygons.map(p=>p.clone())
- return csg;
- }
-
- toPolygons() {
- return this.polygons;
- }
-
- union(csg) {
- let a = new Node(this.clone().polygons);
- let b = new Node(csg.clone().polygons);
- a.clipTo(b);
- b.clipTo(a);
- b.invert();
- b.clipTo(a);
- b.invert();
- a.build(b.allPolygons());
- return CSG.fromPolygons(a.allPolygons());
- }
-
- subtract(csg) {
- let a = new Node(this.clone().polygons);
- let b = new Node(csg.clone().polygons);
- a.invert();
- a.clipTo(b);
- b.clipTo(a);
- b.invert();
- b.clipTo(a);
- b.invert();
- a.build(b.allPolygons());
- a.invert();
- return CSG.fromPolygons(a.allPolygons());
- }
-
- intersect(csg) {
- let a = new Node(this.clone().polygons);
- let b = new Node(csg.clone().polygons);
- a.invert();
- b.clipTo(a);
- b.invert();
- a.clipTo(b);
- b.clipTo(a);
- a.build(b.allPolygons());
- a.invert();
- return CSG.fromPolygons(a.allPolygons());
- }
-
- // Return a new CSG solid with solid and empty space switched. This solid is
- // not modified.
- inverse() {
- let csg = this.clone();
- csg.polygons.forEach(p=>p.flip());
- return csg;
- }
-}
-
-// Construct a CSG solid from a list of `Polygon` instances.
-CSG.fromPolygons=function(polygons) {
- let csg = new CSG();
- csg.polygons = polygons;
- return csg;
-}
-
-// # class Vector
-
-// Represents a 3D vector.
-//
-// Example usage:
-//
-// new CSG.Vector(1, 2, 3);
-
-
-
-class Vector {
- constructor(x=0, y=0, z=0) {
- this.x=x;
- this.y=y;
- this.z=z;
- }
- copy(v){
- this.x=v.x;
- this.y=v.y;
- this.z=v.z;
- return this
- }
- clone() {
- return new Vector(this.x,this.y,this.z)
- }
- negate() {
- this.x*=-1;
- this.y*=-1;
- this.z*=-1;
- return this
- }
- add(a) {
- this.x+=a.x
- this.y+=a.y
- this.z+=a.z
- return this;
- }
- sub(a) {
- this.x-=a.x
- this.y-=a.y
- this.z-=a.z
- return this
- }
- times(a) {
- this.x*=a
- this.y*=a
- this.z*=a
- return this
- }
- dividedBy(a) {
- this.x/=a
- this.y/=a
- this.z/=a
- return this
- }
- lerp(a, t) {
- return this.add(tv0.copy(a).sub(this).times(t))
- }
- unit() {
- return this.dividedBy(this.length())
- }
- length(){
- return Math.sqrt((this.x**2)+(this.y**2)+(this.z**2))
- }
- normalize(){
- return this.unit()
- }
- cross(b) {
- let a = this;
- const ax = a.x, ay = a.y, az = a.z;
- const bx = b.x, by = b.y, bz = b.z;
-
- this.x = ay * bz - az * by;
- this.y = az * bx - ax * bz;
- this.z = ax * by - ay * bx;
-
- return this;
- }
- dot(b){
- return (this.x*b.x)+(this.y*b.y)+(this.z*b.z)
- }
-}
-
-//Temporaries used to avoid internal allocation..
-let tv0=new Vector()
-let tv1=new Vector()
-
-
-// # class Vertex
-
-// Represents a vertex of a polygon. Use your own vertex class instead of this
-// one to provide additional features like texture coordinates and vertex
-// colors. Custom vertex classes need to provide a `pos` property and `clone()`,
-// `flip()`, and `interpolate()` methods that behave analogous to the ones
-// defined by `CSG.Vertex`. This class provides `normal` so convenience
-// functions like `CSG.sphere()` can return a smooth vertex normal, but `normal`
-// is not used anywhere else.
-
-class Vertex {
-
- constructor(pos, normal, uv, color) {
- this.pos = new Vector().copy(pos);
- this.normal = new Vector().copy(normal);
- uv && (this.uv = new Vector().copy(uv)) && (this.uv.z=0);
- color && (this.color = new Vector().copy(color));
- }
-
- clone() {
- return new Vertex(this.pos,this.normal,this.uv,this.color);
- }
-
- // Invert all orientation-specific data (e.g. vertex normal). Called when the
- // orientation of a polygon is flipped.
- flip() {
- this.normal.negate();
- }
-
- // Create a new vertex between this vertex and `other` by linearly
- // interpolating all properties using a parameter of `t`. Subclasses should
- // override this to interpolate additional properties.
- interpolate(other, t) {
- return new Vertex(this.pos.clone().lerp(other.pos, t),this.normal.clone().lerp(other.normal, t),this.uv&&other.uv&&this.uv.clone().lerp(other.uv, t), this.color&&other.color&&this.color.clone().lerp(other.color,t))
- }
-}
-;
-// # class Plane
-
-// Represents a plane in 3D space.
-
-class Plane {
- constructor(normal, w) {
- this.normal = normal;
- this.w = w;
- }
-
- clone() {
- return new Plane(this.normal.clone(),this.w);
- }
-
- flip() {
- this.normal.negate();
- this.w = -this.w;
- }
-
- // Split `polygon` by this plane if needed, then put the polygon or polygon
- // fragments in the appropriate lists. Coplanar polygons go into either
- // `coplanarFront` or `coplanarBack` depending on their orientation with
- // respect to this plane. Polygons in front or in back of this plane go into
- // either `front` or `back`.
- splitPolygon(polygon, coplanarFront, coplanarBack, front, back) {
- const COPLANAR = 0;
- const FRONT = 1;
- const BACK = 2;
- const SPANNING = 3;
-
- // Classify each point as well as the entire polygon into one of the above
- // four classes.
- let polygonType = 0;
- let types = [];
- for (let i = 0; i < polygon.vertices.length; i++) {
- let t = this.normal.dot(polygon.vertices[i].pos) - this.w;
- let type = (t < -Plane.EPSILON) ? BACK : (t > Plane.EPSILON) ? FRONT : COPLANAR;
- polygonType |= type;
- types.push(type);
- }
-
- // Put the polygon in the correct list, splitting it when necessary.
- switch (polygonType) {
- case COPLANAR:
- (this.normal.dot(polygon.plane.normal) > 0 ? coplanarFront : coplanarBack).push(polygon);
- break;
- case FRONT:
- front.push(polygon);
- break;
- case BACK:
- back.push(polygon);
- break;
- case SPANNING:
- let f = []
- , b = [];
- for (let i = 0; i < polygon.vertices.length; i++) {
- let j = (i + 1) % polygon.vertices.length;
- let ti = types[i]
- , tj = types[j];
- let vi = polygon.vertices[i]
- , vj = polygon.vertices[j];
- if (ti != BACK)
- f.push(vi);
- if (ti != FRONT)
- b.push(ti != BACK ? vi.clone() : vi);
- if ((ti | tj) == SPANNING) {
- let t = (this.w - this.normal.dot(vi.pos)) / this.normal.dot(tv0.copy(vj.pos).sub(vi.pos));
- let v = vi.interpolate(vj, t);
- f.push(v);
- b.push(v.clone());
- }
- }
- if (f.length >= 3)
- front.push(new Polygon(f,polygon.shared));
- if (b.length >= 3)
- back.push(new Polygon(b,polygon.shared));
- break;
- }
- }
-
-}
-
-// `Plane.EPSILON` is the tolerance used by `splitPolygon()` to decide if a
-// point is on the plane.
-Plane.EPSILON = 1e-5;
-
-Plane.fromPoints = function(a, b, c) {
- let n = tv0.copy(b).sub(a).cross(tv1.copy(c).sub(a)).normalize()
- return new Plane(n.clone(),n.dot(a));
-}
-
-
-// # class Polygon
-
-// Represents a convex polygon. The vertices used to initialize a polygon must
-// be coplanar and form a convex loop. They do not have to be `Vertex`
-// instances but they must behave similarly (duck typing can be used for
-// customization).
-//
-// Each convex polygon has a `shared` property, which is shared between all
-// polygons that are clones of each other or were split from the same polygon.
-// This can be used to define per-polygon properties (such as surface color).
-
-class Polygon {
- constructor(vertices, shared) {
- this.vertices = vertices;
- this.shared = shared;
- this.plane = Plane.fromPoints(vertices[0].pos, vertices[1].pos, vertices[2].pos);
- }
- clone() {
- return new Polygon(this.vertices.map(v=>v.clone()),this.shared);
- }
- flip() {
- this.vertices.reverse().forEach(v=>v.flip())
- this.plane.flip();
- }
-}
-
-// # class Node
-
-// Holds a node in a BSP tree. A BSP tree is built from a collection of polygons
-// by picking a polygon to split along. That polygon (and all other coplanar
-// polygons) are added directly to that node and the other polygons are added to
-// the front and/or back subtrees. This is not a leafy BSP tree since there is
-// no distinction between internal and leaf nodes.
-
-class Node {
- constructor(polygons) {
- this.plane = null;
- this.front = null;
- this.back = null;
- this.polygons = [];
- if (polygons)
- this.build(polygons);
- }
- clone() {
- let node = new Node();
- node.plane = this.plane && this.plane.clone();
- node.front = this.front && this.front.clone();
- node.back = this.back && this.back.clone();
- node.polygons = this.polygons.map(p=>p.clone());
- return node;
- }
-
- // Convert solid space to empty space and empty space to solid space.
- invert() {
- for (let i = 0; i < this.polygons.length; i++)
- this.polygons[i].flip();
-
- this.plane && this.plane.flip();
- this.front && this.front.invert();
- this.back && this.back.invert();
- let temp = this.front;
- this.front = this.back;
- this.back = temp;
- }
-
- // Recursively remove all polygons in `polygons` that are inside this BSP
- // tree.
- clipPolygons(polygons) {
- if (!this.plane)
- return polygons.slice();
- let front = []
- , back = [];
-
- for (let i = 0; i < polygons.length; i++) {
- this.plane.splitPolygon(polygons[i], front, back, front, back);
- }
- if (this.front)
- front = this.front.clipPolygons(front);
- if (this.back)
- back = this.back.clipPolygons(back);
- else
- back = [];
- //return front;
- return front.concat(back);
- }
-
- // Remove all polygons in this BSP tree that are inside the other BSP tree
- // `bsp`.
- clipTo(bsp) {
- this.polygons = bsp.clipPolygons(this.polygons);
- if (this.front)
- this.front.clipTo(bsp);
- if (this.back)
- this.back.clipTo(bsp);
- }
-
- // Return a list of all polygons in this BSP tree.
- allPolygons() {
- let polygons = this.polygons.slice();
- if (this.front)
- polygons = polygons.concat(this.front.allPolygons());
- if (this.back)
- polygons = polygons.concat(this.back.allPolygons());
- return polygons;
- }
-
- // Build a BSP tree out of `polygons`. When called on an existing tree, the
- // new polygons are filtered down to the bottom of the tree and become new
- // nodes there. Each set of polygons is partitioned using the first polygon
- // (no heuristic is used to pick a good split).
- build(polygons) {
- if (!polygons.length)
- return;
- if (!this.plane)
- this.plane = polygons[0].plane.clone();
- let front = []
- , back = [];
- for (let i = 0; i < polygons.length; i++) {
- this.plane.splitPolygon(polygons[i], this.polygons, this.polygons, front, back);
- }
- if (front.length) {
- if (!this.front)
- this.front = new Node();
- this.front.build(front);
- }
- if (back.length) {
- if (!this.back)
- this.back = new Node();
- this.back.build(back);
- }
- }
-}
-
-// Inflate/deserialize a vanilla struct into a CSG structure webworker.
-CSG.fromJSON=function(json){
- return CSG.fromPolygons(json.polygons.map(p=>new Polygon(p.vertices.map(v=> new Vertex(v.pos,v.normal,v.uv)),p.shared)))
-}
-
-export {CSG,Vertex,Vector,Polygon,Plane}
-
-
-
-// Return a new CSG solid representing space in either this solid or in the
-// solid `csg`. Neither this solid nor the solid `csg` are modified.
-//
-// A.union(B)
-//
-// +-------+ +-------+
-// | | | |
-// | A | | |
-// | +--+----+ = | +----+
-// +----+--+ | +----+ |
-// | B | | |
-// | | | |
-// +-------+ +-------+
-//
-// Return a new CSG solid representing space in this solid but not in the
-// solid `csg`. Neither this solid nor the solid `csg` are modified.
-//
-// A.subtract(B)
-//
-// +-------+ +-------+
-// | | | |
-// | A | | |
-// | +--+----+ = | +--+
-// +----+--+ | +----+
-// | B |
-// | |
-// +-------+
-//
-// Return a new CSG solid representing space both this solid and in the
-// solid `csg`. Neither this solid nor the solid `csg` are modified.
-//
-// A.intersect(B)
-//
-// +-------+
-// | |
-// | A |
-// | +--+----+ = +--+
-// +----+--+ | +--+
-// | B |
-// | |
-// +-------+
-//
-
diff --git a/test/csg-worker.js b/test/csg-worker.js
deleted file mode 100644
index a76ad2c..0000000
--- a/test/csg-worker.js
+++ /dev/null
@@ -1,76 +0,0 @@
-import {CSG} from "./csg-lib.js"
-
-
-let gWorkersStarted = false;
-let gWorker;
-let gWorkerUrl;
-
-let taskId = 0;
-let tasks={}
-let spawnWorker=()=>{
- const worker = new Worker(gWorkerUrl)
-
- worker.onmessage = function(e) {
- let rslt = JSON.parse(e.data)
- let task = tasks[rslt.taskId]
- delete tasks[rslt.taskId]
- task.resolve(CSG.fromJSON(rslt.result))
- //console.log('Message received from worker');
- gWorker.busy = false;
- }
- return gWorker = {worker,busy:false};
-}
-
-let getWorker=()=>{
- if(!gWorkersStarted){
- gWorkersStarted = true;
- return fetch('../csg-lib.js').then(function(response) {
- return response.text().then(function(text) {
- text = text.slice(0, text.lastIndexOf('export'));
- const code = text + `
- self.onmessage=(message)=>{
- let task = JSON.parse(message.data)
- //console.log("Got task:"+task.op+' '+task.taskId)
- postMessage(JSON.stringify({
- taskId:task.taskId,
- result : CSG.fromJSON(task.a)[task.op](CSG.fromJSON(task.b))
- }))
- }
- console.log('CSG worker started!')`
- const blob = new Blob([code],{
- type: 'application/javascript'
- })
- gWorkerUrl = URL.createObjectURL(blob);
-
-
- }).then(()=>{
- return spawnWorker()
- })
- });
- }
- if(gWorker && (!gWorker.busy)){
- gWorker.busy = true;
-
- return {then:(fn)=>{return fn(gWorker);}}
- }
- return{
- then:function(){return this}
- }
-}
-
-CSG.doAsync=(a,op,b)=>{
- return getWorker().then((worker)=>{
- let task={a,op,b,taskId}
- tasks[taskId]=task;
- taskId++;
- task.result = new Promise((resolve,reject)=>{
- task.resolve = resolve;
- //console.log("posting to worker:")
- worker.busy = true;
- worker.worker.postMessage(JSON.stringify(task))
- })
- return task.result
- })
-}
-
-export default {}
\ No newline at end of file
diff --git a/test/three-csg.js b/test/three-csg.js
deleted file mode 100644
index afc0f87..0000000
--- a/test/three-csg.js
+++ /dev/null
@@ -1,219 +0,0 @@
-"use strict"
-
-import*as THREE from "three";
-
-
-let { BufferGeometry, Vector3, Vector2} = THREE;
-import {CSG, Vertex, Vector, Polygon} from "./csg-lib.js"
-//import {Geometry} from "../three.js-dev/examples/jsm/deprecated/Geometry.js";
-
-CSG.fromGeometry = function(geom,objectIndex) {
- let polys = []
- if (geom.isGeometry) {
- let fs = geom.faces;
- let vs = geom.vertices;
- let fm = ['a', 'b', 'c']
- for (let i = 0; i < fs.length; i++) {
- let f = fs[i];
- let vertices = []
- for (let j = 0; j < 3; j++)
- vertices.push(new Vertex(vs[f[fm[j]]],f.vertexNormals[j],geom.faceVertexUvs[0][i][j]))
- polys.push(new Polygon(vertices, objectIndex))
- }
- } else if (geom.isBufferGeometry) {
- let vertices, normals, uvs
- let posattr = geom.attributes.position
- let normalattr = geom.attributes.normal
- let uvattr = geom.attributes.uv
- let colorattr = geom.attributes.color
- let index;
- if (geom.index)
- index = geom.index.array;
- else {
- index = new Array((posattr.array.length / posattr.itemSize) | 0);
- for (let i = 0; i < index.length; i++)
- index[i] = i
- }
- let triCount = (index.length / 3) | 0
- polys = new Array(triCount)
- for (let i = 0, pli = 0, l = index.length; i < l; i += 3,
- pli++) {
- let vertices = new Array(3)
- for (let j = 0; j < 3; j++) {
- let vi = index[i + j]
- let vp = vi * 3;
- let vt = vi * 2;
- let x = posattr.array[vp]
- let y = posattr.array[vp + 1]
- let z = posattr.array[vp + 2]
- let nx = normalattr.array[vp]
- let ny = normalattr.array[vp + 1]
- let nz = normalattr.array[vp + 2]
- //let u = uvattr.array[vt]
- //let v = uvattr.array[vt + 1]
- vertices[j] = new Vertex({
- x,
- y,
- z
- },{
- x: nx,
- y: ny,
- z: nz
- },uvattr&&{
- x: uvattr.array[vt],
- y: uvattr.array[vt+1],
- z: 0
- },colorattr&&{x:colorattr.array[vt],y:colorattr.array[vt+1],z:colorattr.array[vt+2]});
- }
- polys[pli] = new Polygon(vertices,objectIndex)
- }
- } else
- console.error("Unsupported CSG input type:" + geom.type)
- return CSG.fromPolygons(polys)
-}
-
-let ttvv0 = new THREE.Vector3()
-let tmpm3 = new THREE.Matrix3();
-CSG.fromMesh = function(mesh,objectIndex) {
- let csg = CSG.fromGeometry(mesh.geometry,objectIndex)
- tmpm3.getNormalMatrix(mesh.matrix);
- for (let i = 0; i < csg.polygons.length; i++) {
- let p = csg.polygons[i]
- for (let j = 0; j < p.vertices.length; j++) {
- let v = p.vertices[j]
- v.pos.copy(ttvv0.copy(v.pos).applyMatrix4(mesh.matrix));
- v.normal.copy(ttvv0.copy(v.normal).applyMatrix3(tmpm3))
- }
- }
- return csg;
-}
-
-let nbuf3=(ct)=>{
- return{
- top:0,
- array:new Float32Array(ct),
- write:function(v){(this.array[this.top++]=v.x);(this.array[this.top++]=v.y);(this.array[this.top++]=v.z);}
- }
-}
-let nbuf2=(ct)=>{
- return{
- top:0,
- array:new Float32Array(ct),
- write:function(v){(this.array[this.top++]=v.x);(this.array[this.top++]=v.y)}
- }
-}
-
-CSG.toGeometry = function(csg, buffered=true) {
- let ps = csg.polygons;
- let geom;
- let g2;
- if(!buffered) //Old geometry path...
- {
- geom = new Geometry();
- let vs = geom.vertices;
- let fvuv = geom.faceVertexUvs[0]
- for (let i = 0; i < ps.length; i++) {
- let p = ps[i]
- let pvs = p.vertices;
- let v0 = vs.length;
- let pvlen = pvs.length
-
- for (let j = 0; j < pvlen; j++)
- vs.push(new THREE.Vector3().copy(pvs[j].pos))
-
- for (let j = 3; j <= pvlen; j++) {
- let fc = new THREE.Face3();
- let fuv = []
- fvuv.push(fuv)
- let fnml = fc.vertexNormals;
- fc.a = v0;
- fc.b = v0 + j - 2;
- fc.c = v0 + j - 1;
-
- fnml.push(new THREE.Vector3().copy(pvs[0].normal))
- fnml.push(new THREE.Vector3().copy(pvs[j - 2].normal))
- fnml.push(new THREE.Vector3().copy(pvs[j - 1].normal))
- fuv.push(new THREE.Vector3().copy(pvs[0].uv))
- fuv.push(new THREE.Vector3().copy(pvs[j - 2].uv))
- fuv.push(new THREE.Vector3().copy(pvs[j - 1].uv))
-
- fc.normal = new THREE.Vector3().copy(p.plane.normal)
- geom.faces.push(fc)
- }
- }
- geom = new THREE.BufferGeometry().fromGeometry(geom)
- geom.verticesNeedUpdate = geom.elementsNeedUpdate = geom.normalsNeedUpdate = true;
- }else { //BufferGeometry path
- let triCount = 0;
- ps.forEach(p=>triCount += (p.vertices.length - 2))
- geom = new THREE.BufferGeometry()
-
- let vertices = nbuf3(triCount * 3 * 3)
- let normals = nbuf3(triCount * 3 * 3)
- let uvs; // = nbuf2(triCount * 2 * 3)
- let colors;
- let grps=[]
- ps.forEach(p=>{
- let pvs = p.vertices
- let pvlen = pvs.length
- if(p.shared!==undefined){
- if(!grps[p.shared])grps[p.shared]=[]
- }
- if(pvlen){
- if(pvs[0].color!==undefined){
- if(!colors)colors = nbuf3(triCount*3*3);
- }
- if(pvs[0].uv!==undefined){
- if(!uvs)uvs = nbuf2(triCount * 2 * 3)
- }
- }
- for (let j = 3; j <= pvlen; j++) {
- (p.shared!==undefined) && (grps[p.shared].push(vertices.top/3,(vertices.top/3)+1,(vertices.top/3)+2));
- vertices.write(pvs[0].pos)
- vertices.write(pvs[j-2].pos)
- vertices.write(pvs[j-1].pos)
- normals.write(pvs[0].normal)
- normals.write(pvs[j-2].normal)
- normals.write(pvs[j-1].normal);
- uvs&&(pvs[0].uv)&&(uvs.write(pvs[0].uv)||uvs.write(pvs[j-2].uv)||uvs.write(pvs[j-1].uv));
- colors&&(colors.write(pvs[0].color)||colors.write(pvs[j-2].color)||colors.write(pvs[j-1].color))
- }
- }
- )
- geom.setAttribute('position', new THREE.BufferAttribute(vertices.array,3));
- geom.setAttribute('normal', new THREE.BufferAttribute(normals.array,3));
- uvs && geom.setAttribute('uv', new THREE.BufferAttribute(uvs.array,2));
- colors && geom.setAttribute('color', new THREE.BufferAttribute(colors.array,3));
- if(grps.length){
- let index = []
- let gbase=0;
- for(let gi=0;gi splitDist ) {
-
- splitDist = dist;
- splitDimIdx = i;
-
- }
-
- }
-
- return splitDimIdx;
-
-}
-
-// copys bounds a into bounds b
-function copyBounds( source, target ) {
-
- target.set( source );
-
-}
-
-// sets bounds target to the union of bounds a and b
-function unionBounds( a, b, target ) {
-
- let aVal, bVal;
- for ( let d = 0; d < 3; d ++ ) {
-
- const d3 = d + 3;
-
- // set the minimum values
- aVal = a[ d ];
- bVal = b[ d ];
- target[ d ] = aVal < bVal ? aVal : bVal;
-
- // set the max values
- aVal = a[ d3 ];
- bVal = b[ d3 ];
- target[ d3 ] = aVal > bVal ? aVal : bVal;
-
- }
-
-}
-
-// expands the given bounds by the provided triangle bounds
-function expandByTriangleBounds( startIndex, triangleBounds, bounds ) {
-
- for ( let d = 0; d < 3; d ++ ) {
-
- const tCenter = triangleBounds[ startIndex + 2 * d ];
- const tHalf = triangleBounds[ startIndex + 2 * d + 1 ];
-
- const tMin = tCenter - tHalf;
- const tMax = tCenter + tHalf;
-
- if ( tMin < bounds[ d ] ) {
-
- bounds[ d ] = tMin;
-
- }
-
- if ( tMax > bounds[ d + 3 ] ) {
-
- bounds[ d + 3 ] = tMax;
-
- }
-
- }
-
-}
-
-// compute bounds surface area
-function computeSurfaceArea( bounds ) {
-
- const d0 = bounds[ 3 ] - bounds[ 0 ];
- const d1 = bounds[ 4 ] - bounds[ 1 ];
- const d2 = bounds[ 5 ] - bounds[ 2 ];
-
- return 2 * ( d0 * d1 + d1 * d2 + d2 * d0 );
-
-}
-
-function ensureIndex( geo, options ) {
-
- if ( ! geo.index ) {
-
- const vertexCount = geo.attributes.position.count;
- const BufferConstructor = options.useSharedArrayBuffer ? SharedArrayBuffer : ArrayBuffer;
- let index;
- if ( vertexCount > 65535 ) {
-
- index = new Uint32Array( new BufferConstructor( 4 * vertexCount ) );
-
- } else {
-
- index = new Uint16Array( new BufferConstructor( 2 * vertexCount ) );
-
- }
-
- geo.setIndex( new BufferAttribute( index, 1 ) );
-
- for ( let i = 0; i < vertexCount; i ++ ) {
-
- index[ i ] = i;
-
- }
-
- }
-
-}
-
-// Computes the set of { offset, count } ranges which need independent BVH roots. Each
-// region in the geometry index that belongs to a different set of material groups requires
-// a separate BVH root, so that triangles indices belonging to one group never get swapped
-// with triangle indices belongs to another group. For example, if the groups were like this:
-//
-// [-------------------------------------------------------------]
-// |__________________|
-// g0 = [0, 20] |______________________||_____________________|
-// g1 = [16, 40] g2 = [41, 60]
-//
-// we would need four BVH roots: [0, 15], [16, 20], [21, 40], [41, 60].
-function getRootIndexRanges( geo ) {
-
- if ( ! geo.groups || ! geo.groups.length ) {
-
- return [ { offset: 0, count: geo.index.count / 3 } ];
-
- }
-
- const ranges = [];
- const rangeBoundaries = new Set();
- for ( const group of geo.groups ) {
-
- rangeBoundaries.add( group.start );
- rangeBoundaries.add( group.start + group.count );
-
- }
-
- // note that if you don't pass in a comparator, it sorts them lexicographically as strings :-(
- const sortedBoundaries = Array.from( rangeBoundaries.values() ).sort( ( a, b ) => a - b );
- for ( let i = 0; i < sortedBoundaries.length - 1; i ++ ) {
-
- const start = sortedBoundaries[ i ], end = sortedBoundaries[ i + 1 ];
- ranges.push( { offset: ( start / 3 ), count: ( end - start ) / 3 } );
-
- }
-
- return ranges;
-
-}
-
-// computes the union of the bounds of all of the given triangles and puts the resulting box in target. If
-// centroidTarget is provided then a bounding box is computed for the centroids of the triangles, as well.
-// These are computed together to avoid redundant accesses to bounds array.
-function getBounds( triangleBounds, offset, count, target, centroidTarget = null ) {
-
- let minx = Infinity;
- let miny = Infinity;
- let minz = Infinity;
- let maxx = - Infinity;
- let maxy = - Infinity;
- let maxz = - Infinity;
-
- let cminx = Infinity;
- let cminy = Infinity;
- let cminz = Infinity;
- let cmaxx = - Infinity;
- let cmaxy = - Infinity;
- let cmaxz = - Infinity;
-
- const includeCentroid = centroidTarget !== null;
- for ( let i = offset * 6, end = ( offset + count ) * 6; i < end; i += 6 ) {
-
- const cx = triangleBounds[ i + 0 ];
- const hx = triangleBounds[ i + 1 ];
- const lx = cx - hx;
- const rx = cx + hx;
- if ( lx < minx ) minx = lx;
- if ( rx > maxx ) maxx = rx;
- if ( includeCentroid && cx < cminx ) cminx = cx;
- if ( includeCentroid && cx > cmaxx ) cmaxx = cx;
-
- const cy = triangleBounds[ i + 2 ];
- const hy = triangleBounds[ i + 3 ];
- const ly = cy - hy;
- const ry = cy + hy;
- if ( ly < miny ) miny = ly;
- if ( ry > maxy ) maxy = ry;
- if ( includeCentroid && cy < cminy ) cminy = cy;
- if ( includeCentroid && cy > cmaxy ) cmaxy = cy;
-
- const cz = triangleBounds[ i + 4 ];
- const hz = triangleBounds[ i + 5 ];
- const lz = cz - hz;
- const rz = cz + hz;
- if ( lz < minz ) minz = lz;
- if ( rz > maxz ) maxz = rz;
- if ( includeCentroid && cz < cminz ) cminz = cz;
- if ( includeCentroid && cz > cmaxz ) cmaxz = cz;
-
- }
-
- target[ 0 ] = minx;
- target[ 1 ] = miny;
- target[ 2 ] = minz;
-
- target[ 3 ] = maxx;
- target[ 4 ] = maxy;
- target[ 5 ] = maxz;
-
- if ( includeCentroid ) {
-
- centroidTarget[ 0 ] = cminx;
- centroidTarget[ 1 ] = cminy;
- centroidTarget[ 2 ] = cminz;
-
- centroidTarget[ 3 ] = cmaxx;
- centroidTarget[ 4 ] = cmaxy;
- centroidTarget[ 5 ] = cmaxz;
-
- }
-
-}
-
-// A stand alone function for retrieving the centroid bounds.
-function getCentroidBounds( triangleBounds, offset, count, centroidTarget ) {
-
- let cminx = Infinity;
- let cminy = Infinity;
- let cminz = Infinity;
- let cmaxx = - Infinity;
- let cmaxy = - Infinity;
- let cmaxz = - Infinity;
-
- for ( let i = offset * 6, end = ( offset + count ) * 6; i < end; i += 6 ) {
-
- const cx = triangleBounds[ i + 0 ];
- if ( cx < cminx ) cminx = cx;
- if ( cx > cmaxx ) cmaxx = cx;
-
- const cy = triangleBounds[ i + 2 ];
- if ( cy < cminy ) cminy = cy;
- if ( cy > cmaxy ) cmaxy = cy;
-
- const cz = triangleBounds[ i + 4 ];
- if ( cz < cminz ) cminz = cz;
- if ( cz > cmaxz ) cmaxz = cz;
-
- }
-
- centroidTarget[ 0 ] = cminx;
- centroidTarget[ 1 ] = cminy;
- centroidTarget[ 2 ] = cminz;
-
- centroidTarget[ 3 ] = cmaxx;
- centroidTarget[ 4 ] = cmaxy;
- centroidTarget[ 5 ] = cmaxz;
-
-}
-
-
-// reorders `tris` such that for `count` elements after `offset`, elements on the left side of the split
-// will be on the left and elements on the right side of the split will be on the right. returns the index
-// of the first element on the right side, or offset + count if there are no elements on the right side.
-function partition( index, triangleBounds, offset, count, split ) {
-
- let left = offset;
- let right = offset + count - 1;
- const pos = split.pos;
- const axisOffset = split.axis * 2;
-
- // hoare partitioning, see e.g. https://en.wikipedia.org/wiki/Quicksort#Hoare_partition_scheme
- while ( true ) {
-
- while ( left <= right && triangleBounds[ left * 6 + axisOffset ] < pos ) {
-
- left ++;
-
- }
-
-
- // if a triangle center lies on the partition plane it is considered to be on the right side
- while ( left <= right && triangleBounds[ right * 6 + axisOffset ] >= pos ) {
-
- right --;
-
- }
-
- if ( left < right ) {
-
- // we need to swap all of the information associated with the triangles at index
- // left and right; that's the verts in the geometry index, the bounds,
- // and perhaps the SAH planes
-
- for ( let i = 0; i < 3; i ++ ) {
-
- let t0 = index[ left * 3 + i ];
- index[ left * 3 + i ] = index[ right * 3 + i ];
- index[ right * 3 + i ] = t0;
-
- let t1 = triangleBounds[ left * 6 + i * 2 + 0 ];
- triangleBounds[ left * 6 + i * 2 + 0 ] = triangleBounds[ right * 6 + i * 2 + 0 ];
- triangleBounds[ right * 6 + i * 2 + 0 ] = t1;
-
- let t2 = triangleBounds[ left * 6 + i * 2 + 1 ];
- triangleBounds[ left * 6 + i * 2 + 1 ] = triangleBounds[ right * 6 + i * 2 + 1 ];
- triangleBounds[ right * 6 + i * 2 + 1 ] = t2;
-
- }
-
- left ++;
- right --;
-
- } else {
-
- return left;
-
- }
-
- }
-
-}
-
-const BIN_COUNT = 32;
-const binsSort = ( a, b ) => a.candidate - b.candidate;
-const sahBins = new Array( BIN_COUNT ).fill().map( () => {
-
- return {
-
- count: 0,
- bounds: new Float32Array( 6 ),
- rightCacheBounds: new Float32Array( 6 ),
- leftCacheBounds: new Float32Array( 6 ),
- candidate: 0,
-
- };
-
-} );
-const leftBounds = new Float32Array( 6 );
-
-function getOptimalSplit( nodeBoundingData, centroidBoundingData, triangleBounds, offset, count, strategy ) {
-
- let axis = - 1;
- let pos = 0;
-
- // Center
- if ( strategy === CENTER ) {
-
- axis = getLongestEdgeIndex( centroidBoundingData );
- if ( axis !== - 1 ) {
-
- pos = ( centroidBoundingData[ axis ] + centroidBoundingData[ axis + 3 ] ) / 2;
-
- }
-
- } else if ( strategy === AVERAGE ) {
-
- axis = getLongestEdgeIndex( nodeBoundingData );
- if ( axis !== - 1 ) {
-
- pos = getAverage( triangleBounds, offset, count, axis );
-
- }
-
- } else if ( strategy === SAH ) {
-
- const rootSurfaceArea = computeSurfaceArea( nodeBoundingData );
- let bestCost = TRIANGLE_INTERSECT_COST * count;
-
- // iterate over all axes
- const cStart = offset * 6;
- const cEnd = ( offset + count ) * 6;
- for ( let a = 0; a < 3; a ++ ) {
-
- const axisLeft = centroidBoundingData[ a ];
- const axisRight = centroidBoundingData[ a + 3 ];
- const axisLength = axisRight - axisLeft;
- const binWidth = axisLength / BIN_COUNT;
-
- // If we have fewer triangles than we're planning to split then just check all
- // the triangle positions because it will be faster.
- if ( count < BIN_COUNT / 4 ) {
-
- // initialize the bin candidates
- const truncatedBins = [ ...sahBins ];
- truncatedBins.length = count;
-
- // set the candidates
- let b = 0;
- for ( let c = cStart; c < cEnd; c += 6, b ++ ) {
-
- const bin = truncatedBins[ b ];
- bin.candidate = triangleBounds[ c + 2 * a ];
- bin.count = 0;
-
- const {
- bounds,
- leftCacheBounds,
- rightCacheBounds,
- } = bin;
- for ( let d = 0; d < 3; d ++ ) {
-
- rightCacheBounds[ d ] = Infinity;
- rightCacheBounds[ d + 3 ] = - Infinity;
-
- leftCacheBounds[ d ] = Infinity;
- leftCacheBounds[ d + 3 ] = - Infinity;
-
- bounds[ d ] = Infinity;
- bounds[ d + 3 ] = - Infinity;
-
- }
-
- expandByTriangleBounds( c, triangleBounds, bounds );
-
- }
-
- truncatedBins.sort( binsSort );
-
- // remove redundant splits
- let splitCount = count;
- for ( let bi = 0; bi < splitCount; bi ++ ) {
-
- const bin = truncatedBins[ bi ];
- while ( bi + 1 < splitCount && truncatedBins[ bi + 1 ].candidate === bin.candidate ) {
-
- truncatedBins.splice( bi + 1, 1 );
- splitCount --;
-
- }
-
- }
-
- // find the appropriate bin for each triangle and expand the bounds.
- for ( let c = cStart; c < cEnd; c += 6 ) {
-
- const center = triangleBounds[ c + 2 * a ];
- for ( let bi = 0; bi < splitCount; bi ++ ) {
-
- const bin = truncatedBins[ bi ];
- if ( center >= bin.candidate ) {
-
- expandByTriangleBounds( c, triangleBounds, bin.rightCacheBounds );
-
- } else {
-
- expandByTriangleBounds( c, triangleBounds, bin.leftCacheBounds );
- bin.count ++;
-
- }
-
- }
-
- }
-
- // expand all the bounds
- for ( let bi = 0; bi < splitCount; bi ++ ) {
-
- const bin = truncatedBins[ bi ];
- const leftCount = bin.count;
- const rightCount = count - bin.count;
-
- // check the cost of this split
- const leftBounds = bin.leftCacheBounds;
- const rightBounds = bin.rightCacheBounds;
-
- let leftProb = 0;
- if ( leftCount !== 0 ) {
-
- leftProb = computeSurfaceArea( leftBounds ) / rootSurfaceArea;
-
- }
-
- let rightProb = 0;
- if ( rightCount !== 0 ) {
-
- rightProb = computeSurfaceArea( rightBounds ) / rootSurfaceArea;
-
- }
-
- const cost = TRAVERSAL_COST + TRIANGLE_INTERSECT_COST * (
- leftProb * leftCount + rightProb * rightCount
- );
-
- if ( cost < bestCost ) {
-
- axis = a;
- bestCost = cost;
- pos = bin.candidate;
-
- }
-
- }
-
- } else {
-
- // reset the bins
- for ( let i = 0; i < BIN_COUNT; i ++ ) {
-
- const bin = sahBins[ i ];
- bin.count = 0;
- bin.candidate = axisLeft + binWidth + i * binWidth;
-
- const bounds = bin.bounds;
- for ( let d = 0; d < 3; d ++ ) {
-
- bounds[ d ] = Infinity;
- bounds[ d + 3 ] = - Infinity;
-
- }
-
- }
-
- // iterate over all center positions
- for ( let c = cStart; c < cEnd; c += 6 ) {
-
- const triCenter = triangleBounds[ c + 2 * a ];
- const relativeCenter = triCenter - axisLeft;
-
- // in the partition function if the centroid lies on the split plane then it is
- // considered to be on the right side of the split
- let binIndex = ~ ~ ( relativeCenter / binWidth );
- if ( binIndex >= BIN_COUNT ) binIndex = BIN_COUNT - 1;
-
- const bin = sahBins[ binIndex ];
- bin.count ++;
-
- expandByTriangleBounds( c, triangleBounds, bin.bounds );
-
- }
-
- // cache the unioned bounds from right to left so we don't have to regenerate them each time
- const lastBin = sahBins[ BIN_COUNT - 1 ];
- copyBounds( lastBin.bounds, lastBin.rightCacheBounds );
- for ( let i = BIN_COUNT - 2; i >= 0; i -- ) {
-
- const bin = sahBins[ i ];
- const nextBin = sahBins[ i + 1 ];
- unionBounds( bin.bounds, nextBin.rightCacheBounds, bin.rightCacheBounds );
-
- }
-
- let leftCount = 0;
- for ( let i = 0; i < BIN_COUNT - 1; i ++ ) {
-
- const bin = sahBins[ i ];
- const binCount = bin.count;
- const bounds = bin.bounds;
-
- const nextBin = sahBins[ i + 1 ];
- const rightBounds = nextBin.rightCacheBounds;
-
- // dont do anything with the bounds if the new bounds have no triangles
- if ( binCount !== 0 ) {
-
- if ( leftCount === 0 ) {
-
- copyBounds( bounds, leftBounds );
-
- } else {
-
- unionBounds( bounds, leftBounds, leftBounds );
-
- }
-
- }
-
- leftCount += binCount;
-
- // check the cost of this split
- let leftProb = 0;
- let rightProb = 0;
-
- if ( leftCount !== 0 ) {
-
- leftProb = computeSurfaceArea( leftBounds ) / rootSurfaceArea;
-
- }
-
- const rightCount = count - leftCount;
- if ( rightCount !== 0 ) {
-
- rightProb = computeSurfaceArea( rightBounds ) / rootSurfaceArea;
-
- }
-
- const cost = TRAVERSAL_COST + TRIANGLE_INTERSECT_COST * (
- leftProb * leftCount + rightProb * rightCount
- );
-
- if ( cost < bestCost ) {
-
- axis = a;
- bestCost = cost;
- pos = bin.candidate;
-
- }
-
- }
-
- }
-
- }
-
- } else {
-
- console.warn( `MeshBVH: Invalid build strategy value ${ strategy } used.` );
-
- }
-
- return { axis, pos };
-
-}
-
-// returns the average coordinate on the specified axis of the all the provided triangles
-function getAverage( triangleBounds, offset, count, axis ) {
-
- let avg = 0;
- for ( let i = offset, end = offset + count; i < end; i ++ ) {
-
- avg += triangleBounds[ i * 6 + axis * 2 ];
-
- }
-
- return avg / count;
-
-}
-
-// precomputes the bounding box for each triangle; required for quickly calculating tree splits.
-// result is an array of size tris.length * 6 where triangle i maps to a
-// [x_center, x_delta, y_center, y_delta, z_center, z_delta] tuple starting at index i * 6,
-// representing the center and half-extent in each dimension of triangle i
-function computeTriangleBounds( geo, fullBounds ) {
-
- const posAttr = geo.attributes.position;
- const posArr = posAttr.array;
- const index = geo.index.array;
- const triCount = index.length / 3;
- const triangleBounds = new Float32Array( triCount * 6 );
-
- // support for an interleaved position buffer
- const bufferOffset = posAttr.offset || 0;
- let stride = 3;
- if ( posAttr.isInterleavedBufferAttribute ) {
-
- stride = posAttr.data.stride;
-
- }
-
- for ( let tri = 0; tri < triCount; tri ++ ) {
-
- const tri3 = tri * 3;
- const tri6 = tri * 6;
- const ai = index[ tri3 + 0 ] * stride + bufferOffset;
- const bi = index[ tri3 + 1 ] * stride + bufferOffset;
- const ci = index[ tri3 + 2 ] * stride + bufferOffset;
-
- for ( let el = 0; el < 3; el ++ ) {
-
- const a = posArr[ ai + el ];
- const b = posArr[ bi + el ];
- const c = posArr[ ci + el ];
-
- let min = a;
- if ( b < min ) min = b;
- if ( c < min ) min = c;
-
- let max = a;
- if ( b > max ) max = b;
- if ( c > max ) max = c;
-
- // Increase the bounds size by float32 epsilon to avoid precision errors when
- // converting to 32 bit float. Scale the epsilon by the size of the numbers being
- // worked with.
- const halfExtents = ( max - min ) / 2;
- const el2 = el * 2;
- triangleBounds[ tri6 + el2 + 0 ] = min + halfExtents;
- triangleBounds[ tri6 + el2 + 1 ] = halfExtents + ( Math.abs( min ) + halfExtents ) * FLOAT32_EPSILON;
-
- if ( min < fullBounds[ el ] ) fullBounds[ el ] = min;
- if ( max > fullBounds[ el + 3 ] ) fullBounds[ el + 3 ] = max;
-
- }
-
- }
-
- return triangleBounds;
-
-}
-
-function buildTree( geo, options ) {
-
- function triggerProgress( trianglesProcessed ) {
-
- if ( onProgress ) {
-
- onProgress( trianglesProcessed / totalTriangles );
-
- }
-
- }
-
- // either recursively splits the given node, creating left and right subtrees for it, or makes it a leaf node,
- // recording the offset and count of its triangles and writing them into the reordered geometry index.
- function splitNode( node, offset, count, centroidBoundingData = null, depth = 0 ) {
-
- if ( ! reachedMaxDepth && depth >= maxDepth ) {
-
- reachedMaxDepth = true;
- if ( verbose ) {
-
- console.warn( `MeshBVH: Max depth of ${ maxDepth } reached when generating BVH. Consider increasing maxDepth.` );
- console.warn( geo );
-
- }
-
- }
-
- // early out if we've met our capacity
- if ( count <= maxLeafTris || depth >= maxDepth ) {
-
- triggerProgress( offset );
- node.offset = offset;
- node.count = count;
- return node;
-
- }
-
- // Find where to split the volume
- const split = getOptimalSplit( node.boundingData, centroidBoundingData, triangleBounds, offset, count, strategy );
- if ( split.axis === - 1 ) {
-
- triggerProgress( offset );
- node.offset = offset;
- node.count = count;
- return node;
-
- }
-
- const splitOffset = partition( indexArray, triangleBounds, offset, count, split );
-
- // create the two new child nodes
- if ( splitOffset === offset || splitOffset === offset + count ) {
-
- triggerProgress( offset );
- node.offset = offset;
- node.count = count;
-
- } else {
-
- node.splitAxis = split.axis;
-
- // create the left child and compute its bounding box
- const left = new MeshBVHNode();
- const lstart = offset;
- const lcount = splitOffset - offset;
- node.left = left;
- left.boundingData = new Float32Array( 6 );
-
- getBounds( triangleBounds, lstart, lcount, left.boundingData, cacheCentroidBoundingData );
- splitNode( left, lstart, lcount, cacheCentroidBoundingData, depth + 1 );
-
- // repeat for right
- const right = new MeshBVHNode();
- const rstart = splitOffset;
- const rcount = count - lcount;
- node.right = right;
- right.boundingData = new Float32Array( 6 );
-
- getBounds( triangleBounds, rstart, rcount, right.boundingData, cacheCentroidBoundingData );
- splitNode( right, rstart, rcount, cacheCentroidBoundingData, depth + 1 );
-
- }
-
- return node;
-
- }
-
- ensureIndex( geo, options );
-
- // Compute the full bounds of the geometry at the same time as triangle bounds because
- // we'll need it for the root bounds in the case with no groups and it should be fast here.
- // We can't use the geometrying bounding box if it's available because it may be out of date.
- const fullBounds = new Float32Array( 6 );
- const cacheCentroidBoundingData = new Float32Array( 6 );
- const triangleBounds = computeTriangleBounds( geo, fullBounds );
- const indexArray = geo.index.array;
- const maxDepth = options.maxDepth;
- const verbose = options.verbose;
- const maxLeafTris = options.maxLeafTris;
- const strategy = options.strategy;
- const onProgress = options.onProgress;
- const totalTriangles = geo.index.count / 3;
- let reachedMaxDepth = false;
-
- const roots = [];
- const ranges = getRootIndexRanges( geo );
-
- if ( ranges.length === 1 ) {
-
- const range = ranges[ 0 ];
- const root = new MeshBVHNode();
- root.boundingData = fullBounds;
- getCentroidBounds( triangleBounds, range.offset, range.count, cacheCentroidBoundingData );
-
- splitNode( root, range.offset, range.count, cacheCentroidBoundingData );
- roots.push( root );
-
- } else {
-
- for ( let range of ranges ) {
-
- const root = new MeshBVHNode();
- root.boundingData = new Float32Array( 6 );
- getBounds( triangleBounds, range.offset, range.count, root.boundingData, cacheCentroidBoundingData );
-
- splitNode( root, range.offset, range.count, cacheCentroidBoundingData );
- roots.push( root );
-
- }
-
- }
-
- return roots;
-
-}
-
-function buildPackedTree( geo, options ) {
-
- // boundingData : 6 float32
- // right / offset : 1 uint32
- // splitAxis / isLeaf + count : 1 uint32 / 2 uint16
- const roots = buildTree( geo, options );
-
- let float32Array;
- let uint32Array;
- let uint16Array;
- const packedRoots = [];
- const BufferConstructor = options.useSharedArrayBuffer ? SharedArrayBuffer : ArrayBuffer;
- for ( let i = 0; i < roots.length; i ++ ) {
-
- const root = roots[ i ];
- let nodeCount = countNodes( root );
-
- const buffer = new BufferConstructor( BYTES_PER_NODE * nodeCount );
- float32Array = new Float32Array( buffer );
- uint32Array = new Uint32Array( buffer );
- uint16Array = new Uint16Array( buffer );
- populateBuffer( 0, root );
- packedRoots.push( buffer );
-
- }
-
- return packedRoots;
-
- function countNodes( node ) {
-
- if ( node.count ) {
-
- return 1;
-
- } else {
-
- return 1 + countNodes( node.left ) + countNodes( node.right );
-
- }
-
- }
-
- function populateBuffer( byteOffset, node ) {
-
- const stride4Offset = byteOffset / 4;
- const stride2Offset = byteOffset / 2;
- const isLeaf = ! ! node.count;
- const boundingData = node.boundingData;
- for ( let i = 0; i < 6; i ++ ) {
-
- float32Array[ stride4Offset + i ] = boundingData[ i ];
-
- }
-
- if ( isLeaf ) {
-
- const offset = node.offset;
- const count = node.count;
- uint32Array[ stride4Offset + 6 ] = offset;
- uint16Array[ stride2Offset + 14 ] = count;
- uint16Array[ stride2Offset + 15 ] = IS_LEAFNODE_FLAG;
- return byteOffset + BYTES_PER_NODE;
-
- } else {
-
- const left = node.left;
- const right = node.right;
- const splitAxis = node.splitAxis;
-
- let nextUnusedPointer;
- nextUnusedPointer = populateBuffer( byteOffset + BYTES_PER_NODE, left );
-
- if ( ( nextUnusedPointer / 4 ) > Math.pow( 2, 32 ) ) {
-
- throw new Error( 'MeshBVH: Cannot store child pointer greater than 32 bits.' );
-
- }
-
- uint32Array[ stride4Offset + 6 ] = nextUnusedPointer / 4;
- nextUnusedPointer = populateBuffer( nextUnusedPointer, right );
-
- uint32Array[ stride4Offset + 7 ] = splitAxis;
- return nextUnusedPointer;
-
- }
-
- }
-
-}
-
-class SeparatingAxisBounds {
-
- constructor() {
-
- this.min = Infinity;
- this.max = - Infinity;
-
- }
-
- setFromPointsField( points, field ) {
-
- let min = Infinity;
- let max = - Infinity;
- for ( let i = 0, l = points.length; i < l; i ++ ) {
-
- const p = points[ i ];
- const val = p[ field ];
- min = val < min ? val : min;
- max = val > max ? val : max;
-
- }
-
- this.min = min;
- this.max = max;
-
- }
-
- setFromPoints( axis, points ) {
-
- let min = Infinity;
- let max = - Infinity;
- for ( let i = 0, l = points.length; i < l; i ++ ) {
-
- const p = points[ i ];
- const val = axis.dot( p );
- min = val < min ? val : min;
- max = val > max ? val : max;
-
- }
-
- this.min = min;
- this.max = max;
-
- }
-
- isSeparated( other ) {
-
- return this.min > other.max || other.min > this.max;
-
- }
-
-}
-
-SeparatingAxisBounds.prototype.setFromBox = ( function () {
-
- const p = new Vector3();
- return function setFromBox( axis, box ) {
-
- const boxMin = box.min;
- const boxMax = box.max;
- let min = Infinity;
- let max = - Infinity;
- for ( let x = 0; x <= 1; x ++ ) {
-
- for ( let y = 0; y <= 1; y ++ ) {
-
- for ( let z = 0; z <= 1; z ++ ) {
-
- p.x = boxMin.x * x + boxMax.x * ( 1 - x );
- p.y = boxMin.y * y + boxMax.y * ( 1 - y );
- p.z = boxMin.z * z + boxMax.z * ( 1 - z );
-
- const val = axis.dot( p );
- min = Math.min( val, min );
- max = Math.max( val, max );
-
- }
-
- }
-
- }
-
- this.min = min;
- this.max = max;
-
- };
-
-} )();
-
-const areIntersecting = ( function () {
-
- const cacheSatBounds = new SeparatingAxisBounds();
- return function areIntersecting( shape1, shape2 ) {
-
- const points1 = shape1.points;
- const satAxes1 = shape1.satAxes;
- const satBounds1 = shape1.satBounds;
-
- const points2 = shape2.points;
- const satAxes2 = shape2.satAxes;
- const satBounds2 = shape2.satBounds;
-
- // check axes of the first shape
- for ( let i = 0; i < 3; i ++ ) {
-
- const sb = satBounds1[ i ];
- const sa = satAxes1[ i ];
- cacheSatBounds.setFromPoints( sa, points2 );
- if ( sb.isSeparated( cacheSatBounds ) ) return false;
-
- }
-
- // check axes of the second shape
- for ( let i = 0; i < 3; i ++ ) {
-
- const sb = satBounds2[ i ];
- const sa = satAxes2[ i ];
- cacheSatBounds.setFromPoints( sa, points1 );
- if ( sb.isSeparated( cacheSatBounds ) ) return false;
-
- }
-
- };
-
-} )();
-
-const closestPointLineToLine = ( function () {
-
- // https://github.com/juj/MathGeoLib/blob/master/src/Geometry/Line.cpp#L56
- const dir1 = new Vector3();
- const dir2 = new Vector3();
- const v02 = new Vector3();
- return function closestPointLineToLine( l1, l2, result ) {
-
- const v0 = l1.start;
- const v10 = dir1;
- const v2 = l2.start;
- const v32 = dir2;
-
- v02.subVectors( v0, v2 );
- dir1.subVectors( l1.end, l2.start );
- dir2.subVectors( l2.end, l2.start );
-
- // float d0232 = v02.Dot(v32);
- const d0232 = v02.dot( v32 );
-
- // float d3210 = v32.Dot(v10);
- const d3210 = v32.dot( v10 );
-
- // float d3232 = v32.Dot(v32);
- const d3232 = v32.dot( v32 );
-
- // float d0210 = v02.Dot(v10);
- const d0210 = v02.dot( v10 );
-
- // float d1010 = v10.Dot(v10);
- const d1010 = v10.dot( v10 );
-
- // float denom = d1010*d3232 - d3210*d3210;
- const denom = d1010 * d3232 - d3210 * d3210;
-
- let d, d2;
- if ( denom !== 0 ) {
-
- d = ( d0232 * d3210 - d0210 * d3232 ) / denom;
-
- } else {
-
- d = 0;
-
- }
-
- d2 = ( d0232 + d * d3210 ) / d3232;
-
- result.x = d;
- result.y = d2;
-
- };
-
-} )();
-
-const closestPointsSegmentToSegment = ( function () {
-
- // https://github.com/juj/MathGeoLib/blob/master/src/Geometry/LineSegment.cpp#L187
- const paramResult = new Vector2();
- const temp1 = new Vector3();
- const temp2 = new Vector3();
- return function closestPointsSegmentToSegment( l1, l2, target1, target2 ) {
-
- closestPointLineToLine( l1, l2, paramResult );
-
- let d = paramResult.x;
- let d2 = paramResult.y;
- if ( d >= 0 && d <= 1 && d2 >= 0 && d2 <= 1 ) {
-
- l1.at( d, target1 );
- l2.at( d2, target2 );
-
- return;
-
- } else if ( d >= 0 && d <= 1 ) {
-
- // Only d2 is out of bounds.
- if ( d2 < 0 ) {
-
- l2.at( 0, target2 );
-
- } else {
-
- l2.at( 1, target2 );
-
- }
-
- l1.closestPointToPoint( target2, true, target1 );
- return;
-
- } else if ( d2 >= 0 && d2 <= 1 ) {
-
- // Only d is out of bounds.
- if ( d < 0 ) {
-
- l1.at( 0, target1 );
-
- } else {
-
- l1.at( 1, target1 );
-
- }
-
- l2.closestPointToPoint( target1, true, target2 );
- return;
-
- } else {
-
- // Both u and u2 are out of bounds.
- let p;
- if ( d < 0 ) {
-
- p = l1.start;
-
- } else {
-
- p = l1.end;
-
- }
-
- let p2;
- if ( d2 < 0 ) {
-
- p2 = l2.start;
-
- } else {
-
- p2 = l2.end;
-
- }
-
- const closestPoint = temp1;
- const closestPoint2 = temp2;
- l1.closestPointToPoint( p2, true, temp1 );
- l2.closestPointToPoint( p, true, temp2 );
-
- if ( closestPoint.distanceToSquared( p2 ) <= closestPoint2.distanceToSquared( p ) ) {
-
- target1.copy( closestPoint );
- target2.copy( p2 );
- return;
-
- } else {
-
- target1.copy( p );
- target2.copy( closestPoint2 );
- return;
-
- }
-
- }
-
- };
-
-} )();
-
-
-const sphereIntersectTriangle = ( function () {
-
- // https://stackoverflow.com/questions/34043955/detect-collision-between-sphere-and-triangle-in-three-js
- const closestPointTemp = new Vector3();
- const projectedPointTemp = new Vector3();
- const planeTemp = new Plane();
- const lineTemp = new Line3();
- return function sphereIntersectTriangle( sphere, triangle ) {
-
- const { radius, center } = sphere;
- const { a, b, c } = triangle;
-
- // phase 1
- lineTemp.start = a;
- lineTemp.end = b;
- const closestPoint1 = lineTemp.closestPointToPoint( center, true, closestPointTemp );
- if ( closestPoint1.distanceTo( center ) <= radius ) return true;
-
- lineTemp.start = a;
- lineTemp.end = c;
- const closestPoint2 = lineTemp.closestPointToPoint( center, true, closestPointTemp );
- if ( closestPoint2.distanceTo( center ) <= radius ) return true;
-
- lineTemp.start = b;
- lineTemp.end = c;
- const closestPoint3 = lineTemp.closestPointToPoint( center, true, closestPointTemp );
- if ( closestPoint3.distanceTo( center ) <= radius ) return true;
-
- // phase 2
- const plane = triangle.getPlane( planeTemp );
- const dp = Math.abs( plane.distanceToPoint( center ) );
- if ( dp <= radius ) {
-
- const pp = plane.projectPoint( center, projectedPointTemp );
- const cp = triangle.containsPoint( pp );
- if ( cp ) return true;
-
- }
-
- return false;
-
- };
-
-} )();
-
-class SeparatingAxisTriangle extends Triangle {
-
- constructor( ...args ) {
-
- super( ...args );
-
- this.isSeparatingAxisTriangle = true;
- this.satAxes = new Array( 4 ).fill().map( () => new Vector3() );
- this.satBounds = new Array( 4 ).fill().map( () => new SeparatingAxisBounds() );
- this.points = [ this.a, this.b, this.c ];
- this.sphere = new Sphere();
- this.plane = new Plane();
- this.needsUpdate = false;
-
- }
-
- intersectsSphere( sphere ) {
-
- return sphereIntersectTriangle( sphere, this );
-
- }
-
- update() {
-
- const a = this.a;
- const b = this.b;
- const c = this.c;
- const points = this.points;
-
- const satAxes = this.satAxes;
- const satBounds = this.satBounds;
-
- const axis0 = satAxes[ 0 ];
- const sab0 = satBounds[ 0 ];
- this.getNormal( axis0 );
- sab0.setFromPoints( axis0, points );
-
- const axis1 = satAxes[ 1 ];
- const sab1 = satBounds[ 1 ];
- axis1.subVectors( a, b );
- sab1.setFromPoints( axis1, points );
-
- const axis2 = satAxes[ 2 ];
- const sab2 = satBounds[ 2 ];
- axis2.subVectors( b, c );
- sab2.setFromPoints( axis2, points );
-
- const axis3 = satAxes[ 3 ];
- const sab3 = satBounds[ 3 ];
- axis3.subVectors( c, a );
- sab3.setFromPoints( axis3, points );
-
- this.sphere.setFromPoints( this.points );
- this.plane.setFromNormalAndCoplanarPoint( axis0, a );
- this.needsUpdate = false;
-
- }
-
-}
-
-SeparatingAxisTriangle.prototype.closestPointToSegment = ( function () {
-
- const point1 = new Vector3();
- const point2 = new Vector3();
- const edge = new Line3();
-
- return function distanceToSegment( segment, target1 = null, target2 = null ) {
-
- const { start, end } = segment;
- const points = this.points;
- let distSq;
- let closestDistanceSq = Infinity;
-
- // check the triangle edges
- for ( let i = 0; i < 3; i ++ ) {
-
- const nexti = ( i + 1 ) % 3;
- edge.start.copy( points[ i ] );
- edge.end.copy( points[ nexti ] );
-
- closestPointsSegmentToSegment( edge, segment, point1, point2 );
-
- distSq = point1.distanceToSquared( point2 );
- if ( distSq < closestDistanceSq ) {
-
- closestDistanceSq = distSq;
- if ( target1 ) target1.copy( point1 );
- if ( target2 ) target2.copy( point2 );
-
- }
-
- }
-
- // check end points
- this.closestPointToPoint( start, point1 );
- distSq = start.distanceToSquared( point1 );
- if ( distSq < closestDistanceSq ) {
-
- closestDistanceSq = distSq;
- if ( target1 ) target1.copy( point1 );
- if ( target2 ) target2.copy( start );
-
- }
-
- this.closestPointToPoint( end, point1 );
- distSq = end.distanceToSquared( point1 );
- if ( distSq < closestDistanceSq ) {
-
- closestDistanceSq = distSq;
- if ( target1 ) target1.copy( point1 );
- if ( target2 ) target2.copy( end );
-
- }
-
- return Math.sqrt( closestDistanceSq );
-
- };
-
-} )();
-
-SeparatingAxisTriangle.prototype.intersectsTriangle = ( function () {
-
- const saTri2 = new SeparatingAxisTriangle();
- const arr1 = new Array( 3 );
- const arr2 = new Array( 3 );
- const cachedSatBounds = new SeparatingAxisBounds();
- const cachedSatBounds2 = new SeparatingAxisBounds();
- const cachedAxis = new Vector3();
- const dir1 = new Vector3();
- const dir2 = new Vector3();
- const tempDir = new Vector3();
- const edge = new Line3();
- const edge1 = new Line3();
- const edge2 = new Line3();
-
- // TODO: If the triangles are coplanar and intersecting the target is nonsensical. It should at least
- // be a line contained by both triangles if not a different special case somehow represented in the return result.
- return function intersectsTriangle( other, target = null ) {
-
- if ( this.needsUpdate ) {
-
- this.update();
-
- }
-
- if ( ! other.isSeparatingAxisTriangle ) {
-
- saTri2.copy( other );
- saTri2.update();
- other = saTri2;
-
- } else if ( other.needsUpdate ) {
-
- other.update();
-
- }
-
- const satBounds1 = this.satBounds;
- const satAxes1 = this.satAxes;
- arr2[ 0 ] = other.a;
- arr2[ 1 ] = other.b;
- arr2[ 2 ] = other.c;
- for ( let i = 0; i < 4; i ++ ) {
-
- const sb = satBounds1[ i ];
- const sa = satAxes1[ i ];
- cachedSatBounds.setFromPoints( sa, arr2 );
- if ( sb.isSeparated( cachedSatBounds ) ) return false;
-
- }
-
- const satBounds2 = other.satBounds;
- const satAxes2 = other.satAxes;
- arr1[ 0 ] = this.a;
- arr1[ 1 ] = this.b;
- arr1[ 2 ] = this.c;
- for ( let i = 0; i < 4; i ++ ) {
-
- const sb = satBounds2[ i ];
- const sa = satAxes2[ i ];
- cachedSatBounds.setFromPoints( sa, arr1 );
- if ( sb.isSeparated( cachedSatBounds ) ) return false;
-
- }
-
- // check crossed axes
- for ( let i = 0; i < 4; i ++ ) {
-
- const sa1 = satAxes1[ i ];
- for ( let i2 = 0; i2 < 4; i2 ++ ) {
-
- const sa2 = satAxes2[ i2 ];
- cachedAxis.crossVectors( sa1, sa2 );
- cachedSatBounds.setFromPoints( cachedAxis, arr1 );
- cachedSatBounds2.setFromPoints( cachedAxis, arr2 );
- if ( cachedSatBounds.isSeparated( cachedSatBounds2 ) ) return false;
-
- }
-
- }
-
- if ( target ) {
-
- const plane1 = this.plane;
- const plane2 = other.plane;
-
- if ( Math.abs( plane1.normal.dot( plane2.normal ) ) > 1.0 - 1e-10 ) {
-
- // TODO find two points that intersect on the edges and make that the result
- console.warn( 'SeparatingAxisTriangle.intersectsTriangle: Triangles are coplanar which does not support an output edge. Setting edge to 0, 0, 0.' );
- target.start.set( 0, 0, 0 );
- target.end.set( 0, 0, 0 );
-
- } else {
-
- // find the edge that intersects the other triangle plane
- const points1 = this.points;
- let found1 = false;
- for ( let i = 0; i < 3; i ++ ) {
-
- const p1 = points1[ i ];
- const p2 = points1[ ( i + 1 ) % 3 ];
-
- edge.start.copy( p1 );
- edge.end.copy( p2 );
-
- if ( plane2.intersectLine( edge, found1 ? edge1.start : edge1.end ) ) {
-
- if ( found1 ) {
-
- break;
-
- }
-
- found1 = true;
-
- }
-
- }
-
- // find the other triangles edge that intersects this plane
- const points2 = other.points;
- let found2 = false;
- for ( let i = 0; i < 3; i ++ ) {
-
- const p1 = points2[ i ];
- const p2 = points2[ ( i + 1 ) % 3 ];
-
- edge.start.copy( p1 );
- edge.end.copy( p2 );
-
- if ( plane1.intersectLine( edge, found2 ? edge2.start : edge2.end ) ) {
-
- if ( found2 ) {
-
- break;
-
- }
-
- found2 = true;
-
- }
-
- }
-
- // find swap the second edge so both lines are running the same direction
- edge1.delta( dir1 );
- edge2.delta( dir2 );
-
-
- if ( dir1.dot( dir2 ) < 0 ) {
-
- let tmp = edge2.start;
- edge2.start = edge2.end;
- edge2.end = tmp;
-
- }
-
- tempDir.subVectors( edge1.start, edge2.start );
- if ( tempDir.dot( dir1 ) > 0 ) {
-
- target.start.copy( edge1.start );
-
- } else {
-
- target.start.copy( edge2.start );
-
- }
-
- tempDir.subVectors( edge1.end, edge2.end );
- if ( tempDir.dot( dir1 ) < 0 ) {
-
- target.end.copy( edge1.end );
-
- } else {
-
- target.end.copy( edge2.end );
-
- }
-
- }
-
- }
-
- return true;
-
- };
-
-} )();
-
-
-SeparatingAxisTriangle.prototype.distanceToPoint = ( function () {
-
- const target = new Vector3();
- return function distanceToPoint( point ) {
-
- this.closestPointToPoint( point, target );
- return point.distanceTo( target );
-
- };
-
-} )();
-
-
-SeparatingAxisTriangle.prototype.distanceToTriangle = ( function () {
-
- const point = new Vector3();
- const point2 = new Vector3();
- const cornerFields = [ 'a', 'b', 'c' ];
- const line1 = new Line3();
- const line2 = new Line3();
-
- return function distanceToTriangle( other, target1 = null, target2 = null ) {
-
- const lineTarget = target1 || target2 ? line1 : null;
- if ( this.intersectsTriangle( other, lineTarget ) ) {
-
- if ( target1 || target2 ) {
-
- if ( target1 ) lineTarget.getCenter( target1 );
- if ( target2 ) lineTarget.getCenter( target2 );
-
- }
-
- return 0;
-
- }
-
- let closestDistanceSq = Infinity;
-
- // check all point distances
- for ( let i = 0; i < 3; i ++ ) {
-
- let dist;
- const field = cornerFields[ i ];
- const otherVec = other[ field ];
- this.closestPointToPoint( otherVec, point );
-
- dist = otherVec.distanceToSquared( point );
-
- if ( dist < closestDistanceSq ) {
-
- closestDistanceSq = dist;
- if ( target1 ) target1.copy( point );
- if ( target2 ) target2.copy( otherVec );
-
- }
-
-
- const thisVec = this[ field ];
- other.closestPointToPoint( thisVec, point );
-
- dist = thisVec.distanceToSquared( point );
-
- if ( dist < closestDistanceSq ) {
-
- closestDistanceSq = dist;
- if ( target1 ) target1.copy( thisVec );
- if ( target2 ) target2.copy( point );
-
- }
-
- }
-
- for ( let i = 0; i < 3; i ++ ) {
-
- const f11 = cornerFields[ i ];
- const f12 = cornerFields[ ( i + 1 ) % 3 ];
- line1.set( this[ f11 ], this[ f12 ] );
- for ( let i2 = 0; i2 < 3; i2 ++ ) {
-
- const f21 = cornerFields[ i2 ];
- const f22 = cornerFields[ ( i2 + 1 ) % 3 ];
- line2.set( other[ f21 ], other[ f22 ] );
-
- closestPointsSegmentToSegment( line1, line2, point, point2 );
-
- const dist = point.distanceToSquared( point2 );
- if ( dist < closestDistanceSq ) {
-
- closestDistanceSq = dist;
- if ( target1 ) target1.copy( point );
- if ( target2 ) target2.copy( point2 );
-
- }
-
- }
-
- }
-
- return Math.sqrt( closestDistanceSq );
-
- };
-
-} )();
-
-class OrientedBox extends Box3 {
-
- constructor( ...args ) {
-
- super( ...args );
-
- this.isOrientedBox = true;
- this.matrix = new Matrix4();
- this.invMatrix = new Matrix4();
- this.points = new Array( 8 ).fill().map( () => new Vector3() );
- this.satAxes = new Array( 3 ).fill().map( () => new Vector3() );
- this.satBounds = new Array( 3 ).fill().map( () => new SeparatingAxisBounds() );
- this.alignedSatBounds = new Array( 3 ).fill().map( () => new SeparatingAxisBounds() );
- this.needsUpdate = false;
-
- }
-
- set( min, max, matrix ) {
-
- super.set( min, max );
- this.matrix = matrix;
- this.needsUpdate = true;
-
- }
-
- copy( other ) {
-
- super.copy( other );
- this.matrix.copy( other.matrix );
- this.needsUpdate = true;
-
- }
-
-}
-
-OrientedBox.prototype.update = ( function () {
-
- return function update() {
-
- const matrix = this.matrix;
- const min = this.min;
- const max = this.max;
-
- const points = this.points;
- for ( let x = 0; x <= 1; x ++ ) {
-
- for ( let y = 0; y <= 1; y ++ ) {
-
- for ( let z = 0; z <= 1; z ++ ) {
-
- const i = ( ( 1 << 0 ) * x ) | ( ( 1 << 1 ) * y ) | ( ( 1 << 2 ) * z );
- const v = points[ i ];
- v.x = x ? max.x : min.x;
- v.y = y ? max.y : min.y;
- v.z = z ? max.z : min.z;
-
- v.applyMatrix4( matrix );
-
- }
-
- }
-
- }
-
- const satBounds = this.satBounds;
- const satAxes = this.satAxes;
- const minVec = points[ 0 ];
- for ( let i = 0; i < 3; i ++ ) {
-
- const axis = satAxes[ i ];
- const sb = satBounds[ i ];
- const index = 1 << i;
- const pi = points[ index ];
-
- axis.subVectors( minVec, pi );
- sb.setFromPoints( axis, points );
-
- }
-
- const alignedSatBounds = this.alignedSatBounds;
- alignedSatBounds[ 0 ].setFromPointsField( points, 'x' );
- alignedSatBounds[ 1 ].setFromPointsField( points, 'y' );
- alignedSatBounds[ 2 ].setFromPointsField( points, 'z' );
-
- this.invMatrix.copy( this.matrix ).invert();
- this.needsUpdate = false;
-
- };
-
-} )();
-
-OrientedBox.prototype.intersectsBox = ( function () {
-
- const aabbBounds = new SeparatingAxisBounds();
- return function intersectsBox( box ) {
-
- // TODO: should this be doing SAT against the AABB?
- if ( this.needsUpdate ) {
-
- this.update();
-
- }
-
- const min = box.min;
- const max = box.max;
- const satBounds = this.satBounds;
- const satAxes = this.satAxes;
- const alignedSatBounds = this.alignedSatBounds;
-
- aabbBounds.min = min.x;
- aabbBounds.max = max.x;
- if ( alignedSatBounds[ 0 ].isSeparated( aabbBounds ) ) return false;
-
- aabbBounds.min = min.y;
- aabbBounds.max = max.y;
- if ( alignedSatBounds[ 1 ].isSeparated( aabbBounds ) ) return false;
-
- aabbBounds.min = min.z;
- aabbBounds.max = max.z;
- if ( alignedSatBounds[ 2 ].isSeparated( aabbBounds ) ) return false;
-
- for ( let i = 0; i < 3; i ++ ) {
-
- const axis = satAxes[ i ];
- const sb = satBounds[ i ];
- aabbBounds.setFromBox( axis, box );
- if ( sb.isSeparated( aabbBounds ) ) return false;
-
- }
-
- return true;
-
- };
-
-} )();
-
-OrientedBox.prototype.intersectsTriangle = ( function () {
-
- const saTri = new SeparatingAxisTriangle();
- const pointsArr = new Array( 3 );
- const cachedSatBounds = new SeparatingAxisBounds();
- const cachedSatBounds2 = new SeparatingAxisBounds();
- const cachedAxis = new Vector3();
- return function intersectsTriangle( triangle ) {
-
- if ( this.needsUpdate ) {
-
- this.update();
-
- }
-
- if ( ! triangle.isSeparatingAxisTriangle ) {
-
- saTri.copy( triangle );
- saTri.update();
- triangle = saTri;
-
- } else if ( triangle.needsUpdate ) {
-
- triangle.update();
-
- }
-
- const satBounds = this.satBounds;
- const satAxes = this.satAxes;
-
- pointsArr[ 0 ] = triangle.a;
- pointsArr[ 1 ] = triangle.b;
- pointsArr[ 2 ] = triangle.c;
-
- for ( let i = 0; i < 3; i ++ ) {
-
- const sb = satBounds[ i ];
- const sa = satAxes[ i ];
- cachedSatBounds.setFromPoints( sa, pointsArr );
- if ( sb.isSeparated( cachedSatBounds ) ) return false;
-
- }
-
- const triSatBounds = triangle.satBounds;
- const triSatAxes = triangle.satAxes;
- const points = this.points;
- for ( let i = 0; i < 3; i ++ ) {
-
- const sb = triSatBounds[ i ];
- const sa = triSatAxes[ i ];
- cachedSatBounds.setFromPoints( sa, points );
- if ( sb.isSeparated( cachedSatBounds ) ) return false;
-
- }
-
- // check crossed axes
- for ( let i = 0; i < 3; i ++ ) {
-
- const sa1 = satAxes[ i ];
- for ( let i2 = 0; i2 < 4; i2 ++ ) {
-
- const sa2 = triSatAxes[ i2 ];
- cachedAxis.crossVectors( sa1, sa2 );
- cachedSatBounds.setFromPoints( cachedAxis, pointsArr );
- cachedSatBounds2.setFromPoints( cachedAxis, points );
- if ( cachedSatBounds.isSeparated( cachedSatBounds2 ) ) return false;
-
- }
-
- }
-
- return true;
-
- };
-
-} )();
-
-OrientedBox.prototype.closestPointToPoint = ( function () {
-
- return function closestPointToPoint( point, target1 ) {
-
- if ( this.needsUpdate ) {
-
- this.update();
-
- }
-
- target1
- .copy( point )
- .applyMatrix4( this.invMatrix )
- .clamp( this.min, this.max )
- .applyMatrix4( this.matrix );
-
- return target1;
-
- };
-
-} )();
-
-OrientedBox.prototype.distanceToPoint = ( function () {
-
- const target = new Vector3();
- return function distanceToPoint( point ) {
-
- this.closestPointToPoint( point, target );
- return point.distanceTo( target );
-
- };
-
-} )();
-
-OrientedBox.prototype.distanceToBox = ( function () {
-
- const xyzFields = [ 'x', 'y', 'z' ];
- const segments1 = new Array( 12 ).fill().map( () => new Line3() );
- const segments2 = new Array( 12 ).fill().map( () => new Line3() );
-
- const point1 = new Vector3();
- const point2 = new Vector3();
-
- // early out if we find a value below threshold
- return function distanceToBox( box, threshold = 0, target1 = null, target2 = null ) {
-
- if ( this.needsUpdate ) {
-
- this.update();
-
- }
-
- if ( this.intersectsBox( box ) ) {
-
- if ( target1 || target2 ) {
-
- box.getCenter( point2 );
- this.closestPointToPoint( point2, point1 );
- box.closestPointToPoint( point1, point2 );
-
- if ( target1 ) target1.copy( point1 );
- if ( target2 ) target2.copy( point2 );
-
- }
-
- return 0;
-
- }
-
- const threshold2 = threshold * threshold;
- const min = box.min;
- const max = box.max;
- const points = this.points;
-
-
- // iterate over every edge and compare distances
- let closestDistanceSq = Infinity;
-
- // check over all these points
- for ( let i = 0; i < 8; i ++ ) {
-
- const p = points[ i ];
- point2.copy( p ).clamp( min, max );
-
- const dist = p.distanceToSquared( point2 );
- if ( dist < closestDistanceSq ) {
-
- closestDistanceSq = dist;
- if ( target1 ) target1.copy( p );
- if ( target2 ) target2.copy( point2 );
-
- if ( dist < threshold2 ) return Math.sqrt( dist );
-
- }
-
- }
-
- // generate and check all line segment distances
- let count = 0;
- for ( let i = 0; i < 3; i ++ ) {
-
- for ( let i1 = 0; i1 <= 1; i1 ++ ) {
-
- for ( let i2 = 0; i2 <= 1; i2 ++ ) {
-
- const nextIndex = ( i + 1 ) % 3;
- const nextIndex2 = ( i + 2 ) % 3;
-
- // get obb line segments
- const index = i1 << nextIndex | i2 << nextIndex2;
- const index2 = 1 << i | i1 << nextIndex | i2 << nextIndex2;
- const p1 = points[ index ];
- const p2 = points[ index2 ];
- const line1 = segments1[ count ];
- line1.set( p1, p2 );
-
-
- // get aabb line segments
- const f1 = xyzFields[ i ];
- const f2 = xyzFields[ nextIndex ];
- const f3 = xyzFields[ nextIndex2 ];
- const line2 = segments2[ count ];
- const start = line2.start;
- const end = line2.end;
-
- start[ f1 ] = min[ f1 ];
- start[ f2 ] = i1 ? min[ f2 ] : max[ f2 ];
- start[ f3 ] = i2 ? min[ f3 ] : max[ f2 ];
-
- end[ f1 ] = max[ f1 ];
- end[ f2 ] = i1 ? min[ f2 ] : max[ f2 ];
- end[ f3 ] = i2 ? min[ f3 ] : max[ f2 ];
-
- count ++;
-
- }
-
- }
-
- }
-
- // check all the other boxes point
- for ( let x = 0; x <= 1; x ++ ) {
-
- for ( let y = 0; y <= 1; y ++ ) {
-
- for ( let z = 0; z <= 1; z ++ ) {
-
- point2.x = x ? max.x : min.x;
- point2.y = y ? max.y : min.y;
- point2.z = z ? max.z : min.z;
-
- this.closestPointToPoint( point2, point1 );
- const dist = point2.distanceToSquared( point1 );
- if ( dist < closestDistanceSq ) {
-
- closestDistanceSq = dist;
- if ( target1 ) target1.copy( point1 );
- if ( target2 ) target2.copy( point2 );
-
- if ( dist < threshold2 ) return Math.sqrt( dist );
-
- }
-
- }
-
- }
-
- }
-
- for ( let i = 0; i < 12; i ++ ) {
-
- const l1 = segments1[ i ];
- for ( let i2 = 0; i2 < 12; i2 ++ ) {
-
- const l2 = segments2[ i2 ];
- closestPointsSegmentToSegment( l1, l2, point1, point2 );
- const dist = point1.distanceToSquared( point2 );
- if ( dist < closestDistanceSq ) {
-
- closestDistanceSq = dist;
- if ( target1 ) target1.copy( point1 );
- if ( target2 ) target2.copy( point2 );
-
- if ( dist < threshold2 ) return Math.sqrt( dist );
-
- }
-
- }
-
- }
-
- return Math.sqrt( closestDistanceSq );
-
- };
-
-} )();
-
-// Ripped and modified From THREE.js Mesh raycast
-// https://github.com/mrdoob/three.js/blob/0aa87c999fe61e216c1133fba7a95772b503eddf/src/objects/Mesh.js#L115
-const vA = /* @__PURE__ */ new Vector3();
-const vB = /* @__PURE__ */ new Vector3();
-const vC = /* @__PURE__ */ new Vector3();
-
-const uvA = /* @__PURE__ */ new Vector2();
-const uvB = /* @__PURE__ */ new Vector2();
-const uvC = /* @__PURE__ */ new Vector2();
-
-const intersectionPoint = /* @__PURE__ */ new Vector3();
-function checkIntersection( ray, pA, pB, pC, point, side ) {
-
- let intersect;
- if ( side === BackSide ) {
-
- intersect = ray.intersectTriangle( pC, pB, pA, true, point );
-
- } else {
-
- intersect = ray.intersectTriangle( pA, pB, pC, side !== DoubleSide, point );
-
- }
-
- if ( intersect === null ) return null;
-
- const distance = ray.origin.distanceTo( point );
-
- return {
-
- distance: distance,
- point: point.clone(),
-
- };
-
-}
-
-function checkBufferGeometryIntersection( ray, position, uv, a, b, c, side ) {
-
- vA.fromBufferAttribute( position, a );
- vB.fromBufferAttribute( position, b );
- vC.fromBufferAttribute( position, c );
-
- const intersection = checkIntersection( ray, vA, vB, vC, intersectionPoint, side );
-
- if ( intersection ) {
-
- if ( uv ) {
-
- uvA.fromBufferAttribute( uv, a );
- uvB.fromBufferAttribute( uv, b );
- uvC.fromBufferAttribute( uv, c );
-
- intersection.uv = Triangle.getUV( intersectionPoint, vA, vB, vC, uvA, uvB, uvC, new Vector2( ) );
-
- }
-
- const face = {
- a: a,
- b: b,
- c: c,
- normal: new Vector3(),
- materialIndex: 0
- };
-
- Triangle.getNormal( vA, vB, vC, face.normal );
-
- intersection.face = face;
- intersection.faceIndex = a;
-
- }
-
- return intersection;
-
-}
-
-// https://github.com/mrdoob/three.js/blob/0aa87c999fe61e216c1133fba7a95772b503eddf/src/objects/Mesh.js#L258
-function intersectTri( geo, side, ray, tri, intersections ) {
-
- const triOffset = tri * 3;
- const a = geo.index.getX( triOffset );
- const b = geo.index.getX( triOffset + 1 );
- const c = geo.index.getX( triOffset + 2 );
-
- const intersection = checkBufferGeometryIntersection( ray, geo.attributes.position, geo.attributes.uv, a, b, c, side );
-
- if ( intersection ) {
-
- intersection.faceIndex = tri;
- if ( intersections ) intersections.push( intersection );
- return intersection;
-
- }
-
- return null;
-
-}
-
-function intersectTris( geo, side, ray, offset, count, intersections ) {
-
- for ( let i = offset, end = offset + count; i < end; i ++ ) {
-
- intersectTri( geo, side, ray, i, intersections );
-
- }
-
-}
-
-function intersectClosestTri( geo, side, ray, offset, count ) {
-
- let dist = Infinity;
- let res = null;
- for ( let i = offset, end = offset + count; i < end; i ++ ) {
-
- const intersection = intersectTri( geo, side, ray, i );
- if ( intersection && intersection.distance < dist ) {
-
- res = intersection;
- dist = intersection.distance;
-
- }
-
- }
-
- return res;
-
-}
-
-// converts the given BVH raycast intersection to align with the three.js raycast
-// structure (include object, world space distance and point).
-function convertRaycastIntersect( hit, object, raycaster ) {
-
- if ( hit === null ) {
-
- return null;
-
- }
-
- hit.point.applyMatrix4( object.matrixWorld );
- hit.distance = hit.point.distanceTo( raycaster.ray.origin );
- hit.object = object;
-
- if ( hit.distance < raycaster.near || hit.distance > raycaster.far ) {
-
- return null;
-
- } else {
-
- return hit;
-
- }
-
-}
-
-// sets the vertices of triangle `tri` with the 3 vertices after i
-function setTriangle( tri, i, index, pos ) {
-
- const ta = tri.a;
- const tb = tri.b;
- const tc = tri.c;
-
- let i0 = i;
- let i1 = i + 1;
- let i2 = i + 2;
- if ( index ) {
-
- i0 = index.getX( i );
- i1 = index.getX( i + 1 );
- i2 = index.getX( i + 2 );
-
- }
-
- ta.x = pos.getX( i0 );
- ta.y = pos.getY( i0 );
- ta.z = pos.getZ( i0 );
-
- tb.x = pos.getX( i1 );
- tb.y = pos.getY( i1 );
- tb.z = pos.getZ( i1 );
-
- tc.x = pos.getX( i2 );
- tc.y = pos.getY( i2 );
- tc.z = pos.getZ( i2 );
-
-}
-
-function iterateOverTriangles(
- offset,
- count,
- geometry,
- intersectsTriangleFunc,
- contained,
- depth,
- triangle
-) {
-
- const index = geometry.index;
- const pos = geometry.attributes.position;
- for ( let i = offset, l = count + offset; i < l; i ++ ) {
-
- setTriangle( triangle, i * 3, index, pos );
- triangle.needsUpdate = true;
-
- if ( intersectsTriangleFunc( triangle, i, contained, depth ) ) {
-
- return true;
-
- }
-
- }
-
- return false;
-
-}
-
-const tempV1 = /* @__PURE__ */ new Vector3();
-const tempV2 = /* @__PURE__ */ new Vector3();
-const tempV3 = /* @__PURE__ */ new Vector3();
-const tempUV1 = /* @__PURE__ */ new Vector2();
-const tempUV2 = /* @__PURE__ */ new Vector2();
-const tempUV3 = /* @__PURE__ */ new Vector2();
-
-function getTriangleHitPointInfo( point, geometry, triangleIndex, target ) {
-
- const indices = geometry.getIndex().array;
- const positions = geometry.getAttribute( 'position' );
- const uvs = geometry.getAttribute( 'uv' );
-
- const a = indices[ triangleIndex * 3 ];
- const b = indices[ triangleIndex * 3 + 1 ];
- const c = indices[ triangleIndex * 3 + 2 ];
-
- tempV1.fromBufferAttribute( positions, a );
- tempV2.fromBufferAttribute( positions, b );
- tempV3.fromBufferAttribute( positions, c );
-
- // find the associated material index
- let materialIndex = 0;
- const groups = geometry.groups;
- const firstVertexIndex = triangleIndex * 3;
- for ( let i = 0, l = groups.length; i < l; i ++ ) {
-
- const group = groups[ i ];
- const { start, count } = group;
- if ( firstVertexIndex >= start && firstVertexIndex < start + count ) {
-
- materialIndex = group.materialIndex;
- break;
-
- }
-
- }
-
- // extract uvs
- let uv = null;
- if ( uvs ) {
-
- tempUV1.fromBufferAttribute( uvs, a );
- tempUV2.fromBufferAttribute( uvs, b );
- tempUV3.fromBufferAttribute( uvs, c );
-
- if ( target && target.uv ) uv = target.uv;
- else uv = new Vector2();
-
- Triangle.getUV( point, tempV1, tempV2, tempV3, tempUV1, tempUV2, tempUV3, uv );
-
- }
-
- // adjust the provided target or create a new one
- if ( target ) {
-
- if ( ! target.face ) target.face = { };
- target.face.a = a;
- target.face.b = b;
- target.face.c = c;
- target.face.materialIndex = materialIndex;
- if ( ! target.face.normal ) target.face.normal = new Vector3();
- Triangle.getNormal( tempV1, tempV2, tempV3, target.face.normal );
-
- if ( ! target.uv ) target.uv = new Vector2();
- target.uv.copy( uv );
-
- return target;
-
- } else {
-
- return {
- face: {
- a: a,
- b: b,
- c: c,
- materialIndex: materialIndex,
- normal: Triangle.getNormal( tempV1, tempV2, tempV3, new Vector3() )
- },
- uv: uv
- };
-
- }
-
-}
-
-class PrimitivePool {
-
- constructor( getNewPrimitive ) {
-
- this._getNewPrimitive = getNewPrimitive;
- this._primitives = [];
-
- }
-
- getPrimitive() {
-
- const primitives = this._primitives;
- if ( primitives.length === 0 ) {
-
- return this._getNewPrimitive();
-
- } else {
-
- return primitives.pop();
-
- }
-
- }
-
- releasePrimitive( primitive ) {
-
- this._primitives.push( primitive );
-
- }
-
-}
-
-function IS_LEAF( n16, uint16Array ) {
-
- return uint16Array[ n16 + 15 ] === 0xFFFF;
-
-}
-
-function OFFSET( n32, uint32Array ) {
-
- return uint32Array[ n32 + 6 ];
-
-}
-
-function COUNT( n16, uint16Array ) {
-
- return uint16Array[ n16 + 14 ];
-
-}
-
-function LEFT_NODE( n32 ) {
-
- return n32 + 8;
-
-}
-
-function RIGHT_NODE( n32, uint32Array ) {
-
- return uint32Array[ n32 + 6 ];
-
-}
-
-function SPLIT_AXIS( n32, uint32Array ) {
-
- return uint32Array[ n32 + 7 ];
-
-}
-
-function BOUNDING_DATA_INDEX( n32 ) {
-
- return n32;
-
-}
-
-const boundingBox$1 = new Box3();
-const boxIntersection = new Vector3();
-const xyzFields = [ 'x', 'y', 'z' ];
-
-function raycast( nodeIndex32, geometry, side, ray, intersects ) {
-
- let nodeIndex16 = nodeIndex32 * 2, float32Array = _float32Array, uint16Array = _uint16Array, uint32Array = _uint32Array;
-
- const isLeaf = IS_LEAF( nodeIndex16, uint16Array );
- if ( isLeaf ) {
-
- const offset = OFFSET( nodeIndex32, uint32Array );
- const count = COUNT( nodeIndex16, uint16Array );
-
- intersectTris( geometry, side, ray, offset, count, intersects );
-
- } else {
-
- const leftIndex = LEFT_NODE( nodeIndex32 );
- if ( intersectRay( leftIndex, float32Array, ray, boxIntersection ) ) {
-
- raycast( leftIndex, geometry, side, ray, intersects );
-
- }
-
- const rightIndex = RIGHT_NODE( nodeIndex32, uint32Array );
- if ( intersectRay( rightIndex, float32Array, ray, boxIntersection ) ) {
-
- raycast( rightIndex, geometry, side, ray, intersects );
-
- }
-
- }
-
-}
-
-function raycastFirst( nodeIndex32, geometry, side, ray ) {
-
- let nodeIndex16 = nodeIndex32 * 2, float32Array = _float32Array, uint16Array = _uint16Array, uint32Array = _uint32Array;
-
- const isLeaf = IS_LEAF( nodeIndex16, uint16Array );
- if ( isLeaf ) {
-
- const offset = OFFSET( nodeIndex32, uint32Array );
- const count = COUNT( nodeIndex16, uint16Array );
- return intersectClosestTri( geometry, side, ray, offset, count );
-
- } else {
-
- // consider the position of the split plane with respect to the oncoming ray; whichever direction
- // the ray is coming from, look for an intersection among that side of the tree first
- const splitAxis = SPLIT_AXIS( nodeIndex32, uint32Array );
- const xyzAxis = xyzFields[ splitAxis ];
- const rayDir = ray.direction[ xyzAxis ];
- const leftToRight = rayDir >= 0;
-
- // c1 is the child to check first
- let c1, c2;
- if ( leftToRight ) {
-
- c1 = LEFT_NODE( nodeIndex32 );
- c2 = RIGHT_NODE( nodeIndex32, uint32Array );
-
- } else {
-
- c1 = RIGHT_NODE( nodeIndex32, uint32Array );
- c2 = LEFT_NODE( nodeIndex32 );
-
- }
-
- const c1Intersection = intersectRay( c1, float32Array, ray, boxIntersection );
- const c1Result = c1Intersection ? raycastFirst( c1, geometry, side, ray ) : null;
-
- // if we got an intersection in the first node and it's closer than the second node's bounding
- // box, we don't need to consider the second node because it couldn't possibly be a better result
- if ( c1Result ) {
-
- // check if the point is within the second bounds
- // "point" is in the local frame of the bvh
- const point = c1Result.point[ xyzAxis ];
- const isOutside = leftToRight ?
- point <= float32Array[ c2 + splitAxis ] : // min bounding data
- point >= float32Array[ c2 + splitAxis + 3 ]; // max bounding data
-
- if ( isOutside ) {
-
- return c1Result;
-
- }
-
- }
-
- // either there was no intersection in the first node, or there could still be a closer
- // intersection in the second, so check the second node and then take the better of the two
- const c2Intersection = intersectRay( c2, float32Array, ray, boxIntersection );
- const c2Result = c2Intersection ? raycastFirst( c2, geometry, side, ray ) : null;
-
- if ( c1Result && c2Result ) {
-
- return c1Result.distance <= c2Result.distance ? c1Result : c2Result;
-
- } else {
-
- return c1Result || c2Result || null;
-
- }
-
- }
-
-}
-
-const shapecast = ( function () {
-
- let _box1, _box2;
- const boxStack = [];
- const boxPool = new PrimitivePool( () => new Box3() );
-
- return function shapecast( ...args ) {
-
- _box1 = boxPool.getPrimitive();
- _box2 = boxPool.getPrimitive();
- boxStack.push( _box1, _box2 );
-
- const result = shapecastTraverse( ...args );
-
- boxPool.releasePrimitive( _box1 );
- boxPool.releasePrimitive( _box2 );
- boxStack.pop();
- boxStack.pop();
-
- const length = boxStack.length;
- if ( length > 0 ) {
-
- _box2 = boxStack[ length - 1 ];
- _box1 = boxStack[ length - 2 ];
-
- }
-
- return result;
-
- };
-
- function shapecastTraverse(
- nodeIndex32,
- geometry,
- intersectsBoundsFunc,
- intersectsRangeFunc,
- nodeScoreFunc = null,
- nodeIndexByteOffset = 0, // offset for unique node identifier
- depth = 0
- ) {
-
- // Define these inside the function so it has access to the local variables needed
- // when converting to the buffer equivalents
- function getLeftOffset( nodeIndex32 ) {
-
- let nodeIndex16 = nodeIndex32 * 2, uint16Array = _uint16Array, uint32Array = _uint32Array;
-
- // traverse until we find a leaf
- while ( ! IS_LEAF( nodeIndex16, uint16Array ) ) {
-
- nodeIndex32 = LEFT_NODE( nodeIndex32 );
- nodeIndex16 = nodeIndex32 * 2;
-
- }
-
- return OFFSET( nodeIndex32, uint32Array );
-
- }
-
- function getRightEndOffset( nodeIndex32 ) {
-
- let nodeIndex16 = nodeIndex32 * 2, uint16Array = _uint16Array, uint32Array = _uint32Array;
-
- // traverse until we find a leaf
- while ( ! IS_LEAF( nodeIndex16, uint16Array ) ) {
-
- // adjust offset to point to the right node
- nodeIndex32 = RIGHT_NODE( nodeIndex32, uint32Array );
- nodeIndex16 = nodeIndex32 * 2;
-
- }
-
- // return the end offset of the triangle range
- return OFFSET( nodeIndex32, uint32Array ) + COUNT( nodeIndex16, uint16Array );
-
- }
-
- let nodeIndex16 = nodeIndex32 * 2, float32Array = _float32Array, uint16Array = _uint16Array, uint32Array = _uint32Array;
-
- const isLeaf = IS_LEAF( nodeIndex16, uint16Array );
- if ( isLeaf ) {
-
- const offset = OFFSET( nodeIndex32, uint32Array );
- const count = COUNT( nodeIndex16, uint16Array );
- arrayToBox( BOUNDING_DATA_INDEX( nodeIndex32 ), float32Array, _box1 );
- return intersectsRangeFunc( offset, count, false, depth, nodeIndexByteOffset + nodeIndex32, _box1 );
-
- } else {
-
- const left = LEFT_NODE( nodeIndex32 );
- const right = RIGHT_NODE( nodeIndex32, uint32Array );
- let c1 = left;
- let c2 = right;
-
- let score1, score2;
- let box1, box2;
- if ( nodeScoreFunc ) {
-
- box1 = _box1;
- box2 = _box2;
-
- // bounding data is not offset
- arrayToBox( BOUNDING_DATA_INDEX( c1 ), float32Array, box1 );
- arrayToBox( BOUNDING_DATA_INDEX( c2 ), float32Array, box2 );
-
- score1 = nodeScoreFunc( box1 );
- score2 = nodeScoreFunc( box2 );
-
- if ( score2 < score1 ) {
-
- c1 = right;
- c2 = left;
-
- const temp = score1;
- score1 = score2;
- score2 = temp;
-
- box1 = box2;
- // box2 is always set before use below
-
- }
-
- }
-
- // Check box 1 intersection
- if ( ! box1 ) {
-
- box1 = _box1;
- arrayToBox( BOUNDING_DATA_INDEX( c1 ), float32Array, box1 );
-
- }
-
- const isC1Leaf = IS_LEAF( c1 * 2, uint16Array );
- const c1Intersection = intersectsBoundsFunc( box1, isC1Leaf, score1, depth + 1, nodeIndexByteOffset + c1 );
-
- let c1StopTraversal;
- if ( c1Intersection === CONTAINED ) {
-
- const offset = getLeftOffset( c1 );
- const end = getRightEndOffset( c1 );
- const count = end - offset;
-
- c1StopTraversal = intersectsRangeFunc( offset, count, true, depth + 1, nodeIndexByteOffset + c1, box1 );
-
- } else {
-
- c1StopTraversal =
- c1Intersection &&
- shapecastTraverse(
- c1,
- geometry,
- intersectsBoundsFunc,
- intersectsRangeFunc,
- nodeScoreFunc,
- nodeIndexByteOffset,
- depth + 1
- );
-
- }
-
- if ( c1StopTraversal ) return true;
-
- // Check box 2 intersection
- // cached box2 will have been overwritten by previous traversal
- box2 = _box2;
- arrayToBox( BOUNDING_DATA_INDEX( c2 ), float32Array, box2 );
-
- const isC2Leaf = IS_LEAF( c2 * 2, uint16Array );
- const c2Intersection = intersectsBoundsFunc( box2, isC2Leaf, score2, depth + 1, nodeIndexByteOffset + c2 );
-
- let c2StopTraversal;
- if ( c2Intersection === CONTAINED ) {
-
- const offset = getLeftOffset( c2 );
- const end = getRightEndOffset( c2 );
- const count = end - offset;
-
- c2StopTraversal = intersectsRangeFunc( offset, count, true, depth + 1, nodeIndexByteOffset + c2, box2 );
-
- } else {
-
- c2StopTraversal =
- c2Intersection &&
- shapecastTraverse(
- c2,
- geometry,
- intersectsBoundsFunc,
- intersectsRangeFunc,
- nodeScoreFunc,
- nodeIndexByteOffset,
- depth + 1
- );
-
- }
-
- if ( c2StopTraversal ) return true;
-
- return false;
-
- }
-
- }
-
-} )();
-
-const intersectsGeometry = ( function () {
-
- const triangle = new SeparatingAxisTriangle();
- const triangle2 = new SeparatingAxisTriangle();
- const invertedMat = new Matrix4();
-
- const obb = new OrientedBox();
- const obb2 = new OrientedBox();
-
- return function intersectsGeometry( nodeIndex32, geometry, otherGeometry, geometryToBvh, cachedObb = null ) {
-
- let nodeIndex16 = nodeIndex32 * 2, float32Array = _float32Array, uint16Array = _uint16Array, uint32Array = _uint32Array;
-
- if ( cachedObb === null ) {
-
- if ( ! otherGeometry.boundingBox ) {
-
- otherGeometry.computeBoundingBox();
-
- }
-
- obb.set( otherGeometry.boundingBox.min, otherGeometry.boundingBox.max, geometryToBvh );
- cachedObb = obb;
-
- }
-
- const isLeaf = IS_LEAF( nodeIndex16, uint16Array );
- if ( isLeaf ) {
-
- const thisGeometry = geometry;
- const thisIndex = thisGeometry.index;
- const thisPos = thisGeometry.attributes.position;
-
- const index = otherGeometry.index;
- const pos = otherGeometry.attributes.position;
-
- const offset = OFFSET( nodeIndex32, uint32Array );
- const count = COUNT( nodeIndex16, uint16Array );
-
- // get the inverse of the geometry matrix so we can transform our triangles into the
- // geometry space we're trying to test. We assume there are fewer triangles being checked
- // here.
- invertedMat.copy( geometryToBvh ).invert();
-
- if ( otherGeometry.boundsTree ) {
-
- arrayToBox( BOUNDING_DATA_INDEX( nodeIndex32 ), float32Array, obb2 );
- obb2.matrix.copy( invertedMat );
- obb2.needsUpdate = true;
-
- const res = otherGeometry.boundsTree.shapecast( {
-
- intersectsBounds: box => obb2.intersectsBox( box ),
-
- intersectsTriangle: tri => {
-
- tri.a.applyMatrix4( geometryToBvh );
- tri.b.applyMatrix4( geometryToBvh );
- tri.c.applyMatrix4( geometryToBvh );
- tri.needsUpdate = true;
-
- for ( let i = offset * 3, l = ( count + offset ) * 3; i < l; i += 3 ) {
-
- // this triangle needs to be transformed into the current BVH coordinate frame
- setTriangle( triangle2, i, thisIndex, thisPos );
- triangle2.needsUpdate = true;
- if ( tri.intersectsTriangle( triangle2 ) ) {
-
- return true;
-
- }
-
- }
-
- return false;
-
- }
-
- } );
-
- return res;
-
- } else {
-
- for ( let i = offset * 3, l = ( count + offset * 3 ); i < l; i += 3 ) {
-
- // this triangle needs to be transformed into the current BVH coordinate frame
- setTriangle( triangle, i, thisIndex, thisPos );
- triangle.a.applyMatrix4( invertedMat );
- triangle.b.applyMatrix4( invertedMat );
- triangle.c.applyMatrix4( invertedMat );
- triangle.needsUpdate = true;
-
- for ( let i2 = 0, l2 = index.count; i2 < l2; i2 += 3 ) {
-
- setTriangle( triangle2, i2, index, pos );
- triangle2.needsUpdate = true;
-
- if ( triangle.intersectsTriangle( triangle2 ) ) {
-
- return true;
-
- }
-
- }
-
- }
-
- }
-
- } else {
-
- const left = nodeIndex32 + 8;
- const right = uint32Array[ nodeIndex32 + 6 ];
-
- arrayToBox( BOUNDING_DATA_INDEX( left ), float32Array, boundingBox$1 );
- const leftIntersection =
- cachedObb.intersectsBox( boundingBox$1 ) &&
- intersectsGeometry( left, geometry, otherGeometry, geometryToBvh, cachedObb );
-
- if ( leftIntersection ) return true;
-
- arrayToBox( BOUNDING_DATA_INDEX( right ), float32Array, boundingBox$1 );
- const rightIntersection =
- cachedObb.intersectsBox( boundingBox$1 ) &&
- intersectsGeometry( right, geometry, otherGeometry, geometryToBvh, cachedObb );
-
- if ( rightIntersection ) return true;
-
- return false;
-
- }
-
- };
-
-} )();
-
-function intersectRay( nodeIndex32, array, ray, target ) {
-
- arrayToBox( nodeIndex32, array, boundingBox$1 );
- return ray.intersectBox( boundingBox$1, target );
-
-}
-
-const bufferStack = [];
-let _prevBuffer;
-let _float32Array;
-let _uint16Array;
-let _uint32Array;
-function setBuffer( buffer ) {
-
- if ( _prevBuffer ) {
-
- bufferStack.push( _prevBuffer );
-
- }
-
- _prevBuffer = buffer;
- _float32Array = new Float32Array( buffer );
- _uint16Array = new Uint16Array( buffer );
- _uint32Array = new Uint32Array( buffer );
-
-}
-
-function clearBuffer() {
-
- _prevBuffer = null;
- _float32Array = null;
- _uint16Array = null;
- _uint32Array = null;
-
- if ( bufferStack.length ) {
-
- setBuffer( bufferStack.pop() );
-
- }
-
-}
-
-const SKIP_GENERATION = Symbol( 'skip tree generation' );
-
-const aabb = /* @__PURE__ */ new Box3();
-const aabb2 = /* @__PURE__ */ new Box3();
-const tempMatrix = /* @__PURE__ */ new Matrix4();
-const obb = /* @__PURE__ */ new OrientedBox();
-const obb2 = /* @__PURE__ */ new OrientedBox();
-const temp = /* @__PURE__ */ new Vector3();
-const temp1 = /* @__PURE__ */ new Vector3();
-const temp2 = /* @__PURE__ */ new Vector3();
-const temp3 = /* @__PURE__ */ new Vector3();
-const temp4 = /* @__PURE__ */ new Vector3();
-const tempBox = /* @__PURE__ */ new Box3();
-const trianglePool = /* @__PURE__ */ new PrimitivePool( () => new SeparatingAxisTriangle() );
-
-class MeshBVH {
-
- static serialize( bvh, options = {} ) {
-
- if ( options.isBufferGeometry ) {
-
- console.warn( 'MeshBVH.serialize: The arguments for the function have changed. See documentation for new signature.' );
-
- return MeshBVH.serialize(
- arguments[ 0 ],
- {
- cloneBuffers: arguments[ 2 ] === undefined ? true : arguments[ 2 ],
- }
- );
-
- }
-
- options = {
- cloneBuffers: true,
- ...options,
- };
-
- const geometry = bvh.geometry;
- const rootData = bvh._roots;
- const indexAttribute = geometry.getIndex();
- let result;
- if ( options.cloneBuffers ) {
-
- result = {
- roots: rootData.map( root => root.slice() ),
- index: indexAttribute.array.slice(),
- };
-
- } else {
-
- result = {
- roots: rootData,
- index: indexAttribute.array,
- };
-
- }
-
- return result;
-
- }
-
- static deserialize( data, geometry, options = {} ) {
-
- if ( typeof options === 'boolean' ) {
-
- console.warn( 'MeshBVH.deserialize: The arguments for the function have changed. See documentation for new signature.' );
-
- return MeshBVH.deserialize(
- arguments[ 0 ],
- arguments[ 1 ],
- {
- setIndex: arguments[ 2 ] === undefined ? true : arguments[ 2 ],
- }
- );
-
- }
-
- options = {
- setIndex: true,
- ...options,
- };
-
- const { index, roots } = data;
- const bvh = new MeshBVH( geometry, { ...options, [ SKIP_GENERATION ]: true } );
- bvh._roots = roots;
-
- if ( options.setIndex ) {
-
- const indexAttribute = geometry.getIndex();
- if ( indexAttribute === null ) {
-
- const newIndex = new BufferAttribute( data.index, 1, false );
- geometry.setIndex( newIndex );
-
- } else if ( indexAttribute.array !== index ) {
-
- indexAttribute.array.set( index );
- indexAttribute.needsUpdate = true;
-
- }
-
- }
-
- return bvh;
-
- }
-
- constructor( geometry, options = {} ) {
-
- if ( ! geometry.isBufferGeometry ) {
-
- throw new Error( 'MeshBVH: Only BufferGeometries are supported.' );
-
- } else if ( geometry.index && geometry.index.isInterleavedBufferAttribute ) {
-
- throw new Error( 'MeshBVH: InterleavedBufferAttribute is not supported for the index attribute.' );
-
- }
-
- // default options
- options = Object.assign( {
-
- strategy: CENTER,
- maxDepth: 40,
- maxLeafTris: 10,
- verbose: true,
- useSharedArrayBuffer: false,
- setBoundingBox: true,
- onProgress: null,
-
- // undocumented options
-
- // Whether to skip generating the tree. Used for deserialization.
- [ SKIP_GENERATION ]: false,
-
- }, options );
-
- if ( options.useSharedArrayBuffer && typeof SharedArrayBuffer === 'undefined' ) {
-
- throw new Error( 'MeshBVH: SharedArrayBuffer is not available.' );
-
- }
-
- this._roots = null;
- if ( ! options[ SKIP_GENERATION ] ) {
-
- this._roots = buildPackedTree( geometry, options );
-
- if ( ! geometry.boundingBox && options.setBoundingBox ) {
-
- geometry.boundingBox = this.getBoundingBox( new Box3() );
-
- }
-
- }
-
- // retain references to the geometry so we can use them it without having to
- // take a geometry reference in every function.
- this.geometry = geometry;
-
- }
-
- refit( nodeIndices = null ) {
-
- if ( nodeIndices && Array.isArray( nodeIndices ) ) {
-
- nodeIndices = new Set( nodeIndices );
-
- }
-
- const geometry = this.geometry;
- const indexArr = geometry.index.array;
- const posAttr = geometry.attributes.position;
- const posArr = posAttr.array;
-
- // support for an interleaved position buffer
- const bufferOffset = posAttr.offset || 0;
- let stride = 3;
- if ( posAttr.isInterleavedBufferAttribute ) {
-
- stride = posAttr.data.stride;
-
- }
-
- let buffer, uint32Array, uint16Array, float32Array;
- let byteOffset = 0;
- const roots = this._roots;
- for ( let i = 0, l = roots.length; i < l; i ++ ) {
-
- buffer = roots[ i ];
- uint32Array = new Uint32Array( buffer );
- uint16Array = new Uint16Array( buffer );
- float32Array = new Float32Array( buffer );
-
- _traverse( 0, byteOffset );
- byteOffset += buffer.byteLength;
-
- }
-
- function _traverse( node32Index, byteOffset, force = false ) {
-
- const node16Index = node32Index * 2;
- const isLeaf = uint16Array[ node16Index + 15 ] === IS_LEAFNODE_FLAG;
- if ( isLeaf ) {
-
- const offset = uint32Array[ node32Index + 6 ];
- const count = uint16Array[ node16Index + 14 ];
-
- let minx = Infinity;
- let miny = Infinity;
- let minz = Infinity;
- let maxx = - Infinity;
- let maxy = - Infinity;
- let maxz = - Infinity;
- for ( let i = 3 * offset, l = 3 * ( offset + count ); i < l; i ++ ) {
-
- const index = indexArr[ i ] * stride + bufferOffset;
- const x = posArr[ index + 0 ];
- const y = posArr[ index + 1 ];
- const z = posArr[ index + 2 ];
-
- if ( x < minx ) minx = x;
- if ( x > maxx ) maxx = x;
-
- if ( y < miny ) miny = y;
- if ( y > maxy ) maxy = y;
-
- if ( z < minz ) minz = z;
- if ( z > maxz ) maxz = z;
-
- }
-
- 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
- ) {
-
- float32Array[ node32Index + 0 ] = minx;
- float32Array[ node32Index + 1 ] = miny;
- float32Array[ node32Index + 2 ] = minz;
-
- float32Array[ node32Index + 3 ] = maxx;
- float32Array[ node32Index + 4 ] = maxy;
- float32Array[ node32Index + 5 ] = maxz;
-
- return true;
-
- } else {
-
- return false;
-
- }
-
- } else {
-
- const left = node32Index + 8;
- const right = uint32Array[ node32Index + 6 ];
-
- // the identifying node indices provided by the shapecast function include offsets of all
- // root buffers to guarantee they're unique between roots so offset left and right indices here.
- const offsetLeft = left + byteOffset;
- const offsetRight = right + byteOffset;
- let forceChildren = force;
- let includesLeft = false;
- let includesRight = false;
-
- if ( nodeIndices ) {
-
- // if we see that neither the left or right child are included in the set that need to be updated
- // then we assume that all children need to be updated.
- if ( ! forceChildren ) {
-
- includesLeft = nodeIndices.has( offsetLeft );
- includesRight = nodeIndices.has( offsetRight );
- forceChildren = ! includesLeft && ! includesRight;
-
- }
-
- } else {
-
- includesLeft = true;
- includesRight = true;
-
- }
-
- const traverseLeft = forceChildren || includesLeft;
- const traverseRight = forceChildren || includesRight;
-
- let leftChange = false;
- if ( traverseLeft ) {
-
- leftChange = _traverse( left, byteOffset, forceChildren );
-
- }
-
- let rightChange = false;
- if ( traverseRight ) {
-
- rightChange = _traverse( right, byteOffset, forceChildren );
-
- }
-
- const didChange = leftChange || rightChange;
- if ( didChange ) {
-
- for ( let i = 0; i < 3; i ++ ) {
-
- const lefti = left + i;
- const righti = right + i;
- const minLeftValue = float32Array[ lefti ];
- const maxLeftValue = float32Array[ lefti + 3 ];
- const minRightValue = float32Array[ righti ];
- const maxRightValue = float32Array[ righti + 3 ];
-
- float32Array[ node32Index + i ] = minLeftValue < minRightValue ? minLeftValue : minRightValue;
- float32Array[ node32Index + i + 3 ] = maxLeftValue > maxRightValue ? maxLeftValue : maxRightValue;
-
- }
-
- }
-
- return didChange;
-
- }
-
- }
-
- }
-
- traverse( callback, rootIndex = 0 ) {
-
- const buffer = this._roots[ rootIndex ];
- const uint32Array = new Uint32Array( buffer );
- const uint16Array = new Uint16Array( buffer );
- _traverse( 0 );
-
- function _traverse( node32Index, depth = 0 ) {
-
- const node16Index = node32Index * 2;
- const isLeaf = uint16Array[ node16Index + 15 ] === IS_LEAFNODE_FLAG;
- if ( isLeaf ) {
-
- const offset = uint32Array[ node32Index + 6 ];
- const count = uint16Array[ node16Index + 14 ];
- callback( depth, isLeaf, new Float32Array( buffer, node32Index * 4, 6 ), offset, count );
-
- } else {
-
- // TODO: use node functions here
- const left = node32Index + BYTES_PER_NODE / 4;
- const right = uint32Array[ node32Index + 6 ];
- const splitAxis = uint32Array[ node32Index + 7 ];
- const stopTraversal = callback( depth, isLeaf, new Float32Array( buffer, node32Index * 4, 6 ), splitAxis );
-
- if ( ! stopTraversal ) {
-
- _traverse( left, depth + 1 );
- _traverse( right, depth + 1 );
-
- }
-
- }
-
- }
-
- }
-
- /* Core Cast Functions */
- raycast( ray, materialOrSide = FrontSide ) {
-
- const roots = this._roots;
- const geometry = this.geometry;
- const intersects = [];
- const isMaterial = materialOrSide.isMaterial;
- const isArrayMaterial = Array.isArray( materialOrSide );
-
- const groups = geometry.groups;
- const side = isMaterial ? materialOrSide.side : materialOrSide;
- for ( let i = 0, l = roots.length; i < l; i ++ ) {
-
- const materialSide = isArrayMaterial ? materialOrSide[ groups[ i ].materialIndex ].side : side;
- const startCount = intersects.length;
-
- setBuffer( roots[ i ] );
- raycast( 0, geometry, materialSide, ray, intersects );
- clearBuffer();
-
- if ( isArrayMaterial ) {
-
- const materialIndex = groups[ i ].materialIndex;
- for ( let j = startCount, jl = intersects.length; j < jl; j ++ ) {
-
- intersects[ j ].face.materialIndex = materialIndex;
-
- }
-
- }
-
- }
-
- return intersects;
-
- }
-
- raycastFirst( ray, materialOrSide = FrontSide ) {
-
- const roots = this._roots;
- const geometry = this.geometry;
- const isMaterial = materialOrSide.isMaterial;
- const isArrayMaterial = Array.isArray( materialOrSide );
-
- let closestResult = null;
-
- const groups = geometry.groups;
- const side = isMaterial ? materialOrSide.side : materialOrSide;
- for ( let i = 0, l = roots.length; i < l; i ++ ) {
-
- const materialSide = isArrayMaterial ? materialOrSide[ groups[ i ].materialIndex ].side : side;
-
- setBuffer( roots[ i ] );
- const result = raycastFirst( 0, geometry, materialSide, ray );
- clearBuffer();
-
- if ( result != null && ( closestResult == null || result.distance < closestResult.distance ) ) {
-
- closestResult = result;
- if ( isArrayMaterial ) {
-
- result.face.materialIndex = groups[ i ].materialIndex;
-
- }
-
- }
-
- }
-
- return closestResult;
-
- }
-
- intersectsGeometry( otherGeometry, geomToMesh ) {
-
- const geometry = this.geometry;
- let result = false;
- for ( const root of this._roots ) {
-
- setBuffer( root );
- result = intersectsGeometry( 0, geometry, otherGeometry, geomToMesh );
- clearBuffer();
-
- if ( result ) {
-
- break;
-
- }
-
- }
-
- return result;
-
- }
-
- shapecast( callbacks, _intersectsTriangleFunc, _orderNodesFunc ) {
-
- const geometry = this.geometry;
- if ( callbacks instanceof Function ) {
-
- if ( _intersectsTriangleFunc ) {
-
- // Support the previous function signature that provided three sequential index buffer
- // indices here.
- const originalTriangleFunc = _intersectsTriangleFunc;
- _intersectsTriangleFunc = ( tri, index, contained, depth ) => {
-
- const i3 = index * 3;
- return originalTriangleFunc( tri, i3, i3 + 1, i3 + 2, contained, depth );
-
- };
-
-
- }
-
- callbacks = {
-
- boundsTraverseOrder: _orderNodesFunc,
- intersectsBounds: callbacks,
- intersectsTriangle: _intersectsTriangleFunc,
- intersectsRange: null,
-
- };
-
- console.warn( 'MeshBVH: Shapecast function signature has changed and now takes an object of callbacks as a second argument. See docs for new signature.' );
-
- }
-
- const triangle = trianglePool.getPrimitive();
- let {
- boundsTraverseOrder,
- intersectsBounds,
- intersectsRange,
- intersectsTriangle,
- } = callbacks;
-
- if ( intersectsRange && intersectsTriangle ) {
-
- const originalIntersectsRange = intersectsRange;
- intersectsRange = ( offset, count, contained, depth, nodeIndex ) => {
-
- if ( ! originalIntersectsRange( offset, count, contained, depth, nodeIndex ) ) {
-
- return iterateOverTriangles( offset, count, geometry, intersectsTriangle, contained, depth, triangle );
-
- }
-
- return true;
-
- };
-
- } else if ( ! intersectsRange ) {
-
- if ( intersectsTriangle ) {
-
- intersectsRange = ( offset, count, contained, depth ) => {
-
- return iterateOverTriangles( offset, count, geometry, intersectsTriangle, contained, depth, triangle );
-
- };
-
- } else {
-
- intersectsRange = ( offset, count, contained ) => {
-
- return contained;
-
- };
-
- }
-
- }
-
- let result = false;
- let byteOffset = 0;
- for ( const root of this._roots ) {
-
- setBuffer( root );
- result = shapecast( 0, geometry, intersectsBounds, intersectsRange, boundsTraverseOrder, byteOffset );
- clearBuffer();
-
- if ( result ) {
-
- break;
-
- }
-
- byteOffset += root.byteLength;
-
- }
-
- trianglePool.releasePrimitive( triangle );
-
- return result;
-
- }
-
- bvhcast( otherBvh, matrixToLocal, callbacks ) {
-
- // BVHCast function for intersecting two BVHs against each other. Ultimately just uses two recursive shapecast calls rather
- // than an approach that walks down the tree (see bvhcast.js file for more info).
-
- let {
- intersectsRanges,
- intersectsTriangles,
- } = callbacks;
-
- const indexAttr = this.geometry.index;
- const positionAttr = this.geometry.attributes.position;
-
- const otherIndexAttr = otherBvh.geometry.index;
- const otherPositionAttr = otherBvh.geometry.attributes.position;
-
- tempMatrix.copy( matrixToLocal ).invert();
-
- const triangle = trianglePool.getPrimitive();
- const triangle2 = trianglePool.getPrimitive();
-
- if ( intersectsTriangles ) {
-
- function iterateOverDoubleTriangles( offset1, count1, offset2, count2, depth1, index1, depth2, index2 ) {
-
- for ( let i2 = offset2, l2 = offset2 + count2; i2 < l2; i2 ++ ) {
-
- setTriangle( triangle2, i2 * 3, otherIndexAttr, otherPositionAttr );
- triangle2.a.applyMatrix4( matrixToLocal );
- triangle2.b.applyMatrix4( matrixToLocal );
- triangle2.c.applyMatrix4( matrixToLocal );
- triangle2.needsUpdate = true;
-
- for ( let i1 = offset1, l1 = offset1 + count1; i1 < l1; i1 ++ ) {
-
- setTriangle( triangle, i1 * 3, indexAttr, positionAttr );
- triangle.needsUpdate = true;
-
- if ( intersectsTriangles( triangle, triangle2, i1, i2, depth1, index1, depth2, index2 ) ) {
-
- return true;
-
- }
-
- }
-
- }
-
- return false;
-
- }
-
- if ( intersectsRanges ) {
-
- const originalIntersectsRanges = intersectsRanges;
- intersectsRanges = function ( offset1, count1, offset2, count2, depth1, index1, depth2, index2 ) {
-
- if ( ! originalIntersectsRanges( offset1, count1, offset2, count2, depth1, index1, depth2, index2 ) ) {
-
- return iterateOverDoubleTriangles( offset1, count1, offset2, count2, depth1, index1, depth2, index2 );
-
- }
-
- return true;
-
- };
-
- } else {
-
- intersectsRanges = iterateOverDoubleTriangles;
-
- }
-
- }
-
- this.getBoundingBox( aabb2 );
- aabb2.applyMatrix4( matrixToLocal );
- const result = this.shapecast( {
-
- intersectsBounds: box => aabb2.intersectsBox( box ),
-
- intersectsRange: ( offset1, count1, contained, depth1, nodeIndex1, box ) => {
-
- aabb.copy( box );
- aabb.applyMatrix4( tempMatrix );
- return otherBvh.shapecast( {
-
- intersectsBounds: box => aabb.intersectsBox( box ),
-
- intersectsRange: ( offset2, count2, contained, depth2, nodeIndex2 ) => {
-
- return intersectsRanges( offset1, count1, offset2, count2, depth1, nodeIndex1, depth2, nodeIndex2 );
-
- },
-
- } );
-
- }
-
- } );
-
- trianglePool.releasePrimitive( triangle );
- trianglePool.releasePrimitive( triangle2 );
- return result;
-
- }
-
- /* Derived Cast Functions */
- intersectsBox( box, boxToMesh ) {
-
- obb.set( box.min, box.max, boxToMesh );
- obb.needsUpdate = true;
-
- return this.shapecast(
- {
- intersectsBounds: box => obb.intersectsBox( box ),
- intersectsTriangle: tri => obb.intersectsTriangle( tri )
- }
- );
-
- }
-
- intersectsSphere( sphere ) {
-
- return this.shapecast(
- {
- intersectsBounds: box => sphere.intersectsBox( box ),
- intersectsTriangle: tri => tri.intersectsSphere( sphere )
- }
- );
-
- }
-
- closestPointToGeometry( otherGeometry, geometryToBvh, target1 = { }, target2 = { }, minThreshold = 0, maxThreshold = Infinity ) {
-
- if ( ! otherGeometry.boundingBox ) {
-
- otherGeometry.computeBoundingBox();
-
- }
-
- obb.set( otherGeometry.boundingBox.min, otherGeometry.boundingBox.max, geometryToBvh );
- obb.needsUpdate = true;
-
- const geometry = this.geometry;
- const pos = geometry.attributes.position;
- const index = geometry.index;
- const otherPos = otherGeometry.attributes.position;
- const otherIndex = otherGeometry.index;
- const triangle = trianglePool.getPrimitive();
- const triangle2 = trianglePool.getPrimitive();
-
- let tempTarget1 = temp1;
- let tempTargetDest1 = temp2;
- let tempTarget2 = null;
- let tempTargetDest2 = null;
-
- if ( target2 ) {
-
- tempTarget2 = temp3;
- tempTargetDest2 = temp4;
-
- }
-
- let closestDistance = Infinity;
- let closestDistanceTriIndex = null;
- let closestDistanceOtherTriIndex = null;
- tempMatrix.copy( geometryToBvh ).invert();
- obb2.matrix.copy( tempMatrix );
- this.shapecast(
- {
-
- boundsTraverseOrder: box => {
-
- return obb.distanceToBox( box, Math.min( closestDistance, maxThreshold ) );
-
- },
-
- intersectsBounds: ( box, isLeaf, score ) => {
-
- if ( score < closestDistance && score < maxThreshold ) {
-
- // if we know the triangles of this bounds will be intersected next then
- // save the bounds to use during triangle checks.
- if ( isLeaf ) {
-
- obb2.min.copy( box.min );
- obb2.max.copy( box.max );
- obb2.needsUpdate = true;
-
- }
-
- return true;
-
- }
-
- return false;
-
- },
-
- intersectsRange: ( offset, count ) => {
-
- if ( otherGeometry.boundsTree ) {
-
- // if the other geometry has a bvh then use the accelerated path where we use shapecast to find
- // the closest bounds in the other geometry to check.
- return otherGeometry.boundsTree.shapecast( {
- boundsTraverseOrder: box => {
-
- return obb2.distanceToBox( box, Math.min( closestDistance, maxThreshold ) );
-
- },
-
- intersectsBounds: ( box, isLeaf, score ) => {
-
- return score < closestDistance && score < maxThreshold;
-
- },
-
- intersectsRange: ( otherOffset, otherCount ) => {
-
- for ( let i2 = otherOffset * 3, l2 = ( otherOffset + otherCount ) * 3; i2 < l2; i2 += 3 ) {
-
- setTriangle( triangle2, i2, otherIndex, otherPos );
- triangle2.a.applyMatrix4( geometryToBvh );
- triangle2.b.applyMatrix4( geometryToBvh );
- triangle2.c.applyMatrix4( geometryToBvh );
- triangle2.needsUpdate = true;
-
- for ( let i = offset * 3, l = ( offset + count ) * 3; i < l; i += 3 ) {
-
- setTriangle( triangle, i, index, pos );
- triangle.needsUpdate = true;
-
- const dist = triangle.distanceToTriangle( triangle2, tempTarget1, tempTarget2 );
- if ( dist < closestDistance ) {
-
- tempTargetDest1.copy( tempTarget1 );
-
- if ( tempTargetDest2 ) {
-
- tempTargetDest2.copy( tempTarget2 );
-
- }
-
- closestDistance = dist;
- closestDistanceTriIndex = i / 3;
- closestDistanceOtherTriIndex = i2 / 3;
-
- }
-
- // stop traversal if we find a point that's under the given threshold
- if ( dist < minThreshold ) {
-
- return true;
-
- }
-
- }
-
- }
-
- },
- } );
-
- } else {
-
- // If no bounds tree then we'll just check every triangle.
- const triCount = otherIndex ? otherIndex.count : otherPos.count;
- for ( let i2 = 0, l2 = triCount; i2 < l2; i2 += 3 ) {
-
- setTriangle( triangle2, i2, otherIndex, otherPos );
- triangle2.a.applyMatrix4( geometryToBvh );
- triangle2.b.applyMatrix4( geometryToBvh );
- triangle2.c.applyMatrix4( geometryToBvh );
- triangle2.needsUpdate = true;
-
- for ( let i = offset * 3, l = ( offset + count ) * 3; i < l; i += 3 ) {
-
- setTriangle( triangle, i, index, pos );
- triangle.needsUpdate = true;
-
- const dist = triangle.distanceToTriangle( triangle2, tempTarget1, tempTarget2 );
- if ( dist < closestDistance ) {
-
- tempTargetDest1.copy( tempTarget1 );
-
- if ( tempTargetDest2 ) {
-
- tempTargetDest2.copy( tempTarget2 );
-
- }
-
- closestDistance = dist;
- closestDistanceTriIndex = i / 3;
- closestDistanceOtherTriIndex = i2 / 3;
-
- }
-
- // stop traversal if we find a point that's under the given threshold
- if ( dist < minThreshold ) {
-
- return true;
-
- }
-
- }
-
- }
-
- }
-
- },
-
- }
-
- );
-
- trianglePool.releasePrimitive( triangle );
- trianglePool.releasePrimitive( triangle2 );
-
- if ( closestDistance === Infinity ) return null;
-
- if ( ! target1.point ) target1.point = tempTargetDest1.clone();
- else target1.point.copy( tempTargetDest1 );
- target1.distance = closestDistance,
- target1.faceIndex = closestDistanceTriIndex;
-
- if ( target2 ) {
-
- if ( ! target2.point ) target2.point = tempTargetDest2.clone();
- else target2.point.copy( tempTargetDest2 );
- target2.point.applyMatrix4( tempMatrix );
- tempTargetDest1.applyMatrix4( tempMatrix );
- target2.distance = tempTargetDest1.sub( target2.point ).length();
- target2.faceIndex = closestDistanceOtherTriIndex;
-
- }
-
- return target1;
-
- }
-
- closestPointToPoint( point, target = { }, minThreshold = 0, maxThreshold = Infinity ) {
-
- // early out if under minThreshold
- // skip checking if over maxThreshold
- // set minThreshold = maxThreshold to quickly check if a point is within a threshold
- // returns Infinity if no value found
- const minThresholdSq = minThreshold * minThreshold;
- const maxThresholdSq = maxThreshold * maxThreshold;
- let closestDistanceSq = Infinity;
- let closestDistanceTriIndex = null;
- this.shapecast(
-
- {
-
- boundsTraverseOrder: box => {
-
- temp.copy( point ).clamp( box.min, box.max );
- return temp.distanceToSquared( point );
-
- },
-
- intersectsBounds: ( box, isLeaf, score ) => {
-
- return score < closestDistanceSq && score < maxThresholdSq;
-
- },
-
- intersectsTriangle: ( tri, triIndex ) => {
-
- tri.closestPointToPoint( point, temp );
- const distSq = point.distanceToSquared( temp );
- if ( distSq < closestDistanceSq ) {
-
- temp1.copy( temp );
- closestDistanceSq = distSq;
- closestDistanceTriIndex = triIndex;
-
- }
-
- if ( distSq < minThresholdSq ) {
-
- return true;
-
- } else {
-
- return false;
-
- }
-
- },
-
- }
-
- );
-
- if ( closestDistanceSq === Infinity ) return null;
-
- const closestDistance = Math.sqrt( closestDistanceSq );
-
- if ( ! target.point ) target.point = temp1.clone();
- else target.point.copy( temp1 );
- target.distance = closestDistance,
- target.faceIndex = closestDistanceTriIndex;
-
- return target;
-
- }
-
- getBoundingBox( target ) {
-
- target.makeEmpty();
-
- const roots = this._roots;
- roots.forEach( buffer => {
-
- arrayToBox( 0, new Float32Array( buffer ), tempBox );
- target.union( tempBox );
-
- } );
-
- return target;
-
- }
-
-}
-
-// Deprecation
-const originalRaycast = MeshBVH.prototype.raycast;
-MeshBVH.prototype.raycast = function ( ...args ) {
-
- if ( args[ 0 ].isMesh ) {
-
- console.warn( 'MeshBVH: The function signature and results frame for "raycast" has changed. See docs for new signature.' );
- const [
- mesh, raycaster, ray, intersects,
- ] = args;
-
- const results = originalRaycast.call( this, ray, mesh.material );
- results.forEach( hit => {
-
- hit = convertRaycastIntersect( hit, mesh, raycaster );
- if ( hit ) {
-
- intersects.push( hit );
-
- }
-
- } );
-
- return intersects;
-
- } else {
-
- return originalRaycast.apply( this, args );
-
- }
-
-};
-
-const originalRaycastFirst = MeshBVH.prototype.raycastFirst;
-MeshBVH.prototype.raycastFirst = function ( ...args ) {
-
- if ( args[ 0 ].isMesh ) {
-
- console.warn( 'MeshBVH: The function signature and results frame for "raycastFirst" has changed. See docs for new signature.' );
- const [
- mesh, raycaster, ray,
- ] = args;
-
- return convertRaycastIntersect( originalRaycastFirst.call( this, ray, mesh.material ), mesh, raycaster );
-
- } else {
-
- return originalRaycastFirst.apply( this, args );
-
- }
-
-};
-
-const originalClosestPointToPoint = MeshBVH.prototype.closestPointToPoint;
-MeshBVH.prototype.closestPointToPoint = function ( ...args ) {
-
-
- if ( args[ 0 ].isMesh ) {
-
- console.warn( 'MeshBVH: The function signature and results frame for "closestPointToPoint" has changed. See docs for new signature.' );
-
- args.unshift();
-
- const target = args[ 1 ];
- const result = {};
- args[ 1 ] = result;
-
- originalClosestPointToPoint.apply( this, args );
-
- if ( target ) {
-
- target.copy( result.point );
-
- }
-
- return result.distance;
-
- } else {
-
- return originalClosestPointToPoint.apply( this, args );
-
- }
-
-};
-
-const originalClosestPointToGeometry = MeshBVH.prototype.closestPointToGeometry;
-MeshBVH.prototype.closestPointToGeometry = function ( ...args ) {
-
- const target1 = args[ 2 ];
- const target2 = args[ 3 ];
- if ( target1 && target1.isVector3 || target2 && target2.isVector3 ) {
-
- console.warn( 'MeshBVH: The function signature and results frame for "closestPointToGeometry" has changed. See docs for new signature.' );
-
- const result1 = {};
- const result2 = {};
- const geometryToBvh = args[ 1 ];
- args[ 2 ] = result1;
- args[ 3 ] = result2;
-
- originalClosestPointToGeometry.apply( this, args );
-
- if ( target1 ) {
-
- target1.copy( result1.point );
-
- }
-
- if ( target2 ) {
-
- target2.copy( result2.point ).applyMatrix4( geometryToBvh );
-
- }
-
- return result1.distance;
-
- } else {
-
- return originalClosestPointToGeometry.apply( this, args );
-
- }
-
-};
-
-const originalRefit = MeshBVH.prototype.refit;
-MeshBVH.prototype.refit = function ( ...args ) {
-
- const nodeIndices = args[ 0 ];
- const terminationIndices = args[ 1 ];
- if ( terminationIndices && ( terminationIndices instanceof Set || Array.isArray( terminationIndices ) ) ) {
-
- console.warn( 'MeshBVH: The function signature for "refit" has changed. See docs for new signature.' );
-
- const newNodeIndices = new Set();
- terminationIndices.forEach( v => newNodeIndices.add( v ) );
- if ( nodeIndices ) {
-
- nodeIndices.forEach( v => newNodeIndices.add( v ) );
-
- }
-
- originalRefit.call( this, newNodeIndices );
-
- } else {
-
- originalRefit.apply( this, args );
-
- }
-
-};
-
-[
- 'intersectsGeometry',
- 'shapecast',
- 'intersectsBox',
- 'intersectsSphere',
-].forEach( name => {
-
- const originalFunc = MeshBVH.prototype[ name ];
- MeshBVH.prototype[ name ] = function ( ...args ) {
-
- if ( args[ 0 ] === null || args[ 0 ].isMesh ) {
-
- args.shift();
- console.warn( `MeshBVH: The function signature for "${ name }" has changed and no longer takes Mesh. See docs for new signature.` );
-
- }
-
- return originalFunc.apply( this, args );
-
- };
-
-} );
-
-const boundingBox = /* @__PURE__ */ new Box3();
-class MeshBVHRootVisualizer extends Object3D {
-
- get isMesh() {
-
- return ! this.displayEdges;
-
- }
-
- get isLineSegments() {
-
- return this.displayEdges;
-
- }
-
- get isLine() {
-
- return this.displayEdges;
-
- }
-
- constructor( mesh, material, depth = 10, group = 0 ) {
-
- super();
-
- this.material = material;
- this.geometry = new BufferGeometry();
- this.name = 'MeshBVHRootVisualizer';
- this.depth = depth;
- this.displayParents = false;
- this.mesh = mesh;
- this.displayEdges = true;
- this._group = group;
-
- }
-
- raycast() {}
-
- update() {
-
- const geometry = this.geometry;
- const boundsTree = this.mesh.geometry.boundsTree;
- const group = this._group;
- geometry.dispose();
- this.visible = false;
- if ( boundsTree ) {
-
- // count the number of bounds required
- const targetDepth = this.depth - 1;
- const displayParents = this.displayParents;
- let boundsCount = 0;
- boundsTree.traverse( ( depth, isLeaf ) => {
-
- if ( depth === targetDepth || isLeaf ) {
-
- boundsCount ++;
- return true;
-
- } else if ( displayParents ) {
-
- boundsCount ++;
-
- }
-
- }, group );
-
- // fill in the position buffer with the bounds corners
- let posIndex = 0;
- const positionArray = new Float32Array( 8 * 3 * boundsCount );
- boundsTree.traverse( ( depth, isLeaf, boundingData ) => {
-
- const terminate = depth === targetDepth || isLeaf;
- if ( terminate || displayParents ) {
-
- arrayToBox( 0, boundingData, boundingBox );
-
- const { min, max } = boundingBox;
- for ( let x = - 1; x <= 1; x += 2 ) {
-
- const xVal = x < 0 ? min.x : max.x;
- for ( let y = - 1; y <= 1; y += 2 ) {
-
- const yVal = y < 0 ? min.y : max.y;
- for ( let z = - 1; z <= 1; z += 2 ) {
-
- const zVal = z < 0 ? min.z : max.z;
- positionArray[ posIndex + 0 ] = xVal;
- positionArray[ posIndex + 1 ] = yVal;
- positionArray[ posIndex + 2 ] = zVal;
-
- posIndex += 3;
-
- }
-
- }
-
- }
-
- return terminate;
-
- }
-
- }, group );
-
- let indexArray;
- let indices;
- if ( this.displayEdges ) {
-
- // fill in the index buffer to point to the corner points
- indices = new Uint8Array( [
- // x axis
- 0, 4,
- 1, 5,
- 2, 6,
- 3, 7,
-
- // y axis
- 0, 2,
- 1, 3,
- 4, 6,
- 5, 7,
-
- // z axis
- 0, 1,
- 2, 3,
- 4, 5,
- 6, 7,
- ] );
-
- } else {
-
- indices = new Uint8Array( [
-
- // X-, X+
- 0, 1, 2,
- 2, 1, 3,
-
- 4, 6, 5,
- 6, 7, 5,
-
- // Y-, Y+
- 1, 4, 5,
- 0, 4, 1,
-
- 2, 3, 6,
- 3, 7, 6,
-
- // Z-, Z+
- 0, 2, 4,
- 2, 6, 4,
-
- 1, 5, 3,
- 3, 5, 7,
-
- ] );
-
- }
-
- if ( positionArray.length > 65535 ) {
-
- indexArray = new Uint32Array( indices.length * boundsCount );
-
- } else {
-
- indexArray = new Uint16Array( indices.length * boundsCount );
-
- }
-
- const indexLength = indices.length;
- for ( let i = 0; i < boundsCount; i ++ ) {
-
- const posOffset = i * 8;
- const indexOffset = i * indexLength;
- for ( let j = 0; j < indexLength; j ++ ) {
-
- indexArray[ indexOffset + j ] = posOffset + indices[ j ];
-
- }
-
- }
-
- // update the geometry
- geometry.setIndex(
- new BufferAttribute( indexArray, 1, false ),
- );
- geometry.setAttribute(
- 'position',
- new BufferAttribute( positionArray, 3, false ),
- );
- this.visible = true;
-
- }
-
- }
-
-}
-
-class MeshBVHVisualizer extends Group {
-
- get color() {
-
- return this.edgeMaterial.color;
-
- }
-
- get opacity() {
-
- return this.edgeMaterial.opacity;
-
- }
-
- set opacity( v ) {
-
- this.edgeMaterial.opacity = v;
- this.meshMaterial.opacity = v;
-
- }
-
- constructor( mesh, depth = 10 ) {
-
- super();
-
- this.name = 'MeshBVHVisualizer';
- this.depth = depth;
- this.mesh = mesh;
- this.displayParents = false;
- this.displayEdges = true;
- this._roots = [];
-
- const edgeMaterial = new LineBasicMaterial( {
- color: 0x00FF88,
- transparent: true,
- opacity: 0.3,
- depthWrite: false,
- } );
-
- const meshMaterial = new MeshBasicMaterial( {
- color: 0x00FF88,
- transparent: true,
- opacity: 0.3,
- depthWrite: false,
- } );
-
- meshMaterial.color = edgeMaterial.color;
-
- this.edgeMaterial = edgeMaterial;
- this.meshMaterial = meshMaterial;
-
- this.update();
-
- }
-
- update() {
-
- const bvh = this.mesh.geometry.boundsTree;
- const totalRoots = bvh ? bvh._roots.length : 0;
- while ( this._roots.length > totalRoots ) {
-
- this._roots.pop();
-
- }
-
- for ( let i = 0; i < totalRoots; i ++ ) {
-
- if ( i >= this._roots.length ) {
-
- const root = new MeshBVHRootVisualizer( this.mesh, this.edgeMaterial, this.depth, i );
- this.add( root );
- this._roots.push( root );
-
- }
-
- const root = this._roots[ i ];
- root.depth = this.depth;
- root.mesh = this.mesh;
- root.displayParents = this.displayParents;
- root.displayEdges = this.displayEdges;
- root.material = this.displayEdges ? this.edgeMaterial : this.meshMaterial;
- root.update();
-
- }
-
- }
-
- updateMatrixWorld( ...args ) {
-
- this.position.copy( this.mesh.position );
- this.rotation.copy( this.mesh.rotation );
- this.scale.copy( this.mesh.scale );
-
- super.updateMatrixWorld( ...args );
-
- }
-
- copy( source ) {
-
- this.depth = source.depth;
- this.mesh = source.mesh;
-
- }
-
- clone() {
-
- return new MeshBVHVisualizer( this.mesh, this.depth );
-
- }
-
- dispose() {
-
- this.edgeMaterial.dispose();
- this.meshMaterial.dispose();
-
- const children = this.children;
- for ( let i = 0, l = children.length; i < l; i ++ ) {
-
- children[ i ].geometry.dispose();
-
- }
-
- }
-
-}
-
-const _box1 = /* @__PURE__ */ new Box3();
-const _box2 = /* @__PURE__ */ new Box3();
-const _vec = /* @__PURE__ */ new Vector3();
-
-// https://stackoverflow.com/questions/1248302/how-to-get-the-size-of-a-javascript-object
-function getPrimitiveSize( el ) {
-
- switch ( typeof el ) {
-
- case 'number':
- return 8;
- case 'string':
- return el.length * 2;
- case 'boolean':
- return 4;
- default:
- return 0;
-
- }
-
-}
-
-function isTypedArray( arr ) {
-
- const regex = /(Uint|Int|Float)(8|16|32)Array/;
- return regex.test( arr.constructor.name );
-
-}
-
-function getRootExtremes( bvh, group ) {
-
- const result = {
- nodeCount: 0,
- leafNodeCount: 0,
-
- depth: {
- min: Infinity, max: - Infinity
- },
- tris: {
- min: Infinity, max: - Infinity
- },
- splits: [ 0, 0, 0 ],
- surfaceAreaScore: 0,
- };
-
- bvh.traverse( ( depth, isLeaf, boundingData, offsetOrSplit, count ) => {
-
- const l0 = boundingData[ 0 + 3 ] - boundingData[ 0 ];
- const l1 = boundingData[ 1 + 3 ] - boundingData[ 1 ];
- const l2 = boundingData[ 2 + 3 ] - boundingData[ 2 ];
-
- const surfaceArea = 2 * ( l0 * l1 + l1 * l2 + l2 * l0 );
-
- result.nodeCount ++;
- if ( isLeaf ) {
-
- result.leafNodeCount ++;
-
- result.depth.min = Math.min( depth, result.depth.min );
- result.depth.max = Math.max( depth, result.depth.max );
-
- result.tris.min = Math.min( count, result.tris.min );
- result.tris.max = Math.max( count, result.tris.max );
-
- result.surfaceAreaScore += surfaceArea * TRIANGLE_INTERSECT_COST * count;
-
- } else {
-
- result.splits[ offsetOrSplit ] ++;
-
- result.surfaceAreaScore += surfaceArea * TRAVERSAL_COST;
-
- }
-
- }, group );
-
- // If there are no leaf nodes because the tree hasn't finished generating yet.
- if ( result.tris.min === Infinity ) {
-
- result.tris.min = 0;
- result.tris.max = 0;
-
- }
-
- if ( result.depth.min === Infinity ) {
-
- result.depth.min = 0;
- result.depth.max = 0;
-
- }
-
- return result;
-
-}
-
-function getBVHExtremes( bvh ) {
-
- return bvh._roots.map( ( root, i ) => getRootExtremes( bvh, i ) );
-
-}
-
-function estimateMemoryInBytes( obj ) {
-
- const traversed = new Set();
- const stack = [ obj ];
- let bytes = 0;
-
- while ( stack.length ) {
-
- const curr = stack.pop();
- if ( traversed.has( curr ) ) {
-
- continue;
-
- }
-
- traversed.add( curr );
-
- for ( let key in curr ) {
-
- if ( ! curr.hasOwnProperty( key ) ) {
-
- continue;
-
- }
-
- bytes += getPrimitiveSize( key );
-
- const value = curr[ key ];
- if ( value && ( typeof value === 'object' || typeof value === 'function' ) ) {
-
- if ( isTypedArray( value ) ) {
-
- bytes += value.byteLength;
-
- } else if ( value instanceof ArrayBuffer ) {
-
- bytes += value.byteLength;
-
- } else {
-
- stack.push( value );
-
- }
-
- } else {
-
- bytes += getPrimitiveSize( value );
-
- }
-
-
- }
-
- }
-
- return bytes;
-
-}
-
-function validateBounds( bvh ) {
-
- const geometry = bvh.geometry;
- const depthStack = [];
- const index = geometry.index;
- const position = geometry.getAttribute( 'position' );
- let passes = true;
-
- bvh.traverse( ( depth, isLeaf, boundingData, offset, count ) => {
-
- const info = {
- depth,
- isLeaf,
- boundingData,
- offset,
- count,
- };
- depthStack[ depth ] = info;
-
- arrayToBox( 0, boundingData, _box1 );
- const parent = depthStack[ depth - 1 ];
-
- if ( isLeaf ) {
-
- // check triangles
- for ( let i = offset * 3, l = ( offset + count ) * 3; i < l; i += 3 ) {
-
- const i0 = index.getX( i );
- const i1 = index.getX( i + 1 );
- const i2 = index.getX( i + 2 );
-
- let isContained;
-
- _vec.fromBufferAttribute( position, i0 );
- isContained = _box1.containsPoint( _vec );
-
- _vec.fromBufferAttribute( position, i1 );
- isContained = isContained && _box1.containsPoint( _vec );
-
- _vec.fromBufferAttribute( position, i2 );
- isContained = isContained && _box1.containsPoint( _vec );
-
- console.assert( isContained, 'Leaf bounds does not fully contain triangle.' );
- passes = passes && isContained;
-
- }
-
- }
-
- if ( parent ) {
-
- // check if my bounds fit in my parents
- arrayToBox( 0, boundingData, _box2 );
-
- const isContained = _box2.containsBox( _box1 );
- console.assert( isContained, 'Parent bounds does not fully contain child.' );
- passes = passes && isContained;
-
- }
-
- } );
-
- return passes;
-
-}
-
-// Returns a simple, human readable object that represents the BVH.
-function getJSONStructure( bvh ) {
-
- const depthStack = [];
-
- bvh.traverse( ( depth, isLeaf, boundingData, offset, count ) => {
-
- const info = {
- bounds: arrayToBox( 0, boundingData, new Box3() ),
- };
-
- if ( isLeaf ) {
-
- info.count = count;
- info.offset = offset;
-
- } else {
-
- info.left = null;
- info.right = null;
-
- }
-
- depthStack[ depth ] = info;
-
- // traversal hits the left then right node
- const parent = depthStack[ depth - 1 ];
- if ( parent ) {
-
- if ( parent.left === null ) {
-
- parent.left = info;
-
- } else {
-
- parent.right = info;
-
- }
-
- }
-
- } );
-
- return depthStack[ 0 ];
-
-}
-
-const ray = /* @__PURE__ */ new Ray();
-const tmpInverseMatrix = /* @__PURE__ */ new Matrix4();
-const origMeshRaycastFunc = Mesh.prototype.raycast;
-
-function acceleratedRaycast( raycaster, intersects ) {
-
- if ( this.geometry.boundsTree ) {
-
- if ( this.material === undefined ) return;
-
- tmpInverseMatrix.copy( this.matrixWorld ).invert();
- ray.copy( raycaster.ray ).applyMatrix4( tmpInverseMatrix );
-
- const bvh = this.geometry.boundsTree;
- if ( raycaster.firstHitOnly === true ) {
-
- const hit = convertRaycastIntersect( bvh.raycastFirst( ray, this.material ), this, raycaster );
- if ( hit ) {
-
- intersects.push( hit );
-
- }
-
- } else {
-
- const hits = bvh.raycast( ray, this.material );
- for ( let i = 0, l = hits.length; i < l; i ++ ) {
-
- const hit = convertRaycastIntersect( hits[ i ], this, raycaster );
- if ( hit ) {
-
- intersects.push( hit );
-
- }
-
- }
-
- }
-
- } else {
-
- origMeshRaycastFunc.call( this, raycaster, intersects );
-
- }
-
-}
-
-function computeBoundsTree( options ) {
-
- this.boundsTree = new MeshBVH( this, options );
- return this.boundsTree;
-
-}
-
-function disposeBoundsTree() {
-
- this.boundsTree = null;
-
-}
-
-function countToStringFormat( count ) {
-
- switch ( count ) {
-
- case 1: return 'R';
- case 2: return 'RG';
- case 3: return 'RGBA';
- case 4: return 'RGBA';
-
- }
-
- throw new Error();
-
-}
-
-function countToFormat( count ) {
-
- switch ( count ) {
-
- case 1: return RedFormat;
- case 2: return RGFormat;
- case 3: return RGBAFormat;
- case 4: return RGBAFormat;
-
- }
-
-}
-
-function countToIntFormat( count ) {
-
- switch ( count ) {
-
- case 1: return RedIntegerFormat;
- case 2: return RGIntegerFormat;
- case 3: return RGBAIntegerFormat;
- case 4: return RGBAIntegerFormat;
-
- }
-
-}
-
-class VertexAttributeTexture extends DataTexture {
-
- constructor() {
-
- super();
- this.minFilter = NearestFilter;
- this.magFilter = NearestFilter;
- this.generateMipmaps = false;
- this.overrideItemSize = null;
- this._forcedType = null;
-
- }
-
- updateFrom( attr ) {
-
- const overrideItemSize = this.overrideItemSize;
- const originalItemSize = attr.itemSize;
- const originalCount = attr.count;
- if ( overrideItemSize !== null ) {
-
- if ( ( originalItemSize * originalCount ) % overrideItemSize !== 0.0 ) {
-
- throw new Error( 'VertexAttributeTexture: overrideItemSize must divide evenly into buffer length.' );
-
- }
-
- attr.itemSize = overrideItemSize;
- attr.count = originalCount * originalItemSize / overrideItemSize;
-
- }
-
- const itemSize = attr.itemSize;
- const count = attr.count;
- const normalized = attr.normalized;
- const originalBufferCons = attr.array.constructor;
- const byteCount = originalBufferCons.BYTES_PER_ELEMENT;
- let targetType = this._forcedType;
- let finalStride = itemSize;
-
- // derive the type of texture this should be in the shader
- if ( targetType === null ) {
-
- switch ( originalBufferCons ) {
-
- case Float32Array:
- targetType = FloatType;
- break;
-
- case Uint8Array:
- case Uint16Array:
- case Uint32Array:
- targetType = UnsignedIntType;
- break;
-
- case Int8Array:
- case Int16Array:
- case Int32Array:
- targetType = IntType;
- break;
-
- }
-
- }
-
- // get the target format to store the texture as
- let type, format, normalizeValue, targetBufferCons;
- let internalFormat = countToStringFormat( itemSize );
- switch ( targetType ) {
-
- case FloatType:
- normalizeValue = 1.0;
- format = countToFormat( itemSize );
-
- if ( normalized && byteCount === 1 ) {
-
- targetBufferCons = originalBufferCons;
- internalFormat += '8';
-
- if ( originalBufferCons === Uint8Array ) {
-
- type = UnsignedByteType;
-
- } else {
-
- type = ByteType;
- internalFormat += '_SNORM';
-
- }
-
- } else {
-
- targetBufferCons = Float32Array;
- internalFormat += '32F';
- type = FloatType;
-
- }
-
- break;
-
- case IntType:
- internalFormat += byteCount * 8 + 'I';
- normalizeValue = normalized ? Math.pow( 2, originalBufferCons.BYTES_PER_ELEMENT * 8 - 1 ) : 1.0;
- format = countToIntFormat( itemSize );
-
- if ( byteCount === 1 ) {
-
- targetBufferCons = Int8Array;
- type = ByteType;
-
- } else if ( byteCount === 2 ) {
-
- targetBufferCons = Int16Array;
- type = ShortType;
-
- } else {
-
- targetBufferCons = Int32Array;
- type = IntType;
-
- }
-
- break;
-
- case UnsignedIntType:
- internalFormat += byteCount * 8 + 'UI';
- normalizeValue = normalized ? Math.pow( 2, originalBufferCons.BYTES_PER_ELEMENT * 8 - 1 ) : 1.0;
- format = countToIntFormat( itemSize );
-
- if ( byteCount === 1 ) {
-
- targetBufferCons = Uint8Array;
- type = UnsignedByteType;
-
- } else if ( byteCount === 2 ) {
-
- targetBufferCons = Uint16Array;
- type = UnsignedShortType;
-
- } else {
-
- targetBufferCons = Uint32Array;
- type = UnsignedIntType;
-
- }
-
- break;
-
- }
-
- // there will be a mismatch between format length and final length because
- // RGBFormat and RGBIntegerFormat was removed
- if ( finalStride === 3 && ( format === RGBAFormat || format === RGBAIntegerFormat ) ) {
-
- finalStride = 4;
-
- }
-
- // copy the data over to the new texture array
- const dimension = Math.ceil( Math.sqrt( count ) );
- const length = finalStride * dimension * dimension;
- const dataArray = new targetBufferCons( length );
- for ( let i = 0; i < count; i ++ ) {
-
- const ii = finalStride * i;
- dataArray[ ii ] = attr.getX( i ) / normalizeValue;
-
- if ( itemSize >= 2 ) {
-
- dataArray[ ii + 1 ] = attr.getY( i ) / normalizeValue;
-
- }
-
- if ( itemSize >= 3 ) {
-
- dataArray[ ii + 2 ] = attr.getZ( i ) / normalizeValue;
-
- if ( finalStride === 4 ) {
-
- dataArray[ ii + 3 ] = 1.0;
-
- }
-
- }
-
- if ( itemSize >= 4 ) {
-
- dataArray[ ii + 3 ] = attr.getW( i ) / normalizeValue;
-
- }
-
- }
-
- this.internalFormat = internalFormat;
- this.format = format;
- this.type = type;
- this.image.width = dimension;
- this.image.height = dimension;
- this.image.data = dataArray;
- this.needsUpdate = true;
-
- attr.itemSize = originalItemSize;
- attr.count = originalCount;
-
- }
-
-}
-
-class UIntVertexAttributeTexture extends VertexAttributeTexture {
-
- constructor() {
-
- super();
- this._forcedType = UnsignedIntType;
-
- }
-
-}
-
-class IntVertexAttributeTexture extends VertexAttributeTexture {
-
- constructor() {
-
- super();
- this._forcedType = IntType;
-
- }
-
-
-}
-
-class FloatVertexAttributeTexture extends VertexAttributeTexture {
-
- constructor() {
-
- super();
- this._forcedType = FloatType;
-
- }
-
-}
-
-function bvhToTextures( bvh, boundsTexture, contentsTexture ) {
-
- const roots = bvh._roots;
-
- if ( roots.length !== 1 ) {
-
- throw new Error( 'MeshBVHUniformStruct: Multi-root BVHs not supported.' );
-
- }
-
- const root = roots[ 0 ];
- const uint16Array = new Uint16Array( root );
- const uint32Array = new Uint32Array( root );
- const float32Array = new Float32Array( root );
-
- // Both bounds need two elements per node so compute the height so it's twice as long as
- // the width so we can expand the row by two and still have a square texture
- const nodeCount = root.byteLength / BYTES_PER_NODE;
- const boundsDimension = 2 * Math.ceil( Math.sqrt( nodeCount / 2 ) );
- const boundsArray = new Float32Array( 4 * boundsDimension * boundsDimension );
-
- const contentsDimension = Math.ceil( Math.sqrt( nodeCount ) );
- const contentsArray = new Uint32Array( 2 * contentsDimension * contentsDimension );
-
- for ( let i = 0; i < nodeCount; i ++ ) {
-
- const nodeIndex32 = i * BYTES_PER_NODE / 4;
- const nodeIndex16 = nodeIndex32 * 2;
- const boundsIndex = BOUNDING_DATA_INDEX( nodeIndex32 );
- for ( let b = 0; b < 3; b ++ ) {
-
- boundsArray[ 8 * i + 0 + b ] = float32Array[ boundsIndex + 0 + b ];
- boundsArray[ 8 * i + 4 + b ] = float32Array[ boundsIndex + 3 + b ];
-
- }
-
- if ( IS_LEAF( nodeIndex16, uint16Array ) ) {
-
- const count = COUNT( nodeIndex16, uint16Array );
- const offset = OFFSET( nodeIndex32, uint32Array );
-
- const mergedLeafCount = 0xffff0000 | count;
- contentsArray[ i * 2 + 0 ] = mergedLeafCount;
- contentsArray[ i * 2 + 1 ] = offset;
-
- } else {
-
- const rightIndex = 4 * RIGHT_NODE( nodeIndex32, uint32Array ) / BYTES_PER_NODE;
- const splitAxis = SPLIT_AXIS( nodeIndex32, uint32Array );
-
- contentsArray[ i * 2 + 0 ] = splitAxis;
- contentsArray[ i * 2 + 1 ] = rightIndex;
-
- }
-
- }
-
- boundsTexture.image.data = boundsArray;
- boundsTexture.image.width = boundsDimension;
- boundsTexture.image.height = boundsDimension;
- boundsTexture.format = RGBAFormat;
- boundsTexture.type = FloatType;
- boundsTexture.internalFormat = 'RGBA32F';
- boundsTexture.minFilter = NearestFilter;
- boundsTexture.magFilter = NearestFilter;
- boundsTexture.generateMipmaps = false;
- boundsTexture.needsUpdate = true;
-
- contentsTexture.image.data = contentsArray;
- contentsTexture.image.width = contentsDimension;
- contentsTexture.image.height = contentsDimension;
- contentsTexture.format = RGIntegerFormat;
- contentsTexture.type = UnsignedIntType;
- contentsTexture.internalFormat = 'RG32UI';
- contentsTexture.minFilter = NearestFilter;
- contentsTexture.magFilter = NearestFilter;
- contentsTexture.generateMipmaps = false;
- contentsTexture.needsUpdate = true;
-
-}
-
-class MeshBVHUniformStruct {
-
- constructor() {
-
- this.autoDispose = true;
- this.index = new UIntVertexAttributeTexture();
- this.position = new FloatVertexAttributeTexture();
- this.bvhBounds = new DataTexture();
- this.bvhContents = new DataTexture();
-
- this.index.overrideItemSize = 3;
-
- }
-
- updateFrom( bvh ) {
-
- const { geometry } = bvh;
-
- bvhToTextures( bvh, this.bvhBounds, this.bvhContents );
-
- this.index.updateFrom( geometry.index );
- this.position.updateFrom( geometry.attributes.position );
-
- }
-
- dispose() {
-
- const { index, position, bvhBounds, bvhContents } = this;
-
- if ( index ) index.dispose();
- if ( position ) position.dispose();
- if ( bvhBounds ) bvhBounds.dispose();
- if ( bvhContents ) bvhContents.dispose();
-
- }
-
-}
-
-const shaderStructs = /* glsl */`
-#ifndef TRI_INTERSECT_EPSILON
-#define TRI_INTERSECT_EPSILON 1e-5
-#endif
-
-#ifndef INFINITY
-#define INFINITY 1e20
-#endif
-
-struct BVH {
-
- usampler2D index;
- sampler2D position;
-
- sampler2D bvhBounds;
- usampler2D bvhContents;
-
-};
-
-// Note that a struct cannot be used for the hit record including faceIndices, faceNormal, barycoord,
-// side, and dist because on some mobile GPUS (such as Adreno) numbers are afforded less precision specifically
-// when in a struct leading to inaccurate hit results. See KhronosGroup/WebGL#3351 for more details.
-`;
-
-const shaderIntersectFunction = /* glsl */`
-
-uvec4 uTexelFetch1D( usampler2D tex, uint index ) {
-
- uint width = uint( textureSize( tex, 0 ).x );
- uvec2 uv;
- uv.x = index % width;
- uv.y = index / width;
-
- return texelFetch( tex, ivec2( uv ), 0 );
-
-}
-
-ivec4 iTexelFetch1D( isampler2D tex, uint index ) {
-
- uint width = uint( textureSize( tex, 0 ).x );
- uvec2 uv;
- uv.x = index % width;
- uv.y = index / width;
-
- return texelFetch( tex, ivec2( uv ), 0 );
-
-}
-
-vec4 texelFetch1D( sampler2D tex, uint index ) {
-
- uint width = uint( textureSize( tex, 0 ).x );
- uvec2 uv;
- uv.x = index % width;
- uv.y = index / width;
-
- return texelFetch( tex, ivec2( uv ), 0 );
-
-}
-
-vec4 textureSampleBarycoord( sampler2D tex, vec3 barycoord, uvec3 faceIndices ) {
-
- return
- barycoord.x * texelFetch1D( tex, faceIndices.x ) +
- barycoord.y * texelFetch1D( tex, faceIndices.y ) +
- barycoord.z * texelFetch1D( tex, faceIndices.z );
-
-}
-
-void ndcToCameraRay(
- vec2 coord, mat4 cameraWorld, mat4 invProjectionMatrix,
- out vec3 rayOrigin, out vec3 rayDirection
-) {
-
- // get camera look direction and near plane for camera clipping
- vec4 lookDirection = cameraWorld * vec4( 0.0, 0.0, - 1.0, 0.0 );
- vec4 nearVector = invProjectionMatrix * vec4( 0.0, 0.0, - 1.0, 1.0 );
- float near = abs( nearVector.z / nearVector.w );
-
- // get the camera direction and position from camera matrices
- vec4 origin = cameraWorld * vec4( 0.0, 0.0, 0.0, 1.0 );
- vec4 direction = invProjectionMatrix * vec4( coord, 0.5, 1.0 );
- direction /= direction.w;
- direction = cameraWorld * direction - origin;
-
- // slide the origin along the ray until it sits at the near clip plane position
- origin.xyz += direction.xyz * near / dot( direction, lookDirection );
-
- rayOrigin = origin.xyz;
- rayDirection = direction.xyz;
-
-}
-
-float intersectsBounds( vec3 rayOrigin, vec3 rayDirection, vec3 boundsMin, vec3 boundsMax ) {
-
- // https://www.reddit.com/r/opengl/comments/8ntzz5/fast_glsl_ray_box_intersection/
- // https://tavianator.com/2011/ray_box.html
- vec3 invDir = 1.0 / rayDirection;
-
- // find intersection distances for each plane
- vec3 tMinPlane = invDir * ( boundsMin - rayOrigin );
- vec3 tMaxPlane = invDir * ( boundsMax - rayOrigin );
-
- // get the min and max distances from each intersection
- vec3 tMinHit = min( tMaxPlane, tMinPlane );
- vec3 tMaxHit = max( tMaxPlane, tMinPlane );
-
- // get the furthest hit distance
- vec2 t = max( tMinHit.xx, tMinHit.yz );
- float t0 = max( t.x, t.y );
-
- // get the minimum hit distance
- t = min( tMaxHit.xx, tMaxHit.yz );
- float t1 = min( t.x, t.y );
-
- // set distance to 0.0 if the ray starts inside the box
- float dist = max( t0, 0.0 );
-
- return t1 >= dist ? dist : INFINITY;
-
-}
-
-bool intersectsTriangle(
- vec3 rayOrigin, vec3 rayDirection, vec3 a, vec3 b, vec3 c,
- out vec3 barycoord, out vec3 norm, out float dist, out float side
-) {
-
- // https://stackoverflow.com/questions/42740765/intersection-between-line-and-triangle-in-3d
- vec3 edge1 = b - a;
- vec3 edge2 = c - a;
- norm = cross( edge1, edge2 );
-
- float det = - dot( rayDirection, norm );
- float invdet = 1.0 / det;
-
- vec3 AO = rayOrigin - a;
- vec3 DAO = cross( AO, rayDirection );
-
- vec4 uvt;
- uvt.x = dot( edge2, DAO ) * invdet;
- uvt.y = - dot( edge1, DAO ) * invdet;
- uvt.z = dot( AO, norm ) * invdet;
- uvt.w = 1.0 - uvt.x - uvt.y;
-
- // set the hit information
- barycoord = uvt.wxy; // arranged in A, B, C order
- dist = uvt.z;
- side = sign( det );
- norm = side * normalize( norm );
-
- // add an epsilon to avoid misses between triangles
- uvt += vec4( TRI_INTERSECT_EPSILON );
-
- return all( greaterThanEqual( uvt, vec4( 0.0 ) ) );
-
-}
-
-bool intersectTriangles(
- BVH bvh, vec3 rayOrigin, vec3 rayDirection, uint offset, uint count,
- inout float minDistance,
-
- // output variables
- out uvec4 faceIndices, out vec3 faceNormal, out vec3 barycoord,
- out float side, out float dist
-) {
-
- bool found = false;
- vec3 localBarycoord, localNormal;
- float localDist, localSide;
- for ( uint i = offset, l = offset + count; i < l; i ++ ) {
-
- uvec3 indices = uTexelFetch1D( bvh.index, i ).xyz;
- vec3 a = texelFetch1D( bvh.position, indices.x ).rgb;
- vec3 b = texelFetch1D( bvh.position, indices.y ).rgb;
- vec3 c = texelFetch1D( bvh.position, indices.z ).rgb;
-
- if (
- intersectsTriangle( rayOrigin, rayDirection, a, b, c, localBarycoord, localNormal, localDist, localSide )
- && localDist < minDistance
- ) {
-
- found = true;
- minDistance = localDist;
-
- faceIndices = uvec4( indices.xyz, i );
- faceNormal = localNormal;
-
- side = localSide;
- barycoord = localBarycoord;
- dist = localDist;
-
- }
-
- }
-
- return found;
-
-}
-
-float intersectsBVHNodeBounds( vec3 rayOrigin, vec3 rayDirection, BVH bvh, uint currNodeIndex ) {
-
- vec3 boundsMin = texelFetch1D( bvh.bvhBounds, currNodeIndex * 2u + 0u ).xyz;
- vec3 boundsMax = texelFetch1D( bvh.bvhBounds, currNodeIndex * 2u + 1u ).xyz;
- return intersectsBounds( rayOrigin, rayDirection, boundsMin, boundsMax );
-
-}
-
-bool bvhIntersectFirstHit(
- BVH bvh, vec3 rayOrigin, vec3 rayDirection,
-
- // output variables
- out uvec4 faceIndices, out vec3 faceNormal, out vec3 barycoord,
- out float side, out float dist
-) {
-
- // stack needs to be twice as long as the deepest tree we expect because
- // we push both the left and right child onto the stack every traversal
- int ptr = 0;
- uint stack[ 60 ];
- stack[ 0 ] = 0u;
-
- float triangleDistance = 1e20;
- bool found = false;
- while ( ptr > - 1 && ptr < 60 ) {
-
- uint currNodeIndex = stack[ ptr ];
- ptr --;
-
- // check if we intersect the current bounds
- float boundsHitDistance = intersectsBVHNodeBounds( rayOrigin, rayDirection, bvh, currNodeIndex );
- if ( boundsHitDistance == INFINITY || boundsHitDistance > triangleDistance ) {
-
- continue;
-
- }
-
- uvec2 boundsInfo = uTexelFetch1D( bvh.bvhContents, currNodeIndex ).xy;
- bool isLeaf = bool( boundsInfo.x & 0xffff0000u );
-
- if ( isLeaf ) {
-
- uint count = boundsInfo.x & 0x0000ffffu;
- uint offset = boundsInfo.y;
-
- found = intersectTriangles(
- bvh, rayOrigin, rayDirection, offset, count, triangleDistance,
- faceIndices, faceNormal, barycoord, side, dist
- ) || found;
-
- } else {
-
- uint leftIndex = currNodeIndex + 1u;
- uint splitAxis = boundsInfo.x & 0x0000ffffu;
- uint rightIndex = boundsInfo.y;
-
- bool leftToRight = rayDirection[ splitAxis ] >= 0.0;
- uint c1 = leftToRight ? leftIndex : rightIndex;
- uint c2 = leftToRight ? rightIndex : leftIndex;
-
- // set c2 in the stack so we traverse it later. We need to keep track of a pointer in
- // the stack while we traverse. The second pointer added is the one that will be
- // traversed first
- ptr ++;
- stack[ ptr ] = c2;
-
- ptr ++;
- stack[ ptr ] = c1;
-
- }
-
- }
-
- return found;
-
-}
-
-`;
-
-export { AVERAGE, CENTER, CONTAINED, FloatVertexAttributeTexture, INTERSECTED, IntVertexAttributeTexture, MeshBVH, MeshBVHUniformStruct, MeshBVHVisualizer, NOT_INTERSECTED, SAH, UIntVertexAttributeTexture, VertexAttributeTexture, acceleratedRaycast, computeBoundsTree, disposeBoundsTree, estimateMemoryInBytes, getBVHExtremes, getJSONStructure, getTriangleHitPointInfo, shaderIntersectFunction, shaderStructs, validateBounds };
-//# sourceMappingURL=./three-mesh-bvh.module.js.map
\ No newline at end of file
diff --git a/test/three-mesh-bvh.module.js.map b/test/three-mesh-bvh.module.js.map
deleted file mode 100644
index 6c23867..0000000
--- a/test/three-mesh-bvh.module.js.map
+++ /dev/null
@@ -1 +0,0 @@
-{"version":3,"file":"index.module.js","sources":["../src/core/Constants.js","../src/core/MeshBVHNode.js","../src/utils/ArrayBoxUtilities.js","../src/core/buildFunctions.js","../src/math/SeparatingAxisBounds.js","../src/math/MathUtilities.js","../src/math/SeparatingAxisTriangle.js","../src/math/OrientedBox.js","../src/utils/ThreeRayIntersectUtilities.js","../src/utils/GeometryRayIntersectUtilities.js","../src/utils/TriangleUtilities.js","../src/utils/PrimitivePool.js","../src/core/nodeBufferFunctions.js","../src/core/castFunctions.js","../src/core/MeshBVH.js","../src/objects/MeshBVHVisualizer.js","../src/debug/Debug.js","../src/utils/ExtensionUtilities.js","../src/gpu/VertexAttributeTexture.js","../src/gpu/MeshBVHUniformStruct.js","../src/gpu/shaderFunctions.js"],"sourcesContent":["// Split strategy constants\r\nexport const CENTER = 0;\r\nexport const AVERAGE = 1;\r\nexport const SAH = 2;\r\n\r\n// Traversal constants\r\nexport const NOT_INTERSECTED = 0;\r\nexport const INTERSECTED = 1;\r\nexport const CONTAINED = 2;\r\n\r\n// SAH cost constants\r\n// TODO: hone these costs more. The relative difference between them should be the\r\n// difference in measured time to perform a triangle intersection vs traversing\r\n// bounds.\r\nexport const TRIANGLE_INTERSECT_COST = 1.25;\r\nexport const TRAVERSAL_COST = 1;\r\n\r\n\r\n// Build constants\r\nexport const BYTES_PER_NODE = 6 * 4 + 4 + 4;\r\nexport const IS_LEAFNODE_FLAG = 0xFFFF;\r\n\r\n// EPSILON for computing floating point error during build\r\n// https://en.wikipedia.org/wiki/Machine_epsilon#Values_for_standard_hardware_floating_point_arithmetics\r\nexport const FLOAT32_EPSILON = Math.pow( 2, - 24 );\r\n\r\n","export class MeshBVHNode {\r\n\r\n\tconstructor() {\r\n\r\n\t\t// internal nodes have boundingData, left, right, and splitAxis\r\n\t\t// leaf nodes have offset and count (referring to primitives in the mesh geometry)\r\n\r\n\t}\r\n\r\n}\r\n","export function arrayToBox( nodeIndex32, array, target ) {\r\n\r\n\ttarget.min.x = array[ nodeIndex32 ];\r\n\ttarget.min.y = array[ nodeIndex32 + 1 ];\r\n\ttarget.min.z = array[ nodeIndex32 + 2 ];\r\n\r\n\ttarget.max.x = array[ nodeIndex32 + 3 ];\r\n\ttarget.max.y = array[ nodeIndex32 + 4 ];\r\n\ttarget.max.z = array[ nodeIndex32 + 5 ];\r\n\r\n\treturn target;\r\n\r\n}\r\n\r\nexport function getLongestEdgeIndex( bounds ) {\r\n\r\n\tlet splitDimIdx = - 1;\r\n\tlet splitDist = - Infinity;\r\n\r\n\tfor ( let i = 0; i < 3; i ++ ) {\r\n\r\n\t\tconst dist = bounds[ i + 3 ] - bounds[ i ];\r\n\t\tif ( dist > splitDist ) {\r\n\r\n\t\t\tsplitDist = dist;\r\n\t\t\tsplitDimIdx = i;\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\treturn splitDimIdx;\r\n\r\n}\r\n\r\n// copys bounds a into bounds b\r\nexport function copyBounds( source, target ) {\r\n\r\n\ttarget.set( source );\r\n\r\n}\r\n\r\n// sets bounds target to the union of bounds a and b\r\nexport function unionBounds( a, b, target ) {\r\n\r\n\tlet aVal, bVal;\r\n\tfor ( let d = 0; d < 3; d ++ ) {\r\n\r\n\t\tconst d3 = d + 3;\r\n\r\n\t\t// set the minimum values\r\n\t\taVal = a[ d ];\r\n\t\tbVal = b[ d ];\r\n\t\ttarget[ d ] = aVal < bVal ? aVal : bVal;\r\n\r\n\t\t// set the max values\r\n\t\taVal = a[ d3 ];\r\n\t\tbVal = b[ d3 ];\r\n\t\ttarget[ d3 ] = aVal > bVal ? aVal : bVal;\r\n\r\n\t}\r\n\r\n}\r\n\r\n// expands the given bounds by the provided triangle bounds\r\nexport function expandByTriangleBounds( startIndex, triangleBounds, bounds ) {\r\n\r\n\tfor ( let d = 0; d < 3; d ++ ) {\r\n\r\n\t\tconst tCenter = triangleBounds[ startIndex + 2 * d ];\r\n\t\tconst tHalf = triangleBounds[ startIndex + 2 * d + 1 ];\r\n\r\n\t\tconst tMin = tCenter - tHalf;\r\n\t\tconst tMax = tCenter + tHalf;\r\n\r\n\t\tif ( tMin < bounds[ d ] ) {\r\n\r\n\t\t\tbounds[ d ] = tMin;\r\n\r\n\t\t}\r\n\r\n\t\tif ( tMax > bounds[ d + 3 ] ) {\r\n\r\n\t\t\tbounds[ d + 3 ] = tMax;\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n}\r\n\r\n// compute bounds surface area\r\nexport function computeSurfaceArea( bounds ) {\r\n\r\n\tconst d0 = bounds[ 3 ] - bounds[ 0 ];\r\n\tconst d1 = bounds[ 4 ] - bounds[ 1 ];\r\n\tconst d2 = bounds[ 5 ] - bounds[ 2 ];\r\n\r\n\treturn 2 * ( d0 * d1 + d1 * d2 + d2 * d0 );\r\n\r\n}\r\n","import { BufferAttribute } from 'three';\r\nimport { MeshBVHNode } from './MeshBVHNode.js';\r\nimport { getLongestEdgeIndex, computeSurfaceArea, copyBounds, unionBounds, expandByTriangleBounds } from '../utils/ArrayBoxUtilities.js';\r\nimport {\r\n\tCENTER, AVERAGE, SAH, TRIANGLE_INTERSECT_COST, TRAVERSAL_COST,\r\n\tBYTES_PER_NODE, FLOAT32_EPSILON, IS_LEAFNODE_FLAG,\r\n} from './Constants.js';\r\n\r\nfunction ensureIndex( geo, options ) {\r\n\r\n\tif ( ! geo.index ) {\r\n\r\n\t\tconst vertexCount = geo.attributes.position.count;\r\n\t\tconst BufferConstructor = options.useSharedArrayBuffer ? SharedArrayBuffer : ArrayBuffer;\r\n\t\tlet index;\r\n\t\tif ( vertexCount > 65535 ) {\r\n\r\n\t\t\tindex = new Uint32Array( new BufferConstructor( 4 * vertexCount ) );\r\n\r\n\t\t} else {\r\n\r\n\t\t\tindex = new Uint16Array( new BufferConstructor( 2 * vertexCount ) );\r\n\r\n\t\t}\r\n\r\n\t\tgeo.setIndex( new BufferAttribute( index, 1 ) );\r\n\r\n\t\tfor ( let i = 0; i < vertexCount; i ++ ) {\r\n\r\n\t\t\tindex[ i ] = i;\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n}\r\n\r\n// Computes the set of { offset, count } ranges which need independent BVH roots. Each\r\n// region in the geometry index that belongs to a different set of material groups requires\r\n// a separate BVH root, so that triangles indices belonging to one group never get swapped\r\n// with triangle indices belongs to another group. For example, if the groups were like this:\r\n//\r\n// [-------------------------------------------------------------]\r\n// |__________________|\r\n// g0 = [0, 20] |______________________||_____________________|\r\n// g1 = [16, 40] g2 = [41, 60]\r\n//\r\n// we would need four BVH roots: [0, 15], [16, 20], [21, 40], [41, 60].\r\nfunction getRootIndexRanges( geo ) {\r\n\r\n\tif ( ! geo.groups || ! geo.groups.length ) {\r\n\r\n\t\treturn [ { offset: 0, count: geo.index.count / 3 } ];\r\n\r\n\t}\r\n\r\n\tconst ranges = [];\r\n\tconst rangeBoundaries = new Set();\r\n\tfor ( const group of geo.groups ) {\r\n\r\n\t\trangeBoundaries.add( group.start );\r\n\t\trangeBoundaries.add( group.start + group.count );\r\n\r\n\t}\r\n\r\n\t// note that if you don't pass in a comparator, it sorts them lexicographically as strings :-(\r\n\tconst sortedBoundaries = Array.from( rangeBoundaries.values() ).sort( ( a, b ) => a - b );\r\n\tfor ( let i = 0; i < sortedBoundaries.length - 1; i ++ ) {\r\n\r\n\t\tconst start = sortedBoundaries[ i ], end = sortedBoundaries[ i + 1 ];\r\n\t\tranges.push( { offset: ( start / 3 ), count: ( end - start ) / 3 } );\r\n\r\n\t}\r\n\r\n\treturn ranges;\r\n\r\n}\r\n\r\n// computes the union of the bounds of all of the given triangles and puts the resulting box in target. If\r\n// centroidTarget is provided then a bounding box is computed for the centroids of the triangles, as well.\r\n// These are computed together to avoid redundant accesses to bounds array.\r\nfunction getBounds( triangleBounds, offset, count, target, centroidTarget = null ) {\r\n\r\n\tlet minx = Infinity;\r\n\tlet miny = Infinity;\r\n\tlet minz = Infinity;\r\n\tlet maxx = - Infinity;\r\n\tlet maxy = - Infinity;\r\n\tlet maxz = - Infinity;\r\n\r\n\tlet cminx = Infinity;\r\n\tlet cminy = Infinity;\r\n\tlet cminz = Infinity;\r\n\tlet cmaxx = - Infinity;\r\n\tlet cmaxy = - Infinity;\r\n\tlet cmaxz = - Infinity;\r\n\r\n\tconst includeCentroid = centroidTarget !== null;\r\n\tfor ( let i = offset * 6, end = ( offset + count ) * 6; i < end; i += 6 ) {\r\n\r\n\t\tconst cx = triangleBounds[ i + 0 ];\r\n\t\tconst hx = triangleBounds[ i + 1 ];\r\n\t\tconst lx = cx - hx;\r\n\t\tconst rx = cx + hx;\r\n\t\tif ( lx < minx ) minx = lx;\r\n\t\tif ( rx > maxx ) maxx = rx;\r\n\t\tif ( includeCentroid && cx < cminx ) cminx = cx;\r\n\t\tif ( includeCentroid && cx > cmaxx ) cmaxx = cx;\r\n\r\n\t\tconst cy = triangleBounds[ i + 2 ];\r\n\t\tconst hy = triangleBounds[ i + 3 ];\r\n\t\tconst ly = cy - hy;\r\n\t\tconst ry = cy + hy;\r\n\t\tif ( ly < miny ) miny = ly;\r\n\t\tif ( ry > maxy ) maxy = ry;\r\n\t\tif ( includeCentroid && cy < cminy ) cminy = cy;\r\n\t\tif ( includeCentroid && cy > cmaxy ) cmaxy = cy;\r\n\r\n\t\tconst cz = triangleBounds[ i + 4 ];\r\n\t\tconst hz = triangleBounds[ i + 5 ];\r\n\t\tconst lz = cz - hz;\r\n\t\tconst rz = cz + hz;\r\n\t\tif ( lz < minz ) minz = lz;\r\n\t\tif ( rz > maxz ) maxz = rz;\r\n\t\tif ( includeCentroid && cz < cminz ) cminz = cz;\r\n\t\tif ( includeCentroid && cz > cmaxz ) cmaxz = cz;\r\n\r\n\t}\r\n\r\n\ttarget[ 0 ] = minx;\r\n\ttarget[ 1 ] = miny;\r\n\ttarget[ 2 ] = minz;\r\n\r\n\ttarget[ 3 ] = maxx;\r\n\ttarget[ 4 ] = maxy;\r\n\ttarget[ 5 ] = maxz;\r\n\r\n\tif ( includeCentroid ) {\r\n\r\n\t\tcentroidTarget[ 0 ] = cminx;\r\n\t\tcentroidTarget[ 1 ] = cminy;\r\n\t\tcentroidTarget[ 2 ] = cminz;\r\n\r\n\t\tcentroidTarget[ 3 ] = cmaxx;\r\n\t\tcentroidTarget[ 4 ] = cmaxy;\r\n\t\tcentroidTarget[ 5 ] = cmaxz;\r\n\r\n\t}\r\n\r\n}\r\n\r\n// A stand alone function for retrieving the centroid bounds.\r\nfunction getCentroidBounds( triangleBounds, offset, count, centroidTarget ) {\r\n\r\n\tlet cminx = Infinity;\r\n\tlet cminy = Infinity;\r\n\tlet cminz = Infinity;\r\n\tlet cmaxx = - Infinity;\r\n\tlet cmaxy = - Infinity;\r\n\tlet cmaxz = - Infinity;\r\n\r\n\tfor ( let i = offset * 6, end = ( offset + count ) * 6; i < end; i += 6 ) {\r\n\r\n\t\tconst cx = triangleBounds[ i + 0 ];\r\n\t\tif ( cx < cminx ) cminx = cx;\r\n\t\tif ( cx > cmaxx ) cmaxx = cx;\r\n\r\n\t\tconst cy = triangleBounds[ i + 2 ];\r\n\t\tif ( cy < cminy ) cminy = cy;\r\n\t\tif ( cy > cmaxy ) cmaxy = cy;\r\n\r\n\t\tconst cz = triangleBounds[ i + 4 ];\r\n\t\tif ( cz < cminz ) cminz = cz;\r\n\t\tif ( cz > cmaxz ) cmaxz = cz;\r\n\r\n\t}\r\n\r\n\tcentroidTarget[ 0 ] = cminx;\r\n\tcentroidTarget[ 1 ] = cminy;\r\n\tcentroidTarget[ 2 ] = cminz;\r\n\r\n\tcentroidTarget[ 3 ] = cmaxx;\r\n\tcentroidTarget[ 4 ] = cmaxy;\r\n\tcentroidTarget[ 5 ] = cmaxz;\r\n\r\n}\r\n\r\n\r\n// reorders `tris` such that for `count` elements after `offset`, elements on the left side of the split\r\n// will be on the left and elements on the right side of the split will be on the right. returns the index\r\n// of the first element on the right side, or offset + count if there are no elements on the right side.\r\nfunction partition( index, triangleBounds, offset, count, split ) {\r\n\r\n\tlet left = offset;\r\n\tlet right = offset + count - 1;\r\n\tconst pos = split.pos;\r\n\tconst axisOffset = split.axis * 2;\r\n\r\n\t// hoare partitioning, see e.g. https://en.wikipedia.org/wiki/Quicksort#Hoare_partition_scheme\r\n\twhile ( true ) {\r\n\r\n\t\twhile ( left <= right && triangleBounds[ left * 6 + axisOffset ] < pos ) {\r\n\r\n\t\t\tleft ++;\r\n\r\n\t\t}\r\n\r\n\r\n\t\t// if a triangle center lies on the partition plane it is considered to be on the right side\r\n\t\twhile ( left <= right && triangleBounds[ right * 6 + axisOffset ] >= pos ) {\r\n\r\n\t\t\tright --;\r\n\r\n\t\t}\r\n\r\n\t\tif ( left < right ) {\r\n\r\n\t\t\t// we need to swap all of the information associated with the triangles at index\r\n\t\t\t// left and right; that's the verts in the geometry index, the bounds,\r\n\t\t\t// and perhaps the SAH planes\r\n\r\n\t\t\tfor ( let i = 0; i < 3; i ++ ) {\r\n\r\n\t\t\t\tlet t0 = index[ left * 3 + i ];\r\n\t\t\t\tindex[ left * 3 + i ] = index[ right * 3 + i ];\r\n\t\t\t\tindex[ right * 3 + i ] = t0;\r\n\r\n\t\t\t\tlet t1 = triangleBounds[ left * 6 + i * 2 + 0 ];\r\n\t\t\t\ttriangleBounds[ left * 6 + i * 2 + 0 ] = triangleBounds[ right * 6 + i * 2 + 0 ];\r\n\t\t\t\ttriangleBounds[ right * 6 + i * 2 + 0 ] = t1;\r\n\r\n\t\t\t\tlet t2 = triangleBounds[ left * 6 + i * 2 + 1 ];\r\n\t\t\t\ttriangleBounds[ left * 6 + i * 2 + 1 ] = triangleBounds[ right * 6 + i * 2 + 1 ];\r\n\t\t\t\ttriangleBounds[ right * 6 + i * 2 + 1 ] = t2;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tleft ++;\r\n\t\t\tright --;\r\n\r\n\t\t} else {\r\n\r\n\t\t\treturn left;\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n}\r\n\r\nconst BIN_COUNT = 32;\r\nconst binsSort = ( a, b ) => a.candidate - b.candidate;\r\nconst sahBins = new Array( BIN_COUNT ).fill().map( () => {\r\n\r\n\treturn {\r\n\r\n\t\tcount: 0,\r\n\t\tbounds: new Float32Array( 6 ),\r\n\t\trightCacheBounds: new Float32Array( 6 ),\r\n\t\tleftCacheBounds: new Float32Array( 6 ),\r\n\t\tcandidate: 0,\r\n\r\n\t};\r\n\r\n} );\r\nconst leftBounds = new Float32Array( 6 );\r\n\r\nfunction getOptimalSplit( nodeBoundingData, centroidBoundingData, triangleBounds, offset, count, strategy ) {\r\n\r\n\tlet axis = - 1;\r\n\tlet pos = 0;\r\n\r\n\t// Center\r\n\tif ( strategy === CENTER ) {\r\n\r\n\t\taxis = getLongestEdgeIndex( centroidBoundingData );\r\n\t\tif ( axis !== - 1 ) {\r\n\r\n\t\t\tpos = ( centroidBoundingData[ axis ] + centroidBoundingData[ axis + 3 ] ) / 2;\r\n\r\n\t\t}\r\n\r\n\t} else if ( strategy === AVERAGE ) {\r\n\r\n\t\taxis = getLongestEdgeIndex( nodeBoundingData );\r\n\t\tif ( axis !== - 1 ) {\r\n\r\n\t\t\tpos = getAverage( triangleBounds, offset, count, axis );\r\n\r\n\t\t}\r\n\r\n\t} else if ( strategy === SAH ) {\r\n\r\n\t\tconst rootSurfaceArea = computeSurfaceArea( nodeBoundingData );\r\n\t\tlet bestCost = TRIANGLE_INTERSECT_COST * count;\r\n\r\n\t\t// iterate over all axes\r\n\t\tconst cStart = offset * 6;\r\n\t\tconst cEnd = ( offset + count ) * 6;\r\n\t\tfor ( let a = 0; a < 3; a ++ ) {\r\n\r\n\t\t\tconst axisLeft = centroidBoundingData[ a ];\r\n\t\t\tconst axisRight = centroidBoundingData[ a + 3 ];\r\n\t\t\tconst axisLength = axisRight - axisLeft;\r\n\t\t\tconst binWidth = axisLength / BIN_COUNT;\r\n\r\n\t\t\t// If we have fewer triangles than we're planning to split then just check all\r\n\t\t\t// the triangle positions because it will be faster.\r\n\t\t\tif ( count < BIN_COUNT / 4 ) {\r\n\r\n\t\t\t\t// initialize the bin candidates\r\n\t\t\t\tconst truncatedBins = [ ...sahBins ];\r\n\t\t\t\ttruncatedBins.length = count;\r\n\r\n\t\t\t\t// set the candidates\r\n\t\t\t\tlet b = 0;\r\n\t\t\t\tfor ( let c = cStart; c < cEnd; c += 6, b ++ ) {\r\n\r\n\t\t\t\t\tconst bin = truncatedBins[ b ];\r\n\t\t\t\t\tbin.candidate = triangleBounds[ c + 2 * a ];\r\n\t\t\t\t\tbin.count = 0;\r\n\r\n\t\t\t\t\tconst {\r\n\t\t\t\t\t\tbounds,\r\n\t\t\t\t\t\tleftCacheBounds,\r\n\t\t\t\t\t\trightCacheBounds,\r\n\t\t\t\t\t} = bin;\r\n\t\t\t\t\tfor ( let d = 0; d < 3; d ++ ) {\r\n\r\n\t\t\t\t\t\trightCacheBounds[ d ] = Infinity;\r\n\t\t\t\t\t\trightCacheBounds[ d + 3 ] = - Infinity;\r\n\r\n\t\t\t\t\t\tleftCacheBounds[ d ] = Infinity;\r\n\t\t\t\t\t\tleftCacheBounds[ d + 3 ] = - Infinity;\r\n\r\n\t\t\t\t\t\tbounds[ d ] = Infinity;\r\n\t\t\t\t\t\tbounds[ d + 3 ] = - Infinity;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\texpandByTriangleBounds( c, triangleBounds, bounds );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\ttruncatedBins.sort( binsSort );\r\n\r\n\t\t\t\t// remove redundant splits\r\n\t\t\t\tlet splitCount = count;\r\n\t\t\t\tfor ( let bi = 0; bi < splitCount; bi ++ ) {\r\n\r\n\t\t\t\t\tconst bin = truncatedBins[ bi ];\r\n\t\t\t\t\twhile ( bi + 1 < splitCount && truncatedBins[ bi + 1 ].candidate === bin.candidate ) {\r\n\r\n\t\t\t\t\t\ttruncatedBins.splice( bi + 1, 1 );\r\n\t\t\t\t\t\tsplitCount --;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// find the appropriate bin for each triangle and expand the bounds.\r\n\t\t\t\tfor ( let c = cStart; c < cEnd; c += 6 ) {\r\n\r\n\t\t\t\t\tconst center = triangleBounds[ c + 2 * a ];\r\n\t\t\t\t\tfor ( let bi = 0; bi < splitCount; bi ++ ) {\r\n\r\n\t\t\t\t\t\tconst bin = truncatedBins[ bi ];\r\n\t\t\t\t\t\tif ( center >= bin.candidate ) {\r\n\r\n\t\t\t\t\t\t\texpandByTriangleBounds( c, triangleBounds, bin.rightCacheBounds );\r\n\r\n\t\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t\texpandByTriangleBounds( c, triangleBounds, bin.leftCacheBounds );\r\n\t\t\t\t\t\t\tbin.count ++;\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// expand all the bounds\r\n\t\t\t\tfor ( let bi = 0; bi < splitCount; bi ++ ) {\r\n\r\n\t\t\t\t\tconst bin = truncatedBins[ bi ];\r\n\t\t\t\t\tconst leftCount = bin.count;\r\n\t\t\t\t\tconst rightCount = count - bin.count;\r\n\r\n\t\t\t\t\t// check the cost of this split\r\n\t\t\t\t\tconst leftBounds = bin.leftCacheBounds;\r\n\t\t\t\t\tconst rightBounds = bin.rightCacheBounds;\r\n\r\n\t\t\t\t\tlet leftProb = 0;\r\n\t\t\t\t\tif ( leftCount !== 0 ) {\r\n\r\n\t\t\t\t\t\tleftProb = computeSurfaceArea( leftBounds ) / rootSurfaceArea;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tlet rightProb = 0;\r\n\t\t\t\t\tif ( rightCount !== 0 ) {\r\n\r\n\t\t\t\t\t\trightProb = computeSurfaceArea( rightBounds ) / rootSurfaceArea;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tconst cost = TRAVERSAL_COST + TRIANGLE_INTERSECT_COST * (\r\n\t\t\t\t\t\tleftProb * leftCount + rightProb * rightCount\r\n\t\t\t\t\t);\r\n\r\n\t\t\t\t\tif ( cost < bestCost ) {\r\n\r\n\t\t\t\t\t\taxis = a;\r\n\t\t\t\t\t\tbestCost = cost;\r\n\t\t\t\t\t\tpos = bin.candidate;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\t// reset the bins\r\n\t\t\t\tfor ( let i = 0; i < BIN_COUNT; i ++ ) {\r\n\r\n\t\t\t\t\tconst bin = sahBins[ i ];\r\n\t\t\t\t\tbin.count = 0;\r\n\t\t\t\t\tbin.candidate = axisLeft + binWidth + i * binWidth;\r\n\r\n\t\t\t\t\tconst bounds = bin.bounds;\r\n\t\t\t\t\tfor ( let d = 0; d < 3; d ++ ) {\r\n\r\n\t\t\t\t\t\tbounds[ d ] = Infinity;\r\n\t\t\t\t\t\tbounds[ d + 3 ] = - Infinity;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// iterate over all center positions\r\n\t\t\t\tfor ( let c = cStart; c < cEnd; c += 6 ) {\r\n\r\n\t\t\t\t\tconst triCenter = triangleBounds[ c + 2 * a ];\r\n\t\t\t\t\tconst relativeCenter = triCenter - axisLeft;\r\n\r\n\t\t\t\t\t// in the partition function if the centroid lies on the split plane then it is\r\n\t\t\t\t\t// considered to be on the right side of the split\r\n\t\t\t\t\tlet binIndex = ~ ~ ( relativeCenter / binWidth );\r\n\t\t\t\t\tif ( binIndex >= BIN_COUNT ) binIndex = BIN_COUNT - 1;\r\n\r\n\t\t\t\t\tconst bin = sahBins[ binIndex ];\r\n\t\t\t\t\tbin.count ++;\r\n\r\n\t\t\t\t\texpandByTriangleBounds( c, triangleBounds, bin.bounds );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// cache the unioned bounds from right to left so we don't have to regenerate them each time\r\n\t\t\t\tconst lastBin = sahBins[ BIN_COUNT - 1 ];\r\n\t\t\t\tcopyBounds( lastBin.bounds, lastBin.rightCacheBounds );\r\n\t\t\t\tfor ( let i = BIN_COUNT - 2; i >= 0; i -- ) {\r\n\r\n\t\t\t\t\tconst bin = sahBins[ i ];\r\n\t\t\t\t\tconst nextBin = sahBins[ i + 1 ];\r\n\t\t\t\t\tunionBounds( bin.bounds, nextBin.rightCacheBounds, bin.rightCacheBounds );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tlet leftCount = 0;\r\n\t\t\t\tfor ( let i = 0; i < BIN_COUNT - 1; i ++ ) {\r\n\r\n\t\t\t\t\tconst bin = sahBins[ i ];\r\n\t\t\t\t\tconst binCount = bin.count;\r\n\t\t\t\t\tconst bounds = bin.bounds;\r\n\r\n\t\t\t\t\tconst nextBin = sahBins[ i + 1 ];\r\n\t\t\t\t\tconst rightBounds = nextBin.rightCacheBounds;\r\n\r\n\t\t\t\t\t// dont do anything with the bounds if the new bounds have no triangles\r\n\t\t\t\t\tif ( binCount !== 0 ) {\r\n\r\n\t\t\t\t\t\tif ( leftCount === 0 ) {\r\n\r\n\t\t\t\t\t\t\tcopyBounds( bounds, leftBounds );\r\n\r\n\t\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t\tunionBounds( bounds, leftBounds, leftBounds );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tleftCount += binCount;\r\n\r\n\t\t\t\t\t// check the cost of this split\r\n\t\t\t\t\tlet leftProb = 0;\r\n\t\t\t\t\tlet rightProb = 0;\r\n\r\n\t\t\t\t\tif ( leftCount !== 0 ) {\r\n\r\n\t\t\t\t\t\tleftProb = computeSurfaceArea( leftBounds ) / rootSurfaceArea;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tconst rightCount = count - leftCount;\r\n\t\t\t\t\tif ( rightCount !== 0 ) {\r\n\r\n\t\t\t\t\t\trightProb = computeSurfaceArea( rightBounds ) / rootSurfaceArea;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tconst cost = TRAVERSAL_COST + TRIANGLE_INTERSECT_COST * (\r\n\t\t\t\t\t\tleftProb * leftCount + rightProb * rightCount\r\n\t\t\t\t\t);\r\n\r\n\t\t\t\t\tif ( cost < bestCost ) {\r\n\r\n\t\t\t\t\t\taxis = a;\r\n\t\t\t\t\t\tbestCost = cost;\r\n\t\t\t\t\t\tpos = bin.candidate;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t} else {\r\n\r\n\t\tconsole.warn( `MeshBVH: Invalid build strategy value ${ strategy } used.` );\r\n\r\n\t}\r\n\r\n\treturn { axis, pos };\r\n\r\n}\r\n\r\n// returns the average coordinate on the specified axis of the all the provided triangles\r\nfunction getAverage( triangleBounds, offset, count, axis ) {\r\n\r\n\tlet avg = 0;\r\n\tfor ( let i = offset, end = offset + count; i < end; i ++ ) {\r\n\r\n\t\tavg += triangleBounds[ i * 6 + axis * 2 ];\r\n\r\n\t}\r\n\r\n\treturn avg / count;\r\n\r\n}\r\n\r\n// precomputes the bounding box for each triangle; required for quickly calculating tree splits.\r\n// result is an array of size tris.length * 6 where triangle i maps to a\r\n// [x_center, x_delta, y_center, y_delta, z_center, z_delta] tuple starting at index i * 6,\r\n// representing the center and half-extent in each dimension of triangle i\r\nfunction computeTriangleBounds( geo, fullBounds ) {\r\n\r\n\tconst posAttr = geo.attributes.position;\r\n\tconst posArr = posAttr.array;\r\n\tconst index = geo.index.array;\r\n\tconst triCount = index.length / 3;\r\n\tconst triangleBounds = new Float32Array( triCount * 6 );\r\n\r\n\t// support for an interleaved position buffer\r\n\tconst bufferOffset = posAttr.offset || 0;\r\n\tlet stride = 3;\r\n\tif ( posAttr.isInterleavedBufferAttribute ) {\r\n\r\n\t\tstride = posAttr.data.stride;\r\n\r\n\t}\r\n\r\n\tfor ( let tri = 0; tri < triCount; tri ++ ) {\r\n\r\n\t\tconst tri3 = tri * 3;\r\n\t\tconst tri6 = tri * 6;\r\n\t\tconst ai = index[ tri3 + 0 ] * stride + bufferOffset;\r\n\t\tconst bi = index[ tri3 + 1 ] * stride + bufferOffset;\r\n\t\tconst ci = index[ tri3 + 2 ] * stride + bufferOffset;\r\n\r\n\t\tfor ( let el = 0; el < 3; el ++ ) {\r\n\r\n\t\t\tconst a = posArr[ ai + el ];\r\n\t\t\tconst b = posArr[ bi + el ];\r\n\t\t\tconst c = posArr[ ci + el ];\r\n\r\n\t\t\tlet min = a;\r\n\t\t\tif ( b < min ) min = b;\r\n\t\t\tif ( c < min ) min = c;\r\n\r\n\t\t\tlet max = a;\r\n\t\t\tif ( b > max ) max = b;\r\n\t\t\tif ( c > max ) max = c;\r\n\r\n\t\t\t// Increase the bounds size by float32 epsilon to avoid precision errors when\r\n\t\t\t// converting to 32 bit float. Scale the epsilon by the size of the numbers being\r\n\t\t\t// worked with.\r\n\t\t\tconst halfExtents = ( max - min ) / 2;\r\n\t\t\tconst el2 = el * 2;\r\n\t\t\ttriangleBounds[ tri6 + el2 + 0 ] = min + halfExtents;\r\n\t\t\ttriangleBounds[ tri6 + el2 + 1 ] = halfExtents + ( Math.abs( min ) + halfExtents ) * FLOAT32_EPSILON;\r\n\r\n\t\t\tif ( min < fullBounds[ el ] ) fullBounds[ el ] = min;\r\n\t\t\tif ( max > fullBounds[ el + 3 ] ) fullBounds[ el + 3 ] = max;\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\treturn triangleBounds;\r\n\r\n}\r\n\r\nexport function buildTree( geo, options ) {\r\n\r\n\tfunction triggerProgress( trianglesProcessed ) {\r\n\r\n\t\tif ( onProgress ) {\r\n\r\n\t\t\tonProgress( trianglesProcessed / totalTriangles );\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t// either recursively splits the given node, creating left and right subtrees for it, or makes it a leaf node,\r\n\t// recording the offset and count of its triangles and writing them into the reordered geometry index.\r\n\tfunction splitNode( node, offset, count, centroidBoundingData = null, depth = 0 ) {\r\n\r\n\t\tif ( ! reachedMaxDepth && depth >= maxDepth ) {\r\n\r\n\t\t\treachedMaxDepth = true;\r\n\t\t\tif ( verbose ) {\r\n\r\n\t\t\t\tconsole.warn( `MeshBVH: Max depth of ${ maxDepth } reached when generating BVH. Consider increasing maxDepth.` );\r\n\t\t\t\tconsole.warn( geo );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t// early out if we've met our capacity\r\n\t\tif ( count <= maxLeafTris || depth >= maxDepth ) {\r\n\r\n\t\t\ttriggerProgress( offset );\r\n\t\t\tnode.offset = offset;\r\n\t\t\tnode.count = count;\r\n\t\t\treturn node;\r\n\r\n\t\t}\r\n\r\n\t\t// Find where to split the volume\r\n\t\tconst split = getOptimalSplit( node.boundingData, centroidBoundingData, triangleBounds, offset, count, strategy );\r\n\t\tif ( split.axis === - 1 ) {\r\n\r\n\t\t\ttriggerProgress( offset );\r\n\t\t\tnode.offset = offset;\r\n\t\t\tnode.count = count;\r\n\t\t\treturn node;\r\n\r\n\t\t}\r\n\r\n\t\tconst splitOffset = partition( indexArray, triangleBounds, offset, count, split );\r\n\r\n\t\t// create the two new child nodes\r\n\t\tif ( splitOffset === offset || splitOffset === offset + count ) {\r\n\r\n\t\t\ttriggerProgress( offset );\r\n\t\t\tnode.offset = offset;\r\n\t\t\tnode.count = count;\r\n\r\n\t\t} else {\r\n\r\n\t\t\tnode.splitAxis = split.axis;\r\n\r\n\t\t\t// create the left child and compute its bounding box\r\n\t\t\tconst left = new MeshBVHNode();\r\n\t\t\tconst lstart = offset;\r\n\t\t\tconst lcount = splitOffset - offset;\r\n\t\t\tnode.left = left;\r\n\t\t\tleft.boundingData = new Float32Array( 6 );\r\n\r\n\t\t\tgetBounds( triangleBounds, lstart, lcount, left.boundingData, cacheCentroidBoundingData );\r\n\t\t\tsplitNode( left, lstart, lcount, cacheCentroidBoundingData, depth + 1 );\r\n\r\n\t\t\t// repeat for right\r\n\t\t\tconst right = new MeshBVHNode();\r\n\t\t\tconst rstart = splitOffset;\r\n\t\t\tconst rcount = count - lcount;\r\n\t\t\tnode.right = right;\r\n\t\t\tright.boundingData = new Float32Array( 6 );\r\n\r\n\t\t\tgetBounds( triangleBounds, rstart, rcount, right.boundingData, cacheCentroidBoundingData );\r\n\t\t\tsplitNode( right, rstart, rcount, cacheCentroidBoundingData, depth + 1 );\r\n\r\n\t\t}\r\n\r\n\t\treturn node;\r\n\r\n\t}\r\n\r\n\tensureIndex( geo, options );\r\n\r\n\t// Compute the full bounds of the geometry at the same time as triangle bounds because\r\n\t// we'll need it for the root bounds in the case with no groups and it should be fast here.\r\n\t// We can't use the geometrying bounding box if it's available because it may be out of date.\r\n\tconst fullBounds = new Float32Array( 6 );\r\n\tconst cacheCentroidBoundingData = new Float32Array( 6 );\r\n\tconst triangleBounds = computeTriangleBounds( geo, fullBounds );\r\n\tconst indexArray = geo.index.array;\r\n\tconst maxDepth = options.maxDepth;\r\n\tconst verbose = options.verbose;\r\n\tconst maxLeafTris = options.maxLeafTris;\r\n\tconst strategy = options.strategy;\r\n\tconst onProgress = options.onProgress;\r\n\tconst totalTriangles = geo.index.count / 3;\r\n\tlet reachedMaxDepth = false;\r\n\r\n\tconst roots = [];\r\n\tconst ranges = getRootIndexRanges( geo );\r\n\r\n\tif ( ranges.length === 1 ) {\r\n\r\n\t\tconst range = ranges[ 0 ];\r\n\t\tconst root = new MeshBVHNode();\r\n\t\troot.boundingData = fullBounds;\r\n\t\tgetCentroidBounds( triangleBounds, range.offset, range.count, cacheCentroidBoundingData );\r\n\r\n\t\tsplitNode( root, range.offset, range.count, cacheCentroidBoundingData );\r\n\t\troots.push( root );\r\n\r\n\t} else {\r\n\r\n\t\tfor ( let range of ranges ) {\r\n\r\n\t\t\tconst root = new MeshBVHNode();\r\n\t\t\troot.boundingData = new Float32Array( 6 );\r\n\t\t\tgetBounds( triangleBounds, range.offset, range.count, root.boundingData, cacheCentroidBoundingData );\r\n\r\n\t\t\tsplitNode( root, range.offset, range.count, cacheCentroidBoundingData );\r\n\t\t\troots.push( root );\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\treturn roots;\r\n\r\n}\r\n\r\nexport function buildPackedTree( geo, options ) {\r\n\r\n\t// boundingData \t\t\t\t: 6 float32\r\n\t// right / offset \t\t\t\t: 1 uint32\r\n\t// splitAxis / isLeaf + count \t: 1 uint32 / 2 uint16\r\n\tconst roots = buildTree( geo, options );\r\n\r\n\tlet float32Array;\r\n\tlet uint32Array;\r\n\tlet uint16Array;\r\n\tconst packedRoots = [];\r\n\tconst BufferConstructor = options.useSharedArrayBuffer ? SharedArrayBuffer : ArrayBuffer;\r\n\tfor ( let i = 0; i < roots.length; i ++ ) {\r\n\r\n\t\tconst root = roots[ i ];\r\n\t\tlet nodeCount = countNodes( root );\r\n\r\n\t\tconst buffer = new BufferConstructor( BYTES_PER_NODE * nodeCount );\r\n\t\tfloat32Array = new Float32Array( buffer );\r\n\t\tuint32Array = new Uint32Array( buffer );\r\n\t\tuint16Array = new Uint16Array( buffer );\r\n\t\tpopulateBuffer( 0, root );\r\n\t\tpackedRoots.push( buffer );\r\n\r\n\t}\r\n\r\n\treturn packedRoots;\r\n\r\n\tfunction countNodes( node ) {\r\n\r\n\t\tif ( node.count ) {\r\n\r\n\t\t\treturn 1;\r\n\r\n\t\t} else {\r\n\r\n\t\t\treturn 1 + countNodes( node.left ) + countNodes( node.right );\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tfunction populateBuffer( byteOffset, node ) {\r\n\r\n\t\tconst stride4Offset = byteOffset / 4;\r\n\t\tconst stride2Offset = byteOffset / 2;\r\n\t\tconst isLeaf = ! ! node.count;\r\n\t\tconst boundingData = node.boundingData;\r\n\t\tfor ( let i = 0; i < 6; i ++ ) {\r\n\r\n\t\t\tfloat32Array[ stride4Offset + i ] = boundingData[ i ];\r\n\r\n\t\t}\r\n\r\n\t\tif ( isLeaf ) {\r\n\r\n\t\t\tconst offset = node.offset;\r\n\t\t\tconst count = node.count;\r\n\t\t\tuint32Array[ stride4Offset + 6 ] = offset;\r\n\t\t\tuint16Array[ stride2Offset + 14 ] = count;\r\n\t\t\tuint16Array[ stride2Offset + 15 ] = IS_LEAFNODE_FLAG;\r\n\t\t\treturn byteOffset + BYTES_PER_NODE;\r\n\r\n\t\t} else {\r\n\r\n\t\t\tconst left = node.left;\r\n\t\t\tconst right = node.right;\r\n\t\t\tconst splitAxis = node.splitAxis;\r\n\r\n\t\t\tlet nextUnusedPointer;\r\n\t\t\tnextUnusedPointer = populateBuffer( byteOffset + BYTES_PER_NODE, left );\r\n\r\n\t\t\tif ( ( nextUnusedPointer / 4 ) > Math.pow( 2, 32 ) ) {\r\n\r\n\t\t\t\tthrow new Error( 'MeshBVH: Cannot store child pointer greater than 32 bits.' );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tuint32Array[ stride4Offset + 6 ] = nextUnusedPointer / 4;\r\n\t\t\tnextUnusedPointer = populateBuffer( nextUnusedPointer, right );\r\n\r\n\t\t\tuint32Array[ stride4Offset + 7 ] = splitAxis;\r\n\t\t\treturn nextUnusedPointer;\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n}\r\n","import { Vector3 } from 'three';\r\n\r\nexport class SeparatingAxisBounds {\r\n\r\n\tconstructor() {\r\n\r\n\t\tthis.min = Infinity;\r\n\t\tthis.max = - Infinity;\r\n\r\n\t}\r\n\r\n\tsetFromPointsField( points, field ) {\r\n\r\n\t\tlet min = Infinity;\r\n\t\tlet max = - Infinity;\r\n\t\tfor ( let i = 0, l = points.length; i < l; i ++ ) {\r\n\r\n\t\t\tconst p = points[ i ];\r\n\t\t\tconst val = p[ field ];\r\n\t\t\tmin = val < min ? val : min;\r\n\t\t\tmax = val > max ? val : max;\r\n\r\n\t\t}\r\n\r\n\t\tthis.min = min;\r\n\t\tthis.max = max;\r\n\r\n\t}\r\n\r\n\tsetFromPoints( axis, points ) {\r\n\r\n\t\tlet min = Infinity;\r\n\t\tlet max = - Infinity;\r\n\t\tfor ( let i = 0, l = points.length; i < l; i ++ ) {\r\n\r\n\t\t\tconst p = points[ i ];\r\n\t\t\tconst val = axis.dot( p );\r\n\t\t\tmin = val < min ? val : min;\r\n\t\t\tmax = val > max ? val : max;\r\n\r\n\t\t}\r\n\r\n\t\tthis.min = min;\r\n\t\tthis.max = max;\r\n\r\n\t}\r\n\r\n\tisSeparated( other ) {\r\n\r\n\t\treturn this.min > other.max || other.min > this.max;\r\n\r\n\t}\r\n\r\n}\r\n\r\nSeparatingAxisBounds.prototype.setFromBox = ( function () {\r\n\r\n\tconst p = new Vector3();\r\n\treturn function setFromBox( axis, box ) {\r\n\r\n\t\tconst boxMin = box.min;\r\n\t\tconst boxMax = box.max;\r\n\t\tlet min = Infinity;\r\n\t\tlet max = - Infinity;\r\n\t\tfor ( let x = 0; x <= 1; x ++ ) {\r\n\r\n\t\t\tfor ( let y = 0; y <= 1; y ++ ) {\r\n\r\n\t\t\t\tfor ( let z = 0; z <= 1; z ++ ) {\r\n\r\n\t\t\t\t\tp.x = boxMin.x * x + boxMax.x * ( 1 - x );\r\n\t\t\t\t\tp.y = boxMin.y * y + boxMax.y * ( 1 - y );\r\n\t\t\t\t\tp.z = boxMin.z * z + boxMax.z * ( 1 - z );\r\n\r\n\t\t\t\t\tconst val = axis.dot( p );\r\n\t\t\t\t\tmin = Math.min( val, min );\r\n\t\t\t\t\tmax = Math.max( val, max );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tthis.min = min;\r\n\t\tthis.max = max;\r\n\r\n\t};\r\n\r\n} )();\r\n\r\nexport const areIntersecting = ( function () {\r\n\r\n\tconst cacheSatBounds = new SeparatingAxisBounds();\r\n\treturn function areIntersecting( shape1, shape2 ) {\r\n\r\n\t\tconst points1 = shape1.points;\r\n\t\tconst satAxes1 = shape1.satAxes;\r\n\t\tconst satBounds1 = shape1.satBounds;\r\n\r\n\t\tconst points2 = shape2.points;\r\n\t\tconst satAxes2 = shape2.satAxes;\r\n\t\tconst satBounds2 = shape2.satBounds;\r\n\r\n\t\t// check axes of the first shape\r\n\t\tfor ( let i = 0; i < 3; i ++ ) {\r\n\r\n\t\t\tconst sb = satBounds1[ i ];\r\n\t\t\tconst sa = satAxes1[ i ];\r\n\t\t\tcacheSatBounds.setFromPoints( sa, points2 );\r\n\t\t\tif ( sb.isSeparated( cacheSatBounds ) ) return false;\r\n\r\n\t\t}\r\n\r\n\t\t// check axes of the second shape\r\n\t\tfor ( let i = 0; i < 3; i ++ ) {\r\n\r\n\t\t\tconst sb = satBounds2[ i ];\r\n\t\t\tconst sa = satAxes2[ i ];\r\n\t\t\tcacheSatBounds.setFromPoints( sa, points1 );\r\n\t\t\tif ( sb.isSeparated( cacheSatBounds ) ) return false;\r\n\r\n\t\t}\r\n\r\n\t};\r\n\r\n} )();\r\n","import { Vector3, Vector2, Plane, Line3 } from 'three';\r\n\r\nexport const closestPointLineToLine = ( function () {\r\n\r\n\t// https://github.com/juj/MathGeoLib/blob/master/src/Geometry/Line.cpp#L56\r\n\tconst dir1 = new Vector3();\r\n\tconst dir2 = new Vector3();\r\n\tconst v02 = new Vector3();\r\n\treturn function closestPointLineToLine( l1, l2, result ) {\r\n\r\n\t\tconst v0 = l1.start;\r\n\t\tconst v10 = dir1;\r\n\t\tconst v2 = l2.start;\r\n\t\tconst v32 = dir2;\r\n\r\n\t\tv02.subVectors( v0, v2 );\r\n\t\tdir1.subVectors( l1.end, l2.start );\r\n\t\tdir2.subVectors( l2.end, l2.start );\r\n\r\n\t\t// float d0232 = v02.Dot(v32);\r\n\t\tconst d0232 = v02.dot( v32 );\r\n\r\n\t\t// float d3210 = v32.Dot(v10);\r\n\t\tconst d3210 = v32.dot( v10 );\r\n\r\n\t\t// float d3232 = v32.Dot(v32);\r\n\t\tconst d3232 = v32.dot( v32 );\r\n\r\n\t\t// float d0210 = v02.Dot(v10);\r\n\t\tconst d0210 = v02.dot( v10 );\r\n\r\n\t\t// float d1010 = v10.Dot(v10);\r\n\t\tconst d1010 = v10.dot( v10 );\r\n\r\n\t\t// float denom = d1010*d3232 - d3210*d3210;\r\n\t\tconst denom = d1010 * d3232 - d3210 * d3210;\r\n\r\n\t\tlet d, d2;\r\n\t\tif ( denom !== 0 ) {\r\n\r\n\t\t\td = ( d0232 * d3210 - d0210 * d3232 ) / denom;\r\n\r\n\t\t} else {\r\n\r\n\t\t\td = 0;\r\n\r\n\t\t}\r\n\r\n\t\td2 = ( d0232 + d * d3210 ) / d3232;\r\n\r\n\t\tresult.x = d;\r\n\t\tresult.y = d2;\r\n\r\n\t};\r\n\r\n} )();\r\n\r\nexport const closestPointsSegmentToSegment = ( function () {\r\n\r\n\t// https://github.com/juj/MathGeoLib/blob/master/src/Geometry/LineSegment.cpp#L187\r\n\tconst paramResult = new Vector2();\r\n\tconst temp1 = new Vector3();\r\n\tconst temp2 = new Vector3();\r\n\treturn function closestPointsSegmentToSegment( l1, l2, target1, target2 ) {\r\n\r\n\t\tclosestPointLineToLine( l1, l2, paramResult );\r\n\r\n\t\tlet d = paramResult.x;\r\n\t\tlet d2 = paramResult.y;\r\n\t\tif ( d >= 0 && d <= 1 && d2 >= 0 && d2 <= 1 ) {\r\n\r\n\t\t\tl1.at( d, target1 );\r\n\t\t\tl2.at( d2, target2 );\r\n\r\n\t\t\treturn;\r\n\r\n\t\t} else if ( d >= 0 && d <= 1 ) {\r\n\r\n\t\t\t// Only d2 is out of bounds.\r\n\t\t\tif ( d2 < 0 ) {\r\n\r\n\t\t\t\tl2.at( 0, target2 );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tl2.at( 1, target2 );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tl1.closestPointToPoint( target2, true, target1 );\r\n\t\t\treturn;\r\n\r\n\t\t} else if ( d2 >= 0 && d2 <= 1 ) {\r\n\r\n\t\t\t// Only d is out of bounds.\r\n\t\t\tif ( d < 0 ) {\r\n\r\n\t\t\t\tl1.at( 0, target1 );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tl1.at( 1, target1 );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tl2.closestPointToPoint( target1, true, target2 );\r\n\t\t\treturn;\r\n\r\n\t\t} else {\r\n\r\n\t\t\t// Both u and u2 are out of bounds.\r\n\t\t\tlet p;\r\n\t\t\tif ( d < 0 ) {\r\n\r\n\t\t\t\tp = l1.start;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tp = l1.end;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tlet p2;\r\n\t\t\tif ( d2 < 0 ) {\r\n\r\n\t\t\t\tp2 = l2.start;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tp2 = l2.end;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tconst closestPoint = temp1;\r\n\t\t\tconst closestPoint2 = temp2;\r\n\t\t\tl1.closestPointToPoint( p2, true, temp1 );\r\n\t\t\tl2.closestPointToPoint( p, true, temp2 );\r\n\r\n\t\t\tif ( closestPoint.distanceToSquared( p2 ) <= closestPoint2.distanceToSquared( p ) ) {\r\n\r\n\t\t\t\ttarget1.copy( closestPoint );\r\n\t\t\t\ttarget2.copy( p2 );\r\n\t\t\t\treturn;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\ttarget1.copy( p );\r\n\t\t\t\ttarget2.copy( closestPoint2 );\r\n\t\t\t\treturn;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t};\r\n\r\n} )();\r\n\r\n\r\nexport const sphereIntersectTriangle = ( function () {\r\n\r\n\t// https://stackoverflow.com/questions/34043955/detect-collision-between-sphere-and-triangle-in-three-js\r\n\tconst closestPointTemp = new Vector3();\r\n\tconst projectedPointTemp = new Vector3();\r\n\tconst planeTemp = new Plane();\r\n\tconst lineTemp = new Line3();\r\n\treturn function sphereIntersectTriangle( sphere, triangle ) {\r\n\r\n\t\tconst { radius, center } = sphere;\r\n\t\tconst { a, b, c } = triangle;\r\n\r\n\t\t// phase 1\r\n\t\tlineTemp.start = a;\r\n\t\tlineTemp.end = b;\r\n\t\tconst closestPoint1 = lineTemp.closestPointToPoint( center, true, closestPointTemp );\r\n\t\tif ( closestPoint1.distanceTo( center ) <= radius ) return true;\r\n\r\n\t\tlineTemp.start = a;\r\n\t\tlineTemp.end = c;\r\n\t\tconst closestPoint2 = lineTemp.closestPointToPoint( center, true, closestPointTemp );\r\n\t\tif ( closestPoint2.distanceTo( center ) <= radius ) return true;\r\n\r\n\t\tlineTemp.start = b;\r\n\t\tlineTemp.end = c;\r\n\t\tconst closestPoint3 = lineTemp.closestPointToPoint( center, true, closestPointTemp );\r\n\t\tif ( closestPoint3.distanceTo( center ) <= radius ) return true;\r\n\r\n\t\t// phase 2\r\n\t\tconst plane = triangle.getPlane( planeTemp );\r\n\t\tconst dp = Math.abs( plane.distanceToPoint( center ) );\r\n\t\tif ( dp <= radius ) {\r\n\r\n\t\t\tconst pp = plane.projectPoint( center, projectedPointTemp );\r\n\t\t\tconst cp = triangle.containsPoint( pp );\r\n\t\t\tif ( cp ) return true;\r\n\r\n\t\t}\r\n\r\n\t\treturn false;\r\n\r\n\t};\r\n\r\n} )();\r\n","import { Triangle, Vector3, Line3, Sphere, Plane } from 'three';\r\nimport { SeparatingAxisBounds } from './SeparatingAxisBounds.js';\r\nimport { closestPointsSegmentToSegment, sphereIntersectTriangle } from './MathUtilities.js';\r\n\r\nexport class SeparatingAxisTriangle extends Triangle {\r\n\r\n\tconstructor( ...args ) {\r\n\r\n\t\tsuper( ...args );\r\n\r\n\t\tthis.isSeparatingAxisTriangle = true;\r\n\t\tthis.satAxes = new Array( 4 ).fill().map( () => new Vector3() );\r\n\t\tthis.satBounds = new Array( 4 ).fill().map( () => new SeparatingAxisBounds() );\r\n\t\tthis.points = [ this.a, this.b, this.c ];\r\n\t\tthis.sphere = new Sphere();\r\n\t\tthis.plane = new Plane();\r\n\t\tthis.needsUpdate = false;\r\n\r\n\t}\r\n\r\n\tintersectsSphere( sphere ) {\r\n\r\n\t\treturn sphereIntersectTriangle( sphere, this );\r\n\r\n\t}\r\n\r\n\tupdate() {\r\n\r\n\t\tconst a = this.a;\r\n\t\tconst b = this.b;\r\n\t\tconst c = this.c;\r\n\t\tconst points = this.points;\r\n\r\n\t\tconst satAxes = this.satAxes;\r\n\t\tconst satBounds = this.satBounds;\r\n\r\n\t\tconst axis0 = satAxes[ 0 ];\r\n\t\tconst sab0 = satBounds[ 0 ];\r\n\t\tthis.getNormal( axis0 );\r\n\t\tsab0.setFromPoints( axis0, points );\r\n\r\n\t\tconst axis1 = satAxes[ 1 ];\r\n\t\tconst sab1 = satBounds[ 1 ];\r\n\t\taxis1.subVectors( a, b );\r\n\t\tsab1.setFromPoints( axis1, points );\r\n\r\n\t\tconst axis2 = satAxes[ 2 ];\r\n\t\tconst sab2 = satBounds[ 2 ];\r\n\t\taxis2.subVectors( b, c );\r\n\t\tsab2.setFromPoints( axis2, points );\r\n\r\n\t\tconst axis3 = satAxes[ 3 ];\r\n\t\tconst sab3 = satBounds[ 3 ];\r\n\t\taxis3.subVectors( c, a );\r\n\t\tsab3.setFromPoints( axis3, points );\r\n\r\n\t\tthis.sphere.setFromPoints( this.points );\r\n\t\tthis.plane.setFromNormalAndCoplanarPoint( axis0, a );\r\n\t\tthis.needsUpdate = false;\r\n\r\n\t}\r\n\r\n}\r\n\r\nSeparatingAxisTriangle.prototype.closestPointToSegment = ( function () {\r\n\r\n\tconst point1 = new Vector3();\r\n\tconst point2 = new Vector3();\r\n\tconst edge = new Line3();\r\n\r\n\treturn function distanceToSegment( segment, target1 = null, target2 = null ) {\r\n\r\n\t\tconst { start, end } = segment;\r\n\t\tconst points = this.points;\r\n\t\tlet distSq;\r\n\t\tlet closestDistanceSq = Infinity;\r\n\r\n\t\t// check the triangle edges\r\n\t\tfor ( let i = 0; i < 3; i ++ ) {\r\n\r\n\t\t\tconst nexti = ( i + 1 ) % 3;\r\n\t\t\tedge.start.copy( points[ i ] );\r\n\t\t\tedge.end.copy( points[ nexti ] );\r\n\r\n\t\t\tclosestPointsSegmentToSegment( edge, segment, point1, point2 );\r\n\r\n\t\t\tdistSq = point1.distanceToSquared( point2 );\r\n\t\t\tif ( distSq < closestDistanceSq ) {\r\n\r\n\t\t\t\tclosestDistanceSq = distSq;\r\n\t\t\t\tif ( target1 ) target1.copy( point1 );\r\n\t\t\t\tif ( target2 ) target2.copy( point2 );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t// check end points\r\n\t\tthis.closestPointToPoint( start, point1 );\r\n\t\tdistSq = start.distanceToSquared( point1 );\r\n\t\tif ( distSq < closestDistanceSq ) {\r\n\r\n\t\t\tclosestDistanceSq = distSq;\r\n\t\t\tif ( target1 ) target1.copy( point1 );\r\n\t\t\tif ( target2 ) target2.copy( start );\r\n\r\n\t\t}\r\n\r\n\t\tthis.closestPointToPoint( end, point1 );\r\n\t\tdistSq = end.distanceToSquared( point1 );\r\n\t\tif ( distSq < closestDistanceSq ) {\r\n\r\n\t\t\tclosestDistanceSq = distSq;\r\n\t\t\tif ( target1 ) target1.copy( point1 );\r\n\t\t\tif ( target2 ) target2.copy( end );\r\n\r\n\t\t}\r\n\r\n\t\treturn Math.sqrt( closestDistanceSq );\r\n\r\n\t};\r\n\r\n} )();\r\n\r\nSeparatingAxisTriangle.prototype.intersectsTriangle = ( function () {\r\n\r\n\tconst saTri2 = new SeparatingAxisTriangle();\r\n\tconst arr1 = new Array( 3 );\r\n\tconst arr2 = new Array( 3 );\r\n\tconst cachedSatBounds = new SeparatingAxisBounds();\r\n\tconst cachedSatBounds2 = new SeparatingAxisBounds();\r\n\tconst cachedAxis = new Vector3();\r\n\tconst dir1 = new Vector3();\r\n\tconst dir2 = new Vector3();\r\n\tconst tempDir = new Vector3();\r\n\tconst edge = new Line3();\r\n\tconst edge1 = new Line3();\r\n\tconst edge2 = new Line3();\r\n\r\n\t// TODO: If the triangles are coplanar and intersecting the target is nonsensical. It should at least\r\n\t// be a line contained by both triangles if not a different special case somehow represented in the return result.\r\n\treturn function intersectsTriangle( other, target = null ) {\r\n\r\n\t\tif ( this.needsUpdate ) {\r\n\r\n\t\t\tthis.update();\r\n\r\n\t\t}\r\n\r\n\t\tif ( ! other.isSeparatingAxisTriangle ) {\r\n\r\n\t\t\tsaTri2.copy( other );\r\n\t\t\tsaTri2.update();\r\n\t\t\tother = saTri2;\r\n\r\n\t\t} else if ( other.needsUpdate ) {\r\n\r\n\t\t\tother.update();\r\n\r\n\t\t}\r\n\r\n\t\tconst satBounds1 = this.satBounds;\r\n\t\tconst satAxes1 = this.satAxes;\r\n\t\tarr2[ 0 ] = other.a;\r\n\t\tarr2[ 1 ] = other.b;\r\n\t\tarr2[ 2 ] = other.c;\r\n\t\tfor ( let i = 0; i < 4; i ++ ) {\r\n\r\n\t\t\tconst sb = satBounds1[ i ];\r\n\t\t\tconst sa = satAxes1[ i ];\r\n\t\t\tcachedSatBounds.setFromPoints( sa, arr2 );\r\n\t\t\tif ( sb.isSeparated( cachedSatBounds ) ) return false;\r\n\r\n\t\t}\r\n\r\n\t\tconst satBounds2 = other.satBounds;\r\n\t\tconst satAxes2 = other.satAxes;\r\n\t\tarr1[ 0 ] = this.a;\r\n\t\tarr1[ 1 ] = this.b;\r\n\t\tarr1[ 2 ] = this.c;\r\n\t\tfor ( let i = 0; i < 4; i ++ ) {\r\n\r\n\t\t\tconst sb = satBounds2[ i ];\r\n\t\t\tconst sa = satAxes2[ i ];\r\n\t\t\tcachedSatBounds.setFromPoints( sa, arr1 );\r\n\t\t\tif ( sb.isSeparated( cachedSatBounds ) ) return false;\r\n\r\n\t\t}\r\n\r\n\t\t// check crossed axes\r\n\t\tfor ( let i = 0; i < 4; i ++ ) {\r\n\r\n\t\t\tconst sa1 = satAxes1[ i ];\r\n\t\t\tfor ( let i2 = 0; i2 < 4; i2 ++ ) {\r\n\r\n\t\t\t\tconst sa2 = satAxes2[ i2 ];\r\n\t\t\t\tcachedAxis.crossVectors( sa1, sa2 );\r\n\t\t\t\tcachedSatBounds.setFromPoints( cachedAxis, arr1 );\r\n\t\t\t\tcachedSatBounds2.setFromPoints( cachedAxis, arr2 );\r\n\t\t\t\tif ( cachedSatBounds.isSeparated( cachedSatBounds2 ) ) return false;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tif ( target ) {\r\n\r\n\t\t\tconst plane1 = this.plane;\r\n\t\t\tconst plane2 = other.plane;\r\n\r\n\t\t\tif ( Math.abs( plane1.normal.dot( plane2.normal ) ) > 1.0 - 1e-10 ) {\r\n\r\n\t\t\t\t// TODO find two points that intersect on the edges and make that the result\r\n\t\t\t\tconsole.warn( 'SeparatingAxisTriangle.intersectsTriangle: Triangles are coplanar which does not support an output edge. Setting edge to 0, 0, 0.' );\r\n\t\t\t\ttarget.start.set( 0, 0, 0 );\r\n\t\t\t\ttarget.end.set( 0, 0, 0 );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\t// find the edge that intersects the other triangle plane\r\n\t\t\t\tconst points1 = this.points;\r\n\t\t\t\tlet found1 = false;\r\n\t\t\t\tfor ( let i = 0; i < 3; i ++ ) {\r\n\r\n\t\t\t\t\tconst p1 = points1[ i ];\r\n\t\t\t\t\tconst p2 = points1[ ( i + 1 ) % 3 ];\r\n\r\n\t\t\t\t\tedge.start.copy( p1 );\r\n\t\t\t\t\tedge.end.copy( p2 );\r\n\r\n\t\t\t\t\tif ( plane2.intersectLine( edge, found1 ? edge1.start : edge1.end ) ) {\r\n\r\n\t\t\t\t\t\tif ( found1 ) {\r\n\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tfound1 = true;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// find the other triangles edge that intersects this plane\r\n\t\t\t\tconst points2 = other.points;\r\n\t\t\t\tlet found2 = false;\r\n\t\t\t\tfor ( let i = 0; i < 3; i ++ ) {\r\n\r\n\t\t\t\t\tconst p1 = points2[ i ];\r\n\t\t\t\t\tconst p2 = points2[ ( i + 1 ) % 3 ];\r\n\r\n\t\t\t\t\tedge.start.copy( p1 );\r\n\t\t\t\t\tedge.end.copy( p2 );\r\n\r\n\t\t\t\t\tif ( plane1.intersectLine( edge, found2 ? edge2.start : edge2.end ) ) {\r\n\r\n\t\t\t\t\t\tif ( found2 ) {\r\n\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tfound2 = true;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// find swap the second edge so both lines are running the same direction\r\n\t\t\t\tedge1.delta( dir1 );\r\n\t\t\t\tedge2.delta( dir2 );\r\n\r\n\r\n\t\t\t\tif ( dir1.dot( dir2 ) < 0 ) {\r\n\r\n\t\t\t\t\tlet tmp = edge2.start;\r\n\t\t\t\t\tedge2.start = edge2.end;\r\n\t\t\t\t\tedge2.end = tmp;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\ttempDir.subVectors( edge1.start, edge2.start );\r\n\t\t\t\tif ( tempDir.dot( dir1 ) > 0 ) {\r\n\r\n\t\t\t\t\ttarget.start.copy( edge1.start );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\ttarget.start.copy( edge2.start );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\ttempDir.subVectors( edge1.end, edge2.end );\r\n\t\t\t\tif ( tempDir.dot( dir1 ) < 0 ) {\r\n\r\n\t\t\t\t\ttarget.end.copy( edge1.end );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\ttarget.end.copy( edge2.end );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\treturn true;\r\n\r\n\t};\r\n\r\n} )();\r\n\r\n\r\nSeparatingAxisTriangle.prototype.distanceToPoint = ( function () {\r\n\r\n\tconst target = new Vector3();\r\n\treturn function distanceToPoint( point ) {\r\n\r\n\t\tthis.closestPointToPoint( point, target );\r\n\t\treturn point.distanceTo( target );\r\n\r\n\t};\r\n\r\n} )();\r\n\r\n\r\nSeparatingAxisTriangle.prototype.distanceToTriangle = ( function () {\r\n\r\n\tconst point = new Vector3();\r\n\tconst point2 = new Vector3();\r\n\tconst cornerFields = [ 'a', 'b', 'c' ];\r\n\tconst line1 = new Line3();\r\n\tconst line2 = new Line3();\r\n\r\n\treturn function distanceToTriangle( other, target1 = null, target2 = null ) {\r\n\r\n\t\tconst lineTarget = target1 || target2 ? line1 : null;\r\n\t\tif ( this.intersectsTriangle( other, lineTarget ) ) {\r\n\r\n\t\t\tif ( target1 || target2 ) {\r\n\r\n\t\t\t\tif ( target1 ) lineTarget.getCenter( target1 );\r\n\t\t\t\tif ( target2 ) lineTarget.getCenter( target2 );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn 0;\r\n\r\n\t\t}\r\n\r\n\t\tlet closestDistanceSq = Infinity;\r\n\r\n\t\t// check all point distances\r\n\t\tfor ( let i = 0; i < 3; i ++ ) {\r\n\r\n\t\t\tlet dist;\r\n\t\t\tconst field = cornerFields[ i ];\r\n\t\t\tconst otherVec = other[ field ];\r\n\t\t\tthis.closestPointToPoint( otherVec, point );\r\n\r\n\t\t\tdist = otherVec.distanceToSquared( point );\r\n\r\n\t\t\tif ( dist < closestDistanceSq ) {\r\n\r\n\t\t\t\tclosestDistanceSq = dist;\r\n\t\t\t\tif ( target1 ) target1.copy( point );\r\n\t\t\t\tif ( target2 ) target2.copy( otherVec );\r\n\r\n\t\t\t}\r\n\r\n\r\n\t\t\tconst thisVec = this[ field ];\r\n\t\t\tother.closestPointToPoint( thisVec, point );\r\n\r\n\t\t\tdist = thisVec.distanceToSquared( point );\r\n\r\n\t\t\tif ( dist < closestDistanceSq ) {\r\n\r\n\t\t\t\tclosestDistanceSq = dist;\r\n\t\t\t\tif ( target1 ) target1.copy( thisVec );\r\n\t\t\t\tif ( target2 ) target2.copy( point );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfor ( let i = 0; i < 3; i ++ ) {\r\n\r\n\t\t\tconst f11 = cornerFields[ i ];\r\n\t\t\tconst f12 = cornerFields[ ( i + 1 ) % 3 ];\r\n\t\t\tline1.set( this[ f11 ], this[ f12 ] );\r\n\t\t\tfor ( let i2 = 0; i2 < 3; i2 ++ ) {\r\n\r\n\t\t\t\tconst f21 = cornerFields[ i2 ];\r\n\t\t\t\tconst f22 = cornerFields[ ( i2 + 1 ) % 3 ];\r\n\t\t\t\tline2.set( other[ f21 ], other[ f22 ] );\r\n\r\n\t\t\t\tclosestPointsSegmentToSegment( line1, line2, point, point2 );\r\n\r\n\t\t\t\tconst dist = point.distanceToSquared( point2 );\r\n\t\t\t\tif ( dist < closestDistanceSq ) {\r\n\r\n\t\t\t\t\tclosestDistanceSq = dist;\r\n\t\t\t\t\tif ( target1 ) target1.copy( point );\r\n\t\t\t\t\tif ( target2 ) target2.copy( point2 );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\treturn Math.sqrt( closestDistanceSq );\r\n\r\n\t};\r\n\r\n} )();\r\n\r\n","import { Box3, Vector3, Matrix4, Line3 } from 'three';\r\nimport { SeparatingAxisBounds } from './SeparatingAxisBounds.js';\r\nimport { SeparatingAxisTriangle } from './SeparatingAxisTriangle.js';\r\nimport { closestPointsSegmentToSegment } from './MathUtilities.js';\r\n\r\nexport class OrientedBox extends Box3 {\r\n\r\n\tconstructor( ...args ) {\r\n\r\n\t\tsuper( ...args );\r\n\r\n\t\tthis.isOrientedBox = true;\r\n\t\tthis.matrix = new Matrix4();\r\n\t\tthis.invMatrix = new Matrix4();\r\n\t\tthis.points = new Array( 8 ).fill().map( () => new Vector3() );\r\n\t\tthis.satAxes = new Array( 3 ).fill().map( () => new Vector3() );\r\n\t\tthis.satBounds = new Array( 3 ).fill().map( () => new SeparatingAxisBounds() );\r\n\t\tthis.alignedSatBounds = new Array( 3 ).fill().map( () => new SeparatingAxisBounds() );\r\n\t\tthis.needsUpdate = false;\r\n\r\n\t}\r\n\r\n\tset( min, max, matrix ) {\r\n\r\n\t\tsuper.set( min, max );\r\n\t\tthis.matrix = matrix;\r\n\t\tthis.needsUpdate = true;\r\n\r\n\t}\r\n\r\n\tcopy( other ) {\r\n\r\n\t\tsuper.copy( other );\r\n\t\tthis.matrix.copy( other.matrix );\r\n\t\tthis.needsUpdate = true;\r\n\r\n\t}\r\n\r\n}\r\n\r\nOrientedBox.prototype.update = ( function () {\r\n\r\n\treturn function update() {\r\n\r\n\t\tconst matrix = this.matrix;\r\n\t\tconst min = this.min;\r\n\t\tconst max = this.max;\r\n\r\n\t\tconst points = this.points;\r\n\t\tfor ( let x = 0; x <= 1; x ++ ) {\r\n\r\n\t\t\tfor ( let y = 0; y <= 1; y ++ ) {\r\n\r\n\t\t\t\tfor ( let z = 0; z <= 1; z ++ ) {\r\n\r\n\t\t\t\t\tconst i = ( ( 1 << 0 ) * x ) | ( ( 1 << 1 ) * y ) | ( ( 1 << 2 ) * z );\r\n\t\t\t\t\tconst v = points[ i ];\r\n\t\t\t\t\tv.x = x ? max.x : min.x;\r\n\t\t\t\t\tv.y = y ? max.y : min.y;\r\n\t\t\t\t\tv.z = z ? max.z : min.z;\r\n\r\n\t\t\t\t\tv.applyMatrix4( matrix );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tconst satBounds = this.satBounds;\r\n\t\tconst satAxes = this.satAxes;\r\n\t\tconst minVec = points[ 0 ];\r\n\t\tfor ( let i = 0; i < 3; i ++ ) {\r\n\r\n\t\t\tconst axis = satAxes[ i ];\r\n\t\t\tconst sb = satBounds[ i ];\r\n\t\t\tconst index = 1 << i;\r\n\t\t\tconst pi = points[ index ];\r\n\r\n\t\t\taxis.subVectors( minVec, pi );\r\n\t\t\tsb.setFromPoints( axis, points );\r\n\r\n\t\t}\r\n\r\n\t\tconst alignedSatBounds = this.alignedSatBounds;\r\n\t\talignedSatBounds[ 0 ].setFromPointsField( points, 'x' );\r\n\t\talignedSatBounds[ 1 ].setFromPointsField( points, 'y' );\r\n\t\talignedSatBounds[ 2 ].setFromPointsField( points, 'z' );\r\n\r\n\t\tthis.invMatrix.copy( this.matrix ).invert();\r\n\t\tthis.needsUpdate = false;\r\n\r\n\t};\r\n\r\n} )();\r\n\r\nOrientedBox.prototype.intersectsBox = ( function () {\r\n\r\n\tconst aabbBounds = new SeparatingAxisBounds();\r\n\treturn function intersectsBox( box ) {\r\n\r\n\t\t// TODO: should this be doing SAT against the AABB?\r\n\t\tif ( this.needsUpdate ) {\r\n\r\n\t\t\tthis.update();\r\n\r\n\t\t}\r\n\r\n\t\tconst min = box.min;\r\n\t\tconst max = box.max;\r\n\t\tconst satBounds = this.satBounds;\r\n\t\tconst satAxes = this.satAxes;\r\n\t\tconst alignedSatBounds = this.alignedSatBounds;\r\n\r\n\t\taabbBounds.min = min.x;\r\n\t\taabbBounds.max = max.x;\r\n\t\tif ( alignedSatBounds[ 0 ].isSeparated( aabbBounds ) ) return false;\r\n\r\n\t\taabbBounds.min = min.y;\r\n\t\taabbBounds.max = max.y;\r\n\t\tif ( alignedSatBounds[ 1 ].isSeparated( aabbBounds ) ) return false;\r\n\r\n\t\taabbBounds.min = min.z;\r\n\t\taabbBounds.max = max.z;\r\n\t\tif ( alignedSatBounds[ 2 ].isSeparated( aabbBounds ) ) return false;\r\n\r\n\t\tfor ( let i = 0; i < 3; i ++ ) {\r\n\r\n\t\t\tconst axis = satAxes[ i ];\r\n\t\t\tconst sb = satBounds[ i ];\r\n\t\t\taabbBounds.setFromBox( axis, box );\r\n\t\t\tif ( sb.isSeparated( aabbBounds ) ) return false;\r\n\r\n\t\t}\r\n\r\n\t\treturn true;\r\n\r\n\t};\r\n\r\n} )();\r\n\r\nOrientedBox.prototype.intersectsTriangle = ( function () {\r\n\r\n\tconst saTri = new SeparatingAxisTriangle();\r\n\tconst pointsArr = new Array( 3 );\r\n\tconst cachedSatBounds = new SeparatingAxisBounds();\r\n\tconst cachedSatBounds2 = new SeparatingAxisBounds();\r\n\tconst cachedAxis = new Vector3();\r\n\treturn function intersectsTriangle( triangle ) {\r\n\r\n\t\tif ( this.needsUpdate ) {\r\n\r\n\t\t\tthis.update();\r\n\r\n\t\t}\r\n\r\n\t\tif ( ! triangle.isSeparatingAxisTriangle ) {\r\n\r\n\t\t\tsaTri.copy( triangle );\r\n\t\t\tsaTri.update();\r\n\t\t\ttriangle = saTri;\r\n\r\n\t\t} else if ( triangle.needsUpdate ) {\r\n\r\n\t\t\ttriangle.update();\r\n\r\n\t\t}\r\n\r\n\t\tconst satBounds = this.satBounds;\r\n\t\tconst satAxes = this.satAxes;\r\n\r\n\t\tpointsArr[ 0 ] = triangle.a;\r\n\t\tpointsArr[ 1 ] = triangle.b;\r\n\t\tpointsArr[ 2 ] = triangle.c;\r\n\r\n\t\tfor ( let i = 0; i < 3; i ++ ) {\r\n\r\n\t\t\tconst sb = satBounds[ i ];\r\n\t\t\tconst sa = satAxes[ i ];\r\n\t\t\tcachedSatBounds.setFromPoints( sa, pointsArr );\r\n\t\t\tif ( sb.isSeparated( cachedSatBounds ) ) return false;\r\n\r\n\t\t}\r\n\r\n\t\tconst triSatBounds = triangle.satBounds;\r\n\t\tconst triSatAxes = triangle.satAxes;\r\n\t\tconst points = this.points;\r\n\t\tfor ( let i = 0; i < 3; i ++ ) {\r\n\r\n\t\t\tconst sb = triSatBounds[ i ];\r\n\t\t\tconst sa = triSatAxes[ i ];\r\n\t\t\tcachedSatBounds.setFromPoints( sa, points );\r\n\t\t\tif ( sb.isSeparated( cachedSatBounds ) ) return false;\r\n\r\n\t\t}\r\n\r\n\t\t// check crossed axes\r\n\t\tfor ( let i = 0; i < 3; i ++ ) {\r\n\r\n\t\t\tconst sa1 = satAxes[ i ];\r\n\t\t\tfor ( let i2 = 0; i2 < 4; i2 ++ ) {\r\n\r\n\t\t\t\tconst sa2 = triSatAxes[ i2 ];\r\n\t\t\t\tcachedAxis.crossVectors( sa1, sa2 );\r\n\t\t\t\tcachedSatBounds.setFromPoints( cachedAxis, pointsArr );\r\n\t\t\t\tcachedSatBounds2.setFromPoints( cachedAxis, points );\r\n\t\t\t\tif ( cachedSatBounds.isSeparated( cachedSatBounds2 ) ) return false;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\treturn true;\r\n\r\n\t};\r\n\r\n} )();\r\n\r\nOrientedBox.prototype.closestPointToPoint = ( function () {\r\n\r\n\treturn function closestPointToPoint( point, target1 ) {\r\n\r\n\t\tif ( this.needsUpdate ) {\r\n\r\n\t\t\tthis.update();\r\n\r\n\t\t}\r\n\r\n\t\ttarget1\r\n\t\t\t.copy( point )\r\n\t\t\t.applyMatrix4( this.invMatrix )\r\n\t\t\t.clamp( this.min, this.max )\r\n\t\t\t.applyMatrix4( this.matrix );\r\n\r\n\t\treturn target1;\r\n\r\n\t};\r\n\r\n} )();\r\n\r\nOrientedBox.prototype.distanceToPoint = ( function () {\r\n\r\n\tconst target = new Vector3();\r\n\treturn function distanceToPoint( point ) {\r\n\r\n\t\tthis.closestPointToPoint( point, target );\r\n\t\treturn point.distanceTo( target );\r\n\r\n\t};\r\n\r\n} )();\r\n\r\nOrientedBox.prototype.distanceToBox = ( function () {\r\n\r\n\tconst xyzFields = [ 'x', 'y', 'z' ];\r\n\tconst segments1 = new Array( 12 ).fill().map( () => new Line3() );\r\n\tconst segments2 = new Array( 12 ).fill().map( () => new Line3() );\r\n\r\n\tconst point1 = new Vector3();\r\n\tconst point2 = new Vector3();\r\n\r\n\t// early out if we find a value below threshold\r\n\treturn function distanceToBox( box, threshold = 0, target1 = null, target2 = null ) {\r\n\r\n\t\tif ( this.needsUpdate ) {\r\n\r\n\t\t\tthis.update();\r\n\r\n\t\t}\r\n\r\n\t\tif ( this.intersectsBox( box ) ) {\r\n\r\n\t\t\tif ( target1 || target2 ) {\r\n\r\n\t\t\t\tbox.getCenter( point2 );\r\n\t\t\t\tthis.closestPointToPoint( point2, point1 );\r\n\t\t\t\tbox.closestPointToPoint( point1, point2 );\r\n\r\n\t\t\t\tif ( target1 ) target1.copy( point1 );\r\n\t\t\t\tif ( target2 ) target2.copy( point2 );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn 0;\r\n\r\n\t\t}\r\n\r\n\t\tconst threshold2 = threshold * threshold;\r\n\t\tconst min = box.min;\r\n\t\tconst max = box.max;\r\n\t\tconst points = this.points;\r\n\r\n\r\n\t\t// iterate over every edge and compare distances\r\n\t\tlet closestDistanceSq = Infinity;\r\n\r\n\t\t// check over all these points\r\n\t\tfor ( let i = 0; i < 8; i ++ ) {\r\n\r\n\t\t\tconst p = points[ i ];\r\n\t\t\tpoint2.copy( p ).clamp( min, max );\r\n\r\n\t\t\tconst dist = p.distanceToSquared( point2 );\r\n\t\t\tif ( dist < closestDistanceSq ) {\r\n\r\n\t\t\t\tclosestDistanceSq = dist;\r\n\t\t\t\tif ( target1 ) target1.copy( p );\r\n\t\t\t\tif ( target2 ) target2.copy( point2 );\r\n\r\n\t\t\t\tif ( dist < threshold2 ) return Math.sqrt( dist );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t// generate and check all line segment distances\r\n\t\tlet count = 0;\r\n\t\tfor ( let i = 0; i < 3; i ++ ) {\r\n\r\n\t\t\tfor ( let i1 = 0; i1 <= 1; i1 ++ ) {\r\n\r\n\t\t\t\tfor ( let i2 = 0; i2 <= 1; i2 ++ ) {\r\n\r\n\t\t\t\t\tconst nextIndex = ( i + 1 ) % 3;\r\n\t\t\t\t\tconst nextIndex2 = ( i + 2 ) % 3;\r\n\r\n\t\t\t\t\t// get obb line segments\r\n\t\t\t\t\tconst index = i1 << nextIndex | i2 << nextIndex2;\r\n\t\t\t\t\tconst index2 = 1 << i | i1 << nextIndex | i2 << nextIndex2;\r\n\t\t\t\t\tconst p1 = points[ index ];\r\n\t\t\t\t\tconst p2 = points[ index2 ];\r\n\t\t\t\t\tconst line1 = segments1[ count ];\r\n\t\t\t\t\tline1.set( p1, p2 );\r\n\r\n\r\n\t\t\t\t\t// get aabb line segments\r\n\t\t\t\t\tconst f1 = xyzFields[ i ];\r\n\t\t\t\t\tconst f2 = xyzFields[ nextIndex ];\r\n\t\t\t\t\tconst f3 = xyzFields[ nextIndex2 ];\r\n\t\t\t\t\tconst line2 = segments2[ count ];\r\n\t\t\t\t\tconst start = line2.start;\r\n\t\t\t\t\tconst end = line2.end;\r\n\r\n\t\t\t\t\tstart[ f1 ] = min[ f1 ];\r\n\t\t\t\t\tstart[ f2 ] = i1 ? min[ f2 ] : max[ f2 ];\r\n\t\t\t\t\tstart[ f3 ] = i2 ? min[ f3 ] : max[ f2 ];\r\n\r\n\t\t\t\t\tend[ f1 ] = max[ f1 ];\r\n\t\t\t\t\tend[ f2 ] = i1 ? min[ f2 ] : max[ f2 ];\r\n\t\t\t\t\tend[ f3 ] = i2 ? min[ f3 ] : max[ f2 ];\r\n\r\n\t\t\t\t\tcount ++;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t// check all the other boxes point\r\n\t\tfor ( let x = 0; x <= 1; x ++ ) {\r\n\r\n\t\t\tfor ( let y = 0; y <= 1; y ++ ) {\r\n\r\n\t\t\t\tfor ( let z = 0; z <= 1; z ++ ) {\r\n\r\n\t\t\t\t\tpoint2.x = x ? max.x : min.x;\r\n\t\t\t\t\tpoint2.y = y ? max.y : min.y;\r\n\t\t\t\t\tpoint2.z = z ? max.z : min.z;\r\n\r\n\t\t\t\t\tthis.closestPointToPoint( point2, point1 );\r\n\t\t\t\t\tconst dist = point2.distanceToSquared( point1 );\r\n\t\t\t\t\tif ( dist < closestDistanceSq ) {\r\n\r\n\t\t\t\t\t\tclosestDistanceSq = dist;\r\n\t\t\t\t\t\tif ( target1 ) target1.copy( point1 );\r\n\t\t\t\t\t\tif ( target2 ) target2.copy( point2 );\r\n\r\n\t\t\t\t\t\tif ( dist < threshold2 ) return Math.sqrt( dist );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfor ( let i = 0; i < 12; i ++ ) {\r\n\r\n\t\t\tconst l1 = segments1[ i ];\r\n\t\t\tfor ( let i2 = 0; i2 < 12; i2 ++ ) {\r\n\r\n\t\t\t\tconst l2 = segments2[ i2 ];\r\n\t\t\t\tclosestPointsSegmentToSegment( l1, l2, point1, point2 );\r\n\t\t\t\tconst dist = point1.distanceToSquared( point2 );\r\n\t\t\t\tif ( dist < closestDistanceSq ) {\r\n\r\n\t\t\t\t\tclosestDistanceSq = dist;\r\n\t\t\t\t\tif ( target1 ) target1.copy( point1 );\r\n\t\t\t\t\tif ( target2 ) target2.copy( point2 );\r\n\r\n\t\t\t\t\tif ( dist < threshold2 ) return Math.sqrt( dist );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\treturn Math.sqrt( closestDistanceSq );\r\n\r\n\t};\r\n\r\n} )();\r\n","import { Vector3, Vector2, Triangle, DoubleSide, BackSide } from 'three';\r\n\r\n// Ripped and modified From THREE.js Mesh raycast\r\n// https://github.com/mrdoob/three.js/blob/0aa87c999fe61e216c1133fba7a95772b503eddf/src/objects/Mesh.js#L115\r\nconst vA = /* @__PURE__ */ new Vector3();\r\nconst vB = /* @__PURE__ */ new Vector3();\r\nconst vC = /* @__PURE__ */ new Vector3();\r\n\r\nconst uvA = /* @__PURE__ */ new Vector2();\r\nconst uvB = /* @__PURE__ */ new Vector2();\r\nconst uvC = /* @__PURE__ */ new Vector2();\r\n\r\nconst intersectionPoint = /* @__PURE__ */ new Vector3();\r\nfunction checkIntersection( ray, pA, pB, pC, point, side ) {\r\n\r\n\tlet intersect;\r\n\tif ( side === BackSide ) {\r\n\r\n\t\tintersect = ray.intersectTriangle( pC, pB, pA, true, point );\r\n\r\n\t} else {\r\n\r\n\t\tintersect = ray.intersectTriangle( pA, pB, pC, side !== DoubleSide, point );\r\n\r\n\t}\r\n\r\n\tif ( intersect === null ) return null;\r\n\r\n\tconst distance = ray.origin.distanceTo( point );\r\n\r\n\treturn {\r\n\r\n\t\tdistance: distance,\r\n\t\tpoint: point.clone(),\r\n\r\n\t};\r\n\r\n}\r\n\r\nfunction checkBufferGeometryIntersection( ray, position, uv, a, b, c, side ) {\r\n\r\n\tvA.fromBufferAttribute( position, a );\r\n\tvB.fromBufferAttribute( position, b );\r\n\tvC.fromBufferAttribute( position, c );\r\n\r\n\tconst intersection = checkIntersection( ray, vA, vB, vC, intersectionPoint, side );\r\n\r\n\tif ( intersection ) {\r\n\r\n\t\tif ( uv ) {\r\n\r\n\t\t\tuvA.fromBufferAttribute( uv, a );\r\n\t\t\tuvB.fromBufferAttribute( uv, b );\r\n\t\t\tuvC.fromBufferAttribute( uv, c );\r\n\r\n\t\t\tintersection.uv = Triangle.getUV( intersectionPoint, vA, vB, vC, uvA, uvB, uvC, new Vector2( ) );\r\n\r\n\t\t}\r\n\r\n\t\tconst face = {\r\n\t\t\ta: a,\r\n\t\t\tb: b,\r\n\t\t\tc: c,\r\n\t\t\tnormal: new Vector3(),\r\n\t\t\tmaterialIndex: 0\r\n\t\t};\r\n\r\n\t\tTriangle.getNormal( vA, vB, vC, face.normal );\r\n\r\n\t\tintersection.face = face;\r\n\t\tintersection.faceIndex = a;\r\n\r\n\t}\r\n\r\n\treturn intersection;\r\n\r\n}\r\n\r\n// https://github.com/mrdoob/three.js/blob/0aa87c999fe61e216c1133fba7a95772b503eddf/src/objects/Mesh.js#L258\r\nfunction intersectTri( geo, side, ray, tri, intersections ) {\r\n\r\n\tconst triOffset = tri * 3;\r\n\tconst a = geo.index.getX( triOffset );\r\n\tconst b = geo.index.getX( triOffset + 1 );\r\n\tconst c = geo.index.getX( triOffset + 2 );\r\n\r\n\tconst intersection = checkBufferGeometryIntersection( ray, geo.attributes.position, geo.attributes.uv, a, b, c, side );\r\n\r\n\tif ( intersection ) {\r\n\r\n\t\tintersection.faceIndex = tri;\r\n\t\tif ( intersections ) intersections.push( intersection );\r\n\t\treturn intersection;\r\n\r\n\t}\r\n\r\n\treturn null;\r\n\r\n}\r\n\r\nexport { intersectTri };\r\n","import { intersectTri } from './ThreeRayIntersectUtilities.js';\r\n\r\nexport function intersectTris( geo, side, ray, offset, count, intersections ) {\r\n\r\n\tfor ( let i = offset, end = offset + count; i < end; i ++ ) {\r\n\r\n\t\tintersectTri( geo, side, ray, i, intersections );\r\n\r\n\t}\r\n\r\n}\r\n\r\nexport function intersectClosestTri( geo, side, ray, offset, count ) {\r\n\r\n\tlet dist = Infinity;\r\n\tlet res = null;\r\n\tfor ( let i = offset, end = offset + count; i < end; i ++ ) {\r\n\r\n\t\tconst intersection = intersectTri( geo, side, ray, i );\r\n\t\tif ( intersection && intersection.distance < dist ) {\r\n\r\n\t\t\tres = intersection;\r\n\t\t\tdist = intersection.distance;\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\treturn res;\r\n\r\n}\r\n\r\n// converts the given BVH raycast intersection to align with the three.js raycast\r\n// structure (include object, world space distance and point).\r\nexport function convertRaycastIntersect( hit, object, raycaster ) {\r\n\r\n\tif ( hit === null ) {\r\n\r\n\t\treturn null;\r\n\r\n\t}\r\n\r\n\thit.point.applyMatrix4( object.matrixWorld );\r\n\thit.distance = hit.point.distanceTo( raycaster.ray.origin );\r\n\thit.object = object;\r\n\r\n\tif ( hit.distance < raycaster.near || hit.distance > raycaster.far ) {\r\n\r\n\t\treturn null;\r\n\r\n\t} else {\r\n\r\n\t\treturn hit;\r\n\r\n\t}\r\n\r\n}\r\n","\r\nimport { Vector2, Vector3, Triangle } from 'three';\r\n\r\n// sets the vertices of triangle `tri` with the 3 vertices after i\r\nexport function setTriangle( tri, i, index, pos ) {\r\n\r\n\tconst ta = tri.a;\r\n\tconst tb = tri.b;\r\n\tconst tc = tri.c;\r\n\r\n\tlet i0 = i;\r\n\tlet i1 = i + 1;\r\n\tlet i2 = i + 2;\r\n\tif ( index ) {\r\n\r\n\t\ti0 = index.getX( i );\r\n\t\ti1 = index.getX( i + 1 );\r\n\t\ti2 = index.getX( i + 2 );\r\n\r\n\t}\r\n\r\n\tta.x = pos.getX( i0 );\r\n\tta.y = pos.getY( i0 );\r\n\tta.z = pos.getZ( i0 );\r\n\r\n\ttb.x = pos.getX( i1 );\r\n\ttb.y = pos.getY( i1 );\r\n\ttb.z = pos.getZ( i1 );\r\n\r\n\ttc.x = pos.getX( i2 );\r\n\ttc.y = pos.getY( i2 );\r\n\ttc.z = pos.getZ( i2 );\r\n\r\n}\r\n\r\nexport function iterateOverTriangles(\r\n\toffset,\r\n\tcount,\r\n\tgeometry,\r\n\tintersectsTriangleFunc,\r\n\tcontained,\r\n\tdepth,\r\n\ttriangle\r\n) {\r\n\r\n\tconst index = geometry.index;\r\n\tconst pos = geometry.attributes.position;\r\n\tfor ( let i = offset, l = count + offset; i < l; i ++ ) {\r\n\r\n\t\tsetTriangle( triangle, i * 3, index, pos );\r\n\t\ttriangle.needsUpdate = true;\r\n\r\n\t\tif ( intersectsTriangleFunc( triangle, i, contained, depth ) ) {\r\n\r\n\t\t\treturn true;\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\treturn false;\r\n\r\n}\r\n\r\nconst tempV1 = /* @__PURE__ */ new Vector3();\r\nconst tempV2 = /* @__PURE__ */ new Vector3();\r\nconst tempV3 = /* @__PURE__ */ new Vector3();\r\nconst tempUV1 = /* @__PURE__ */ new Vector2();\r\nconst tempUV2 = /* @__PURE__ */ new Vector2();\r\nconst tempUV3 = /* @__PURE__ */ new Vector2();\r\n\r\nexport function getTriangleHitPointInfo( point, geometry, triangleIndex, target ) {\r\n\r\n\tconst indices = geometry.getIndex().array;\r\n\tconst positions = geometry.getAttribute( 'position' );\r\n\tconst uvs = geometry.getAttribute( 'uv' );\r\n\r\n\tconst a = indices[ triangleIndex * 3 ];\r\n\tconst b = indices[ triangleIndex * 3 + 1 ];\r\n\tconst c = indices[ triangleIndex * 3 + 2 ];\r\n\r\n\ttempV1.fromBufferAttribute( positions, a );\r\n\ttempV2.fromBufferAttribute( positions, b );\r\n\ttempV3.fromBufferAttribute( positions, c );\r\n\r\n\t// find the associated material index\r\n\tlet materialIndex = 0;\r\n\tconst groups = geometry.groups;\r\n\tconst firstVertexIndex = triangleIndex * 3;\r\n\tfor ( let i = 0, l = groups.length; i < l; i ++ ) {\r\n\r\n\t\tconst group = groups[ i ];\r\n\t\tconst { start, count } = group;\r\n\t\tif ( firstVertexIndex >= start && firstVertexIndex < start + count ) {\r\n\r\n\t\t\tmaterialIndex = group.materialIndex;\r\n\t\t\tbreak;\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t// extract uvs\r\n\tlet uv = null;\r\n\tif ( uvs ) {\r\n\r\n\t\ttempUV1.fromBufferAttribute( uvs, a );\r\n\t\ttempUV2.fromBufferAttribute( uvs, b );\r\n\t\ttempUV3.fromBufferAttribute( uvs, c );\r\n\r\n\t\tif ( target && target.uv ) uv = target.uv;\r\n\t\telse uv = new Vector2();\r\n\r\n\t\tTriangle.getUV( point, tempV1, tempV2, tempV3, tempUV1, tempUV2, tempUV3, uv );\r\n\r\n\t}\r\n\r\n\t// adjust the provided target or create a new one\r\n\tif ( target ) {\r\n\r\n\t\tif ( ! target.face ) target.face = { };\r\n\t\ttarget.face.a = a;\r\n\t\ttarget.face.b = b;\r\n\t\ttarget.face.c = c;\r\n\t\ttarget.face.materialIndex = materialIndex;\r\n\t\tif ( ! target.face.normal ) target.face.normal = new Vector3();\r\n\t\tTriangle.getNormal( tempV1, tempV2, tempV3, target.face.normal );\r\n\r\n\t\tif ( ! target.uv ) target.uv = new Vector2();\r\n\t\ttarget.uv.copy( uv );\r\n\r\n\t\treturn target;\r\n\r\n\t} else {\r\n\r\n\t\treturn {\r\n\t\t\tface: {\r\n\t\t\t\ta: a,\r\n\t\t\t\tb: b,\r\n\t\t\t\tc: c,\r\n\t\t\t\tmaterialIndex: materialIndex,\r\n\t\t\t\tnormal: Triangle.getNormal( tempV1, tempV2, tempV3, new Vector3() )\r\n\t\t\t},\r\n\t\t\tuv: uv\r\n\t\t};\r\n\r\n\t}\r\n\r\n}\r\n","export class PrimitivePool {\r\n\r\n\tconstructor( getNewPrimitive ) {\r\n\r\n\t\tthis._getNewPrimitive = getNewPrimitive;\r\n\t\tthis._primitives = [];\r\n\r\n\t}\r\n\r\n\tgetPrimitive() {\r\n\r\n\t\tconst primitives = this._primitives;\r\n\t\tif ( primitives.length === 0 ) {\r\n\r\n\t\t\treturn this._getNewPrimitive();\r\n\r\n\t\t} else {\r\n\r\n\t\t\treturn primitives.pop();\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\treleasePrimitive( primitive ) {\r\n\r\n\t\tthis._primitives.push( primitive );\r\n\r\n\t}\r\n\r\n}\r\n","export function IS_LEAF( n16, uint16Array ) {\r\n\r\n\treturn uint16Array[ n16 + 15 ] === 0xFFFF;\r\n\r\n}\r\n\r\nexport function OFFSET( n32, uint32Array ) {\r\n\r\n\treturn uint32Array[ n32 + 6 ];\r\n\r\n}\r\n\r\nexport function COUNT( n16, uint16Array ) {\r\n\r\n\treturn uint16Array[ n16 + 14 ];\r\n\r\n}\r\n\r\nexport function LEFT_NODE( n32 ) {\r\n\r\n\treturn n32 + 8;\r\n\r\n}\r\n\r\nexport function RIGHT_NODE( n32, uint32Array ) {\r\n\r\n\treturn uint32Array[ n32 + 6 ];\r\n\r\n}\r\n\r\nexport function SPLIT_AXIS( n32, uint32Array ) {\r\n\r\n\treturn uint32Array[ n32 + 7 ];\r\n\r\n}\r\n\r\nexport function BOUNDING_DATA_INDEX( n32 ) {\r\n\r\n\treturn n32;\r\n\r\n}\r\n","import { Box3, Vector3, Matrix4 } from 'three';\r\nimport { CONTAINED } from './Constants.js';\r\n\r\nimport { OrientedBox } from '../math/OrientedBox.js';\r\nimport { SeparatingAxisTriangle } from '../math/SeparatingAxisTriangle.js';\r\nimport { intersectTris, intersectClosestTri } from '../utils/GeometryRayIntersectUtilities.js';\r\nimport { setTriangle } from '../utils/TriangleUtilities.js';\r\nimport { arrayToBox } from '../utils/ArrayBoxUtilities.js';\r\nimport { PrimitivePool } from '../utils/PrimitivePool.js';\r\nimport { COUNT, OFFSET, LEFT_NODE, RIGHT_NODE, IS_LEAF, BOUNDING_DATA_INDEX, SPLIT_AXIS } from './nodeBufferFunctions.js';\r\n\r\nconst boundingBox = new Box3();\r\nconst boxIntersection = new Vector3();\r\nconst xyzFields = [ 'x', 'y', 'z' ];\r\n\r\nexport function raycast( nodeIndex32, geometry, side, ray, intersects ) {\r\n\r\n\tlet nodeIndex16 = nodeIndex32 * 2, float32Array = _float32Array, uint16Array = _uint16Array, uint32Array = _uint32Array;\r\n\r\n\tconst isLeaf = IS_LEAF( nodeIndex16, uint16Array );\r\n\tif ( isLeaf ) {\r\n\r\n\t\tconst offset = OFFSET( nodeIndex32, uint32Array );\r\n\t\tconst count = COUNT( nodeIndex16, uint16Array );\r\n\r\n\t\tintersectTris( geometry, side, ray, offset, count, intersects );\r\n\r\n\t} else {\r\n\r\n\t\tconst leftIndex = LEFT_NODE( nodeIndex32 );\r\n\t\tif ( intersectRay( leftIndex, float32Array, ray, boxIntersection ) ) {\r\n\r\n\t\t\traycast( leftIndex, geometry, side, ray, intersects );\r\n\r\n\t\t}\r\n\r\n\t\tconst rightIndex = RIGHT_NODE( nodeIndex32, uint32Array );\r\n\t\tif ( intersectRay( rightIndex, float32Array, ray, boxIntersection ) ) {\r\n\r\n\t\t\traycast( rightIndex, geometry, side, ray, intersects );\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n}\r\n\r\nexport function raycastFirst( nodeIndex32, geometry, side, ray ) {\r\n\r\n\tlet nodeIndex16 = nodeIndex32 * 2, float32Array = _float32Array, uint16Array = _uint16Array, uint32Array = _uint32Array;\r\n\r\n\tconst isLeaf = IS_LEAF( nodeIndex16, uint16Array );\r\n\tif ( isLeaf ) {\r\n\r\n\t\tconst offset = OFFSET( nodeIndex32, uint32Array );\r\n\t\tconst count = COUNT( nodeIndex16, uint16Array );\r\n\t\treturn intersectClosestTri( geometry, side, ray, offset, count );\r\n\r\n\t} else {\r\n\r\n\t\t// consider the position of the split plane with respect to the oncoming ray; whichever direction\r\n\t\t// the ray is coming from, look for an intersection among that side of the tree first\r\n\t\tconst splitAxis = SPLIT_AXIS( nodeIndex32, uint32Array );\r\n\t\tconst xyzAxis = xyzFields[ splitAxis ];\r\n\t\tconst rayDir = ray.direction[ xyzAxis ];\r\n\t\tconst leftToRight = rayDir >= 0;\r\n\r\n\t\t// c1 is the child to check first\r\n\t\tlet c1, c2;\r\n\t\tif ( leftToRight ) {\r\n\r\n\t\t\tc1 = LEFT_NODE( nodeIndex32 );\r\n\t\t\tc2 = RIGHT_NODE( nodeIndex32, uint32Array );\r\n\r\n\t\t} else {\r\n\r\n\t\t\tc1 = RIGHT_NODE( nodeIndex32, uint32Array );\r\n\t\t\tc2 = LEFT_NODE( nodeIndex32 );\r\n\r\n\t\t}\r\n\r\n\t\tconst c1Intersection = intersectRay( c1, float32Array, ray, boxIntersection );\r\n\t\tconst c1Result = c1Intersection ? raycastFirst( c1, geometry, side, ray ) : null;\r\n\r\n\t\t// if we got an intersection in the first node and it's closer than the second node's bounding\r\n\t\t// box, we don't need to consider the second node because it couldn't possibly be a better result\r\n\t\tif ( c1Result ) {\r\n\r\n\t\t\t// check if the point is within the second bounds\r\n\t\t\t// \"point\" is in the local frame of the bvh\r\n\t\t\tconst point = c1Result.point[ xyzAxis ];\r\n\t\t\tconst isOutside = leftToRight ?\r\n\t\t\t\tpoint <= float32Array[ c2 + splitAxis ] : // min bounding data\r\n\t\t\t\tpoint >= float32Array[ c2 + splitAxis + 3 ]; // max bounding data\r\n\r\n\t\t\tif ( isOutside ) {\r\n\r\n\t\t\t\treturn c1Result;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t// either there was no intersection in the first node, or there could still be a closer\r\n\t\t// intersection in the second, so check the second node and then take the better of the two\r\n\t\tconst c2Intersection = intersectRay( c2, float32Array, ray, boxIntersection );\r\n\t\tconst c2Result = c2Intersection ? raycastFirst( c2, geometry, side, ray ) : null;\r\n\r\n\t\tif ( c1Result && c2Result ) {\r\n\r\n\t\t\treturn c1Result.distance <= c2Result.distance ? c1Result : c2Result;\r\n\r\n\t\t} else {\r\n\r\n\t\t\treturn c1Result || c2Result || null;\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n}\r\n\r\nexport const shapecast = ( function () {\r\n\r\n\tlet _box1, _box2;\r\n\tconst boxStack = [];\r\n\tconst boxPool = new PrimitivePool( () => new Box3() );\r\n\r\n\treturn function shapecast( ...args ) {\r\n\r\n\t\t_box1 = boxPool.getPrimitive();\r\n\t\t_box2 = boxPool.getPrimitive();\r\n\t\tboxStack.push( _box1, _box2 );\r\n\r\n\t\tconst result = shapecastTraverse( ...args );\r\n\r\n\t\tboxPool.releasePrimitive( _box1 );\r\n\t\tboxPool.releasePrimitive( _box2 );\r\n\t\tboxStack.pop();\r\n\t\tboxStack.pop();\r\n\r\n\t\tconst length = boxStack.length;\r\n\t\tif ( length > 0 ) {\r\n\r\n\t\t\t_box2 = boxStack[ length - 1 ];\r\n\t\t\t_box1 = boxStack[ length - 2 ];\r\n\r\n\t\t}\r\n\r\n\t\treturn result;\r\n\r\n\t};\r\n\r\n\tfunction shapecastTraverse(\r\n\t\tnodeIndex32,\r\n\t\tgeometry,\r\n\t\tintersectsBoundsFunc,\r\n\t\tintersectsRangeFunc,\r\n\t\tnodeScoreFunc = null,\r\n\t\tnodeIndexByteOffset = 0, // offset for unique node identifier\r\n\t\tdepth = 0\r\n\t) {\r\n\r\n\t\t// Define these inside the function so it has access to the local variables needed\r\n\t\t// when converting to the buffer equivalents\r\n\t\tfunction getLeftOffset( nodeIndex32 ) {\r\n\r\n\t\t\tlet nodeIndex16 = nodeIndex32 * 2, uint16Array = _uint16Array, uint32Array = _uint32Array;\r\n\r\n\t\t\t// traverse until we find a leaf\r\n\t\t\twhile ( ! IS_LEAF( nodeIndex16, uint16Array ) ) {\r\n\r\n\t\t\t\tnodeIndex32 = LEFT_NODE( nodeIndex32 );\r\n\t\t\t\tnodeIndex16 = nodeIndex32 * 2;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn OFFSET( nodeIndex32, uint32Array );\r\n\r\n\t\t}\r\n\r\n\t\tfunction getRightEndOffset( nodeIndex32 ) {\r\n\r\n\t\t\tlet nodeIndex16 = nodeIndex32 * 2, uint16Array = _uint16Array, uint32Array = _uint32Array;\r\n\r\n\t\t\t// traverse until we find a leaf\r\n\t\t\twhile ( ! IS_LEAF( nodeIndex16, uint16Array ) ) {\r\n\r\n\t\t\t\t// adjust offset to point to the right node\r\n\t\t\t\tnodeIndex32 = RIGHT_NODE( nodeIndex32, uint32Array );\r\n\t\t\t\tnodeIndex16 = nodeIndex32 * 2;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// return the end offset of the triangle range\r\n\t\t\treturn OFFSET( nodeIndex32, uint32Array ) + COUNT( nodeIndex16, uint16Array );\r\n\r\n\t\t}\r\n\r\n\t\tlet nodeIndex16 = nodeIndex32 * 2, float32Array = _float32Array, uint16Array = _uint16Array, uint32Array = _uint32Array;\r\n\r\n\t\tconst isLeaf = IS_LEAF( nodeIndex16, uint16Array );\r\n\t\tif ( isLeaf ) {\r\n\r\n\t\t\tconst offset = OFFSET( nodeIndex32, uint32Array );\r\n\t\t\tconst count = COUNT( nodeIndex16, uint16Array );\r\n\t\t\tarrayToBox( BOUNDING_DATA_INDEX( nodeIndex32 ), float32Array, _box1 );\r\n\t\t\treturn intersectsRangeFunc( offset, count, false, depth, nodeIndexByteOffset + nodeIndex32, _box1 );\r\n\r\n\t\t} else {\r\n\r\n\t\t\tconst left = LEFT_NODE( nodeIndex32 );\r\n\t\t\tconst right = RIGHT_NODE( nodeIndex32, uint32Array );\r\n\t\t\tlet c1 = left;\r\n\t\t\tlet c2 = right;\r\n\r\n\t\t\tlet score1, score2;\r\n\t\t\tlet box1, box2;\r\n\t\t\tif ( nodeScoreFunc ) {\r\n\r\n\t\t\t\tbox1 = _box1;\r\n\t\t\t\tbox2 = _box2;\r\n\r\n\t\t\t\t// bounding data is not offset\r\n\t\t\t\tarrayToBox( BOUNDING_DATA_INDEX( c1 ), float32Array, box1 );\r\n\t\t\t\tarrayToBox( BOUNDING_DATA_INDEX( c2 ), float32Array, box2 );\r\n\r\n\t\t\t\tscore1 = nodeScoreFunc( box1 );\r\n\t\t\t\tscore2 = nodeScoreFunc( box2 );\r\n\r\n\t\t\t\tif ( score2 < score1 ) {\r\n\r\n\t\t\t\t\tc1 = right;\r\n\t\t\t\t\tc2 = left;\r\n\r\n\t\t\t\t\tconst temp = score1;\r\n\t\t\t\t\tscore1 = score2;\r\n\t\t\t\t\tscore2 = temp;\r\n\r\n\t\t\t\t\tbox1 = box2;\r\n\t\t\t\t\t// box2 is always set before use below\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// Check box 1 intersection\r\n\t\t\tif ( ! box1 ) {\r\n\r\n\t\t\t\tbox1 = _box1;\r\n\t\t\t\tarrayToBox( BOUNDING_DATA_INDEX( c1 ), float32Array, box1 );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tconst isC1Leaf = IS_LEAF( c1 * 2, uint16Array );\r\n\t\t\tconst c1Intersection = intersectsBoundsFunc( box1, isC1Leaf, score1, depth + 1, nodeIndexByteOffset + c1 );\r\n\r\n\t\t\tlet c1StopTraversal;\r\n\t\t\tif ( c1Intersection === CONTAINED ) {\r\n\r\n\t\t\t\tconst offset = getLeftOffset( c1 );\r\n\t\t\t\tconst end = getRightEndOffset( c1 );\r\n\t\t\t\tconst count = end - offset;\r\n\r\n\t\t\t\tc1StopTraversal = intersectsRangeFunc( offset, count, true, depth + 1, nodeIndexByteOffset + c1, box1 );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tc1StopTraversal =\r\n\t\t\t\t\tc1Intersection &&\r\n\t\t\t\t\tshapecastTraverse(\r\n\t\t\t\t\t\tc1,\r\n\t\t\t\t\t\tgeometry,\r\n\t\t\t\t\t\tintersectsBoundsFunc,\r\n\t\t\t\t\t\tintersectsRangeFunc,\r\n\t\t\t\t\t\tnodeScoreFunc,\r\n\t\t\t\t\t\tnodeIndexByteOffset,\r\n\t\t\t\t\t\tdepth + 1\r\n\t\t\t\t\t);\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( c1StopTraversal ) return true;\r\n\r\n\t\t\t// Check box 2 intersection\r\n\t\t\t// cached box2 will have been overwritten by previous traversal\r\n\t\t\tbox2 = _box2;\r\n\t\t\tarrayToBox( BOUNDING_DATA_INDEX( c2 ), float32Array, box2 );\r\n\r\n\t\t\tconst isC2Leaf = IS_LEAF( c2 * 2, uint16Array );\r\n\t\t\tconst c2Intersection = intersectsBoundsFunc( box2, isC2Leaf, score2, depth + 1, nodeIndexByteOffset + c2 );\r\n\r\n\t\t\tlet c2StopTraversal;\r\n\t\t\tif ( c2Intersection === CONTAINED ) {\r\n\r\n\t\t\t\tconst offset = getLeftOffset( c2 );\r\n\t\t\t\tconst end = getRightEndOffset( c2 );\r\n\t\t\t\tconst count = end - offset;\r\n\r\n\t\t\t\tc2StopTraversal = intersectsRangeFunc( offset, count, true, depth + 1, nodeIndexByteOffset + c2, box2 );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tc2StopTraversal =\r\n\t\t\t\t\tc2Intersection &&\r\n\t\t\t\t\tshapecastTraverse(\r\n\t\t\t\t\t\tc2,\r\n\t\t\t\t\t\tgeometry,\r\n\t\t\t\t\t\tintersectsBoundsFunc,\r\n\t\t\t\t\t\tintersectsRangeFunc,\r\n\t\t\t\t\t\tnodeScoreFunc,\r\n\t\t\t\t\t\tnodeIndexByteOffset,\r\n\t\t\t\t\t\tdepth + 1\r\n\t\t\t\t\t);\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( c2StopTraversal ) return true;\r\n\r\n\t\t\treturn false;\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n} )();\r\n\r\nexport const intersectsGeometry = ( function () {\r\n\r\n\tconst triangle = new SeparatingAxisTriangle();\r\n\tconst triangle2 = new SeparatingAxisTriangle();\r\n\tconst invertedMat = new Matrix4();\r\n\r\n\tconst obb = new OrientedBox();\r\n\tconst obb2 = new OrientedBox();\r\n\r\n\treturn function intersectsGeometry( nodeIndex32, geometry, otherGeometry, geometryToBvh, cachedObb = null ) {\r\n\r\n\t\tlet nodeIndex16 = nodeIndex32 * 2, float32Array = _float32Array, uint16Array = _uint16Array, uint32Array = _uint32Array;\r\n\r\n\t\tif ( cachedObb === null ) {\r\n\r\n\t\t\tif ( ! otherGeometry.boundingBox ) {\r\n\r\n\t\t\t\totherGeometry.computeBoundingBox();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tobb.set( otherGeometry.boundingBox.min, otherGeometry.boundingBox.max, geometryToBvh );\r\n\t\t\tcachedObb = obb;\r\n\r\n\t\t}\r\n\r\n\t\tconst isLeaf = IS_LEAF( nodeIndex16, uint16Array );\r\n\t\tif ( isLeaf ) {\r\n\r\n\t\t\tconst thisGeometry = geometry;\r\n\t\t\tconst thisIndex = thisGeometry.index;\r\n\t\t\tconst thisPos = thisGeometry.attributes.position;\r\n\r\n\t\t\tconst index = otherGeometry.index;\r\n\t\t\tconst pos = otherGeometry.attributes.position;\r\n\r\n\t\t\tconst offset = OFFSET( nodeIndex32, uint32Array );\r\n\t\t\tconst count = COUNT( nodeIndex16, uint16Array );\r\n\r\n\t\t\t// get the inverse of the geometry matrix so we can transform our triangles into the\r\n\t\t\t// geometry space we're trying to test. We assume there are fewer triangles being checked\r\n\t\t\t// here.\r\n\t\t\tinvertedMat.copy( geometryToBvh ).invert();\r\n\r\n\t\t\tif ( otherGeometry.boundsTree ) {\r\n\r\n\t\t\t\tarrayToBox( BOUNDING_DATA_INDEX( nodeIndex32 ), float32Array, obb2 );\r\n\t\t\t\tobb2.matrix.copy( invertedMat );\r\n\t\t\t\tobb2.needsUpdate = true;\r\n\r\n\t\t\t\tconst res = otherGeometry.boundsTree.shapecast( {\r\n\r\n\t\t\t\t\tintersectsBounds: box => obb2.intersectsBox( box ),\r\n\r\n\t\t\t\t\tintersectsTriangle: tri => {\r\n\r\n\t\t\t\t\t\ttri.a.applyMatrix4( geometryToBvh );\r\n\t\t\t\t\t\ttri.b.applyMatrix4( geometryToBvh );\r\n\t\t\t\t\t\ttri.c.applyMatrix4( geometryToBvh );\r\n\t\t\t\t\t\ttri.needsUpdate = true;\r\n\r\n\t\t\t\t\t\tfor ( let i = offset * 3, l = ( count + offset ) * 3; i < l; i += 3 ) {\r\n\r\n\t\t\t\t\t\t\t// this triangle needs to be transformed into the current BVH coordinate frame\r\n\t\t\t\t\t\t\tsetTriangle( triangle2, i, thisIndex, thisPos );\r\n\t\t\t\t\t\t\ttriangle2.needsUpdate = true;\r\n\t\t\t\t\t\t\tif ( tri.intersectsTriangle( triangle2 ) ) {\r\n\r\n\t\t\t\t\t\t\t\treturn true;\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\treturn false;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t} );\r\n\r\n\t\t\t\treturn res;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tfor ( let i = offset * 3, l = ( count + offset * 3 ); i < l; i += 3 ) {\r\n\r\n\t\t\t\t\t// this triangle needs to be transformed into the current BVH coordinate frame\r\n\t\t\t\t\tsetTriangle( triangle, i, thisIndex, thisPos );\r\n\t\t\t\t\ttriangle.a.applyMatrix4( invertedMat );\r\n\t\t\t\t\ttriangle.b.applyMatrix4( invertedMat );\r\n\t\t\t\t\ttriangle.c.applyMatrix4( invertedMat );\r\n\t\t\t\t\ttriangle.needsUpdate = true;\r\n\r\n\t\t\t\t\tfor ( let i2 = 0, l2 = index.count; i2 < l2; i2 += 3 ) {\r\n\r\n\t\t\t\t\t\tsetTriangle( triangle2, i2, index, pos );\r\n\t\t\t\t\t\ttriangle2.needsUpdate = true;\r\n\r\n\t\t\t\t\t\tif ( triangle.intersectsTriangle( triangle2 ) ) {\r\n\r\n\t\t\t\t\t\t\treturn true;\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t} else {\r\n\r\n\t\t\tconst left = nodeIndex32 + 8;\r\n\t\t\tconst right = uint32Array[ nodeIndex32 + 6 ];\r\n\r\n\t\t\tarrayToBox( BOUNDING_DATA_INDEX( left ), float32Array, boundingBox );\r\n\t\t\tconst leftIntersection =\r\n\t\t\t\tcachedObb.intersectsBox( boundingBox ) &&\r\n\t\t\t\tintersectsGeometry( left, geometry, otherGeometry, geometryToBvh, cachedObb );\r\n\r\n\t\t\tif ( leftIntersection ) return true;\r\n\r\n\t\t\tarrayToBox( BOUNDING_DATA_INDEX( right ), float32Array, boundingBox );\r\n\t\t\tconst rightIntersection =\r\n\t\t\t\tcachedObb.intersectsBox( boundingBox ) &&\r\n\t\t\t\tintersectsGeometry( right, geometry, otherGeometry, geometryToBvh, cachedObb );\r\n\r\n\t\t\tif ( rightIntersection ) return true;\r\n\r\n\t\t\treturn false;\r\n\r\n\t\t}\r\n\r\n\t};\r\n\r\n} )();\r\n\r\nfunction intersectRay( nodeIndex32, array, ray, target ) {\r\n\r\n\tarrayToBox( nodeIndex32, array, boundingBox );\r\n\treturn ray.intersectBox( boundingBox, target );\r\n\r\n}\r\n\r\nconst bufferStack = [];\r\nlet _prevBuffer;\r\nlet _float32Array;\r\nlet _uint16Array;\r\nlet _uint32Array;\r\nexport function setBuffer( buffer ) {\r\n\r\n\tif ( _prevBuffer ) {\r\n\r\n\t\tbufferStack.push( _prevBuffer );\r\n\r\n\t}\r\n\r\n\t_prevBuffer = buffer;\r\n\t_float32Array = new Float32Array( buffer );\r\n\t_uint16Array = new Uint16Array( buffer );\r\n\t_uint32Array = new Uint32Array( buffer );\r\n\r\n}\r\n\r\nexport function clearBuffer() {\r\n\r\n\t_prevBuffer = null;\r\n\t_float32Array = null;\r\n\t_uint16Array = null;\r\n\t_uint32Array = null;\r\n\r\n\tif ( bufferStack.length ) {\r\n\r\n\t\tsetBuffer( bufferStack.pop() );\r\n\r\n\t}\r\n\r\n}\r\n","import { Vector3, BufferAttribute, Box3, FrontSide, Matrix4 } from 'three';\r\nimport { CENTER, BYTES_PER_NODE, IS_LEAFNODE_FLAG } from './Constants.js';\r\nimport { buildPackedTree } from './buildFunctions.js';\r\nimport {\r\n\traycast,\r\n\traycastFirst,\r\n\tshapecast,\r\n\tintersectsGeometry,\r\n\tsetBuffer,\r\n\tclearBuffer,\r\n} from './castFunctions.js';\r\nimport { OrientedBox } from '../math/OrientedBox.js';\r\nimport { SeparatingAxisTriangle } from '../math/SeparatingAxisTriangle.js';\r\nimport { PrimitivePool } from '../utils/PrimitivePool.js';\r\nimport { arrayToBox } from '../utils/ArrayBoxUtilities.js';\r\nimport { iterateOverTriangles, setTriangle } from '../utils/TriangleUtilities.js';\r\nimport { convertRaycastIntersect } from '../utils/GeometryRayIntersectUtilities.js';\r\n\r\nconst SKIP_GENERATION = Symbol( 'skip tree generation' );\r\n\r\nconst aabb = /* @__PURE__ */ new Box3();\r\nconst aabb2 = /* @__PURE__ */ new Box3();\r\nconst tempMatrix = /* @__PURE__ */ new Matrix4();\r\nconst obb = /* @__PURE__ */ new OrientedBox();\r\nconst obb2 = /* @__PURE__ */ new OrientedBox();\r\nconst temp = /* @__PURE__ */ new Vector3();\r\nconst temp1 = /* @__PURE__ */ new Vector3();\r\nconst temp2 = /* @__PURE__ */ new Vector3();\r\nconst temp3 = /* @__PURE__ */ new Vector3();\r\nconst temp4 = /* @__PURE__ */ new Vector3();\r\nconst tempBox = /* @__PURE__ */ new Box3();\r\nconst trianglePool = /* @__PURE__ */ new PrimitivePool( () => new SeparatingAxisTriangle() );\r\n\r\nexport class MeshBVH {\r\n\r\n\tstatic serialize( bvh, options = {} ) {\r\n\r\n\t\tif ( options.isBufferGeometry ) {\r\n\r\n\t\t\tconsole.warn( 'MeshBVH.serialize: The arguments for the function have changed. See documentation for new signature.' );\r\n\r\n\t\t\treturn MeshBVH.serialize(\r\n\t\t\t\targuments[ 0 ],\r\n\t\t\t\t{\r\n\t\t\t\t\tcloneBuffers: arguments[ 2 ] === undefined ? true : arguments[ 2 ],\r\n\t\t\t\t}\r\n\t\t\t);\r\n\r\n\t\t}\r\n\r\n\t\toptions = {\r\n\t\t\tcloneBuffers: true,\r\n\t\t\t...options,\r\n\t\t};\r\n\r\n\t\tconst geometry = bvh.geometry;\r\n\t\tconst rootData = bvh._roots;\r\n\t\tconst indexAttribute = geometry.getIndex();\r\n\t\tlet result;\r\n\t\tif ( options.cloneBuffers ) {\r\n\r\n\t\t\tresult = {\r\n\t\t\t\troots: rootData.map( root => root.slice() ),\r\n\t\t\t\tindex: indexAttribute.array.slice(),\r\n\t\t\t};\r\n\r\n\t\t} else {\r\n\r\n\t\t\tresult = {\r\n\t\t\t\troots: rootData,\r\n\t\t\t\tindex: indexAttribute.array,\r\n\t\t\t};\r\n\r\n\t\t}\r\n\r\n\t\treturn result;\r\n\r\n\t}\r\n\r\n\tstatic deserialize( data, geometry, options = {} ) {\r\n\r\n\t\tif ( typeof options === 'boolean' ) {\r\n\r\n\t\t\tconsole.warn( 'MeshBVH.deserialize: The arguments for the function have changed. See documentation for new signature.' );\r\n\r\n\t\t\treturn MeshBVH.deserialize(\r\n\t\t\t\targuments[ 0 ],\r\n\t\t\t\targuments[ 1 ],\r\n\t\t\t\t{\r\n\t\t\t\t\tsetIndex: arguments[ 2 ] === undefined ? true : arguments[ 2 ],\r\n\t\t\t\t}\r\n\t\t\t);\r\n\r\n\t\t}\r\n\r\n\t\toptions = {\r\n\t\t\tsetIndex: true,\r\n\t\t\t...options,\r\n\t\t};\r\n\r\n\t\tconst { index, roots } = data;\r\n\t\tconst bvh = new MeshBVH( geometry, { ...options, [ SKIP_GENERATION ]: true } );\r\n\t\tbvh._roots = roots;\r\n\r\n\t\tif ( options.setIndex ) {\r\n\r\n\t\t\tconst indexAttribute = geometry.getIndex();\r\n\t\t\tif ( indexAttribute === null ) {\r\n\r\n\t\t\t\tconst newIndex = new BufferAttribute( data.index, 1, false );\r\n\t\t\t\tgeometry.setIndex( newIndex );\r\n\r\n\t\t\t} else if ( indexAttribute.array !== index ) {\r\n\r\n\t\t\t\tindexAttribute.array.set( index );\r\n\t\t\t\tindexAttribute.needsUpdate = true;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\treturn bvh;\r\n\r\n\t}\r\n\r\n\tconstructor( geometry, options = {} ) {\r\n\r\n\t\tif ( ! geometry.isBufferGeometry ) {\r\n\r\n\t\t\tthrow new Error( 'MeshBVH: Only BufferGeometries are supported.' );\r\n\r\n\t\t} else if ( geometry.index && geometry.index.isInterleavedBufferAttribute ) {\r\n\r\n\t\t\tthrow new Error( 'MeshBVH: InterleavedBufferAttribute is not supported for the index attribute.' );\r\n\r\n\t\t}\r\n\r\n\t\t// default options\r\n\t\toptions = Object.assign( {\r\n\r\n\t\t\tstrategy: CENTER,\r\n\t\t\tmaxDepth: 40,\r\n\t\t\tmaxLeafTris: 10,\r\n\t\t\tverbose: true,\r\n\t\t\tuseSharedArrayBuffer: false,\r\n\t\t\tsetBoundingBox: true,\r\n\t\t\tonProgress: null,\r\n\r\n\t\t\t// undocumented options\r\n\r\n\t\t\t// Whether to skip generating the tree. Used for deserialization.\r\n\t\t\t[ SKIP_GENERATION ]: false,\r\n\r\n\t\t}, options );\r\n\r\n\t\tif ( options.useSharedArrayBuffer && typeof SharedArrayBuffer === 'undefined' ) {\r\n\r\n\t\t\tthrow new Error( 'MeshBVH: SharedArrayBuffer is not available.' );\r\n\r\n\t\t}\r\n\r\n\t\tthis._roots = null;\r\n\t\tif ( ! options[ SKIP_GENERATION ] ) {\r\n\r\n\t\t\tthis._roots = buildPackedTree( geometry, options );\r\n\r\n\t\t\tif ( ! geometry.boundingBox && options.setBoundingBox ) {\r\n\r\n\t\t\t\tgeometry.boundingBox = this.getBoundingBox( new Box3() );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t// retain references to the geometry so we can use them it without having to\r\n\t\t// take a geometry reference in every function.\r\n\t\tthis.geometry = geometry;\r\n\r\n\t}\r\n\r\n\trefit( nodeIndices = null ) {\r\n\r\n\t\tif ( nodeIndices && Array.isArray( nodeIndices ) ) {\r\n\r\n\t\t\tnodeIndices = new Set( nodeIndices );\r\n\r\n\t\t}\r\n\r\n\t\tconst geometry = this.geometry;\r\n\t\tconst indexArr = geometry.index.array;\r\n\t\tconst posAttr = geometry.attributes.position;\r\n\t\tconst posArr = posAttr.array;\r\n\r\n\t\t// support for an interleaved position buffer\r\n\t\tconst bufferOffset = posAttr.offset || 0;\r\n\t\tlet stride = 3;\r\n\t\tif ( posAttr.isInterleavedBufferAttribute ) {\r\n\r\n\t\t\tstride = posAttr.data.stride;\r\n\r\n\t\t}\r\n\r\n\t\tlet buffer, uint32Array, uint16Array, float32Array;\r\n\t\tlet byteOffset = 0;\r\n\t\tconst roots = this._roots;\r\n\t\tfor ( let i = 0, l = roots.length; i < l; i ++ ) {\r\n\r\n\t\t\tbuffer = roots[ i ];\r\n\t\t\tuint32Array = new Uint32Array( buffer );\r\n\t\t\tuint16Array = new Uint16Array( buffer );\r\n\t\t\tfloat32Array = new Float32Array( buffer );\r\n\r\n\t\t\t_traverse( 0, byteOffset );\r\n\t\t\tbyteOffset += buffer.byteLength;\r\n\r\n\t\t}\r\n\r\n\t\tfunction _traverse( node32Index, byteOffset, force = false ) {\r\n\r\n\t\t\tconst node16Index = node32Index * 2;\r\n\t\t\tconst isLeaf = uint16Array[ node16Index + 15 ] === IS_LEAFNODE_FLAG;\r\n\t\t\tif ( isLeaf ) {\r\n\r\n\t\t\t\tconst offset = uint32Array[ node32Index + 6 ];\r\n\t\t\t\tconst count = uint16Array[ node16Index + 14 ];\r\n\r\n\t\t\t\tlet minx = Infinity;\r\n\t\t\t\tlet miny = Infinity;\r\n\t\t\t\tlet minz = Infinity;\r\n\t\t\t\tlet maxx = - Infinity;\r\n\t\t\t\tlet maxy = - Infinity;\r\n\t\t\t\tlet maxz = - Infinity;\r\n\t\t\t\tfor ( let i = 3 * offset, l = 3 * ( offset + count ); i < l; i ++ ) {\r\n\r\n\t\t\t\t\tconst index = indexArr[ i ] * stride + bufferOffset;\r\n\t\t\t\t\tconst x = posArr[ index + 0 ];\r\n\t\t\t\t\tconst y = posArr[ index + 1 ];\r\n\t\t\t\t\tconst z = posArr[ index + 2 ];\r\n\r\n\t\t\t\t\tif ( x < minx ) minx = x;\r\n\t\t\t\t\tif ( x > maxx ) maxx = x;\r\n\r\n\t\t\t\t\tif ( y < miny ) miny = y;\r\n\t\t\t\t\tif ( y > maxy ) maxy = y;\r\n\r\n\t\t\t\t\tif ( z < minz ) minz = z;\r\n\t\t\t\t\tif ( z > maxz ) maxz = z;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (\r\n\t\t\t\t\tfloat32Array[ node32Index + 0 ] !== minx ||\r\n\t\t\t\t\tfloat32Array[ node32Index + 1 ] !== miny ||\r\n\t\t\t\t\tfloat32Array[ node32Index + 2 ] !== minz ||\r\n\r\n\t\t\t\t\tfloat32Array[ node32Index + 3 ] !== maxx ||\r\n\t\t\t\t\tfloat32Array[ node32Index + 4 ] !== maxy ||\r\n\t\t\t\t\tfloat32Array[ node32Index + 5 ] !== maxz\r\n\t\t\t\t) {\r\n\r\n\t\t\t\t\tfloat32Array[ node32Index + 0 ] = minx;\r\n\t\t\t\t\tfloat32Array[ node32Index + 1 ] = miny;\r\n\t\t\t\t\tfloat32Array[ node32Index + 2 ] = minz;\r\n\r\n\t\t\t\t\tfloat32Array[ node32Index + 3 ] = maxx;\r\n\t\t\t\t\tfloat32Array[ node32Index + 4 ] = maxy;\r\n\t\t\t\t\tfloat32Array[ node32Index + 5 ] = maxz;\r\n\r\n\t\t\t\t\treturn true;\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\treturn false;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tconst left = node32Index + 8;\r\n\t\t\t\tconst right = uint32Array[ node32Index + 6 ];\r\n\r\n\t\t\t\t// the identifying node indices provided by the shapecast function include offsets of all\r\n\t\t\t\t// root buffers to guarantee they're unique between roots so offset left and right indices here.\r\n\t\t\t\tconst offsetLeft = left + byteOffset;\r\n\t\t\t\tconst offsetRight = right + byteOffset;\r\n\t\t\t\tlet forceChildren = force;\r\n\t\t\t\tlet includesLeft = false;\r\n\t\t\t\tlet includesRight = false;\r\n\r\n\t\t\t\tif ( nodeIndices ) {\r\n\r\n\t\t\t\t\t// if we see that neither the left or right child are included in the set that need to be updated\r\n\t\t\t\t\t// then we assume that all children need to be updated.\r\n\t\t\t\t\tif ( ! forceChildren ) {\r\n\r\n\t\t\t\t\t\tincludesLeft = nodeIndices.has( offsetLeft );\r\n\t\t\t\t\t\tincludesRight = nodeIndices.has( offsetRight );\r\n\t\t\t\t\t\tforceChildren = ! includesLeft && ! includesRight;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tincludesLeft = true;\r\n\t\t\t\t\tincludesRight = true;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tconst traverseLeft = forceChildren || includesLeft;\r\n\t\t\t\tconst traverseRight = forceChildren || includesRight;\r\n\r\n\t\t\t\tlet leftChange = false;\r\n\t\t\t\tif ( traverseLeft ) {\r\n\r\n\t\t\t\t\tleftChange = _traverse( left, byteOffset, forceChildren );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tlet rightChange = false;\r\n\t\t\t\tif ( traverseRight ) {\r\n\r\n\t\t\t\t\trightChange = _traverse( right, byteOffset, forceChildren );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tconst didChange = leftChange || rightChange;\r\n\t\t\t\tif ( didChange ) {\r\n\r\n\t\t\t\t\tfor ( let i = 0; i < 3; i ++ ) {\r\n\r\n\t\t\t\t\t\tconst lefti = left + i;\r\n\t\t\t\t\t\tconst righti = right + i;\r\n\t\t\t\t\t\tconst minLeftValue = float32Array[ lefti ];\r\n\t\t\t\t\t\tconst maxLeftValue = float32Array[ lefti + 3 ];\r\n\t\t\t\t\t\tconst minRightValue = float32Array[ righti ];\r\n\t\t\t\t\t\tconst maxRightValue = float32Array[ righti + 3 ];\r\n\r\n\t\t\t\t\t\tfloat32Array[ node32Index + i ] = minLeftValue < minRightValue ? minLeftValue : minRightValue;\r\n\t\t\t\t\t\tfloat32Array[ node32Index + i + 3 ] = maxLeftValue > maxRightValue ? maxLeftValue : maxRightValue;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn didChange;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\ttraverse( callback, rootIndex = 0 ) {\r\n\r\n\t\tconst buffer = this._roots[ rootIndex ];\r\n\t\tconst uint32Array = new Uint32Array( buffer );\r\n\t\tconst uint16Array = new Uint16Array( buffer );\r\n\t\t_traverse( 0 );\r\n\r\n\t\tfunction _traverse( node32Index, depth = 0 ) {\r\n\r\n\t\t\tconst node16Index = node32Index * 2;\r\n\t\t\tconst isLeaf = uint16Array[ node16Index + 15 ] === IS_LEAFNODE_FLAG;\r\n\t\t\tif ( isLeaf ) {\r\n\r\n\t\t\t\tconst offset = uint32Array[ node32Index + 6 ];\r\n\t\t\t\tconst count = uint16Array[ node16Index + 14 ];\r\n\t\t\t\tcallback( depth, isLeaf, new Float32Array( buffer, node32Index * 4, 6 ), offset, count );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\t// TODO: use node functions here\r\n\t\t\t\tconst left = node32Index + BYTES_PER_NODE / 4;\r\n\t\t\t\tconst right = uint32Array[ node32Index + 6 ];\r\n\t\t\t\tconst splitAxis = uint32Array[ node32Index + 7 ];\r\n\t\t\t\tconst stopTraversal = callback( depth, isLeaf, new Float32Array( buffer, node32Index * 4, 6 ), splitAxis );\r\n\r\n\t\t\t\tif ( ! stopTraversal ) {\r\n\r\n\t\t\t\t\t_traverse( left, depth + 1 );\r\n\t\t\t\t\t_traverse( right, depth + 1 );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t/* Core Cast Functions */\r\n\traycast( ray, materialOrSide = FrontSide ) {\r\n\r\n\t\tconst roots = this._roots;\r\n\t\tconst geometry = this.geometry;\r\n\t\tconst intersects = [];\r\n\t\tconst isMaterial = materialOrSide.isMaterial;\r\n\t\tconst isArrayMaterial = Array.isArray( materialOrSide );\r\n\r\n\t\tconst groups = geometry.groups;\r\n\t\tconst side = isMaterial ? materialOrSide.side : materialOrSide;\r\n\t\tfor ( let i = 0, l = roots.length; i < l; i ++ ) {\r\n\r\n\t\t\tconst materialSide = isArrayMaterial ? materialOrSide[ groups[ i ].materialIndex ].side : side;\r\n\t\t\tconst startCount = intersects.length;\r\n\r\n\t\t\tsetBuffer( roots[ i ] );\r\n\t\t\traycast( 0, geometry, materialSide, ray, intersects );\r\n\t\t\tclearBuffer();\r\n\r\n\t\t\tif ( isArrayMaterial ) {\r\n\r\n\t\t\t\tconst materialIndex = groups[ i ].materialIndex;\r\n\t\t\t\tfor ( let j = startCount, jl = intersects.length; j < jl; j ++ ) {\r\n\r\n\t\t\t\t\tintersects[ j ].face.materialIndex = materialIndex;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\treturn intersects;\r\n\r\n\t}\r\n\r\n\traycastFirst( ray, materialOrSide = FrontSide ) {\r\n\r\n\t\tconst roots = this._roots;\r\n\t\tconst geometry = this.geometry;\r\n\t\tconst isMaterial = materialOrSide.isMaterial;\r\n\t\tconst isArrayMaterial = Array.isArray( materialOrSide );\r\n\r\n\t\tlet closestResult = null;\r\n\r\n\t\tconst groups = geometry.groups;\r\n\t\tconst side = isMaterial ? materialOrSide.side : materialOrSide;\r\n\t\tfor ( let i = 0, l = roots.length; i < l; i ++ ) {\r\n\r\n\t\t\tconst materialSide = isArrayMaterial ? materialOrSide[ groups[ i ].materialIndex ].side : side;\r\n\r\n\t\t\tsetBuffer( roots[ i ] );\r\n\t\t\tconst result = raycastFirst( 0, geometry, materialSide, ray );\r\n\t\t\tclearBuffer();\r\n\r\n\t\t\tif ( result != null && ( closestResult == null || result.distance < closestResult.distance ) ) {\r\n\r\n\t\t\t\tclosestResult = result;\r\n\t\t\t\tif ( isArrayMaterial ) {\r\n\r\n\t\t\t\t\tresult.face.materialIndex = groups[ i ].materialIndex;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\treturn closestResult;\r\n\r\n\t}\r\n\r\n\tintersectsGeometry( otherGeometry, geomToMesh ) {\r\n\r\n\t\tconst geometry = this.geometry;\r\n\t\tlet result = false;\r\n\t\tfor ( const root of this._roots ) {\r\n\r\n\t\t\tsetBuffer( root );\r\n\t\t\tresult = intersectsGeometry( 0, geometry, otherGeometry, geomToMesh );\r\n\t\t\tclearBuffer();\r\n\r\n\t\t\tif ( result ) {\r\n\r\n\t\t\t\tbreak;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\treturn result;\r\n\r\n\t}\r\n\r\n\tshapecast( callbacks, _intersectsTriangleFunc, _orderNodesFunc ) {\r\n\r\n\t\tconst geometry = this.geometry;\r\n\t\tif ( callbacks instanceof Function ) {\r\n\r\n\t\t\tif ( _intersectsTriangleFunc ) {\r\n\r\n\t\t\t\t// Support the previous function signature that provided three sequential index buffer\r\n\t\t\t\t// indices here.\r\n\t\t\t\tconst originalTriangleFunc = _intersectsTriangleFunc;\r\n\t\t\t\t_intersectsTriangleFunc = ( tri, index, contained, depth ) => {\r\n\r\n\t\t\t\t\tconst i3 = index * 3;\r\n\t\t\t\t\treturn originalTriangleFunc( tri, i3, i3 + 1, i3 + 2, contained, depth );\r\n\r\n\t\t\t\t};\r\n\r\n\r\n\t\t\t}\r\n\r\n\t\t\tcallbacks = {\r\n\r\n\t\t\t\tboundsTraverseOrder: _orderNodesFunc,\r\n\t\t\t\tintersectsBounds: callbacks,\r\n\t\t\t\tintersectsTriangle: _intersectsTriangleFunc,\r\n\t\t\t\tintersectsRange: null,\r\n\r\n\t\t\t};\r\n\r\n\t\t\tconsole.warn( 'MeshBVH: Shapecast function signature has changed and now takes an object of callbacks as a second argument. See docs for new signature.' );\r\n\r\n\t\t}\r\n\r\n\t\tconst triangle = trianglePool.getPrimitive();\r\n\t\tlet {\r\n\t\t\tboundsTraverseOrder,\r\n\t\t\tintersectsBounds,\r\n\t\t\tintersectsRange,\r\n\t\t\tintersectsTriangle,\r\n\t\t} = callbacks;\r\n\r\n\t\tif ( intersectsRange && intersectsTriangle ) {\r\n\r\n\t\t\tconst originalIntersectsRange = intersectsRange;\r\n\t\t\tintersectsRange = ( offset, count, contained, depth, nodeIndex ) => {\r\n\r\n\t\t\t\tif ( ! originalIntersectsRange( offset, count, contained, depth, nodeIndex ) ) {\r\n\r\n\t\t\t\t\treturn iterateOverTriangles( offset, count, geometry, intersectsTriangle, contained, depth, triangle );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn true;\r\n\r\n\t\t\t};\r\n\r\n\t\t} else if ( ! intersectsRange ) {\r\n\r\n\t\t\tif ( intersectsTriangle ) {\r\n\r\n\t\t\t\tintersectsRange = ( offset, count, contained, depth ) => {\r\n\r\n\t\t\t\t\treturn iterateOverTriangles( offset, count, geometry, intersectsTriangle, contained, depth, triangle );\r\n\r\n\t\t\t\t};\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tintersectsRange = ( offset, count, contained ) => {\r\n\r\n\t\t\t\t\treturn contained;\r\n\r\n\t\t\t\t};\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tlet result = false;\r\n\t\tlet byteOffset = 0;\r\n\t\tfor ( const root of this._roots ) {\r\n\r\n\t\t\tsetBuffer( root );\r\n\t\t\tresult = shapecast( 0, geometry, intersectsBounds, intersectsRange, boundsTraverseOrder, byteOffset );\r\n\t\t\tclearBuffer();\r\n\r\n\t\t\tif ( result ) {\r\n\r\n\t\t\t\tbreak;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tbyteOffset += root.byteLength;\r\n\r\n\t\t}\r\n\r\n\t\ttrianglePool.releasePrimitive( triangle );\r\n\r\n\t\treturn result;\r\n\r\n\t}\r\n\r\n\tbvhcast( otherBvh, matrixToLocal, callbacks ) {\r\n\r\n\t\t// BVHCast function for intersecting two BVHs against each other. Ultimately just uses two recursive shapecast calls rather\r\n\t\t// than an approach that walks down the tree (see bvhcast.js file for more info).\r\n\r\n\t\tlet {\r\n\t\t\tintersectsRanges,\r\n\t\t\tintersectsTriangles,\r\n\t\t} = callbacks;\r\n\r\n\t\tconst indexAttr = this.geometry.index;\r\n\t\tconst positionAttr = this.geometry.attributes.position;\r\n\r\n\t\tconst otherIndexAttr = otherBvh.geometry.index;\r\n\t\tconst otherPositionAttr = otherBvh.geometry.attributes.position;\r\n\r\n\t\ttempMatrix.copy( matrixToLocal ).invert();\r\n\r\n\t\tconst triangle = trianglePool.getPrimitive();\r\n\t\tconst triangle2 = trianglePool.getPrimitive();\r\n\r\n\t\tif ( intersectsTriangles ) {\r\n\r\n\t\t\tfunction iterateOverDoubleTriangles( offset1, count1, offset2, count2, depth1, index1, depth2, index2 ) {\r\n\r\n\t\t\t\tfor ( let i2 = offset2, l2 = offset2 + count2; i2 < l2; i2 ++ ) {\r\n\r\n\t\t\t\t\tsetTriangle( triangle2, i2 * 3, otherIndexAttr, otherPositionAttr );\r\n\t\t\t\t\ttriangle2.a.applyMatrix4( matrixToLocal );\r\n\t\t\t\t\ttriangle2.b.applyMatrix4( matrixToLocal );\r\n\t\t\t\t\ttriangle2.c.applyMatrix4( matrixToLocal );\r\n\t\t\t\t\ttriangle2.needsUpdate = true;\r\n\r\n\t\t\t\t\tfor ( let i1 = offset1, l1 = offset1 + count1; i1 < l1; i1 ++ ) {\r\n\r\n\t\t\t\t\t\tsetTriangle( triangle, i1 * 3, indexAttr, positionAttr );\r\n\t\t\t\t\t\ttriangle.needsUpdate = true;\r\n\r\n\t\t\t\t\t\tif ( intersectsTriangles( triangle, triangle2, i1, i2, depth1, index1, depth2, index2 ) ) {\r\n\r\n\t\t\t\t\t\t\treturn true;\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn false;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( intersectsRanges ) {\r\n\r\n\t\t\t\tconst originalIntersectsRanges = intersectsRanges;\r\n\t\t\t\tintersectsRanges = function ( offset1, count1, offset2, count2, depth1, index1, depth2, index2 ) {\r\n\r\n\t\t\t\t\tif ( ! originalIntersectsRanges( offset1, count1, offset2, count2, depth1, index1, depth2, index2 ) ) {\r\n\r\n\t\t\t\t\t\treturn iterateOverDoubleTriangles( offset1, count1, offset2, count2, depth1, index1, depth2, index2 );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\treturn true;\r\n\r\n\t\t\t\t};\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tintersectsRanges = iterateOverDoubleTriangles;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tthis.getBoundingBox( aabb2 );\r\n\t\taabb2.applyMatrix4( matrixToLocal );\r\n\t\tconst result = this.shapecast( {\r\n\r\n\t\t\tintersectsBounds: box => aabb2.intersectsBox( box ),\r\n\r\n\t\t\tintersectsRange: ( offset1, count1, contained, depth1, nodeIndex1, box ) => {\r\n\r\n\t\t\t\taabb.copy( box );\r\n\t\t\t\taabb.applyMatrix4( tempMatrix );\r\n\t\t\t\treturn otherBvh.shapecast( {\r\n\r\n\t\t\t\t\tintersectsBounds: box => aabb.intersectsBox( box ),\r\n\r\n\t\t\t\t\tintersectsRange: ( offset2, count2, contained, depth2, nodeIndex2 ) => {\r\n\r\n\t\t\t\t\t\treturn intersectsRanges( offset1, count1, offset2, count2, depth1, nodeIndex1, depth2, nodeIndex2 );\r\n\r\n\t\t\t\t\t},\r\n\r\n\t\t\t\t} );\r\n\r\n\t\t\t}\r\n\r\n\t\t} );\r\n\r\n\t\ttrianglePool.releasePrimitive( triangle );\r\n\t\ttrianglePool.releasePrimitive( triangle2 );\r\n\t\treturn result;\r\n\r\n\t}\r\n\r\n\t/* Derived Cast Functions */\r\n\tintersectsBox( box, boxToMesh ) {\r\n\r\n\t\tobb.set( box.min, box.max, boxToMesh );\r\n\t\tobb.needsUpdate = true;\r\n\r\n\t\treturn this.shapecast(\r\n\t\t\t{\r\n\t\t\t\tintersectsBounds: box => obb.intersectsBox( box ),\r\n\t\t\t\tintersectsTriangle: tri => obb.intersectsTriangle( tri )\r\n\t\t\t}\r\n\t\t);\r\n\r\n\t}\r\n\r\n\tintersectsSphere( sphere ) {\r\n\r\n\t\treturn this.shapecast(\r\n\t\t\t{\r\n\t\t\t\tintersectsBounds: box => sphere.intersectsBox( box ),\r\n\t\t\t\tintersectsTriangle: tri => tri.intersectsSphere( sphere )\r\n\t\t\t}\r\n\t\t);\r\n\r\n\t}\r\n\r\n\tclosestPointToGeometry( otherGeometry, geometryToBvh, target1 = { }, target2 = { }, minThreshold = 0, maxThreshold = Infinity ) {\r\n\r\n\t\tif ( ! otherGeometry.boundingBox ) {\r\n\r\n\t\t\totherGeometry.computeBoundingBox();\r\n\r\n\t\t}\r\n\r\n\t\tobb.set( otherGeometry.boundingBox.min, otherGeometry.boundingBox.max, geometryToBvh );\r\n\t\tobb.needsUpdate = true;\r\n\r\n\t\tconst geometry = this.geometry;\r\n\t\tconst pos = geometry.attributes.position;\r\n\t\tconst index = geometry.index;\r\n\t\tconst otherPos = otherGeometry.attributes.position;\r\n\t\tconst otherIndex = otherGeometry.index;\r\n\t\tconst triangle = trianglePool.getPrimitive();\r\n\t\tconst triangle2 = trianglePool.getPrimitive();\r\n\r\n\t\tlet tempTarget1 = temp1;\r\n\t\tlet tempTargetDest1 = temp2;\r\n\t\tlet tempTarget2 = null;\r\n\t\tlet tempTargetDest2 = null;\r\n\r\n\t\tif ( target2 ) {\r\n\r\n\t\t\ttempTarget2 = temp3;\r\n\t\t\ttempTargetDest2 = temp4;\r\n\r\n\t\t}\r\n\r\n\t\tlet closestDistance = Infinity;\r\n\t\tlet closestDistanceTriIndex = null;\r\n\t\tlet closestDistanceOtherTriIndex = null;\r\n\t\ttempMatrix.copy( geometryToBvh ).invert();\r\n\t\tobb2.matrix.copy( tempMatrix );\r\n\t\tthis.shapecast(\r\n\t\t\t{\r\n\r\n\t\t\t\tboundsTraverseOrder: box => {\r\n\r\n\t\t\t\t\treturn obb.distanceToBox( box, Math.min( closestDistance, maxThreshold ) );\r\n\r\n\t\t\t\t},\r\n\r\n\t\t\t\tintersectsBounds: ( box, isLeaf, score ) => {\r\n\r\n\t\t\t\t\tif ( score < closestDistance && score < maxThreshold ) {\r\n\r\n\t\t\t\t\t\t// if we know the triangles of this bounds will be intersected next then\r\n\t\t\t\t\t\t// save the bounds to use during triangle checks.\r\n\t\t\t\t\t\tif ( isLeaf ) {\r\n\r\n\t\t\t\t\t\t\tobb2.min.copy( box.min );\r\n\t\t\t\t\t\t\tobb2.max.copy( box.max );\r\n\t\t\t\t\t\t\tobb2.needsUpdate = true;\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\treturn true;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\treturn false;\r\n\r\n\t\t\t\t},\r\n\r\n\t\t\t\tintersectsRange: ( offset, count ) => {\r\n\r\n\t\t\t\t\tif ( otherGeometry.boundsTree ) {\r\n\r\n\t\t\t\t\t\t// if the other geometry has a bvh then use the accelerated path where we use shapecast to find\r\n\t\t\t\t\t\t// the closest bounds in the other geometry to check.\r\n\t\t\t\t\t\treturn otherGeometry.boundsTree.shapecast( {\r\n\t\t\t\t\t\t\tboundsTraverseOrder: box => {\r\n\r\n\t\t\t\t\t\t\t\treturn obb2.distanceToBox( box, Math.min( closestDistance, maxThreshold ) );\r\n\r\n\t\t\t\t\t\t\t},\r\n\r\n\t\t\t\t\t\t\tintersectsBounds: ( box, isLeaf, score ) => {\r\n\r\n\t\t\t\t\t\t\t\treturn score < closestDistance && score < maxThreshold;\r\n\r\n\t\t\t\t\t\t\t},\r\n\r\n\t\t\t\t\t\t\tintersectsRange: ( otherOffset, otherCount ) => {\r\n\r\n\t\t\t\t\t\t\t\tfor ( let i2 = otherOffset * 3, l2 = ( otherOffset + otherCount ) * 3; i2 < l2; i2 += 3 ) {\r\n\r\n\t\t\t\t\t\t\t\t\tsetTriangle( triangle2, i2, otherIndex, otherPos );\r\n\t\t\t\t\t\t\t\t\ttriangle2.a.applyMatrix4( geometryToBvh );\r\n\t\t\t\t\t\t\t\t\ttriangle2.b.applyMatrix4( geometryToBvh );\r\n\t\t\t\t\t\t\t\t\ttriangle2.c.applyMatrix4( geometryToBvh );\r\n\t\t\t\t\t\t\t\t\ttriangle2.needsUpdate = true;\r\n\r\n\t\t\t\t\t\t\t\t\tfor ( let i = offset * 3, l = ( offset + count ) * 3; i < l; i += 3 ) {\r\n\r\n\t\t\t\t\t\t\t\t\t\tsetTriangle( triangle, i, index, pos );\r\n\t\t\t\t\t\t\t\t\t\ttriangle.needsUpdate = true;\r\n\r\n\t\t\t\t\t\t\t\t\t\tconst dist = triangle.distanceToTriangle( triangle2, tempTarget1, tempTarget2 );\r\n\t\t\t\t\t\t\t\t\t\tif ( dist < closestDistance ) {\r\n\r\n\t\t\t\t\t\t\t\t\t\t\ttempTargetDest1.copy( tempTarget1 );\r\n\r\n\t\t\t\t\t\t\t\t\t\t\tif ( tempTargetDest2 ) {\r\n\r\n\t\t\t\t\t\t\t\t\t\t\t\ttempTargetDest2.copy( tempTarget2 );\r\n\r\n\t\t\t\t\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\t\t\t\t\tclosestDistance = dist;\r\n\t\t\t\t\t\t\t\t\t\t\tclosestDistanceTriIndex = i / 3;\r\n\t\t\t\t\t\t\t\t\t\t\tclosestDistanceOtherTriIndex = i2 / 3;\r\n\r\n\t\t\t\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\t\t\t\t// stop traversal if we find a point that's under the given threshold\r\n\t\t\t\t\t\t\t\t\t\tif ( dist < minThreshold ) {\r\n\r\n\t\t\t\t\t\t\t\t\t\t\treturn true;\r\n\r\n\t\t\t\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\t},\r\n\t\t\t\t\t\t} );\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t// If no bounds tree then we'll just check every triangle.\r\n\t\t\t\t\t\tconst triCount = otherIndex ? otherIndex.count : otherPos.count;\r\n\t\t\t\t\t\tfor ( let i2 = 0, l2 = triCount; i2 < l2; i2 += 3 ) {\r\n\r\n\t\t\t\t\t\t\tsetTriangle( triangle2, i2, otherIndex, otherPos );\r\n\t\t\t\t\t\t\ttriangle2.a.applyMatrix4( geometryToBvh );\r\n\t\t\t\t\t\t\ttriangle2.b.applyMatrix4( geometryToBvh );\r\n\t\t\t\t\t\t\ttriangle2.c.applyMatrix4( geometryToBvh );\r\n\t\t\t\t\t\t\ttriangle2.needsUpdate = true;\r\n\r\n\t\t\t\t\t\t\tfor ( let i = offset * 3, l = ( offset + count ) * 3; i < l; i += 3 ) {\r\n\r\n\t\t\t\t\t\t\t\tsetTriangle( triangle, i, index, pos );\r\n\t\t\t\t\t\t\t\ttriangle.needsUpdate = true;\r\n\r\n\t\t\t\t\t\t\t\tconst dist = triangle.distanceToTriangle( triangle2, tempTarget1, tempTarget2 );\r\n\t\t\t\t\t\t\t\tif ( dist < closestDistance ) {\r\n\r\n\t\t\t\t\t\t\t\t\ttempTargetDest1.copy( tempTarget1 );\r\n\r\n\t\t\t\t\t\t\t\t\tif ( tempTargetDest2 ) {\r\n\r\n\t\t\t\t\t\t\t\t\t\ttempTargetDest2.copy( tempTarget2 );\r\n\r\n\t\t\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\t\t\tclosestDistance = dist;\r\n\t\t\t\t\t\t\t\t\tclosestDistanceTriIndex = i / 3;\r\n\t\t\t\t\t\t\t\t\tclosestDistanceOtherTriIndex = i2 / 3;\r\n\r\n\t\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\t\t// stop traversal if we find a point that's under the given threshold\r\n\t\t\t\t\t\t\t\tif ( dist < minThreshold ) {\r\n\r\n\t\t\t\t\t\t\t\t\treturn true;\r\n\r\n\t\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t},\r\n\r\n\t\t\t}\r\n\r\n\t\t);\r\n\r\n\t\ttrianglePool.releasePrimitive( triangle );\r\n\t\ttrianglePool.releasePrimitive( triangle2 );\r\n\r\n\t\tif ( closestDistance === Infinity ) return null;\r\n\r\n\t\tif ( ! target1.point ) target1.point = tempTargetDest1.clone();\r\n\t\telse target1.point.copy( tempTargetDest1 );\r\n\t\ttarget1.distance = closestDistance,\r\n\t\ttarget1.faceIndex = closestDistanceTriIndex;\r\n\r\n\t\tif ( target2 ) {\r\n\r\n\t\t\tif ( ! target2.point ) target2.point = tempTargetDest2.clone();\r\n\t\t\telse target2.point.copy( tempTargetDest2 );\r\n\t\t\ttarget2.point.applyMatrix4( tempMatrix );\r\n\t\t\ttempTargetDest1.applyMatrix4( tempMatrix );\r\n\t\t\ttarget2.distance = tempTargetDest1.sub( target2.point ).length();\r\n\t\t\ttarget2.faceIndex = closestDistanceOtherTriIndex;\r\n\r\n\t\t}\r\n\r\n\t\treturn target1;\r\n\r\n\t}\r\n\r\n\tclosestPointToPoint( point, target = { }, minThreshold = 0, maxThreshold = Infinity ) {\r\n\r\n\t\t// early out if under minThreshold\r\n\t\t// skip checking if over maxThreshold\r\n\t\t// set minThreshold = maxThreshold to quickly check if a point is within a threshold\r\n\t\t// returns Infinity if no value found\r\n\t\tconst minThresholdSq = minThreshold * minThreshold;\r\n\t\tconst maxThresholdSq = maxThreshold * maxThreshold;\r\n\t\tlet closestDistanceSq = Infinity;\r\n\t\tlet closestDistanceTriIndex = null;\r\n\t\tthis.shapecast(\r\n\r\n\t\t\t{\r\n\r\n\t\t\t\tboundsTraverseOrder: box => {\r\n\r\n\t\t\t\t\ttemp.copy( point ).clamp( box.min, box.max );\r\n\t\t\t\t\treturn temp.distanceToSquared( point );\r\n\r\n\t\t\t\t},\r\n\r\n\t\t\t\tintersectsBounds: ( box, isLeaf, score ) => {\r\n\r\n\t\t\t\t\treturn score < closestDistanceSq && score < maxThresholdSq;\r\n\r\n\t\t\t\t},\r\n\r\n\t\t\t\tintersectsTriangle: ( tri, triIndex ) => {\r\n\r\n\t\t\t\t\ttri.closestPointToPoint( point, temp );\r\n\t\t\t\t\tconst distSq = point.distanceToSquared( temp );\r\n\t\t\t\t\tif ( distSq < closestDistanceSq ) {\r\n\r\n\t\t\t\t\t\ttemp1.copy( temp );\r\n\t\t\t\t\t\tclosestDistanceSq = distSq;\r\n\t\t\t\t\t\tclosestDistanceTriIndex = triIndex;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif ( distSq < minThresholdSq ) {\r\n\r\n\t\t\t\t\t\treturn true;\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\treturn false;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t},\r\n\r\n\t\t\t}\r\n\r\n\t\t);\r\n\r\n\t\tif ( closestDistanceSq === Infinity ) return null;\r\n\r\n\t\tconst closestDistance = Math.sqrt( closestDistanceSq );\r\n\r\n\t\tif ( ! target.point ) target.point = temp1.clone();\r\n\t\telse target.point.copy( temp1 );\r\n\t\ttarget.distance = closestDistance,\r\n\t\ttarget.faceIndex = closestDistanceTriIndex;\r\n\r\n\t\treturn target;\r\n\r\n\t}\r\n\r\n\tgetBoundingBox( target ) {\r\n\r\n\t\ttarget.makeEmpty();\r\n\r\n\t\tconst roots = this._roots;\r\n\t\troots.forEach( buffer => {\r\n\r\n\t\t\tarrayToBox( 0, new Float32Array( buffer ), tempBox );\r\n\t\t\ttarget.union( tempBox );\r\n\r\n\t\t} );\r\n\r\n\t\treturn target;\r\n\r\n\t}\r\n\r\n}\r\n\r\n// Deprecation\r\nconst originalRaycast = MeshBVH.prototype.raycast;\r\nMeshBVH.prototype.raycast = function ( ...args ) {\r\n\r\n\tif ( args[ 0 ].isMesh ) {\r\n\r\n\t\tconsole.warn( 'MeshBVH: The function signature and results frame for \"raycast\" has changed. See docs for new signature.' );\r\n\t\tconst [\r\n\t\t\tmesh, raycaster, ray, intersects,\r\n\t\t] = args;\r\n\r\n\t\tconst results = originalRaycast.call( this, ray, mesh.material );\r\n\t\tresults.forEach( hit => {\r\n\r\n\t\t\thit = convertRaycastIntersect( hit, mesh, raycaster );\r\n\t\t\tif ( hit ) {\r\n\r\n\t\t\t\tintersects.push( hit );\r\n\r\n\t\t\t}\r\n\r\n\t\t} );\r\n\r\n\t\treturn intersects;\r\n\r\n\t} else {\r\n\r\n\t\treturn originalRaycast.apply( this, args );\r\n\r\n\t}\r\n\r\n};\r\n\r\nconst originalRaycastFirst = MeshBVH.prototype.raycastFirst;\r\nMeshBVH.prototype.raycastFirst = function ( ...args ) {\r\n\r\n\tif ( args[ 0 ].isMesh ) {\r\n\r\n\t\tconsole.warn( 'MeshBVH: The function signature and results frame for \"raycastFirst\" has changed. See docs for new signature.' );\r\n\t\tconst [\r\n\t\t\tmesh, raycaster, ray,\r\n\t\t] = args;\r\n\r\n\t\treturn convertRaycastIntersect( originalRaycastFirst.call( this, ray, mesh.material ), mesh, raycaster );\r\n\r\n\t} else {\r\n\r\n\t\treturn originalRaycastFirst.apply( this, args );\r\n\r\n\t}\r\n\r\n};\r\n\r\nconst originalClosestPointToPoint = MeshBVH.prototype.closestPointToPoint;\r\nMeshBVH.prototype.closestPointToPoint = function ( ...args ) {\r\n\r\n\r\n\tif ( args[ 0 ].isMesh ) {\r\n\r\n\t\tconsole.warn( 'MeshBVH: The function signature and results frame for \"closestPointToPoint\" has changed. See docs for new signature.' );\r\n\r\n\t\targs.unshift();\r\n\r\n\t\tconst target = args[ 1 ];\r\n\t\tconst result = {};\r\n\t\targs[ 1 ] = result;\r\n\r\n\t\toriginalClosestPointToPoint.apply( this, args );\r\n\r\n\t\tif ( target ) {\r\n\r\n\t\t\ttarget.copy( result.point );\r\n\r\n\t\t}\r\n\r\n\t\treturn result.distance;\r\n\r\n\t} else {\r\n\r\n\t\treturn originalClosestPointToPoint.apply( this, args );\r\n\r\n\t}\r\n\r\n};\r\n\r\nconst originalClosestPointToGeometry = MeshBVH.prototype.closestPointToGeometry;\r\nMeshBVH.prototype.closestPointToGeometry = function ( ...args ) {\r\n\r\n\tconst target1 = args[ 2 ];\r\n\tconst target2 = args[ 3 ];\r\n\tif ( target1 && target1.isVector3 || target2 && target2.isVector3 ) {\r\n\r\n\t\tconsole.warn( 'MeshBVH: The function signature and results frame for \"closestPointToGeometry\" has changed. See docs for new signature.' );\r\n\r\n\t\tconst result1 = {};\r\n\t\tconst result2 = {};\r\n\t\tconst geometryToBvh = args[ 1 ];\r\n\t\targs[ 2 ] = result1;\r\n\t\targs[ 3 ] = result2;\r\n\r\n\t\toriginalClosestPointToGeometry.apply( this, args );\r\n\r\n\t\tif ( target1 ) {\r\n\r\n\t\t\ttarget1.copy( result1.point );\r\n\r\n\t\t}\r\n\r\n\t\tif ( target2 ) {\r\n\r\n\t\t\ttarget2.copy( result2.point ).applyMatrix4( geometryToBvh );\r\n\r\n\t\t}\r\n\r\n\t\treturn result1.distance;\r\n\r\n\t} else {\r\n\r\n\t\treturn originalClosestPointToGeometry.apply( this, args );\r\n\r\n\t}\r\n\r\n};\r\n\r\nconst originalRefit = MeshBVH.prototype.refit;\r\nMeshBVH.prototype.refit = function ( ...args ) {\r\n\r\n\tconst nodeIndices = args[ 0 ];\r\n\tconst terminationIndices = args[ 1 ];\r\n\tif ( terminationIndices && ( terminationIndices instanceof Set || Array.isArray( terminationIndices ) ) ) {\r\n\r\n\t\tconsole.warn( 'MeshBVH: The function signature for \"refit\" has changed. See docs for new signature.' );\r\n\r\n\t\tconst newNodeIndices = new Set();\r\n\t\tterminationIndices.forEach( v => newNodeIndices.add( v ) );\r\n\t\tif ( nodeIndices ) {\r\n\r\n\t\t\tnodeIndices.forEach( v => newNodeIndices.add( v ) );\r\n\r\n\t\t}\r\n\r\n\t\toriginalRefit.call( this, newNodeIndices );\r\n\r\n\t} else {\r\n\r\n\t\toriginalRefit.apply( this, args );\r\n\r\n\t}\r\n\r\n};\r\n\r\n[\r\n\t'intersectsGeometry',\r\n\t'shapecast',\r\n\t'intersectsBox',\r\n\t'intersectsSphere',\r\n].forEach( name => {\r\n\r\n\tconst originalFunc = MeshBVH.prototype[ name ];\r\n\tMeshBVH.prototype[ name ] = function ( ...args ) {\r\n\r\n\t\tif ( args[ 0 ] === null || args[ 0 ].isMesh ) {\r\n\r\n\t\t\targs.shift();\r\n\t\t\tconsole.warn( `MeshBVH: The function signature for \"${ name }\" has changed and no longer takes Mesh. See docs for new signature.` );\r\n\r\n\t\t}\r\n\r\n\t\treturn originalFunc.apply( this, args );\r\n\r\n\t};\r\n\r\n} );\r\n","import { LineBasicMaterial, BufferAttribute, Box3, Group, MeshBasicMaterial, Object3D, BufferGeometry } from 'three';\r\nimport { arrayToBox } from '../utils/ArrayBoxUtilities.js';\r\n\r\nconst boundingBox = /* @__PURE__ */ new Box3();\r\nclass MeshBVHRootVisualizer extends Object3D {\r\n\r\n\tget isMesh() {\r\n\r\n\t\treturn ! this.displayEdges;\r\n\r\n\t}\r\n\r\n\tget isLineSegments() {\r\n\r\n\t\treturn this.displayEdges;\r\n\r\n\t}\r\n\r\n\tget isLine() {\r\n\r\n\t\treturn this.displayEdges;\r\n\r\n\t}\r\n\r\n\tconstructor( mesh, material, depth = 10, group = 0 ) {\r\n\r\n\t\tsuper();\r\n\r\n\t\tthis.material = material;\r\n\t\tthis.geometry = new BufferGeometry();\r\n\t\tthis.name = 'MeshBVHRootVisualizer';\r\n\t\tthis.depth = depth;\r\n\t\tthis.displayParents = false;\r\n\t\tthis.mesh = mesh;\r\n\t\tthis.displayEdges = true;\r\n\t\tthis._group = group;\r\n\r\n\t}\r\n\r\n\traycast() {}\r\n\r\n\tupdate() {\r\n\r\n\t\tconst geometry = this.geometry;\r\n\t\tconst boundsTree = this.mesh.geometry.boundsTree;\r\n\t\tconst group = this._group;\r\n\t\tgeometry.dispose();\r\n\t\tthis.visible = false;\r\n\t\tif ( boundsTree ) {\r\n\r\n\t\t\t// count the number of bounds required\r\n\t\t\tconst targetDepth = this.depth - 1;\r\n\t\t\tconst displayParents = this.displayParents;\r\n\t\t\tlet boundsCount = 0;\r\n\t\t\tboundsTree.traverse( ( depth, isLeaf ) => {\r\n\r\n\t\t\t\tif ( depth === targetDepth || isLeaf ) {\r\n\r\n\t\t\t\t\tboundsCount ++;\r\n\t\t\t\t\treturn true;\r\n\r\n\t\t\t\t} else if ( displayParents ) {\r\n\r\n\t\t\t\t\tboundsCount ++;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}, group );\r\n\r\n\t\t\t// fill in the position buffer with the bounds corners\r\n\t\t\tlet posIndex = 0;\r\n\t\t\tconst positionArray = new Float32Array( 8 * 3 * boundsCount );\r\n\t\t\tboundsTree.traverse( ( depth, isLeaf, boundingData ) => {\r\n\r\n\t\t\t\tconst terminate = depth === targetDepth || isLeaf;\r\n\t\t\t\tif ( terminate || displayParents ) {\r\n\r\n\t\t\t\t\tarrayToBox( 0, boundingData, boundingBox );\r\n\r\n\t\t\t\t\tconst { min, max } = boundingBox;\r\n\t\t\t\t\tfor ( let x = - 1; x <= 1; x += 2 ) {\r\n\r\n\t\t\t\t\t\tconst xVal = x < 0 ? min.x : max.x;\r\n\t\t\t\t\t\tfor ( let y = - 1; y <= 1; y += 2 ) {\r\n\r\n\t\t\t\t\t\t\tconst yVal = y < 0 ? min.y : max.y;\r\n\t\t\t\t\t\t\tfor ( let z = - 1; z <= 1; z += 2 ) {\r\n\r\n\t\t\t\t\t\t\t\tconst zVal = z < 0 ? min.z : max.z;\r\n\t\t\t\t\t\t\t\tpositionArray[ posIndex + 0 ] = xVal;\r\n\t\t\t\t\t\t\t\tpositionArray[ posIndex + 1 ] = yVal;\r\n\t\t\t\t\t\t\t\tpositionArray[ posIndex + 2 ] = zVal;\r\n\r\n\t\t\t\t\t\t\t\tposIndex += 3;\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\treturn terminate;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}, group );\r\n\r\n\t\t\tlet indexArray;\r\n\t\t\tlet indices;\r\n\t\t\tif ( this.displayEdges ) {\r\n\r\n\t\t\t\t// fill in the index buffer to point to the corner points\r\n\t\t\t\tindices = new Uint8Array( [\r\n\t\t\t\t\t// x axis\r\n\t\t\t\t\t0, 4,\r\n\t\t\t\t\t1, 5,\r\n\t\t\t\t\t2, 6,\r\n\t\t\t\t\t3, 7,\r\n\r\n\t\t\t\t\t// y axis\r\n\t\t\t\t\t0, 2,\r\n\t\t\t\t\t1, 3,\r\n\t\t\t\t\t4, 6,\r\n\t\t\t\t\t5, 7,\r\n\r\n\t\t\t\t\t// z axis\r\n\t\t\t\t\t0, 1,\r\n\t\t\t\t\t2, 3,\r\n\t\t\t\t\t4, 5,\r\n\t\t\t\t\t6, 7,\r\n\t\t\t\t] );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tindices = new Uint8Array( [\r\n\r\n\t\t\t\t\t// X-, X+\r\n\t\t\t\t\t0, 1, 2,\r\n\t\t\t\t\t2, 1, 3,\r\n\r\n\t\t\t\t\t4, 6, 5,\r\n\t\t\t\t\t6, 7, 5,\r\n\r\n\t\t\t\t\t// Y-, Y+\r\n\t\t\t\t\t1, 4, 5,\r\n\t\t\t\t\t0, 4, 1,\r\n\r\n\t\t\t\t\t2, 3, 6,\r\n\t\t\t\t\t3, 7, 6,\r\n\r\n\t\t\t\t\t// Z-, Z+\r\n\t\t\t\t\t0, 2, 4,\r\n\t\t\t\t\t2, 6, 4,\r\n\r\n\t\t\t\t\t1, 5, 3,\r\n\t\t\t\t\t3, 5, 7,\r\n\r\n\t\t\t\t] );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( positionArray.length > 65535 ) {\r\n\r\n\t\t\t\tindexArray = new Uint32Array( indices.length * boundsCount );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tindexArray = new Uint16Array( indices.length * boundsCount );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tconst indexLength = indices.length;\r\n\t\t\tfor ( let i = 0; i < boundsCount; i ++ ) {\r\n\r\n\t\t\t\tconst posOffset = i * 8;\r\n\t\t\t\tconst indexOffset = i * indexLength;\r\n\t\t\t\tfor ( let j = 0; j < indexLength; j ++ ) {\r\n\r\n\t\t\t\t\tindexArray[ indexOffset + j ] = posOffset + indices[ j ];\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// update the geometry\r\n\t\t\tgeometry.setIndex(\r\n\t\t\t\tnew BufferAttribute( indexArray, 1, false ),\r\n\t\t\t);\r\n\t\t\tgeometry.setAttribute(\r\n\t\t\t\t'position',\r\n\t\t\t\tnew BufferAttribute( positionArray, 3, false ),\r\n\t\t\t);\r\n\t\t\tthis.visible = true;\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n}\r\n\r\nclass MeshBVHVisualizer extends Group {\r\n\r\n\tget color() {\r\n\r\n\t\treturn this.edgeMaterial.color;\r\n\r\n\t}\r\n\r\n\tget opacity() {\r\n\r\n\t\treturn this.edgeMaterial.opacity;\r\n\r\n\t}\r\n\r\n\tset opacity( v ) {\r\n\r\n\t\tthis.edgeMaterial.opacity = v;\r\n\t\tthis.meshMaterial.opacity = v;\r\n\r\n\t}\r\n\r\n\tconstructor( mesh, depth = 10 ) {\r\n\r\n\t\tsuper();\r\n\r\n\t\tthis.name = 'MeshBVHVisualizer';\r\n\t\tthis.depth = depth;\r\n\t\tthis.mesh = mesh;\r\n\t\tthis.displayParents = false;\r\n\t\tthis.displayEdges = true;\r\n\t\tthis._roots = [];\r\n\r\n\t\tconst edgeMaterial = new LineBasicMaterial( {\r\n\t\t\tcolor: 0x00FF88,\r\n\t\t\ttransparent: true,\r\n\t\t\topacity: 0.3,\r\n\t\t\tdepthWrite: false,\r\n\t\t} );\r\n\r\n\t\tconst meshMaterial = new MeshBasicMaterial( {\r\n\t\t\tcolor: 0x00FF88,\r\n\t\t\ttransparent: true,\r\n\t\t\topacity: 0.3,\r\n\t\t\tdepthWrite: false,\r\n\t\t} );\r\n\r\n\t\tmeshMaterial.color = edgeMaterial.color;\r\n\r\n\t\tthis.edgeMaterial = edgeMaterial;\r\n\t\tthis.meshMaterial = meshMaterial;\r\n\r\n\t\tthis.update();\r\n\r\n\t}\r\n\r\n\tupdate() {\r\n\r\n\t\tconst bvh = this.mesh.geometry.boundsTree;\r\n\t\tconst totalRoots = bvh ? bvh._roots.length : 0;\r\n\t\twhile ( this._roots.length > totalRoots ) {\r\n\r\n\t\t\tthis._roots.pop();\r\n\r\n\t\t}\r\n\r\n\t\tfor ( let i = 0; i < totalRoots; i ++ ) {\r\n\r\n\t\t\tif ( i >= this._roots.length ) {\r\n\r\n\t\t\t\tconst root = new MeshBVHRootVisualizer( this.mesh, this.edgeMaterial, this.depth, i );\r\n\t\t\t\tthis.add( root );\r\n\t\t\t\tthis._roots.push( root );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tconst root = this._roots[ i ];\r\n\t\t\troot.depth = this.depth;\r\n\t\t\troot.mesh = this.mesh;\r\n\t\t\troot.displayParents = this.displayParents;\r\n\t\t\troot.displayEdges = this.displayEdges;\r\n\t\t\troot.material = this.displayEdges ? this.edgeMaterial : this.meshMaterial;\r\n\t\t\troot.update();\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tupdateMatrixWorld( ...args ) {\r\n\r\n\t\tthis.position.copy( this.mesh.position );\r\n\t\tthis.rotation.copy( this.mesh.rotation );\r\n\t\tthis.scale.copy( this.mesh.scale );\r\n\r\n\t\tsuper.updateMatrixWorld( ...args );\r\n\r\n\t}\r\n\r\n\tcopy( source ) {\r\n\r\n\t\tthis.depth = source.depth;\r\n\t\tthis.mesh = source.mesh;\r\n\r\n\t}\r\n\r\n\tclone() {\r\n\r\n\t\treturn new MeshBVHVisualizer( this.mesh, this.depth );\r\n\r\n\t}\r\n\r\n\tdispose() {\r\n\r\n\t\tthis.edgeMaterial.dispose();\r\n\t\tthis.meshMaterial.dispose();\r\n\r\n\t\tconst children = this.children;\r\n\t\tfor ( let i = 0, l = children.length; i < l; i ++ ) {\r\n\r\n\t\t\tchildren[ i ].geometry.dispose();\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n}\r\n\r\n\r\nexport { MeshBVHVisualizer };\r\n","import { Box3, Vector3 } from 'three';\r\nimport { TRAVERSAL_COST, TRIANGLE_INTERSECT_COST } from '../core/Constants.js';\r\nimport { arrayToBox } from '../utils/ArrayBoxUtilities.js';\r\n\r\nconst _box1 = /* @__PURE__ */ new Box3();\r\nconst _box2 = /* @__PURE__ */ new Box3();\r\nconst _vec = /* @__PURE__ */ new Vector3();\r\n\r\n// https://stackoverflow.com/questions/1248302/how-to-get-the-size-of-a-javascript-object\r\nfunction getPrimitiveSize( el ) {\r\n\r\n\tswitch ( typeof el ) {\r\n\r\n\t\tcase 'number':\r\n\t\t\treturn 8;\r\n\t\tcase 'string':\r\n\t\t\treturn el.length * 2;\r\n\t\tcase 'boolean':\r\n\t\t\treturn 4;\r\n\t\tdefault:\r\n\t\t\treturn 0;\r\n\r\n\t}\r\n\r\n}\r\n\r\nfunction isTypedArray( arr ) {\r\n\r\n\tconst regex = /(Uint|Int|Float)(8|16|32)Array/;\r\n\treturn regex.test( arr.constructor.name );\r\n\r\n}\r\n\r\nfunction getRootExtremes( bvh, group ) {\r\n\r\n\tconst result = {\r\n\t\tnodeCount: 0,\r\n\t\tleafNodeCount: 0,\r\n\r\n\t\tdepth: {\r\n\t\t\tmin: Infinity, max: - Infinity\r\n\t\t},\r\n\t\ttris: {\r\n\t\t\tmin: Infinity, max: - Infinity\r\n\t\t},\r\n\t\tsplits: [ 0, 0, 0 ],\r\n\t\tsurfaceAreaScore: 0,\r\n\t};\r\n\r\n\tbvh.traverse( ( depth, isLeaf, boundingData, offsetOrSplit, count ) => {\r\n\r\n\t\tconst l0 = boundingData[ 0 + 3 ] - boundingData[ 0 ];\r\n\t\tconst l1 = boundingData[ 1 + 3 ] - boundingData[ 1 ];\r\n\t\tconst l2 = boundingData[ 2 + 3 ] - boundingData[ 2 ];\r\n\r\n\t\tconst surfaceArea = 2 * ( l0 * l1 + l1 * l2 + l2 * l0 );\r\n\r\n\t\tresult.nodeCount ++;\r\n\t\tif ( isLeaf ) {\r\n\r\n\t\t\tresult.leafNodeCount ++;\r\n\r\n\t\t\tresult.depth.min = Math.min( depth, result.depth.min );\r\n\t\t\tresult.depth.max = Math.max( depth, result.depth.max );\r\n\r\n\t\t\tresult.tris.min = Math.min( count, result.tris.min );\r\n\t\t\tresult.tris.max = Math.max( count, result.tris.max );\r\n\r\n\t\t\tresult.surfaceAreaScore += surfaceArea * TRIANGLE_INTERSECT_COST * count;\r\n\r\n\t\t} else {\r\n\r\n\t\t\tresult.splits[ offsetOrSplit ] ++;\r\n\r\n\t\t\tresult.surfaceAreaScore += surfaceArea * TRAVERSAL_COST;\r\n\r\n\t\t}\r\n\r\n\t}, group );\r\n\r\n\t// If there are no leaf nodes because the tree hasn't finished generating yet.\r\n\tif ( result.tris.min === Infinity ) {\r\n\r\n\t\tresult.tris.min = 0;\r\n\t\tresult.tris.max = 0;\r\n\r\n\t}\r\n\r\n\tif ( result.depth.min === Infinity ) {\r\n\r\n\t\tresult.depth.min = 0;\r\n\t\tresult.depth.max = 0;\r\n\r\n\t}\r\n\r\n\treturn result;\r\n\r\n}\r\n\r\nfunction getBVHExtremes( bvh ) {\r\n\r\n\treturn bvh._roots.map( ( root, i ) => getRootExtremes( bvh, i ) );\r\n\r\n}\r\n\r\nfunction estimateMemoryInBytes( obj ) {\r\n\r\n\tconst traversed = new Set();\r\n\tconst stack = [ obj ];\r\n\tlet bytes = 0;\r\n\r\n\twhile ( stack.length ) {\r\n\r\n\t\tconst curr = stack.pop();\r\n\t\tif ( traversed.has( curr ) ) {\r\n\r\n\t\t\tcontinue;\r\n\r\n\t\t}\r\n\r\n\t\ttraversed.add( curr );\r\n\r\n\t\tfor ( let key in curr ) {\r\n\r\n\t\t\tif ( ! curr.hasOwnProperty( key ) ) {\r\n\r\n\t\t\t\tcontinue;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tbytes += getPrimitiveSize( key );\r\n\r\n\t\t\tconst value = curr[ key ];\r\n\t\t\tif ( value && ( typeof value === 'object' || typeof value === 'function' ) ) {\r\n\r\n\t\t\t\tif ( isTypedArray( value ) ) {\r\n\r\n\t\t\t\t\tbytes += value.byteLength;\r\n\r\n\t\t\t\t} else if ( value instanceof ArrayBuffer ) {\r\n\r\n\t\t\t\t\tbytes += value.byteLength;\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tstack.push( value );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tbytes += getPrimitiveSize( value );\r\n\r\n\t\t\t}\r\n\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\treturn bytes;\r\n\r\n}\r\n\r\nfunction validateBounds( bvh ) {\r\n\r\n\tconst geometry = bvh.geometry;\r\n\tconst depthStack = [];\r\n\tconst index = geometry.index;\r\n\tconst position = geometry.getAttribute( 'position' );\r\n\tlet passes = true;\r\n\r\n\tbvh.traverse( ( depth, isLeaf, boundingData, offset, count ) => {\r\n\r\n\t\tconst info = {\r\n\t\t\tdepth,\r\n\t\t\tisLeaf,\r\n\t\t\tboundingData,\r\n\t\t\toffset,\r\n\t\t\tcount,\r\n\t\t};\r\n\t\tdepthStack[ depth ] = info;\r\n\r\n\t\tarrayToBox( 0, boundingData, _box1 );\r\n\t\tconst parent = depthStack[ depth - 1 ];\r\n\r\n\t\tif ( isLeaf ) {\r\n\r\n\t\t\t// check triangles\r\n\t\t\tfor ( let i = offset * 3, l = ( offset + count ) * 3; i < l; i += 3 ) {\r\n\r\n\t\t\t\tconst i0 = index.getX( i );\r\n\t\t\t\tconst i1 = index.getX( i + 1 );\r\n\t\t\t\tconst i2 = index.getX( i + 2 );\r\n\r\n\t\t\t\tlet isContained;\r\n\r\n\t\t\t\t_vec.fromBufferAttribute( position, i0 );\r\n\t\t\t\tisContained = _box1.containsPoint( _vec );\r\n\r\n\t\t\t\t_vec.fromBufferAttribute( position, i1 );\r\n\t\t\t\tisContained = isContained && _box1.containsPoint( _vec );\r\n\r\n\t\t\t\t_vec.fromBufferAttribute( position, i2 );\r\n\t\t\t\tisContained = isContained && _box1.containsPoint( _vec );\r\n\r\n\t\t\t\tconsole.assert( isContained, 'Leaf bounds does not fully contain triangle.' );\r\n\t\t\t\tpasses = passes && isContained;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tif ( parent ) {\r\n\r\n\t\t\t// check if my bounds fit in my parents\r\n\t\t\tarrayToBox( 0, boundingData, _box2 );\r\n\r\n\t\t\tconst isContained = _box2.containsBox( _box1 );\r\n\t\t\tconsole.assert( isContained, 'Parent bounds does not fully contain child.' );\r\n\t\t\tpasses = passes && isContained;\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\treturn passes;\r\n\r\n}\r\n\r\n// Returns a simple, human readable object that represents the BVH.\r\nfunction getJSONStructure( bvh ) {\r\n\r\n\tconst depthStack = [];\r\n\r\n\tbvh.traverse( ( depth, isLeaf, boundingData, offset, count ) => {\r\n\r\n\t\tconst info = {\r\n\t\t\tbounds: arrayToBox( 0, boundingData, new Box3() ),\r\n\t\t};\r\n\r\n\t\tif ( isLeaf ) {\r\n\r\n\t\t\tinfo.count = count;\r\n\t\t\tinfo.offset = offset;\r\n\r\n\t\t} else {\r\n\r\n\t\t\tinfo.left = null;\r\n\t\t\tinfo.right = null;\r\n\r\n\t\t}\r\n\r\n\t\tdepthStack[ depth ] = info;\r\n\r\n\t\t// traversal hits the left then right node\r\n\t\tconst parent = depthStack[ depth - 1 ];\r\n\t\tif ( parent ) {\r\n\r\n\t\t\tif ( parent.left === null ) {\r\n\r\n\t\t\t\tparent.left = info;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tparent.right = info;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\treturn depthStack[ 0 ];\r\n\r\n}\r\n\r\nexport { estimateMemoryInBytes, getBVHExtremes, validateBounds, getJSONStructure };\r\n","import { Ray, Matrix4, Mesh } from 'three';\r\nimport { convertRaycastIntersect } from './GeometryRayIntersectUtilities.js';\r\nimport { MeshBVH } from '../core/MeshBVH.js';\r\n\r\nconst ray = /* @__PURE__ */ new Ray();\r\nconst tmpInverseMatrix = /* @__PURE__ */ new Matrix4();\r\nconst origMeshRaycastFunc = Mesh.prototype.raycast;\r\n\r\nexport function acceleratedRaycast( raycaster, intersects ) {\r\n\r\n\tif ( this.geometry.boundsTree ) {\r\n\r\n\t\tif ( this.material === undefined ) return;\r\n\r\n\t\ttmpInverseMatrix.copy( this.matrixWorld ).invert();\r\n\t\tray.copy( raycaster.ray ).applyMatrix4( tmpInverseMatrix );\r\n\r\n\t\tconst bvh = this.geometry.boundsTree;\r\n\t\tif ( raycaster.firstHitOnly === true ) {\r\n\r\n\t\t\tconst hit = convertRaycastIntersect( bvh.raycastFirst( ray, this.material ), this, raycaster );\r\n\t\t\tif ( hit ) {\r\n\r\n\t\t\t\tintersects.push( hit );\r\n\r\n\t\t\t}\r\n\r\n\t\t} else {\r\n\r\n\t\t\tconst hits = bvh.raycast( ray, this.material );\r\n\t\t\tfor ( let i = 0, l = hits.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tconst hit = convertRaycastIntersect( hits[ i ], this, raycaster );\r\n\t\t\t\tif ( hit ) {\r\n\r\n\t\t\t\t\tintersects.push( hit );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t} else {\r\n\r\n\t\torigMeshRaycastFunc.call( this, raycaster, intersects );\r\n\r\n\t}\r\n\r\n}\r\n\r\nexport function computeBoundsTree( options ) {\r\n\r\n\tthis.boundsTree = new MeshBVH( this, options );\r\n\treturn this.boundsTree;\r\n\r\n}\r\n\r\nexport function disposeBoundsTree() {\r\n\r\n\tthis.boundsTree = null;\r\n\r\n}\r\n","import {\r\n\tDataTexture,\r\n\tFloatType,\r\n\tIntType,\r\n\tUnsignedIntType,\r\n\tByteType,\r\n\tUnsignedByteType,\r\n\tShortType,\r\n\tUnsignedShortType,\r\n\r\n\tRedFormat,\r\n\tRGFormat,\r\n\tRGBAFormat,\r\n\r\n\tRedIntegerFormat,\r\n\tRGIntegerFormat,\r\n\tRGBAIntegerFormat,\r\n\r\n\tNearestFilter,\r\n} from 'three';\r\n\r\nfunction countToStringFormat( count ) {\r\n\r\n\tswitch ( count ) {\r\n\r\n\t\tcase 1: return 'R';\r\n\t\tcase 2: return 'RG';\r\n\t\tcase 3: return 'RGBA';\r\n\t\tcase 4: return 'RGBA';\r\n\r\n\t}\r\n\r\n\tthrow new Error();\r\n\r\n}\r\n\r\nfunction countToFormat( count ) {\r\n\r\n\tswitch ( count ) {\r\n\r\n\t\tcase 1: return RedFormat;\r\n\t\tcase 2: return RGFormat;\r\n\t\tcase 3: return RGBAFormat;\r\n\t\tcase 4: return RGBAFormat;\r\n\r\n\t}\r\n\r\n}\r\n\r\nfunction countToIntFormat( count ) {\r\n\r\n\tswitch ( count ) {\r\n\r\n\t\tcase 1: return RedIntegerFormat;\r\n\t\tcase 2: return RGIntegerFormat;\r\n\t\tcase 3: return RGBAIntegerFormat;\r\n\t\tcase 4: return RGBAIntegerFormat;\r\n\r\n\t}\r\n\r\n}\r\n\r\nexport class VertexAttributeTexture extends DataTexture {\r\n\r\n\tconstructor() {\r\n\r\n\t\tsuper();\r\n\t\tthis.minFilter = NearestFilter;\r\n\t\tthis.magFilter = NearestFilter;\r\n\t\tthis.generateMipmaps = false;\r\n\t\tthis.overrideItemSize = null;\r\n\t\tthis._forcedType = null;\r\n\r\n\t}\r\n\r\n\tupdateFrom( attr ) {\r\n\r\n\t\tconst overrideItemSize = this.overrideItemSize;\r\n\t\tconst originalItemSize = attr.itemSize;\r\n\t\tconst originalCount = attr.count;\r\n\t\tif ( overrideItemSize !== null ) {\r\n\r\n\t\t\tif ( ( originalItemSize * originalCount ) % overrideItemSize !== 0.0 ) {\r\n\r\n\t\t\t\tthrow new Error( 'VertexAttributeTexture: overrideItemSize must divide evenly into buffer length.' );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tattr.itemSize = overrideItemSize;\r\n\t\t\tattr.count = originalCount * originalItemSize / overrideItemSize;\r\n\r\n\t\t}\r\n\r\n\t\tconst itemSize = attr.itemSize;\r\n\t\tconst count = attr.count;\r\n\t\tconst normalized = attr.normalized;\r\n\t\tconst originalBufferCons = attr.array.constructor;\r\n\t\tconst byteCount = originalBufferCons.BYTES_PER_ELEMENT;\r\n\t\tlet targetType = this._forcedType;\r\n\t\tlet finalStride = itemSize;\r\n\r\n\t\t// derive the type of texture this should be in the shader\r\n\t\tif ( targetType === null ) {\r\n\r\n\t\t\tswitch ( originalBufferCons ) {\r\n\r\n\t\t\t\tcase Float32Array:\r\n\t\t\t\t\ttargetType = FloatType;\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase Uint8Array:\r\n\t\t\t\tcase Uint16Array:\r\n\t\t\t\tcase Uint32Array:\r\n\t\t\t\t\ttargetType = UnsignedIntType;\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase Int8Array:\r\n\t\t\t\tcase Int16Array:\r\n\t\t\t\tcase Int32Array:\r\n\t\t\t\t\ttargetType = IntType;\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t// get the target format to store the texture as\r\n\t\tlet type, format, normalizeValue, targetBufferCons;\r\n\t\tlet internalFormat = countToStringFormat( itemSize );\r\n\t\tswitch ( targetType ) {\r\n\r\n\t\t\tcase FloatType:\r\n\t\t\t\tnormalizeValue = 1.0;\r\n\t\t\t\tformat = countToFormat( itemSize );\r\n\r\n\t\t\t\tif ( normalized && byteCount === 1 ) {\r\n\r\n\t\t\t\t\ttargetBufferCons = originalBufferCons;\r\n\t\t\t\t\tinternalFormat += '8';\r\n\r\n\t\t\t\t\tif ( originalBufferCons === Uint8Array ) {\r\n\r\n\t\t\t\t\t\ttype = UnsignedByteType;\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\ttype = ByteType;\r\n\t\t\t\t\t\tinternalFormat += '_SNORM';\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\ttargetBufferCons = Float32Array;\r\n\t\t\t\t\tinternalFormat += '32F';\r\n\t\t\t\t\ttype = FloatType;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tcase IntType:\r\n\t\t\t\tinternalFormat += byteCount * 8 + 'I';\r\n\t\t\t\tnormalizeValue = normalized ? Math.pow( 2, originalBufferCons.BYTES_PER_ELEMENT * 8 - 1 ) : 1.0;\r\n\t\t\t\tformat = countToIntFormat( itemSize );\r\n\r\n\t\t\t\tif ( byteCount === 1 ) {\r\n\r\n\t\t\t\t\ttargetBufferCons = Int8Array;\r\n\t\t\t\t\ttype = ByteType;\r\n\r\n\t\t\t\t} else if ( byteCount === 2 ) {\r\n\r\n\t\t\t\t\ttargetBufferCons = Int16Array;\r\n\t\t\t\t\ttype = ShortType;\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\ttargetBufferCons = Int32Array;\r\n\t\t\t\t\ttype = IntType;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tcase UnsignedIntType:\r\n\t\t\t\tinternalFormat += byteCount * 8 + 'UI';\r\n\t\t\t\tnormalizeValue = normalized ? Math.pow( 2, originalBufferCons.BYTES_PER_ELEMENT * 8 - 1 ) : 1.0;\r\n\t\t\t\tformat = countToIntFormat( itemSize );\r\n\r\n\t\t\t\tif ( byteCount === 1 ) {\r\n\r\n\t\t\t\t\ttargetBufferCons = Uint8Array;\r\n\t\t\t\t\ttype = UnsignedByteType;\r\n\r\n\t\t\t\t} else if ( byteCount === 2 ) {\r\n\r\n\t\t\t\t\ttargetBufferCons = Uint16Array;\r\n\t\t\t\t\ttype = UnsignedShortType;\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\ttargetBufferCons = Uint32Array;\r\n\t\t\t\t\ttype = UnsignedIntType;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tbreak;\r\n\r\n\t\t}\r\n\r\n\t\t// there will be a mismatch between format length and final length because\r\n\t\t// RGBFormat and RGBIntegerFormat was removed\r\n\t\tif ( finalStride === 3 && ( format === RGBAFormat || format === RGBAIntegerFormat ) ) {\r\n\r\n\t\t\tfinalStride = 4;\r\n\r\n\t\t}\r\n\r\n\t\t// copy the data over to the new texture array\r\n\t\tconst dimension = Math.ceil( Math.sqrt( count ) );\r\n\t\tconst length = finalStride * dimension * dimension;\r\n\t\tconst dataArray = new targetBufferCons( length );\r\n\t\tfor ( let i = 0; i < count; i ++ ) {\r\n\r\n\t\t\tconst ii = finalStride * i;\r\n\t\t\tdataArray[ ii ] = attr.getX( i ) / normalizeValue;\r\n\r\n\t\t\tif ( itemSize >= 2 ) {\r\n\r\n\t\t\t\tdataArray[ ii + 1 ] = attr.getY( i ) / normalizeValue;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( itemSize >= 3 ) {\r\n\r\n\t\t\t\tdataArray[ ii + 2 ] = attr.getZ( i ) / normalizeValue;\r\n\r\n\t\t\t\tif ( finalStride === 4 ) {\r\n\r\n\t\t\t\t\tdataArray[ ii + 3 ] = 1.0;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( itemSize >= 4 ) {\r\n\r\n\t\t\t\tdataArray[ ii + 3 ] = attr.getW( i ) / normalizeValue;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tthis.internalFormat = internalFormat;\r\n\t\tthis.format = format;\r\n\t\tthis.type = type;\r\n\t\tthis.image.width = dimension;\r\n\t\tthis.image.height = dimension;\r\n\t\tthis.image.data = dataArray;\r\n\t\tthis.needsUpdate = true;\r\n\r\n\t\tattr.itemSize = originalItemSize;\r\n\t\tattr.count = originalCount;\r\n\r\n\t}\r\n\r\n}\r\n\r\nexport class UIntVertexAttributeTexture extends VertexAttributeTexture {\r\n\r\n\tconstructor() {\r\n\r\n\t\tsuper();\r\n\t\tthis._forcedType = UnsignedIntType;\r\n\r\n\t}\r\n\r\n}\r\n\r\nexport class IntVertexAttributeTexture extends VertexAttributeTexture {\r\n\r\n\tconstructor() {\r\n\r\n\t\tsuper();\r\n\t\tthis._forcedType = IntType;\r\n\r\n\t}\r\n\r\n\r\n}\r\n\r\nexport class FloatVertexAttributeTexture extends VertexAttributeTexture {\r\n\r\n\tconstructor() {\r\n\r\n\t\tsuper();\r\n\t\tthis._forcedType = FloatType;\r\n\r\n\t}\r\n\r\n}\r\n","import {\r\n\tDataTexture,\r\n\tFloatType,\r\n\tUnsignedIntType,\r\n\tRGBAFormat,\r\n\tRGIntegerFormat,\r\n\tNearestFilter,\r\n} from 'three';\r\nimport {\r\n\tFloatVertexAttributeTexture,\r\n\tUIntVertexAttributeTexture,\r\n} from './VertexAttributeTexture.js';\r\nimport { BYTES_PER_NODE } from '../core/Constants.js';\r\nimport {\r\n\tBOUNDING_DATA_INDEX,\r\n\tCOUNT,\r\n\tIS_LEAF,\r\n\tRIGHT_NODE,\r\n\tOFFSET,\r\n\tSPLIT_AXIS,\r\n} from '../core/nodeBufferFunctions.js';\r\n\r\nfunction bvhToTextures( bvh, boundsTexture, contentsTexture ) {\r\n\r\n\tconst roots = bvh._roots;\r\n\r\n\tif ( roots.length !== 1 ) {\r\n\r\n\t\tthrow new Error( 'MeshBVHUniformStruct: Multi-root BVHs not supported.' );\r\n\r\n\t}\r\n\r\n\tconst root = roots[ 0 ];\r\n\tconst uint16Array = new Uint16Array( root );\r\n\tconst uint32Array = new Uint32Array( root );\r\n\tconst float32Array = new Float32Array( root );\r\n\r\n\t// Both bounds need two elements per node so compute the height so it's twice as long as\r\n\t// the width so we can expand the row by two and still have a square texture\r\n\tconst nodeCount = root.byteLength / BYTES_PER_NODE;\r\n\tconst boundsDimension = 2 * Math.ceil( Math.sqrt( nodeCount / 2 ) );\r\n\tconst boundsArray = new Float32Array( 4 * boundsDimension * boundsDimension );\r\n\r\n\tconst contentsDimension = Math.ceil( Math.sqrt( nodeCount ) );\r\n\tconst contentsArray = new Uint32Array( 2 * contentsDimension * contentsDimension );\r\n\r\n\tfor ( let i = 0; i < nodeCount; i ++ ) {\r\n\r\n\t\tconst nodeIndex32 = i * BYTES_PER_NODE / 4;\r\n\t\tconst nodeIndex16 = nodeIndex32 * 2;\r\n\t\tconst boundsIndex = BOUNDING_DATA_INDEX( nodeIndex32 );\r\n\t\tfor ( let b = 0; b < 3; b ++ ) {\r\n\r\n\t\t\tboundsArray[ 8 * i + 0 + b ] = float32Array[ boundsIndex + 0 + b ];\r\n\t\t\tboundsArray[ 8 * i + 4 + b ] = float32Array[ boundsIndex + 3 + b ];\r\n\r\n\t\t}\r\n\r\n\t\tif ( IS_LEAF( nodeIndex16, uint16Array ) ) {\r\n\r\n\t\t\tconst count = COUNT( nodeIndex16, uint16Array );\r\n\t\t\tconst offset = OFFSET( nodeIndex32, uint32Array );\r\n\r\n\t\t\tconst mergedLeafCount = 0xffff0000 | count;\r\n\t\t\tcontentsArray[ i * 2 + 0 ] = mergedLeafCount;\r\n\t\t\tcontentsArray[ i * 2 + 1 ] = offset;\r\n\r\n\t\t} else {\r\n\r\n\t\t\tconst rightIndex = 4 * RIGHT_NODE( nodeIndex32, uint32Array ) / BYTES_PER_NODE;\r\n\t\t\tconst splitAxis = SPLIT_AXIS( nodeIndex32, uint32Array );\r\n\r\n\t\t\tcontentsArray[ i * 2 + 0 ] = splitAxis;\r\n\t\t\tcontentsArray[ i * 2 + 1 ] = rightIndex;\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tboundsTexture.image.data = boundsArray;\r\n\tboundsTexture.image.width = boundsDimension;\r\n\tboundsTexture.image.height = boundsDimension;\r\n\tboundsTexture.format = RGBAFormat;\r\n\tboundsTexture.type = FloatType;\r\n\tboundsTexture.internalFormat = 'RGBA32F';\r\n\tboundsTexture.minFilter = NearestFilter;\r\n\tboundsTexture.magFilter = NearestFilter;\r\n\tboundsTexture.generateMipmaps = false;\r\n\tboundsTexture.needsUpdate = true;\r\n\r\n\tcontentsTexture.image.data = contentsArray;\r\n\tcontentsTexture.image.width = contentsDimension;\r\n\tcontentsTexture.image.height = contentsDimension;\r\n\tcontentsTexture.format = RGIntegerFormat;\r\n\tcontentsTexture.type = UnsignedIntType;\r\n\tcontentsTexture.internalFormat = 'RG32UI';\r\n\tcontentsTexture.minFilter = NearestFilter;\r\n\tcontentsTexture.magFilter = NearestFilter;\r\n\tcontentsTexture.generateMipmaps = false;\r\n\tcontentsTexture.needsUpdate = true;\r\n\r\n}\r\n\r\nexport class MeshBVHUniformStruct {\r\n\r\n\tconstructor() {\r\n\r\n\t\tthis.autoDispose = true;\r\n\t\tthis.index = new UIntVertexAttributeTexture();\r\n\t\tthis.position = new FloatVertexAttributeTexture();\r\n\t\tthis.bvhBounds = new DataTexture();\r\n\t\tthis.bvhContents = new DataTexture();\r\n\r\n\t\tthis.index.overrideItemSize = 3;\r\n\r\n\t}\r\n\r\n\tupdateFrom( bvh ) {\r\n\r\n\t\tconst { geometry } = bvh;\r\n\r\n\t\tbvhToTextures( bvh, this.bvhBounds, this.bvhContents );\r\n\r\n\t\tthis.index.updateFrom( geometry.index );\r\n\t\tthis.position.updateFrom( geometry.attributes.position );\r\n\r\n\t}\r\n\r\n\tdispose() {\r\n\r\n\t\tconst { index, position, bvhBounds, bvhContents } = this;\r\n\r\n\t\tif ( index ) index.dispose();\r\n\t\tif ( position ) position.dispose();\r\n\t\tif ( bvhBounds ) bvhBounds.dispose();\r\n\t\tif ( bvhContents ) bvhContents.dispose();\r\n\r\n\t}\r\n\r\n}\r\n","export const shaderStructs = /* glsl */`\r\n#ifndef TRI_INTERSECT_EPSILON\r\n#define TRI_INTERSECT_EPSILON 1e-5\r\n#endif\r\n\r\n#ifndef INFINITY\r\n#define INFINITY 1e20\r\n#endif\r\n\r\nstruct BVH {\r\n\r\n\tusampler2D index;\r\n\tsampler2D position;\r\n\r\n\tsampler2D bvhBounds;\r\n\tusampler2D bvhContents;\r\n\r\n};\r\n\r\n// Note that a struct cannot be used for the hit record including faceIndices, faceNormal, barycoord,\r\n// side, and dist because on some mobile GPUS (such as Adreno) numbers are afforded less precision specifically\r\n// when in a struct leading to inaccurate hit results. See KhronosGroup/WebGL#3351 for more details.\r\n`;\r\n\r\nexport const shaderIntersectFunction = /* glsl */`\r\n\r\nuvec4 uTexelFetch1D( usampler2D tex, uint index ) {\r\n\r\n\tuint width = uint( textureSize( tex, 0 ).x );\r\n\tuvec2 uv;\r\n\tuv.x = index % width;\r\n\tuv.y = index / width;\r\n\r\n\treturn texelFetch( tex, ivec2( uv ), 0 );\r\n\r\n}\r\n\r\nivec4 iTexelFetch1D( isampler2D tex, uint index ) {\r\n\r\n\tuint width = uint( textureSize( tex, 0 ).x );\r\n\tuvec2 uv;\r\n\tuv.x = index % width;\r\n\tuv.y = index / width;\r\n\r\n\treturn texelFetch( tex, ivec2( uv ), 0 );\r\n\r\n}\r\n\r\nvec4 texelFetch1D( sampler2D tex, uint index ) {\r\n\r\n\tuint width = uint( textureSize( tex, 0 ).x );\r\n\tuvec2 uv;\r\n\tuv.x = index % width;\r\n\tuv.y = index / width;\r\n\r\n\treturn texelFetch( tex, ivec2( uv ), 0 );\r\n\r\n}\r\n\r\nvec4 textureSampleBarycoord( sampler2D tex, vec3 barycoord, uvec3 faceIndices ) {\r\n\r\n\treturn\r\n\t\tbarycoord.x * texelFetch1D( tex, faceIndices.x ) +\r\n\t\tbarycoord.y * texelFetch1D( tex, faceIndices.y ) +\r\n\t\tbarycoord.z * texelFetch1D( tex, faceIndices.z );\r\n\r\n}\r\n\r\nvoid ndcToCameraRay(\r\n\tvec2 coord, mat4 cameraWorld, mat4 invProjectionMatrix,\r\n\tout vec3 rayOrigin, out vec3 rayDirection\r\n) {\r\n\r\n\t// get camera look direction and near plane for camera clipping\r\n\tvec4 lookDirection = cameraWorld * vec4( 0.0, 0.0, - 1.0, 0.0 );\r\n\tvec4 nearVector = invProjectionMatrix * vec4( 0.0, 0.0, - 1.0, 1.0 );\r\n\tfloat near = abs( nearVector.z / nearVector.w );\r\n\r\n\t// get the camera direction and position from camera matrices\r\n\tvec4 origin = cameraWorld * vec4( 0.0, 0.0, 0.0, 1.0 );\r\n\tvec4 direction = invProjectionMatrix * vec4( coord, 0.5, 1.0 );\r\n\tdirection /= direction.w;\r\n\tdirection = cameraWorld * direction - origin;\r\n\r\n\t// slide the origin along the ray until it sits at the near clip plane position\r\n\torigin.xyz += direction.xyz * near / dot( direction, lookDirection );\r\n\r\n\trayOrigin = origin.xyz;\r\n\trayDirection = direction.xyz;\r\n\r\n}\r\n\r\nfloat intersectsBounds( vec3 rayOrigin, vec3 rayDirection, vec3 boundsMin, vec3 boundsMax ) {\r\n\r\n\t// https://www.reddit.com/r/opengl/comments/8ntzz5/fast_glsl_ray_box_intersection/\r\n\t// https://tavianator.com/2011/ray_box.html\r\n\tvec3 invDir = 1.0 / rayDirection;\r\n\r\n\t// find intersection distances for each plane\r\n\tvec3 tMinPlane = invDir * ( boundsMin - rayOrigin );\r\n\tvec3 tMaxPlane = invDir * ( boundsMax - rayOrigin );\r\n\r\n\t// get the min and max distances from each intersection\r\n\tvec3 tMinHit = min( tMaxPlane, tMinPlane );\r\n\tvec3 tMaxHit = max( tMaxPlane, tMinPlane );\r\n\r\n\t// get the furthest hit distance\r\n\tvec2 t = max( tMinHit.xx, tMinHit.yz );\r\n\tfloat t0 = max( t.x, t.y );\r\n\r\n\t// get the minimum hit distance\r\n\tt = min( tMaxHit.xx, tMaxHit.yz );\r\n\tfloat t1 = min( t.x, t.y );\r\n\r\n\t// set distance to 0.0 if the ray starts inside the box\r\n\tfloat dist = max( t0, 0.0 );\r\n\r\n\treturn t1 >= dist ? dist : INFINITY;\r\n\r\n}\r\n\r\nbool intersectsTriangle(\r\n\tvec3 rayOrigin, vec3 rayDirection, vec3 a, vec3 b, vec3 c,\r\n\tout vec3 barycoord, out vec3 norm, out float dist, out float side\r\n) {\r\n\r\n\t// https://stackoverflow.com/questions/42740765/intersection-between-line-and-triangle-in-3d\r\n\tvec3 edge1 = b - a;\r\n\tvec3 edge2 = c - a;\r\n\tnorm = cross( edge1, edge2 );\r\n\r\n\tfloat det = - dot( rayDirection, norm );\r\n\tfloat invdet = 1.0 / det;\r\n\r\n\tvec3 AO = rayOrigin - a;\r\n\tvec3 DAO = cross( AO, rayDirection );\r\n\r\n\tvec4 uvt;\r\n\tuvt.x = dot( edge2, DAO ) * invdet;\r\n\tuvt.y = - dot( edge1, DAO ) * invdet;\r\n\tuvt.z = dot( AO, norm ) * invdet;\r\n\tuvt.w = 1.0 - uvt.x - uvt.y;\r\n\r\n\t// set the hit information\r\n\tbarycoord = uvt.wxy; // arranged in A, B, C order\r\n\tdist = uvt.z;\r\n\tside = sign( det );\r\n\tnorm = side * normalize( norm );\r\n\r\n\t// add an epsilon to avoid misses between triangles\r\n\tuvt += vec4( TRI_INTERSECT_EPSILON );\r\n\r\n\treturn all( greaterThanEqual( uvt, vec4( 0.0 ) ) );\r\n\r\n}\r\n\r\nbool intersectTriangles(\r\n\tBVH bvh, vec3 rayOrigin, vec3 rayDirection, uint offset, uint count,\r\n\tinout float minDistance,\r\n\r\n\t// output variables\r\n\tout uvec4 faceIndices, out vec3 faceNormal, out vec3 barycoord,\r\n\tout float side, out float dist\r\n) {\r\n\r\n\tbool found = false;\r\n\tvec3 localBarycoord, localNormal;\r\n\tfloat localDist, localSide;\r\n\tfor ( uint i = offset, l = offset + count; i < l; i ++ ) {\r\n\r\n\t\tuvec3 indices = uTexelFetch1D( bvh.index, i ).xyz;\r\n\t\tvec3 a = texelFetch1D( bvh.position, indices.x ).rgb;\r\n\t\tvec3 b = texelFetch1D( bvh.position, indices.y ).rgb;\r\n\t\tvec3 c = texelFetch1D( bvh.position, indices.z ).rgb;\r\n\r\n\t\tif (\r\n\t\t\tintersectsTriangle( rayOrigin, rayDirection, a, b, c, localBarycoord, localNormal, localDist, localSide )\r\n\t\t\t&& localDist < minDistance\r\n\t\t) {\r\n\r\n\t\t\tfound = true;\r\n\t\t\tminDistance = localDist;\r\n\r\n\t\t\tfaceIndices = uvec4( indices.xyz, i );\r\n\t\t\tfaceNormal = localNormal;\r\n\r\n\t\t\tside = localSide;\r\n\t\t\tbarycoord = localBarycoord;\r\n\t\t\tdist = localDist;\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\treturn found;\r\n\r\n}\r\n\r\nfloat intersectsBVHNodeBounds( vec3 rayOrigin, vec3 rayDirection, BVH bvh, uint currNodeIndex ) {\r\n\r\n\tvec3 boundsMin = texelFetch1D( bvh.bvhBounds, currNodeIndex * 2u + 0u ).xyz;\r\n\tvec3 boundsMax = texelFetch1D( bvh.bvhBounds, currNodeIndex * 2u + 1u ).xyz;\r\n\treturn intersectsBounds( rayOrigin, rayDirection, boundsMin, boundsMax );\r\n\r\n}\r\n\r\nbool bvhIntersectFirstHit(\r\n\tBVH bvh, vec3 rayOrigin, vec3 rayDirection,\r\n\r\n\t// output variables\r\n\tout uvec4 faceIndices, out vec3 faceNormal, out vec3 barycoord,\r\n\tout float side, out float dist\r\n) {\r\n\r\n\t// stack needs to be twice as long as the deepest tree we expect because\r\n\t// we push both the left and right child onto the stack every traversal\r\n\tint ptr = 0;\r\n\tuint stack[ 60 ];\r\n\tstack[ 0 ] = 0u;\r\n\r\n\tfloat triangleDistance = 1e20;\r\n\tbool found = false;\r\n\twhile ( ptr > - 1 && ptr < 60 ) {\r\n\r\n\t\tuint currNodeIndex = stack[ ptr ];\r\n\t\tptr --;\r\n\r\n\t\t// check if we intersect the current bounds\r\n\t\tfloat boundsHitDistance = intersectsBVHNodeBounds( rayOrigin, rayDirection, bvh, currNodeIndex );\r\n\t\tif ( boundsHitDistance == INFINITY || boundsHitDistance > triangleDistance ) {\r\n\r\n\t\t\tcontinue;\r\n\r\n\t\t}\r\n\r\n\t\tuvec2 boundsInfo = uTexelFetch1D( bvh.bvhContents, currNodeIndex ).xy;\r\n\t\tbool isLeaf = bool( boundsInfo.x & 0xffff0000u );\r\n\r\n\t\tif ( isLeaf ) {\r\n\r\n\t\t\tuint count = boundsInfo.x & 0x0000ffffu;\r\n\t\t\tuint offset = boundsInfo.y;\r\n\r\n\t\t\tfound = intersectTriangles(\r\n\t\t\t\tbvh, rayOrigin, rayDirection, offset, count, triangleDistance,\r\n\t\t\t\tfaceIndices, faceNormal, barycoord, side, dist\r\n\t\t\t) || found;\r\n\r\n\t\t} else {\r\n\r\n\t\t\tuint leftIndex = currNodeIndex + 1u;\r\n\t\t\tuint splitAxis = boundsInfo.x & 0x0000ffffu;\r\n\t\t\tuint rightIndex = boundsInfo.y;\r\n\r\n\t\t\tbool leftToRight = rayDirection[ splitAxis ] >= 0.0;\r\n\t\t\tuint c1 = leftToRight ? leftIndex : rightIndex;\r\n\t\t\tuint c2 = leftToRight ? rightIndex : leftIndex;\r\n\r\n\t\t\t// set c2 in the stack so we traverse it later. We need to keep track of a pointer in\r\n\t\t\t// the stack while we traverse. The second pointer added is the one that will be\r\n\t\t\t// traversed first\r\n\t\t\tptr ++;\r\n\t\t\tstack[ ptr ] = c2;\r\n\r\n\t\t\tptr ++;\r\n\t\t\tstack[ ptr ] = c1;\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\treturn found;\r\n\r\n}\r\n\r\n`;\r\n"],"names":["boundingBox"],"mappings":"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AAC,OAAO,EAAE,CAAC;AAC/B,EAAE,KAAK,QAAQ,GAAG,QAAQ,CAAC,OAAO,EAAE,CAAC;AACrC,EAAE,KAAK,SAAS,GAAG,SAAS,CAAC,OAAO,EAAE,CAAC;AACvC,EAAE,KAAK,WAAW,GAAG,WAAW,CAAC,OAAO,EAAE,CAAC;AAC3C;AACA,EAAE;AACF;AACA;;AC3IY,MAAC,aAAa,aAAa,CAAC;AACxC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAE;AACF;AACY,MAAC,uBAAuB,aAAa,CAAC;AAClD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;"}
\ No newline at end of file
diff --git a/three-triangle-intersection.js b/three-triangle-intersection.js
deleted file mode 100644
index 90e2422..0000000
--- a/three-triangle-intersection.js
+++ /dev/null
@@ -1,570 +0,0 @@
-import { Vector2, Vector3 } from 'three';
-const _v1 = new Vector3();
-const _v2 = new Vector3();
-const _v3 = new Vector3();
-
-// https://github.com/benardp/contours/blob/master/freestyle/view_map/triangle_triangle_intersection.c
-function triangleIntersectsTriangle(triangleA, triangleB, additions = { coplanar: false, source: new Vector3(), target: new Vector3() }) {
- let p1 = triangleA.a;
- let q1 = triangleA.b;
- let r1 = triangleA.c;
-
- let p2 = triangleB.a;
- let q2 = triangleB.b;
- let r2 = triangleB.c;
-
- // Compute distance signs of p1, q1 and r1
- // to the plane of triangleB (p2,q2,r2)
-
- // _v1.copy(triangleB.a).sub(triangleB.c);
- // _v2.copy(triangleB.b).sub(triangleB.c);
- _v1.copy(p2).sub(r2);
- _v2.copy(q2).sub(r2);
- let N2 = (new Vector3()).copy(_v1).cross(_v2);
-
- _v1.copy(p1).sub(r2);
- let dp1 = _v1.dot(N2);
- _v1.copy(q1).sub(r2);
- let dq1 = _v1.dot(N2);
- _v1.copy(r1).sub(r2);
- let dr1 = _v1.dot(N2);
-
- if (((dp1 * dq1) > 0) && ((dp1 * dr1) > 0)) {
- // console.log("test 1 out");
- return false;
- }
-
- // Compute distance signs of p2, q2 and r2
- // to the plane of triangleA (p1,q1,r1)
- _v1.copy(q1).sub(p1);
- _v2.copy(r1).sub(p1);
- let N1 = (new Vector3()).copy(_v1).cross(_v2);
-
- _v1.copy(p2).sub(r1);
- let dp2 = _v1.dot(N1);
- _v1.copy(q2).sub(r1);
- let dq2 = _v1.dot(N1);
- _v1.copy(r2).sub(r1);
- let dr2 = _v1.dot(N1);
-
- if (((dp2 * dq2) > 0) & ((dp2 * dr2) > 0)) {
- // console.log("test 2 out");
- return false;
- }
-
-
- // test
- // if (zero_test(dp1) || zero_test(dq1) || zero_test(dr1) || zero_test(dp2) || zero_test(dq2) || zero_test(dr2)) {
- // additions.coplanar = 1;
- // return false;
- // }
-
- additions.N2 = N2;
- additions.N1 = N1;
-
- if (dp1 > 0) {
- if (dq1 > 0) {
- return tri_tri_intersection(r1, p1, q1, p2, r2, q2, dp2, dr2, dq2, additions);
- }
- else if (dr1 > 0) {
- return tri_tri_intersection(q1, r1, p1, p2, r2, q2, dp2, dr2, dq2, additions);
- }
- else {
- return tri_tri_intersection(p1, q1, r1, p2, q2, r2, dp2, dq2, dr2, additions);
- }
- }
- else if (dp1 < 0) {
- if (dq1 < 0) {
- return tri_tri_intersection(r1, p1, q1, p2, q2, r2, dp2, dq2, dr2, additions);
- }
- else if (dr1 < 0) {
- return tri_tri_intersection(q1, r1, p1, p2, q2, r2, dp2, dq2, dr2, additions);
- }
- else {
- return tri_tri_intersection(p1, q1, r1, p2, r2, q2, dp2, dr2, dq2, additions);
- }
- }
- else {
- if (dq1 < 0) {
- if (dr1 >= 0) {
- return tri_tri_intersection(q1, r1, p1, p2, r2, q2, dp2, dr2, dq2, additions);
- }
- else {
- return tri_tri_intersection(p1, q1, r1, p2, q2, r2, dp2, dq2, dr2, additions);
- }
- }
- else if (dq1 > 0) {
- if (dr1 > 0) {
- return tri_tri_intersection(p1, q1, r1, p2, r2, q2, dp2, dr2, dq2, additions);
- }
- else {
- return tri_tri_intersection(q1, r1, p1, p2, q2, r2, dp2, dq2, dr2, additions);
- }
- }
- else {
- if (dr1 > 0) {
- return tri_tri_intersection(r1, p1, q1, p2, q2, r2, dp2, dq2, dr2, additions);
- }
- else if (dr1 < 0) {
- return tri_tri_intersection(r1, p1, q1, p2, r2, q2, dp2, dr2, dq2, additions);
- }
- else {
- // triangles are co-planar
- additions.coplanar = true;
- return coplanar_tri_tri3d(p1, q1, r1, p2, q2, r2, N1, N2);
- }
- }
- }
-
-
-}
-
-function zero_test(x) {
- return (x == 0);
-}
-function tri_tri_intersection(p1, q1, r1, p2, q2, r2, dp2, dq2, dr2, additions) {
- if (dp2 > 0) {
- if (dq2 > 0) {
- return construct_intersection(p1, r1, q1, r2, p2, q2, additions);
- }
- else if (dr2 > 0) {
- return construct_intersection(p1, r1, q1, q2, r2, p2, additions);
- }
- else {
- return construct_intersection(p1, q1, r1, p2, q2, r2, additions);
- }
- }
- else if (dp2 < 0) {
- if (dq2 < 0) {
- return construct_intersection(p1, q1, r1, r2, p2, q2, additions);
- }
- else if (dr2 < 0) {
- return construct_intersection(p1, q1, r1, q2, r2, p2, additions);
- }
- else {
- return construct_intersection(p1, r1, q1, p2, q2, r2, additions);
- }
- }
- else {
- if (dq2 < 0) {
- if (dr2 >= 0) {
- return construct_intersection(p1, r1, q1, q2, r2, p2, additions);
- }
- else {
- return construct_intersection(p1, q1, r1, p2, q2, r2, additions);
- }
- }
- else if (dq2 > 0) {
- if (dr2 > 0) {
- return construct_intersection(p1, r1, q1, p2, q2, r2, additions);
- }
- else {
- return construct_intersection(p1, q1, r1, q2, r2, p2, additions);
- }
- }
- else {
- if (dr2 > 0) {
- return construct_intersection(p1, q1, r1, r2, p2, q2, additions);
- }
- else if (dr2 < 0) {
- return construct_intersection(p1, r1, q1, r2, p2, q2, additions);
- }
- else {
- additions.coplanar = true;
- // return coplanar_tri_tri3d(p1, q1, r1, p2, q2, r2, additions);
- return coplanar_tri_tri3d(p1, q1, r1, p2, q2, r2, additions.N1, additions.N2);
- }
- }
- }
-}
-
-function coplanar_tri_tri3d(p1, q1, r1, p2, q2, r2, normal_1, normal_2) {
- let P1 = new Vector2(), Q1 = new Vector2(), R1 = new Vector2();
- let P2 = new Vector2(), Q2 = new Vector2(), R2 = new Vector2();
- let n_x, n_y, n_z;
-
- n_x = normal_1.x < 0 ? -normal_1.x : normal_1.x;
- n_y = normal_1.y < 0 ? -normal_1.y : normal_1.y;
- n_z = normal_1.z < 0 ? -normal_1.z : normal_1.z;
-
- /* Projection of the triangles in 3D onto 2D such that the area of
- the projection is maximized. */
-
- if ((n_x > n_z) && (n_x >= n_y)) { // Project onto plane YZ
- P1.x = q1.z, P1.y = q1.y;
- Q1.x = p1.z, Q1.y = p1.y;
- R1.x = r1.z, R1.y = r1.y;
-
- P2.x = q2.z, P2.y = q2.y;
- Q2.x = p2.z, Q2.y = p2.y;
- R2.x = r2.z, R2.y = r2.y;
- }
- else if ((n_y > n_z) && (n_y >= n_x)) { // Project onto plane XZ
- P1.x = q1.x, P1.y = q1.z;
- Q1.x = p1.x, Q1.y = p1.z;
- R1.x = r1.x, R1.y = r1.z;
-
- P2.x = q2.x, P2.y = q2.z;
- Q2.x = p2.x, Q2.y = p2.z;
- R2.x = r2.x, R2.y = r2.z;
- }
- else { // Project onto plane XY
- P1.x = p1.x, P1.y = p1.y;
- Q1.x = q1.x, Q1.y = q1.y;
- R1.x = r1.x, R1.y = r1.y;
-
- P2.x = p2.x, P2.y = p2.y;
- Q2.x = q2.x, Q2.y = q2.y;
- R2.x = r2.x, R2.y = r2.y;
- }
-
- return tri_tri_overlap_test_2d(P1, Q1, R1, P2, Q2, R2);
-
-}
-
-function tri_tri_overlap_test_2d(p1, q1, r1, p2, q2, r2) {
- if (ORIENT_2D(p1, q1, r1) < 0) {
- if (ORIENT_2D(p2, q2, r2) < 0) {
- return ccw_tri_tri_intersection_2d(p1, r1, q1, p2, r2, q2);
- }
- else {
- return ccw_tri_tri_intersection_2d(p1, r1, q1, p2, q2, r2);
- }
- }
- else {
- if (ORIENT_2D(p2, q2, r2) < 0) {
- return ccw_tri_tri_intersection_2d(p1, q1, r1, p2, r2, q2);
- }
- else {
- return ccw_tri_tri_intersection_2d(p1, q1, r1, p2, q2, r2);
- }
- }
-}
-
-function ORIENT_2D(a, b, c) {
- return ((a.x - c.x) * (b.y - c.y) - (a.y - c.y) * (b.x - c.y));
-}
-
-function ccw_tri_tri_intersection_2d(p1, q1, r1, p2, q2, r2) {
- if (ORIENT_2D(p2, q2, p1) >= 0) {
- if (ORIENT_2D(q2, r2, p1) >= 0) {
- if (ORIENT_2D(r2, p2, p1) >= 0) {
- return true;
- }
- else {
- return intersection_test_edge(p1, q1, r1, p2, q2, r2);
- }
- }
- else {
- if (ORIENT_2D(r2, p2, p1) >= 0) {
- return intersection_test_edge(p1, q1, r1, r2, p2, q2);
- }
- else {
- return intersection_test_vertex(p1, q1, r1, p2, q2, r2)
- }
- }
- }
- else {
- if (ORIENT_2D(q2, r2, p1) >= 0) {
- if (ORIENT_2D(r2, p2, p1) >= 0) {
- return intersection_test_edge(p1, q1, r2, q2, r2, p2);
- }
- else {
- return intersection_test_vertex(p1, q1, r1, q2, r2, p2);
- }
- }
- else {
- return intersection_test_vertex(p1, q1, r1, r2, p2, q2);
- }
- }
-}
-
-function intersection_test_edge(P1, Q1, R1, P2, Q2, R2) {
- if (ORIENT_2D(R2, P2, Q1) >= 0) {
- if (ORIENT_2D(P1, P2, Q1) >= 0) {
- if (ORIENT_2D(P1, Q1, R2) >= 0) {
- return true;
- }
- else {
- return false;
- }
- }
- else {
- if (ORIENT_2D(Q1, R1, P2) >= 0) {
- if (ORIENT_2D(R1, P1, P2) >= 0) {
- return true;
- }
- else {
- return false;
- }
- }
- else {
- return false;
- }
- }
- } else {
- if (ORIENT_2D(R2, P2, R1) >= 0) {
- if (ORIENT_2D(P1, P2, R1) >= 0) {
- if (ORIENT_2D(P1, R1, R2) >= 0) {
- return true;
- }
- else {
- if (ORIENT_2D(Q1, R1, R2) >= 0) {
- return true;
- }
- else {
- return false;
- }
- }
- }
- else {
- return false;
- }
- }
- else {
- return false;
- }
- }
-}
-
-function intersection_test_vertex(P1, Q1, R1, P2, Q2, R2) {
- if (ORIENT_2D(R2, P2, Q1) >= 0) {
- if (ORIENT_2D(R2, Q2, Q1) <= 0) {
- if (ORIENT_2D(P1, P2, Q1) > 0) {
- if (ORIENT_2D(P1, Q2, Q1) <= 0) {
- return true;
- }
- else {
- return false;
- }
- }
- else {
- if (ORIENT_2D(P1, P2, R1) >= 0) {
- if (ORIENT_2D(Q1, R1, P2) >= 0) {
- return true;
- }
- else {
- return false;
- }
- }
- else {
- return false;
- }
- }
- }
- else {
- if (ORIENT_2D(P1, Q2, Q1) <= 0) {
- if (ORIENT_2D(R2, Q2, R1) <= 0) {
- if (ORIENT_2D(Q1, R1, Q2) >= 0) {
- return true;
- }
- else {
- return false;
- }
- }
- else {
- return false;
- }
- }
- else {
- return false;
- }
- }
- }
- else {
- if (ORIENT_2D(R2, P2, R1) >= 0) {
- if (ORIENT_2D(Q1, R1, R2) >= 0) {
- if (ORIENT_2D(P1, P2, R1) >= 0) {
- return true;
- }
- else {
- return false;
- }
- }
- else {
- if (ORIENT_2D(Q1, R1, Q2) >= 0) {
- if (ORIENT_2D(R2, R1, Q2) >= 0) {
- return true;
- }
- else {
- return false;
- }
- }
- else {
- return false;
- }
- }
- }
- else {
- return false;
- }
- }
-};
-function construct_intersection(p1, q1, r1, p2, q2, r2, additions) {
- let alpha;
- let N = new Vector3();
- _v1.subVectors(q1, p1);
- _v2.subVectors(r2, p1);
- N.copy(_v1).cross(_v2);
- _v3.subVectors(p2, p1);
- if (_v3.dot(N) > 0) {
- _v1.subVectors(r1, p1);
- N.copy(_v1).cross(_v2);
- if (_v3.dot(N) <= 0) {
- _v2.subVectors(q2, p1);
- N.copy(_v1).cross(_v2);
- if (_v3.dot(N) > 0) {
- _v1.subVectors(p1, p2);
- _v2.subVectors(p1, r1);
- alpha = _v1.dot(additions.N2) / _v2.dot(additions.N2);
- _v1.copy(_v2).multiplyScalar(alpha);
- additions.source.subVectors(p1, _v1);
- _v1.subVectors(p2, p1);
- _v2.subVectors(p2, r2);
- alpha = _v1.dot(additions.N1) / _v2.dot(additions.N1);
- _v1.copy(_v2).multiplyScalar(alpha);
- additions.target.subVectors(p2, _v1);
- return true;
- }
- else {
- _v1.subVectors(p2, p1);
- _v2.subVectors(p2, q2);
- alpha = _v1.dot(additions.N1) / _v2.dot(additions.N1);
- _v1.copy(_v2).multiplyScalar(alpha);
- additions.source.subVectors(p2, _v1);
- _v1.subVectors(p2, p1);
- _v2.subVectors(p2, r2);
- alpha = _v1.dot(additions.N1) / _v2.dot(additions.N1);
- _v1.copy(_v2).multiplyScalar(alpha);
- additions.target.subVectors(p2, _v1);
- return true;
- }
- }
- else {
- return false;
- }
- }
- else {
- _v2.subVectors(q2, p1);
- N.copy(_v1).cross(_v2);
- if (_v3.dot(N) < 0) {
- return false;
- }
- else {
- _v1.subVectors(r1, p1);
- N.copy(_v1).cross(_v2);
- if (_v3.dot(N) >= 0) {
- _v1.subVectors(p1, p2);
- _v2.subVectors(p1, r1);
- alpha = _v1.dot(additions.N2) / _v2.dot(additions.N2);
- _v1.copy(_v2).multiplyScalar(alpha);
- additions.source.subVectors(p1, _v1);
- _v1.subVectors(p1, p2);
- _v2.subVectors(p1, q1);
- alpha = _v1.dot(additions.N2) / _v2.dot(additions.N2);
- _v1.copy(_v2).multiplyScalar(alpha);
- additions.target.subVectors(p1, _v1);
- return true;
- }
- else {
- _v1.subVectors(p2, p1);
- _v2.subVectors(p2, q2);
- alpha = _v1.dot(additions.N1) / _v2.dot(additions.N1);
- _v1.copy(_v2).multiplyScalar(alpha);
- additions.source.subVectors(p2, _v1);
- _v1.subVectors(p1, p2);
- _v2.subVectors(p1, q1);
- alpha = _v1.dot(additions.N2) / _v2.dot(additions.N2);
- _v1.copy(_v2).multiplyScalar(alpha);
- additions.target.subVectors(p1, _v1);
- return true;
- }
- }
- }
-}
-function pointOnLine(line, point) {
- let ab = _v1.copy(line.end).sub(line.start);
- let ac = _v2.copy(point).sub(line.start);
- let area = _v3.copy(ab).cross(ac).length();
- let CD = area / ab.length();
- return CD;
-}
-function lineIntersects(line1, line2, points) {
- const r = (new Vector3()).copy(line1.end).sub(line1.start);
- const s = (new Vector3()).copy(line2.end).sub(line2.start);
- const q = (new Vector3()).copy(line1.start).sub(line2.start);
- // const w = _v3.copy( line2.start ).sub( line1.start );
-
- let dotqr = q.dot(r);
- let dotqs = q.dot(s);
- let dotrs = r.dot(s);
- let dotrr = r.dot(r);
- let dotss = s.dot(s);
-
- let denom = (dotrr * dotss) - (dotrs * dotrs);
- let numer = (dotqs * dotrs) - (dotqr * dotss);
-
- let t = numer / denom;
- let u = (dotqs + t * dotrs) / dotss;
-
- let p0 = r.multiplyScalar(t).add(line1.start);
- let p1 = s.multiplyScalar(u).add(line2.start);
-
- let onSegment = false;
- let intersects = false;
-
- if ((0 <= t) && (t <= 1) && (0<= u) && (u<=1)) {
- onSegment = true;
- }
- let p0p1Length = _v1.copy(p0).sub(p1).length();
- if (p0p1Length <= 1e-5) {
- intersects = true;
- }
- // console.log("lineIntersects?", intersects, onSegment, p0, p1, denom, numer, t, u);
- if (!(intersects && onSegment)) {
- // return [];
- return false;
- }
- points && points.push(p0, p1);
- // return [p0, p1];
- return true;
-}
-function getLines(triangle) {
- return [
- { start: triangle.a, end: triangle.b },
- { start: triangle.b, end: triangle.c },
- { start: triangle.c, end: triangle.a }
- ];
-}
-
-function checkTrianglesIntersection(triangle1, triangle2, additions = { coplanar: false, source: new Vector3(), target: new Vector3() }) {
- // let additions = {
- // coplanar: false,
- // source: new Vector3(),
- // target: new Vector3()
- // };
- let triangleIntersects = triangleIntersectsTriangle(triangle1, triangle2, additions);
- // console.log("??? 1", triangleIntersects, additions);
- additions.triangleCheck = triangleIntersects;
- if (!triangleIntersects && additions.coplanar) {
- // console.log("check failed, checking lines");
- let triangle1Lines = getLines(triangle1);
- let triangle2Lines = getLines(triangle2);
- let intersects = false;
- for (let i = 0; i < 3; i++) {
- intersects = false;
- for (let j = 0; j < 3; j++) {
- intersects = lineIntersects(triangle1Lines[i], triangle2Lines[j]);
- if (intersects) {
- break;
- }
- }
- if (intersects) {
- break;
- }
- }
- return intersects;
- }
- return triangleIntersects;
-}
-export { triangleIntersectsTriangle, checkTrianglesIntersection, getLines, lineIntersects };
\ No newline at end of file