import {
  BackSide,
  Box3,
  BufferAttribute,
  BufferGeometry,
  ByteType,
  DataTexture,
  DoubleSide,
  FloatType,
  FrontSide,
  Group,
  IntType,
  Line3,
  LineBasicMaterial,
  Matrix3,
  Matrix4,
  Mesh,
  MeshBasicMaterial,
  NearestFilter,
  Object3D,
  Plane,
  RGBAFormat,
  RGBAIntegerFormat,
  RGFormat,
  RGIntegerFormat,
  Ray,
  RedFormat,
  RedIntegerFormat,
  ShortType,
  Sphere,
  Triangle,
  UnsignedByteType,
  UnsignedIntType,
  UnsignedShortType,
  Vector2,
  Vector3,
  Vector4
} from "./chunk-5JQWN2BK.js";
import "./chunk-CL4PTTKD.js";

// node_modules/three-mesh-bvh/src/core/Constants.js
var CENTER = 0;
var AVERAGE = 1;
var SAH = 2;
var NOT_INTERSECTED = 0;
var INTERSECTED = 1;
var CONTAINED = 2;
var TRIANGLE_INTERSECT_COST = 1.25;
var TRAVERSAL_COST = 1;
var BYTES_PER_NODE = 6 * 4 + 4 + 4;
var IS_LEAFNODE_FLAG = 65535;
var FLOAT32_EPSILON = Math.pow(2, -24);

// node_modules/three-mesh-bvh/src/core/MeshBVHNode.js
var MeshBVHNode = class {
  constructor() {
  }
};

// node_modules/three-mesh-bvh/src/utils/ArrayBoxUtilities.js
function arrayToBox(nodeIndex32, array, target) {
  target.min.x = array[nodeIndex32];
  target.min.y = array[nodeIndex32 + 1];
  target.min.z = array[nodeIndex32 + 2];
  target.max.x = array[nodeIndex32 + 3];
  target.max.y = array[nodeIndex32 + 4];
  target.max.z = array[nodeIndex32 + 5];
  return target;
}
function getLongestEdgeIndex(bounds) {
  let splitDimIdx = -1;
  let splitDist = -Infinity;
  for (let i = 0; i < 3; i++) {
    const dist = bounds[i + 3] - bounds[i];
    if (dist > splitDist) {
      splitDist = dist;
      splitDimIdx = i;
    }
  }
  return splitDimIdx;
}
function copyBounds(source, target) {
  target.set(source);
}
function unionBounds(a, b, target) {
  let aVal, bVal;
  for (let d = 0; d < 3; d++) {
    const d3 = d + 3;
    aVal = a[d];
    bVal = b[d];
    target[d] = aVal < bVal ? aVal : bVal;
    aVal = a[d3];
    bVal = b[d3];
    target[d3] = aVal > bVal ? aVal : bVal;
  }
}
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;
    }
  }
}
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);
}

// node_modules/three-mesh-bvh/src/core/buildFunctions.js
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;
    }
  }
}
function getRootIndexRanges(geo) {
  if (!geo.groups || !geo.groups.length) {
    return [{ offset: 0, count: geo.index.count / 3 }];
  }
  const ranges = [];
  const rangeBoundaries = /* @__PURE__ */ new Set();
  for (const group of geo.groups) {
    rangeBoundaries.add(group.start);
    rangeBoundaries.add(group.start + group.count);
  }
  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;
}
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;
  }
}
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;
}
function partition(index, triangleBounds, offset, count, split) {
  let left = offset;
  let right = offset + count - 1;
  const pos = split.pos;
  const axisOffset = split.axis * 2;
  while (true) {
    while (left <= right && triangleBounds[left * 6 + axisOffset] < pos) {
      left++;
    }
    while (left <= right && triangleBounds[right * 6 + axisOffset] >= pos) {
      right--;
    }
    if (left < right) {
      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;
    }
  }
}
var BIN_COUNT = 32;
var binsSort = (a, b) => a.candidate - b.candidate;
var sahBins = new Array(BIN_COUNT).fill().map(() => {
  return {
    count: 0,
    bounds: new Float32Array(6),
    rightCacheBounds: new Float32Array(6),
    leftCacheBounds: new Float32Array(6),
    candidate: 0
  };
});
var leftBounds = new Float32Array(6);
function getOptimalSplit(nodeBoundingData, centroidBoundingData, triangleBounds, offset, count, strategy) {
  let axis = -1;
  let pos = 0;
  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;
    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 (count < BIN_COUNT / 4) {
        const truncatedBins = [...sahBins];
        truncatedBins.length = count;
        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);
        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--;
          }
        }
        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++;
            }
          }
        }
        for (let bi = 0; bi < splitCount; bi++) {
          const bin = truncatedBins[bi];
          const leftCount = bin.count;
          const rightCount = count - bin.count;
          const leftBounds2 = bin.leftCacheBounds;
          const rightBounds = bin.rightCacheBounds;
          let leftProb = 0;
          if (leftCount !== 0) {
            leftProb = computeSurfaceArea(leftBounds2) / 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 {
        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;
          }
        }
        for (let c = cStart; c < cEnd; c += 6) {
          const triCenter = triangleBounds[c + 2 * a];
          const relativeCenter = triCenter - axisLeft;
          let binIndex = ~~(relativeCenter / binWidth);
          if (binIndex >= BIN_COUNT)
            binIndex = BIN_COUNT - 1;
          const bin = sahBins[binIndex];
          bin.count++;
          expandByTriangleBounds(c, triangleBounds, bin.bounds);
        }
        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;
          if (binCount !== 0) {
            if (leftCount === 0) {
              copyBounds(bounds, leftBounds);
            } else {
              unionBounds(bounds, leftBounds, leftBounds);
            }
          }
          leftCount += binCount;
          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 };
}
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;
}
function computeTriangleBounds(geo, fullBounds) {
  const posAttr = geo.attributes.position;
  const index = geo.index.array;
  const triCount = index.length / 3;
  const triangleBounds = new Float32Array(triCount * 6);
  const normalized = posAttr.normalized;
  const posArr = posAttr.array;
  const bufferOffset = posAttr.offset || 0;
  let stride = 3;
  if (posAttr.isInterleavedBufferAttribute) {
    stride = posAttr.data.stride;
  }
  const getters = ["getX", "getY", "getZ"];
  for (let tri = 0; tri < triCount; tri++) {
    const tri3 = tri * 3;
    const tri6 = tri * 6;
    let ai, bi, ci;
    if (normalized) {
      ai = index[tri3 + 0];
      bi = index[tri3 + 1];
      ci = index[tri3 + 2];
    } else {
      ai = index[tri3 + 0] * stride + bufferOffset;
      bi = index[tri3 + 1] * stride + bufferOffset;
      ci = index[tri3 + 2] * stride + bufferOffset;
    }
    for (let el = 0; el < 3; el++) {
      let a, b, c;
      if (normalized) {
        a = posAttr[getters[el]](ai);
        b = posAttr[getters[el]](bi);
        c = posAttr[getters[el]](ci);
      } else {
        a = posArr[ai + el];
        b = posArr[bi + el];
        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;
      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);
    }
  }
  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);
      }
    }
    if (count <= maxLeafTris || depth >= maxDepth) {
      triggerProgress(offset + count);
      node.offset = offset;
      node.count = count;
      return node;
    }
    const split = getOptimalSplit(node.boundingData, centroidBoundingData, triangleBounds, offset, count, strategy);
    if (split.axis === -1) {
      triggerProgress(offset + count);
      node.offset = offset;
      node.count = count;
      return node;
    }
    const splitOffset = partition(indexArray, triangleBounds, offset, count, split);
    if (splitOffset === offset || splitOffset === offset + count) {
      triggerProgress(offset + count);
      node.offset = offset;
      node.count = count;
    } else {
      node.splitAxis = split.axis;
      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);
      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);
  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) {
  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;
    }
  }
}

// node_modules/three-mesh-bvh/src/math/SeparatingAxisBounds.js
var SeparatingAxisBounds = class {
  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;
  };
}();
var areIntersecting = function() {
  const cacheSatBounds = new SeparatingAxisBounds();
  return function areIntersecting2(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;
    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;
    }
    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;
    }
  };
}();

// node_modules/three-mesh-bvh/src/math/MathUtilities.js
var closestPointLineToLine = function() {
  const dir1 = new Vector3();
  const dir2 = new Vector3();
  const v02 = new Vector3();
  return function closestPointLineToLine2(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, l1.start);
    dir2.subVectors(l2.end, l2.start);
    const d0232 = v02.dot(v32);
    const d3210 = v32.dot(v10);
    const d3232 = v32.dot(v32);
    const d0210 = v02.dot(v10);
    const d1010 = v10.dot(v10);
    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;
  };
}();
var closestPointsSegmentToSegment = function() {
  const paramResult = new Vector2();
  const temp12 = new Vector3();
  const temp22 = new Vector3();
  return function closestPointsSegmentToSegment2(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) {
      if (d2 < 0) {
        l2.at(0, target2);
      } else {
        l2.at(1, target2);
      }
      l1.closestPointToPoint(target2, true, target1);
      return;
    } else if (d2 >= 0 && d2 <= 1) {
      if (d < 0) {
        l1.at(0, target1);
      } else {
        l1.at(1, target1);
      }
      l2.closestPointToPoint(target1, true, target2);
      return;
    } else {
      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 = temp12;
      const closestPoint2 = temp22;
      l1.closestPointToPoint(p2, true, temp12);
      l2.closestPointToPoint(p, true, temp22);
      if (closestPoint.distanceToSquared(p2) <= closestPoint2.distanceToSquared(p)) {
        target1.copy(closestPoint);
        target2.copy(p2);
        return;
      } else {
        target1.copy(p);
        target2.copy(closestPoint2);
        return;
      }
    }
  };
}();
var sphereIntersectTriangle = function() {
  const closestPointTemp = new Vector3();
  const projectedPointTemp = new Vector3();
  const planeTemp = new Plane();
  const lineTemp = new Line3();
  return function sphereIntersectTriangle2(sphere, triangle) {
    const { radius, center } = sphere;
    const { a, b, c } = triangle;
    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;
    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;
  };
}();

// node_modules/three-mesh-bvh/src/math/ExtendedTriangle.js
var DIST_EPSILON = 1e-15;
function isNearZero(value) {
  return Math.abs(value) < DIST_EPSILON;
}
var ExtendedTriangle = class extends Triangle {
  constructor(...args) {
    super(...args);
    this.isExtendedTriangle = 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 = true;
  }
  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;
  }
};
ExtendedTriangle.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;
    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);
      }
    }
    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);
  };
}();
ExtendedTriangle.prototype.intersectsTriangle = function() {
  const saTri2 = new ExtendedTriangle();
  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();
  return function intersectsTriangle(other, target = null, suppressLog = false) {
    if (this.needsUpdate) {
      this.update();
    }
    if (!other.isExtendedTriangle) {
      saTri2.copy(other);
      saTri2.update();
      other = saTri2;
    } else if (other.needsUpdate) {
      other.update();
    }
    const plane1 = this.plane;
    const plane2 = other.plane;
    if (Math.abs(plane1.normal.dot(plane2.normal)) > 1 - 1e-10) {
      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;
      }
      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) {
        if (!suppressLog) {
          console.warn("ExtendedTriangle.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);
      }
      return true;
    } else {
      const points1 = this.points;
      let found1 = false;
      let count1 = 0;
      for (let i = 0; i < 3; i++) {
        const p = points1[i];
        const pNext = points1[(i + 1) % 3];
        edge.start.copy(p);
        edge.end.copy(pNext);
        edge.delta(dir1);
        const targetPoint = found1 ? edge1.start : edge1.end;
        const startIntersects = isNearZero(plane2.distanceToPoint(p));
        if (isNearZero(plane2.normal.dot(dir1)) && startIntersects) {
          edge1.copy(edge);
          count1 = 2;
          break;
        }
        const doesIntersect = plane2.intersectLine(edge, targetPoint) || startIntersects;
        if (doesIntersect && !isNearZero(targetPoint.distanceTo(pNext))) {
          count1++;
          if (found1) {
            break;
          }
          found1 = true;
        }
      }
      if (count1 === 1 && other.containsPoint(edge1.end)) {
        if (target) {
          target.start.copy(edge1.end);
          target.end.copy(edge1.end);
        }
        return true;
      } else if (count1 !== 2) {
        return false;
      }
      const points2 = other.points;
      let found2 = false;
      let count2 = 0;
      for (let i = 0; i < 3; i++) {
        const p = points2[i];
        const pNext = points2[(i + 1) % 3];
        edge.start.copy(p);
        edge.end.copy(pNext);
        edge.delta(dir2);
        const targetPoint = found2 ? edge2.start : edge2.end;
        const startIntersects = isNearZero(plane1.distanceToPoint(p));
        if (isNearZero(plane1.normal.dot(dir2)) && startIntersects) {
          edge2.copy(edge);
          count2 = 2;
          break;
        }
        const doesIntersect = plane1.intersectLine(edge, targetPoint) || startIntersects;
        if (doesIntersect && !isNearZero(targetPoint.distanceTo(pNext))) {
          count2++;
          if (found2) {
            break;
          }
          found2 = true;
        }
      }
      if (count2 === 1 && this.containsPoint(edge2.end)) {
        if (target) {
          target.start.copy(edge2.end);
          target.end.copy(edge2.end);
        }
        return true;
      } else if (count2 !== 2) {
        return false;
      }
      edge1.delta(dir1);
      edge2.delta(dir2);
      if (dir1.dot(dir2) < 0) {
        let tmp = edge2.start;
        edge2.start = edge2.end;
        edge2.end = tmp;
      }
      const s1 = edge1.start.dot(dir1);
      const e1 = edge1.end.dot(dir1);
      const s2 = edge2.start.dot(dir1);
      const e2 = edge2.end.dot(dir1);
      const separated1 = e1 < s2;
      const separated2 = s1 < e2;
      if (s1 !== e2 && s2 !== e1 && separated1 === separated2) {
        return false;
      }
      if (target) {
        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;
    }
  };
}();
ExtendedTriangle.prototype.distanceToPoint = function() {
  const target = new Vector3();
  return function distanceToPoint(point) {
    this.closestPointToPoint(point, target);
    return point.distanceTo(target);
  };
}();
ExtendedTriangle.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;
    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);
  };
}();

// node_modules/three-mesh-bvh/src/math/OrientedBox.js
var OrientedBox = class {
  constructor(min, max, matrix) {
    this.isOrientedBox = true;
    this.min = new Vector3();
    this.max = new Vector3();
    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;
    if (min)
      this.min.copy(min);
    if (max)
      this.max.copy(max);
    if (matrix)
      this.matrix.copy(matrix);
  }
  set(min, max, matrix) {
    this.min.copy(min);
    this.max.copy(max);
    this.matrix.copy(matrix);
    this.needsUpdate = true;
  }
  copy(other) {
    this.min.copy(other.min);
    this.max.copy(other.max);
    this.matrix.copy(other.matrix);
    this.needsUpdate = true;
  }
};
OrientedBox.prototype.update = /* @__PURE__ */ 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) {
    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 ExtendedTriangle();
  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.isExtendedTriangle) {
      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;
    }
    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 = /* @__PURE__ */ 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 xyzFields2 = ["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();
  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;
    let closestDistanceSq = Infinity;
    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);
      }
    }
    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;
          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);
          const f1 = xyzFields2[i];
          const f2 = xyzFields2[nextIndex];
          const f3 = xyzFields2[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++;
        }
      }
    }
    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);
  };
}();

// node_modules/three-mesh-bvh/src/utils/ThreeRayIntersectUtilities.js
var vA = /* @__PURE__ */ new Vector3();
var vB = /* @__PURE__ */ new Vector3();
var vC = /* @__PURE__ */ new Vector3();
var uvA = /* @__PURE__ */ new Vector2();
var uvB = /* @__PURE__ */ new Vector2();
var uvC = /* @__PURE__ */ new Vector2();
var intersectionPoint = /* @__PURE__ */ new Vector3();
function checkIntersection(ray2, pA, pB, pC, point, side) {
  let intersect;
  if (side === BackSide) {
    intersect = ray2.intersectTriangle(pC, pB, pA, true, point);
  } else {
    intersect = ray2.intersectTriangle(pA, pB, pC, side !== DoubleSide, point);
  }
  if (intersect === null)
    return null;
  const distance = ray2.origin.distanceTo(point);
  return {
    distance,
    point: point.clone()
  };
}
function checkBufferGeometryIntersection(ray2, position, uv, a, b, c, side) {
  vA.fromBufferAttribute(position, a);
  vB.fromBufferAttribute(position, b);
  vC.fromBufferAttribute(position, c);
  const intersection = checkIntersection(ray2, 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,
      b,
      c,
      normal: new Vector3(),
      materialIndex: 0
    };
    Triangle.getNormal(vA, vB, vC, face.normal);
    intersection.face = face;
    intersection.faceIndex = a;
  }
  return intersection;
}
function intersectTri(geo, side, ray2, 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(ray2, geo.attributes.position, geo.attributes.uv, a, b, c, side);
  if (intersection) {
    intersection.faceIndex = tri;
    if (intersections)
      intersections.push(intersection);
    return intersection;
  }
  return null;
}

// node_modules/three-mesh-bvh/src/utils/GeometryRayIntersectUtilities.js
function intersectTris(geo, side, ray2, offset, count, intersections) {
  for (let i = offset, end = offset + count; i < end; i++) {
    intersectTri(geo, side, ray2, i, intersections);
  }
}
function intersectClosestTri(geo, side, ray2, offset, count) {
  let dist = Infinity;
  let res = null;
  for (let i = offset, end = offset + count; i < end; i++) {
    const intersection = intersectTri(geo, side, ray2, i);
    if (intersection && intersection.distance < dist) {
      res = intersection;
      dist = intersection.distance;
    }
  }
  return res;
}
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;
  }
}

// node_modules/three-mesh-bvh/src/utils/TriangleUtilities.js
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;
}
var tempV1 = /* @__PURE__ */ new Vector3();
var tempV2 = /* @__PURE__ */ new Vector3();
var tempV3 = /* @__PURE__ */ new Vector3();
var tempUV1 = /* @__PURE__ */ new Vector2();
var tempUV2 = /* @__PURE__ */ new Vector2();
var 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);
  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;
    }
  }
  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);
  }
  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,
        b,
        c,
        materialIndex,
        normal: Triangle.getNormal(tempV1, tempV2, tempV3, new Vector3())
      },
      uv
    };
  }
}

// node_modules/three-mesh-bvh/src/utils/PrimitivePool.js
var PrimitivePool = class {
  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);
  }
};

// node_modules/three-mesh-bvh/src/core/nodeBufferFunctions.js
function IS_LEAF(n16, uint16Array) {
  return uint16Array[n16 + 15] === 65535;
}
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;
}

// node_modules/three-mesh-bvh/src/core/castFunctions.js
var boundingBox = new Box3();
var boxIntersection = new Vector3();
var xyzFields = ["x", "y", "z"];
function raycast(nodeIndex32, geometry, side, ray2, 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, ray2, offset, count, intersects);
  } else {
    const leftIndex = LEFT_NODE(nodeIndex32);
    if (intersectRay(leftIndex, float32Array, ray2, boxIntersection)) {
      raycast(leftIndex, geometry, side, ray2, intersects);
    }
    const rightIndex = RIGHT_NODE(nodeIndex32, uint32Array);
    if (intersectRay(rightIndex, float32Array, ray2, boxIntersection)) {
      raycast(rightIndex, geometry, side, ray2, intersects);
    }
  }
}
function raycastFirst(nodeIndex32, geometry, side, ray2) {
  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, ray2, offset, count);
  } else {
    const splitAxis = SPLIT_AXIS(nodeIndex32, uint32Array);
    const xyzAxis = xyzFields[splitAxis];
    const rayDir = ray2.direction[xyzAxis];
    const leftToRight = rayDir >= 0;
    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, ray2, boxIntersection);
    const c1Result = c1Intersection ? raycastFirst(c1, geometry, side, ray2) : null;
    if (c1Result) {
      const point = c1Result.point[xyzAxis];
      const isOutside = leftToRight ? point <= float32Array[c2 + splitAxis] : (
        // min bounding data
        point >= float32Array[c2 + splitAxis + 3]
      );
      if (isOutside) {
        return c1Result;
      }
    }
    const c2Intersection = intersectRay(c2, float32Array, ray2, boxIntersection);
    const c2Result = c2Intersection ? raycastFirst(c2, geometry, side, ray2) : null;
    if (c1Result && c2Result) {
      return c1Result.distance <= c2Result.distance ? c1Result : c2Result;
    } else {
      return c1Result || c2Result || null;
    }
  }
}
var shapecast = function() {
  let _box12, _box22;
  const boxStack = [];
  const boxPool = new PrimitivePool(() => new Box3());
  return function shapecast2(...args) {
    _box12 = boxPool.getPrimitive();
    _box22 = boxPool.getPrimitive();
    boxStack.push(_box12, _box22);
    const result = shapecastTraverse(...args);
    boxPool.releasePrimitive(_box12);
    boxPool.releasePrimitive(_box22);
    boxStack.pop();
    boxStack.pop();
    const length = boxStack.length;
    if (length > 0) {
      _box22 = boxStack[length - 1];
      _box12 = boxStack[length - 2];
    }
    return result;
  };
  function shapecastTraverse(nodeIndex32, geometry, intersectsBoundsFunc, intersectsRangeFunc, nodeScoreFunc = null, nodeIndexByteOffset = 0, depth = 0) {
    function getLeftOffset(nodeIndex322) {
      let nodeIndex162 = nodeIndex322 * 2, uint16Array2 = _uint16Array, uint32Array2 = _uint32Array;
      while (!IS_LEAF(nodeIndex162, uint16Array2)) {
        nodeIndex322 = LEFT_NODE(nodeIndex322);
        nodeIndex162 = nodeIndex322 * 2;
      }
      return OFFSET(nodeIndex322, uint32Array2);
    }
    function getRightEndOffset(nodeIndex322) {
      let nodeIndex162 = nodeIndex322 * 2, uint16Array2 = _uint16Array, uint32Array2 = _uint32Array;
      while (!IS_LEAF(nodeIndex162, uint16Array2)) {
        nodeIndex322 = RIGHT_NODE(nodeIndex322, uint32Array2);
        nodeIndex162 = nodeIndex322 * 2;
      }
      return OFFSET(nodeIndex322, uint32Array2) + COUNT(nodeIndex162, uint16Array2);
    }
    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, _box12);
      return intersectsRangeFunc(offset, count, false, depth, nodeIndexByteOffset + nodeIndex32, _box12);
    } 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 = _box12;
        box2 = _box22;
        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 temp5 = score1;
          score1 = score2;
          score2 = temp5;
          box1 = box2;
        }
      }
      if (!box1) {
        box1 = _box12;
        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;
      box2 = _box22;
      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;
    }
  }
}();
var intersectsGeometry = function() {
  const triangle = new ExtendedTriangle();
  const triangle2 = new ExtendedTriangle();
  const invertedMat = new Matrix4();
  const obb3 = new OrientedBox();
  const obb22 = new OrientedBox();
  return function intersectsGeometry2(nodeIndex32, geometry, otherGeometry, geometryToBvh, cachedObb = null) {
    let nodeIndex16 = nodeIndex32 * 2, float32Array = _float32Array, uint16Array = _uint16Array, uint32Array = _uint32Array;
    if (cachedObb === null) {
      if (!otherGeometry.boundingBox) {
        otherGeometry.computeBoundingBox();
      }
      obb3.set(otherGeometry.boundingBox.min, otherGeometry.boundingBox.max, geometryToBvh);
      cachedObb = obb3;
    }
    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);
      invertedMat.copy(geometryToBvh).invert();
      if (otherGeometry.boundsTree) {
        arrayToBox(BOUNDING_DATA_INDEX(nodeIndex32), float32Array, obb22);
        obb22.matrix.copy(invertedMat);
        obb22.needsUpdate = true;
        const res = otherGeometry.boundsTree.shapecast({
          intersectsBounds: (box) => obb22.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) {
              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) {
          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);
      const leftIntersection = cachedObb.intersectsBox(boundingBox) && intersectsGeometry2(left, geometry, otherGeometry, geometryToBvh, cachedObb);
      if (leftIntersection)
        return true;
      arrayToBox(BOUNDING_DATA_INDEX(right), float32Array, boundingBox);
      const rightIntersection = cachedObb.intersectsBox(boundingBox) && intersectsGeometry2(right, geometry, otherGeometry, geometryToBvh, cachedObb);
      if (rightIntersection)
        return true;
      return false;
    }
  };
}();
function intersectRay(nodeIndex32, array, ray2, target) {
  arrayToBox(nodeIndex32, array, boundingBox);
  return ray2.intersectBox(boundingBox, target);
}
var bufferStack = [];
var _prevBuffer;
var _float32Array;
var _uint16Array;
var _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());
  }
}

// node_modules/three-mesh-bvh/src/core/MeshBVH.js
var SKIP_GENERATION = Symbol("skip tree generation");
var aabb = /* @__PURE__ */ new Box3();
var aabb2 = /* @__PURE__ */ new Box3();
var tempMatrix = /* @__PURE__ */ new Matrix4();
var obb = /* @__PURE__ */ new OrientedBox();
var obb2 = /* @__PURE__ */ new OrientedBox();
var temp = /* @__PURE__ */ new Vector3();
var temp1 = /* @__PURE__ */ new Vector3();
var temp2 = /* @__PURE__ */ new Vector3();
var temp3 = /* @__PURE__ */ new Vector3();
var temp4 = /* @__PURE__ */ new Vector3();
var tempBox = /* @__PURE__ */ new Box3();
var trianglePool = /* @__PURE__ */ new PrimitivePool(() => new ExtendedTriangle());
var MeshBVH = 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] === void 0 ? 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] === void 0 ? 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.");
    }
    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());
      }
    }
    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;
    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, byteOffset2, 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];
          const x = posAttr.getX(index);
          const y = posAttr.getY(index);
          const z = posAttr.getZ(index);
          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];
        const offsetLeft = left + byteOffset2;
        const offsetRight = right + byteOffset2;
        let forceChildren = force;
        let includesLeft = false;
        let includesRight = false;
        if (nodeIndices) {
          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, byteOffset2, forceChildren);
        }
        let rightChange = false;
        if (traverseRight) {
          rightChange = _traverse(right, byteOffset2, 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 {
        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(ray2, 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, ray2, 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(ray2, 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, ray2);
      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) {
        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) {
    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) {
      let iterateOverDoubleTriangles = function(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;
      }
    }
    otherBvh.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: (box2) => aabb.intersectsBox(box2),
          intersectsRange: (offset2, count2, contained2, 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: (box2) => obb.intersectsBox(box2),
        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);
        },
        intersectsBounds: (box, isLeaf, score) => {
          if (score < closestDistance && score < maxThreshold) {
            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) {
            return otherGeometry.boundsTree.shapecast({
              boundsTraverseOrder: (box) => {
                return obb2.distanceToBox(box);
              },
              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;
                    }
                    if (dist < minThreshold) {
                      return true;
                    }
                  }
                }
              }
            });
          } else {
            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;
                }
                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) {
    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;
  }
};

// node_modules/three-mesh-bvh/src/objects/MeshBVHVisualizer.js
var boundingBox2 = /* @__PURE__ */ new Box3();
var MeshBVHRootVisualizer = class 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) {
      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);
      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, boundingBox2);
          const { min, max } = boundingBox2;
          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) {
        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];
        }
      }
      geometry.setIndex(
        new BufferAttribute(indexArray, 1, false)
      );
      geometry.setAttribute(
        "position",
        new BufferAttribute(positionArray, 3, false)
      );
      this.visible = true;
    }
  }
};
var MeshBVHVisualizer = 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: 65416,
      transparent: true,
      opacity: 0.3,
      depthWrite: false
    });
    const meshMaterial = new MeshBasicMaterial({
      color: 65416,
      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) {
      const root = this._roots.pop();
      root.geometry.dispose();
      this.remove(root);
    }
    for (let i = 0; i < totalRoots; i++) {
      if (i >= this._roots.length) {
        const root2 = new MeshBVHRootVisualizer(this.mesh, this.edgeMaterial, this.depth, i);
        this.add(root2);
        this._roots.push(root2);
      }
      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();
    }
  }
};

// node_modules/three-mesh-bvh/src/debug/Debug.js
var _box1 = /* @__PURE__ */ new Box3();
var _box2 = /* @__PURE__ */ new Box3();
var _vec = /* @__PURE__ */ new Vector3();
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 (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 = /* @__PURE__ */ 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) {
      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) {
      arrayToBox(0, boundingData, _box2);
      const isContained = _box2.containsBox(_box1);
      console.assert(isContained, "Parent bounds does not fully contain child.");
      passes = passes && isContained;
    }
  });
  return passes;
}
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;
    const parent = depthStack[depth - 1];
    if (parent) {
      if (parent.left === null) {
        parent.left = info;
      } else {
        parent.right = info;
      }
    }
  });
  return depthStack[0];
}

// node_modules/three-mesh-bvh/src/utils/ExtensionUtilities.js
var ray = /* @__PURE__ */ new Ray();
var tmpInverseMatrix = /* @__PURE__ */ new Matrix4();
var origMeshRaycastFunc = Mesh.prototype.raycast;
function acceleratedRaycast(raycaster, intersects) {
  if (this.geometry.boundsTree) {
    if (this.material === void 0)
      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;
}

// node_modules/three-mesh-bvh/src/gpu/VertexAttributeTexture.js
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;
  }
}
var VertexAttributeTexture = class 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) {
        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;
    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;
      }
    }
    let type, format, normalizeValue, targetBufferCons;
    let internalFormat = countToStringFormat(itemSize);
    switch (targetType) {
      case FloatType:
        normalizeValue = 1;
        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;
        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;
        format = countToIntFormat(itemSize);
        if (byteCount === 1) {
          targetBufferCons = Uint8Array;
          type = UnsignedByteType;
        } else if (byteCount === 2) {
          targetBufferCons = Uint16Array;
          type = UnsignedShortType;
        } else {
          targetBufferCons = Uint32Array;
          type = UnsignedIntType;
        }
        break;
    }
    if (finalStride === 3 && (format === RGBAFormat || format === RGBAIntegerFormat)) {
      finalStride = 4;
    }
    const dimension = Math.ceil(Math.sqrt(count));
    const length = finalStride * dimension * dimension;
    const dataArray = new targetBufferCons(length);
    const originalNormalized = attr.normalized;
    attr.normalized = false;
    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;
        }
      }
      if (itemSize >= 4) {
        dataArray[ii + 3] = attr.getW(i) / normalizeValue;
      }
    }
    attr.normalized = originalNormalized;
    this.internalFormat = internalFormat;
    this.format = format;
    this.type = type;
    this.image.width = dimension;
    this.image.height = dimension;
    this.image.data = dataArray;
    this.needsUpdate = true;
    this.dispose();
    attr.itemSize = originalItemSize;
    attr.count = originalCount;
  }
};
var UIntVertexAttributeTexture = class extends VertexAttributeTexture {
  constructor() {
    super();
    this._forcedType = UnsignedIntType;
  }
};
var IntVertexAttributeTexture = class extends VertexAttributeTexture {
  constructor() {
    super();
    this._forcedType = IntType;
  }
};
var FloatVertexAttributeTexture = class extends VertexAttributeTexture {
  constructor() {
    super();
    this._forcedType = FloatType;
  }
};

// node_modules/three-mesh-bvh/src/gpu/MeshBVHUniformStruct.js
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);
  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 = 4294901760 | 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;
  boundsTexture.dispose();
  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;
  contentsTexture.dispose();
}
var MeshBVHUniformStruct = class {
  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();
  }
};

// node_modules/three-mesh-bvh/src/gpu/shaderFunctions.js
var 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;

};
`
);
var shaderIntersectFunction = (
  /* glsl */
  `

// Utilities
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;

}

// Raycasting
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;

}
`
);
var shaderDistanceFunction = (
  /* glsl */
  `

float dot2( in vec3 v ) {

	return dot( v, v );

}


// https://www.shadertoy.com/view/ttfGWl
vec3 closestPointToTriangle( vec3 p, vec3 v0, vec3 v1, vec3 v2, out vec3 barycoord ) {

    vec3 v10 = v1 - v0;
    vec3 v21 = v2 - v1;
    vec3 v02 = v0 - v2;

	vec3 p0 = p - v0;
	vec3 p1 = p - v1;
	vec3 p2 = p - v2;

    vec3 nor = cross( v10, v02 );

    // method 2, in barycentric space
    vec3  q = cross( nor, p0 );
    float d = 1.0 / dot2( nor );
    float u = d * dot( q, v02 );
    float v = d * dot( q, v10 );
    float w = 1.0 - u - v;

	if( u < 0.0 ) {

		w = clamp( dot( p2, v02 ) / dot2( v02 ), 0.0, 1.0 );
		u = 0.0;
		v = 1.0 - w;

	} else if( v < 0.0 ) {

		u = clamp( dot( p0, v10 ) / dot2( v10 ), 0.0, 1.0 );
		v = 0.0;
		w = 1.0 - u;

	} else if( w < 0.0 ) {

		v = clamp( dot( p1, v21 ) / dot2( v21 ), 0.0, 1.0 );
		w = 0.0;
		u = 1.0-v;

	}

	barycoord = vec3( u, v, w );
    return u * v1 + v * v2 + w * v0;

}

float distanceToTriangles(
	BVH bvh, vec3 point, uint offset, uint count, float closestDistanceSquared,

	out uvec4 faceIndices, out vec3 faceNormal, out vec3 barycoord, out float side, out vec3 outPoint
) {

	bool found = false;
	uvec3 localIndices;
	vec3 localBarycoord;
	vec3 localNormal;
	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;

		// get the closest point and barycoord
		vec3 closestPoint = closestPointToTriangle( point, a, b, c, localBarycoord );
		vec3 delta = point - closestPoint;
		float sqDist = dot2( delta );
		if ( sqDist < closestDistanceSquared ) {

			// set the output results
			closestDistanceSquared = sqDist;
			faceIndices = uvec4( indices.xyz, i );
			faceNormal = normalize( cross( a - b, b - c ) );
			barycoord = localBarycoord;
			outPoint = closestPoint;
			side = sign( dot( faceNormal, delta ) );

		}

	}

	return closestDistanceSquared;

}

float distanceSqToBounds( vec3 point, vec3 boundsMin, vec3 boundsMax ) {

	vec3 clampedPoint = clamp( point, boundsMin, boundsMax );
	vec3 delta = point - clampedPoint;
	return dot( delta, delta );

}

float distanceSqToBVHNodeBoundsPoint( vec3 point, BVH bvh, uint currNodeIndex ) {

	vec3 boundsMin = texelFetch1D( bvh.bvhBounds, currNodeIndex * 2u + 0u ).xyz;
	vec3 boundsMax = texelFetch1D( bvh.bvhBounds, currNodeIndex * 2u + 1u ).xyz;
	return distanceSqToBounds( point, boundsMin, boundsMax );

}

float bvhClosestPointToPoint(
	BVH bvh, vec3 point,

	// output variables
	out uvec4 faceIndices, out vec3 faceNormal, out vec3 barycoord,
	out float side, out vec3 outPoint
 ) {

	// 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 closestDistanceSquared = pow( 100000.0, 2.0 );
	bool found = false;
	while ( ptr > - 1 && ptr < 60 ) {

		uint currNodeIndex = stack[ ptr ];
		ptr --;

		// check if we intersect the current bounds
		float boundsHitDistance = distanceSqToBVHNodeBoundsPoint( point, bvh, currNodeIndex );
		if ( boundsHitDistance > closestDistanceSquared ) {

			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;
			closestDistanceSquared = distanceToTriangles(
				bvh, point, offset, count, closestDistanceSquared,

				// outputs
				faceIndices, faceNormal, barycoord, side, outPoint
			);

		} else {

			uint leftIndex = currNodeIndex + 1u;
			uint splitAxis = boundsInfo.x & 0x0000ffffu;
			uint rightIndex = boundsInfo.y;
			bool leftToRight = distanceSqToBVHNodeBoundsPoint( point, bvh, leftIndex ) < distanceSqToBVHNodeBoundsPoint( point, bvh, rightIndex );//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 sqrt( closestDistanceSquared );

}
`
);

// node_modules/three-mesh-bvh/src/utils/StaticGeometryGenerator.js
var _positionVector = /* @__PURE__ */ new Vector3();
var _normalVector = /* @__PURE__ */ new Vector3();
var _tangentVector = /* @__PURE__ */ new Vector3();
var _tangentVector4 = /* @__PURE__ */ new Vector4();
var _morphVector = /* @__PURE__ */ new Vector3();
var _temp = /* @__PURE__ */ new Vector3();
var _skinIndex = /* @__PURE__ */ new Vector4();
var _skinWeight = /* @__PURE__ */ new Vector4();
var _matrix = /* @__PURE__ */ new Matrix4();
var _boneMatrix = /* @__PURE__ */ new Matrix4();
function validateAttributes(attr1, attr2) {
  if (!attr1 && !attr2) {
    return;
  }
  const sameCount = attr1.count === attr2.count;
  const sameNormalized = attr1.normalized === attr2.normalized;
  const sameType = attr1.array.constructor === attr2.array.constructor;
  const sameItemSize = attr1.itemSize === attr2.itemSize;
  if (!sameCount || !sameNormalized || !sameType || !sameItemSize) {
    throw new Error();
  }
}
function createAttributeClone(attr, countOverride = null) {
  const cons = attr.array.constructor;
  const normalized = attr.normalized;
  const itemSize = attr.itemSize;
  const count = countOverride === null ? attr.count : countOverride;
  return new BufferAttribute(new cons(itemSize * count), itemSize, normalized);
}
function copyAttributeContents(attr, target, targetOffset = 0) {
  if (attr.isInterleavedBufferAttribute) {
    const itemSize = attr.itemSize;
    for (let i = 0, l = attr.count; i < l; i++) {
      const io = i + targetOffset;
      target.setX(io, attr.getX(i));
      if (itemSize >= 2)
        target.setY(io, attr.getY(i));
      if (itemSize >= 3)
        target.setZ(io, attr.getZ(i));
      if (itemSize >= 4)
        target.setW(io, attr.getW(i));
    }
  } else {
    const array = target.array;
    const cons = array.constructor;
    const byteOffset = array.BYTES_PER_ELEMENT * attr.itemSize * targetOffset;
    const temp5 = new cons(array.buffer, byteOffset, attr.array.length);
    temp5.set(attr.array);
  }
}
function addScaledMatrix(target, matrix, scale) {
  const targetArray = target.elements;
  const matrixArray = matrix.elements;
  for (let i = 0, l = matrixArray.length; i < l; i++) {
    targetArray[i] += matrixArray[i] * scale;
  }
}
function boneNormalTransform(mesh, index, target) {
  const skeleton = mesh.skeleton;
  const geometry = mesh.geometry;
  const bones = skeleton.bones;
  const boneInverses = skeleton.boneInverses;
  _skinIndex.fromBufferAttribute(geometry.attributes.skinIndex, index);
  _skinWeight.fromBufferAttribute(geometry.attributes.skinWeight, index);
  _matrix.elements.fill(0);
  for (let i = 0; i < 4; i++) {
    const weight = _skinWeight.getComponent(i);
    if (weight !== 0) {
      const boneIndex = _skinIndex.getComponent(i);
      _boneMatrix.multiplyMatrices(bones[boneIndex].matrixWorld, boneInverses[boneIndex]);
      addScaledMatrix(_matrix, _boneMatrix, weight);
    }
  }
  _matrix.multiply(mesh.bindMatrix).premultiply(mesh.bindMatrixInverse);
  target.transformDirection(_matrix);
  return target;
}
function applyMorphTarget(morphData, morphInfluences, morphTargetsRelative, i, target) {
  _morphVector.set(0, 0, 0);
  for (let j = 0, jl = morphData.length; j < jl; j++) {
    const influence = morphInfluences[j];
    const morphAttribute = morphData[j];
    if (influence === 0)
      continue;
    _temp.fromBufferAttribute(morphAttribute, i);
    if (morphTargetsRelative) {
      _morphVector.addScaledVector(_temp, influence);
    } else {
      _morphVector.addScaledVector(_temp.sub(target), influence);
    }
  }
  target.add(_morphVector);
}
function mergeBufferGeometries(geometries, options = { useGroups: false, updateIndex: false, skipAttributes: [] }, targetGeometry = new BufferGeometry()) {
  const isIndexed = geometries[0].index !== null;
  const { useGroups = false, updateIndex = false, skipAttributes = [] } = options;
  const attributesUsed = new Set(Object.keys(geometries[0].attributes));
  const attributes = {};
  let offset = 0;
  targetGeometry.clearGroups();
  for (let i = 0; i < geometries.length; ++i) {
    const geometry = geometries[i];
    let attributesCount = 0;
    if (isIndexed !== (geometry.index !== null)) {
      throw new Error("StaticGeometryGenerator: All geometries must have compatible attributes; make sure index attribute exists among all geometries, or in none of them.");
    }
    for (const name in geometry.attributes) {
      if (!attributesUsed.has(name)) {
        throw new Error('StaticGeometryGenerator: All geometries must have compatible attributes; make sure "' + name + '" attribute exists among all geometries, or in none of them.');
      }
      if (attributes[name] === void 0) {
        attributes[name] = [];
      }
      attributes[name].push(geometry.attributes[name]);
      attributesCount++;
    }
    if (attributesCount !== attributesUsed.size) {
      throw new Error("StaticGeometryGenerator: Make sure all geometries have the same number of attributes.");
    }
    if (useGroups) {
      let count;
      if (isIndexed) {
        count = geometry.index.count;
      } else if (geometry.attributes.position !== void 0) {
        count = geometry.attributes.position.count;
      } else {
        throw new Error("StaticGeometryGenerator: The geometry must have either an index or a position attribute");
      }
      targetGeometry.addGroup(offset, count, i);
      offset += count;
    }
  }
  if (isIndexed) {
    let forceUpdateIndex = false;
    if (!targetGeometry.index) {
      let indexCount = 0;
      for (let i = 0; i < geometries.length; ++i) {
        indexCount += geometries[i].index.count;
      }
      targetGeometry.setIndex(new BufferAttribute(new Uint32Array(indexCount), 1, false));
      forceUpdateIndex = true;
    }
    if (updateIndex || forceUpdateIndex) {
      const targetIndex = targetGeometry.index;
      let targetOffset = 0;
      let indexOffset = 0;
      for (let i = 0; i < geometries.length; ++i) {
        const geometry = geometries[i];
        const index = geometry.index;
        if (skipAttributes[i] !== true) {
          for (let j = 0; j < index.count; ++j) {
            targetIndex.setX(targetOffset, index.getX(j) + indexOffset);
            targetOffset++;
          }
        }
        indexOffset += geometry.attributes.position.count;
      }
    }
  }
  for (const name in attributes) {
    const attrList = attributes[name];
    if (!(name in targetGeometry.attributes)) {
      let count = 0;
      for (const key in attrList) {
        count += attrList[key].count;
      }
      targetGeometry.setAttribute(name, createAttributeClone(attributes[name][0], count));
    }
    const targetAttribute = targetGeometry.attributes[name];
    let offset2 = 0;
    for (let i = 0, l = attrList.length; i < l; i++) {
      const attr = attrList[i];
      if (skipAttributes[i] !== true) {
        copyAttributeContents(attr, targetAttribute, offset2);
      }
      offset2 += attr.count;
    }
  }
  return targetGeometry;
}
function checkTypedArrayEquality(a, b) {
  if (a === null || b === null) {
    return a === b;
  }
  if (a.length !== b.length) {
    return false;
  }
  for (let i = 0, l = a.length; i < l; i++) {
    if (a[i] !== b[i]) {
      return false;
    }
  }
  return true;
}
var GeometryDiff = class {
  constructor(mesh) {
    this.matrixWorld = new Matrix4();
    this.geometryHash = null;
    this.boneMatrices = null;
    this.primitiveCount = -1;
    this.mesh = mesh;
    this.update();
  }
  update() {
    const mesh = this.mesh;
    const geometry = mesh.geometry;
    const skeleton = mesh.skeleton;
    const primitiveCount = (geometry.index ? geometry.index.count : geometry.attributes.position.count) / 3;
    this.matrixWorld.copy(mesh.matrixWorld);
    this.geometryHash = geometry.attributes.position.version;
    this.primitiveCount = primitiveCount;
    if (skeleton) {
      if (!skeleton.boneTexture) {
        skeleton.computeBoneTexture();
      }
      skeleton.update();
      const boneMatrices = skeleton.boneMatrices;
      if (!this.boneMatrices || this.boneMatrices.length !== boneMatrices.length) {
        this.boneMatrices = boneMatrices.slice();
      } else {
        this.boneMatrices.set(boneMatrices);
      }
    } else {
      this.boneMatrices = null;
    }
  }
  didChange() {
    const mesh = this.mesh;
    const geometry = mesh.geometry;
    const primitiveCount = (geometry.index ? geometry.index.count : geometry.attributes.position.count) / 3;
    const identical = this.matrixWorld.equals(mesh.matrixWorld) && this.geometryHash === geometry.attributes.position.version && checkTypedArrayEquality(mesh.skeleton && mesh.skeleton.boneMatrices || null, this.boneMatrices) && this.primitiveCount === primitiveCount;
    return !identical;
  }
};
var StaticGeometryGenerator = class {
  constructor(meshes) {
    if (!Array.isArray(meshes)) {
      meshes = [meshes];
    }
    const finalMeshes = [];
    meshes.forEach((object) => {
      object.traverseVisible((c) => {
        if (c.isMesh) {
          finalMeshes.push(c);
        }
      });
    });
    this.meshes = finalMeshes;
    this.useGroups = true;
    this.applyWorldTransforms = true;
    this.attributes = ["position", "normal", "color", "tangent", "uv", "uv2"];
    this._intermediateGeometry = new Array(finalMeshes.length).fill().map(() => new BufferGeometry());
    this._diffMap = /* @__PURE__ */ new WeakMap();
  }
  getMaterials() {
    const materials = [];
    this.meshes.forEach((mesh) => {
      if (Array.isArray(mesh.material)) {
        materials.push(...mesh.material);
      } else {
        materials.push(mesh.material);
      }
    });
    return materials;
  }
  generate(targetGeometry = new BufferGeometry()) {
    let skipAttributes = [];
    const { meshes, useGroups, _intermediateGeometry, _diffMap } = this;
    for (let i = 0, l = meshes.length; i < l; i++) {
      const mesh = meshes[i];
      const geom = _intermediateGeometry[i];
      const diff = _diffMap.get(mesh);
      if (!diff || diff.didChange(mesh)) {
        this._convertToStaticGeometry(mesh, geom);
        skipAttributes.push(false);
        if (!diff) {
          _diffMap.set(mesh, new GeometryDiff(mesh));
        } else {
          diff.update();
        }
      } else {
        skipAttributes.push(true);
      }
    }
    mergeBufferGeometries(_intermediateGeometry, { useGroups, skipAttributes }, targetGeometry);
    for (const key in targetGeometry.attributes) {
      targetGeometry.attributes[key].needsUpdate = true;
    }
    return targetGeometry;
  }
  _convertToStaticGeometry(mesh, targetGeometry = new BufferGeometry()) {
    const geometry = mesh.geometry;
    const applyWorldTransforms = this.applyWorldTransforms;
    const includeNormal = this.attributes.includes("normal");
    const includeTangent = this.attributes.includes("tangent");
    const attributes = geometry.attributes;
    const targetAttributes = targetGeometry.attributes;
    if (!targetGeometry.index) {
      targetGeometry.index = geometry.index;
    }
    if (!targetAttributes.position) {
      targetGeometry.setAttribute("position", createAttributeClone(attributes.position));
    }
    if (includeNormal && !targetAttributes.normal && attributes.normal) {
      targetGeometry.setAttribute("normal", createAttributeClone(attributes.normal));
    }
    if (includeTangent && !targetAttributes.tangent && attributes.tangent) {
      targetGeometry.setAttribute("tangent", createAttributeClone(attributes.tangent));
    }
    validateAttributes(geometry.index, targetGeometry.index);
    validateAttributes(attributes.position, targetAttributes.position);
    if (includeNormal) {
      validateAttributes(attributes.normal, targetAttributes.normal);
    }
    if (includeTangent) {
      validateAttributes(attributes.tangent, targetAttributes.tangent);
    }
    const position = attributes.position;
    const normal = includeNormal ? attributes.normal : null;
    const tangent = includeTangent ? attributes.tangent : null;
    const morphPosition = geometry.morphAttributes.position;
    const morphNormal = geometry.morphAttributes.normal;
    const morphTangent = geometry.morphAttributes.tangent;
    const morphTargetsRelative = geometry.morphTargetsRelative;
    const morphInfluences = mesh.morphTargetInfluences;
    const normalMatrix = new Matrix3();
    normalMatrix.getNormalMatrix(mesh.matrixWorld);
    for (let i = 0, l = attributes.position.count; i < l; i++) {
      _positionVector.fromBufferAttribute(position, i);
      if (normal) {
        _normalVector.fromBufferAttribute(normal, i);
      }
      if (tangent) {
        _tangentVector4.fromBufferAttribute(tangent, i);
        _tangentVector.fromBufferAttribute(tangent, i);
      }
      if (morphInfluences) {
        if (morphPosition) {
          applyMorphTarget(morphPosition, morphInfluences, morphTargetsRelative, i, _positionVector);
        }
        if (morphNormal) {
          applyMorphTarget(morphNormal, morphInfluences, morphTargetsRelative, i, _normalVector);
        }
        if (morphTangent) {
          applyMorphTarget(morphTangent, morphInfluences, morphTargetsRelative, i, _tangentVector);
        }
      }
      if (mesh.isSkinnedMesh) {
        mesh.boneTransform(i, _positionVector);
        if (normal) {
          boneNormalTransform(mesh, i, _normalVector);
        }
        if (tangent) {
          boneNormalTransform(mesh, i, _tangentVector);
        }
      }
      if (applyWorldTransforms) {
        _positionVector.applyMatrix4(mesh.matrixWorld);
      }
      targetAttributes.position.setXYZ(i, _positionVector.x, _positionVector.y, _positionVector.z);
      if (normal) {
        if (applyWorldTransforms) {
          _normalVector.applyNormalMatrix(normalMatrix);
        }
        targetAttributes.normal.setXYZ(i, _normalVector.x, _normalVector.y, _normalVector.z);
      }
      if (tangent) {
        if (applyWorldTransforms) {
          _tangentVector.transformDirection(mesh.matrixWorld);
        }
        targetAttributes.tangent.setXYZW(i, _tangentVector.x, _tangentVector.y, _tangentVector.z, _tangentVector4.w);
      }
    }
    for (const i in this.attributes) {
      const key = this.attributes[i];
      if (key === "position" || key === "tangent" || key === "normal" || !(key in attributes)) {
        continue;
      }
      if (!targetAttributes[key]) {
        targetGeometry.setAttribute(key, createAttributeClone(attributes[key]));
      }
      validateAttributes(attributes[key], targetAttributes[key]);
      copyAttributeContents(attributes[key], targetAttributes[key]);
    }
    return targetGeometry;
  }
};
export {
  AVERAGE,
  CENTER,
  CONTAINED,
  ExtendedTriangle,
  FloatVertexAttributeTexture,
  INTERSECTED,
  IntVertexAttributeTexture,
  MeshBVH,
  MeshBVHUniformStruct,
  MeshBVHVisualizer,
  NOT_INTERSECTED,
  OrientedBox,
  SAH,
  StaticGeometryGenerator,
  UIntVertexAttributeTexture,
  VertexAttributeTexture,
  acceleratedRaycast,
  computeBoundsTree,
  disposeBoundsTree,
  estimateMemoryInBytes,
  getBVHExtremes,
  getJSONStructure,
  getTriangleHitPointInfo,
  shaderDistanceFunction,
  shaderIntersectFunction,
  shaderStructs,
  validateBounds
};
