import * as THREE from "three"; import { SparkRenderer, SplatMesh } from "@sparkjsdev/spark"; import { SPLAT_URL, config } from "./config.js"; import { setupControls } from "./controls.js"; const loadingEl = document.getElementById("loading"); const scene = new THREE.Scene(); scene.background = new THREE.Color(config.background); const camera = new THREE.PerspectiveCamera( 75, innerWidth / innerHeight, 0.01, 1000000, ); camera.position.set(...config.camera.position); camera.lookAt(...config.camera.lookAt); const renderer = new THREE.WebGLRenderer({ antialias: true }); renderer.setPixelRatio(devicePixelRatio); renderer.setSize(innerWidth, innerHeight); document.body.appendChild(renderer.domElement); const spark = new SparkRenderer({ renderer, pagedExtSplats: true, coneFov0: 70.0, coneFov: 120.0, behindFoveate: 0.2, coneFoveate: 0.4, }); scene.add(spark); const mesh = new SplatMesh({ url: SPLAT_URL, paged: true, raycastable: true }); mesh.quaternion.set(...config.quaternion); mesh.position.set(...config.position); mesh.scale.setScalar(config.scale); scene.add(mesh); setupControls(renderer.domElement, camera, mesh); window.addEventListener("resize", () => { camera.aspect = innerWidth / innerHeight; camera.updateProjectionMatrix(); renderer.setSize(innerWidth, innerHeight); }); let firstFrame = true; renderer.setAnimationLoop(() => { renderer.render(scene, camera); if (firstFrame) { firstFrame = false; loadingEl.classList.add("done"); } });