Radiance Cascades 3D - three.js

HTML

<script type="importmap">
  {
    "imports": {
      "three": "https://unpkg.com/[email protected]/build/three.module.js",
      "three/examples/jsm/": "https://unpkg.com/[email protected]/examples/jsm/",
      "three-mesh-bvh": "https://unpkg.com/[email protected]/build/index.module.js"
    }
  }
</script>

CSS

body {
  margin: 0;
  background: black;
}

canvas {
  cursor: grab;
  display: block;
}

canvas:active {
  cursor: grabbing;
}

JavaScript

import * as THREE from 'three'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
import { MeshBVH, MeshBVHUniformStruct, UIntVertexAttributeTexture, BVHShaderGLSL, SAH } from 'three-mesh-bvh'

const BASE_INTERVAL_LENGTH = 0.005
const PROBE_SPACING = 4

function mergeGeometries(geometries) {
  let count = 0
  const attributes = new Map()

  for (const geometry of geometries) {
    count += geometry.index.count
    for (const key in geometry.attributes) {
      const attribute = geometry.attributes[key]

      const itemSize = attributes.get(key)
      if (itemSize === undefined || itemSize < attribute.itemSize) {
        attributes.set(key, attribute.itemSize)
      }
    }
  }

  const geometry = new THREE.BufferGeometry()

  const indices = new Uint32Array(count)
  let indicesOffset = 0
  let vertexOffset = 0
  for (const geometry of geometries) {
    for (let i = 0; i < geometry.index.count; i++) {
      indices[indicesOffset++] = geometry.index.array[i] + vertexOffset
    }
    vertexOffset += geometry.attributes.position.count
  }
  geometry.setIndex(new THREE.BufferAttribute(indices, 1))

  for (const [name, itemSize] of attributes) {
    const array = new Float32Array(count * itemSize)
    let offset = 0

    for (const geometry of geometries) {
      const vertexCount = geometry.attributes.position.count
      const vertexLength = vertexCount * itemSize

      const attribute = geometry.attributes[name]
      if (attribute) {
        array.set(attribute.array, offset)
      } else {
        for (let i = offset; i < offset + length; i++) {
          array[i] = 0
        }
      }

      offset += vertexLength
    }

    geometry.setAttribute(name, new THREE.BufferAttribute(array, itemSize))
  }

  return geometry
}

// Modified...