@selvajs/compute 1.5.1 → 1.5.2-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["/home/runner/work/selva-compute/selva-compute/dist/visualization.cjs","../src/features/visualization/threejs/three-initializer.ts","../src/features/visualization/threejs/three-helpers.ts"],"names":["defaultUp","getScaleValue","scale","mmVal","cmVal","mVal","initThree","canvas","options","config","applyDefaults","scene","createScene","camera","createCamera","renderer","setupRenderer","controls","setupControls","setupEnvironment","setupLighting","addFloor","eventHandlers","setupEventHandlers","parent","getCanvasSize","animate","disposeAnimation","createAnimationLoop","sceneUp","object","material","defaults","bgColor","animateCameraTo","toPosition","toTarget","durationMs","fromPosition","fromTarget","startTime","easeOut","t","tick","elapsed","onFrame","animationId","lastTime","checkResize","width","height","pixelRatio","newW","newH","now","delta","HDRLoader","envMap","error","getLogger","ambientLight","sunlight","pos","shadowSize","shadowNear","shadowFar","floorSize","floorGeometry","floorColor","floorMaterial","floor","selectedObjects","originalMaterials","raycaster","mouse","mouseDownPosition","isFullyVisible","current","fitToView","box","center","size","maxDim","fov","distance","direction","selectionColorObj","clearSelection","obj","handleMouseDown","event","handleCanvasClick","currentMousePosition","rect","intersects","i","clickedObject","clonedMaterial","handleDoubleClick","target","targetPosition","handleKeydown","OrbitControls","CAMERA_CONFIG","updateScene","meshes","initialPositionSet","clearScene","mesh","unionBoundingBox","computeCombinedBoundingBox","parseColor","colorString","trimmed","hex"],"mappings":"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","file":"/home/runner/work/selva-compute/selva-compute/dist/visualization.cjs","sourcesContent":[null,"import * as THREE from 'three';\nimport { OrbitControls } from 'three/addons/controls/OrbitControls.js';\nimport { HDRLoader } from 'three/addons/loaders/HDRLoader.js';\n\nimport { getLogger } from '@/core';\nimport { ThreeInitializerOptions } from '../types';\n\nconst defaultUp = new THREE.Vector3(0, 0, 1);\n\n// Returns scale-specific values for mm, cm, and m scales\nconst getScaleValue = (scale: string, mmVal: number, cmVal: number, mVal: number): number => {\n\tswitch (scale) {\n\t\tcase 'mm':\n\t\t\treturn mmVal;\n\t\tcase 'cm':\n\t\t\treturn cmVal;\n\t\tdefault:\n\t\t\treturn mVal;\n\t}\n};\n\n/**\n * Initializes a Three.js environment with scene, camera, renderer, and event handling.\n */\nexport const initThree = function (\n\tcanvas: HTMLCanvasElement,\n\toptions?: ThreeInitializerOptions\n): {\n\tscene: THREE.Scene;\n\tcamera: THREE.PerspectiveCamera;\n\tcontrols: OrbitControls;\n\trenderer: THREE.WebGLRenderer;\n\tdispose: () => void;\n\tfitToView: () => void;\n\tclearSelection: () => void;\n} {\n\tconst config = applyDefaults(options || {});\n\n\tconst scene = createScene(config);\n\tconst camera = createCamera(config, canvas);\n\tconst renderer = setupRenderer(canvas, config);\n\tconst controls = setupControls(camera, canvas, config);\n\n\tsetupEnvironment(scene, config);\n\tsetupLighting(scene, config);\n\n\tif (config.floor?.enabled) {\n\t\taddFloor(scene, config);\n\t}\n\n\tconst eventHandlers =\n\t\tconfig.events.enableEventHandlers !== false\n\t\t\t? setupEventHandlers(canvas, scene, camera, controls, config)\n\t\t\t: { dispose: () => {}, fitToView: () => {}, clearSelection: () => {} };\n\n\tconst parent = canvas.parentElement;\n\tconst getCanvasSize = () =>\n\t\tparent\n\t\t\t? { width: parent.clientWidth, height: parent.clientHeight }\n\t\t\t: { width: window.innerWidth, height: window.innerHeight };\n\n\t// Resize checked every frame so buffer resize and render happen in the same frame,\n\t// preventing visible blank frames on resize\n\tconst { animate, dispose: disposeAnimation } = createAnimationLoop(\n\t\trenderer,\n\t\tscene,\n\t\tcamera,\n\t\tcontrols,\n\t\tgetCanvasSize,\n\t\tconfig.events.onFrame\n\t);\n\tanimate();\n\n\tconst sceneUp = config.environment?.sceneUp || defaultUp;\n\tscene.up.set(sceneUp.x, sceneUp.y, sceneUp.z);\n\n\tconst dispose = () => {\n\t\tdisposeAnimation();\n\t\teventHandlers.dispose();\n\t\tcontrols.dispose();\n\t\trenderer.dispose();\n\n\t\tscene.traverse((object) => {\n\t\t\tif (object instanceof THREE.Mesh) {\n\t\t\t\tobject.geometry?.dispose();\n\t\t\t\tif (Array.isArray(object.material)) {\n\t\t\t\t\tobject.material.forEach((material) => material.dispose());\n\t\t\t\t} else {\n\t\t\t\t\tobject.material?.dispose();\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t};\n\n\treturn {\n\t\tscene,\n\t\tcamera,\n\t\tcontrols,\n\t\trenderer,\n\t\tdispose,\n\t\tfitToView: eventHandlers.fitToView,\n\t\tclearSelection: eventHandlers.clearSelection\n\t};\n};\n\nfunction applyDefaults(options: ThreeInitializerOptions): Required<ThreeInitializerOptions> {\n\tconst scale = options.sceneScale || 'm';\n\n\t// All Rhino geometry is normalized to METERS (1 unit = 1 meter), sceneScale just changes the viewing perspective\n\tconst scaleDefaults = {\n\t\tmm: {\n\t\t\tcameraDistance: 20,\n\t\t\tnear: 0.1,\n\t\t\tfar: 2000,\n\t\t\tfloorSize: 100,\n\t\t\tlightDistance: 10,\n\t\t\tlightHeight: 20,\n\t\t\tminDistance: 0.1,\n\t\t\tshadowSize: 100,\n\t\t\tscaleFactor: 1000\n\t\t},\n\t\tcm: {\n\t\t\tcameraDistance: 20,\n\t\t\tnear: 0.1,\n\t\t\tfar: 2000,\n\t\t\tfloorSize: 100,\n\t\t\tlightDistance: 25,\n\t\t\tlightHeight: 50,\n\t\t\tminDistance: 0.1,\n\t\t\tshadowSize: 100,\n\t\t\tscaleFactor: 100\n\t\t},\n\t\tm: {\n\t\t\tcameraDistance: 10,\n\t\t\tnear: 0.01,\n\t\t\tfar: 2000,\n\t\t\tfloorSize: 50,\n\t\t\tlightDistance: 25,\n\t\t\tlightHeight: 50,\n\t\t\tminDistance: 0.001,\n\t\t\tshadowSize: 100,\n\t\t\tscaleFactor: 1\n\t\t},\n\t\tinches: {\n\t\t\tcameraDistance: 15,\n\t\t\tnear: 0.1,\n\t\t\tfar: 2000,\n\t\t\tfloorSize: 80,\n\t\t\tlightDistance: 20,\n\t\t\tlightHeight: 40,\n\t\t\tminDistance: 0.1,\n\t\t\tshadowSize: 80,\n\t\t\tscaleFactor: 39.37\n\t\t},\n\t\tfeet: {\n\t\t\tcameraDistance: 8,\n\t\t\tnear: 0.1,\n\t\t\tfar: 2000,\n\t\t\tfloorSize: 40,\n\t\t\tlightDistance: 15,\n\t\t\tlightHeight: 30,\n\t\t\tminDistance: 0.1,\n\t\t\tshadowSize: 60,\n\t\t\tscaleFactor: 3.28084\n\t\t}\n\t};\n\n\tconst defaults = scaleDefaults[scale];\n\n\treturn {\n\t\tsceneScale: scale,\n\t\tcamera: {\n\t\t\tposition:\n\t\t\t\toptions.camera?.position ||\n\t\t\t\tnew THREE.Vector3(\n\t\t\t\t\t-defaults.cameraDistance,\n\t\t\t\t\tdefaults.cameraDistance,\n\t\t\t\t\tdefaults.cameraDistance\n\t\t\t\t),\n\t\t\tfov: options.camera?.fov || 20,\n\t\t\tnear: options.camera?.near || defaults.near,\n\t\t\tfar: options.camera?.far || defaults.far,\n\t\t\ttarget: options.camera?.target || new THREE.Vector3(0, 0, 0)\n\t\t},\n\t\tlighting: {\n\t\t\tenableSunlight: options.lighting?.enableSunlight ?? true,\n\t\t\tsunlightIntensity: options.lighting?.sunlightIntensity || 1,\n\t\t\tsunlightPosition:\n\t\t\t\toptions.lighting?.sunlightPosition ||\n\t\t\t\tnew THREE.Vector3(defaults.lightDistance, defaults.lightHeight, defaults.lightDistance),\n\t\t\tambientLightColor: options.lighting?.ambientLightColor || new THREE.Color(0x404040),\n\t\t\tambientLightIntensity: options.lighting?.ambientLightIntensity || 1,\n\t\t\tsunlightColor: options.lighting?.sunlightColor || 0xffffff // Default to white sunlight\n\t\t},\n\t\tenvironment: {\n\t\t\thdrPath: options.environment?.hdrPath || '/baseHDR.hdr',\n\t\t\tbackgroundColor: options.environment?.backgroundColor || new THREE.Color(0xf0f0f0),\n\t\t\tenableEnvironmentLighting: options.environment?.enableEnvironmentLighting ?? true,\n\t\t\tsceneUp: options.environment?.sceneUp || defaultUp,\n\t\t\tshowEnvironment: options.environment?.showEnvironment ?? false\n\t\t},\n\t\tfloor: {\n\t\t\tenabled: options.floor?.enabled ?? false,\n\t\t\tsize: options.floor?.size || defaults.floorSize,\n\t\t\tcolor: options.floor?.color || new THREE.Color(0x808080),\n\t\t\troughness: options.floor?.roughness || 0.7,\n\t\t\tmetalness: options.floor?.metalness || 0.0,\n\t\t\treceiveShadow: options.floor?.receiveShadow ?? true\n\t\t},\n\t\trender: {\n\t\t\tenableShadows: options.render?.enableShadows ?? true,\n\t\t\tshadowMapSize: options.render?.shadowMapSize || 2048,\n\t\t\tantialias: options.render?.antialias ?? true,\n\t\t\tpixelRatio: options.render?.pixelRatio || Math.min(window.devicePixelRatio, 2),\n\t\t\ttoneMapping: options.render?.toneMapping || THREE.NeutralToneMapping,\n\t\t\ttoneMappingExposure: options.render?.toneMappingExposure || 1,\n\t\t\tpreserveDrawingBuffer: options.render?.preserveDrawingBuffer ?? false\n\t\t},\n\t\tcontrols: {\n\t\t\tenableDamping: options.controls?.enableDamping ?? false,\n\t\t\tdampingFactor: options.controls?.dampingFactor || 0.05,\n\t\t\tautoRotate: options.controls?.autoRotate ?? false,\n\t\t\tautoRotateSpeed: options.controls?.autoRotateSpeed || 0.5,\n\t\t\tenableZoom: options.controls?.enableZoom ?? true,\n\t\t\tenablePan: options.controls?.enablePan ?? true,\n\t\t\tminDistance: options.controls?.minDistance || defaults.minDistance,\n\t\t\tmaxDistance: options.controls?.maxDistance || Infinity\n\t\t},\n\t\tevents: {\n\t\t\tonBackgroundClicked: options.events?.onBackgroundClicked,\n\t\t\tonObjectSelected: options.events?.onObjectSelected,\n\t\t\tonMeshMetadataClicked: options.events?.onMeshMetadataClicked,\n\t\t\tonMeshDoubleClicked: options.events?.onMeshDoubleClicked,\n\t\t\tselectionColor: options.events?.selectionColor || '#ff0000', // Default to red\n\t\t\tenableEventHandlers: options.events?.enableEventHandlers ?? true,\n\t\t\tenableKeyboardControls: options.events?.enableKeyboardControls ?? true,\n\t\t\tenableClickToFocus: options.events?.enableClickToFocus ?? true,\n\t\t\tenableDoubleClickZoom: options.events?.enableDoubleClickZoom ?? true,\n\t\t\tonReady: options.events?.onReady,\n\t\t\tonFrame: options.events?.onFrame\n\t\t}\n\t};\n}\n\nfunction createScene(config: Required<ThreeInitializerOptions>): THREE.Scene {\n\tconst scene = new THREE.Scene();\n\n\tconst bgColor =\n\t\ttypeof config.environment.backgroundColor === 'string'\n\t\t\t? new THREE.Color(config.environment.backgroundColor)\n\t\t\t: config.environment.backgroundColor;\n\tscene.background = bgColor || null;\n\n\treturn scene;\n}\n\nfunction animateCameraTo(\n\tcamera: THREE.PerspectiveCamera,\n\tcontrols: OrbitControls,\n\ttoPosition: THREE.Vector3,\n\ttoTarget: THREE.Vector3,\n\tdurationMs = 200\n): void {\n\tconst fromPosition = camera.position.clone();\n\tconst fromTarget = controls.target.clone();\n\tconst startTime = performance.now();\n\n\tconst easeOut = (t: number) => 1 - Math.pow(1 - t, 3);\n\n\tconst tick = () => {\n\t\tconst elapsed = performance.now() - startTime;\n\t\tconst t = easeOut(Math.min(elapsed / durationMs, 1));\n\n\t\tcamera.position.lerpVectors(fromPosition, toPosition, t);\n\t\tcontrols.target.lerpVectors(fromTarget, toTarget, t);\n\t\tcontrols.update();\n\n\t\tif (t < 1) requestAnimationFrame(tick);\n\t};\n\n\trequestAnimationFrame(tick);\n}\n\n// Resize applied before render so buffer clear and draw happen in the same frame,\n// preventing visible blank frames when the canvas is resized\nfunction createAnimationLoop(\n\trenderer: THREE.WebGLRenderer,\n\tscene: THREE.Scene,\n\tcamera: THREE.PerspectiveCamera,\n\tcontrols: OrbitControls,\n\tgetCanvasSize: () => { width: number; height: number },\n\tonFrame?: (delta: number) => void\n): { animate: () => void; dispose: () => void } {\n\tlet animationId: number | null = null;\n\tlet lastTime = performance.now();\n\n\tconst checkResize = () => {\n\t\tconst { width, height } = getCanvasSize();\n\t\tif (width === 0 || height === 0) return;\n\n\t\tconst pixelRatio = Math.min(window.devicePixelRatio, 2);\n\t\tconst newW = Math.round(width * pixelRatio);\n\t\tconst newH = Math.round(height * pixelRatio);\n\n\t\tif (renderer.domElement.width !== newW || renderer.domElement.height !== newH) {\n\t\t\trenderer.setPixelRatio(pixelRatio);\n\t\t\trenderer.setSize(width, height, false);\n\t\t\tcamera.aspect = width / height;\n\t\t\tcamera.updateProjectionMatrix();\n\t\t}\n\t};\n\n\tconst animate = function () {\n\t\tanimationId = requestAnimationFrame(animate);\n\n\t\tconst now = performance.now();\n\t\tconst delta = (now - lastTime) / 1000;\n\t\tlastTime = now;\n\n\t\tcheckResize();\n\n\t\tif (controls.enableDamping || controls.autoRotate) {\n\t\t\tcontrols.update();\n\t\t}\n\n\t\tonFrame?.(delta);\n\n\t\trenderer.render(scene, camera);\n\t};\n\n\tconst dispose = () => {\n\t\tif (animationId !== null) {\n\t\t\tcancelAnimationFrame(animationId);\n\t\t\tanimationId = null;\n\t\t}\n\t};\n\n\treturn { animate, dispose };\n}\n\nfunction setupEnvironment(scene: THREE.Scene, config: Required<ThreeInitializerOptions>) {\n\tif (config.environment.enableEnvironmentLighting) {\n\t\tnew HDRLoader().load(\n\t\t\tconfig.environment.hdrPath || '/baseHDR.hdr',\n\t\t\tfunction (envMap) {\n\t\t\t\tenvMap.mapping = THREE.EquirectangularReflectionMapping;\n\t\t\t\tscene.environment = envMap;\n\t\t\t\tif (config.environment.showEnvironment) {\n\t\t\t\t\tscene.background = envMap;\n\t\t\t\t}\n\t\t\t\tconfig.events.onReady?.();\n\t\t\t},\n\t\t\tundefined,\n\t\t\tfunction (error) {\n\t\t\t\tgetLogger().warn('HDR texture could not be loaded, falling back to basic lighting:', error);\n\t\t\t\tconfig.events.onReady?.();\n\t\t\t}\n\t\t);\n\t} else {\n\t\tconfig.events.onReady?.();\n\t}\n}\n\nfunction setupLighting(scene: THREE.Scene, config: Required<ThreeInitializerOptions>) {\n\tconst ambientLight = new THREE.AmbientLight(\n\t\tconfig.lighting.ambientLightColor,\n\t\tconfig.lighting.ambientLightIntensity\n\t);\n\tscene.add(ambientLight);\n\n\tif (config.lighting.enableSunlight) {\n\t\tconst sunlight = new THREE.DirectionalLight(\n\t\t\tconfig.lighting.sunlightColor ?? 0xffffff,\n\t\t\tconfig.lighting.sunlightIntensity\n\t\t);\n\t\tconst pos = config.lighting.sunlightPosition;\n\t\tif (pos) {\n\t\t\tsunlight.position.set(pos.x, pos.y, pos.z);\n\t\t}\n\n\t\tif (config.render.enableShadows) {\n\t\t\tsunlight.castShadow = true;\n\t\t\tconst shadowSize = getScaleValue(config.sceneScale, 0.1, 10, 100);\n\n\t\t\tsunlight.shadow.camera.left = -shadowSize;\n\t\t\tsunlight.shadow.camera.right = shadowSize;\n\t\t\tsunlight.shadow.camera.top = shadowSize;\n\t\t\tsunlight.shadow.camera.bottom = -shadowSize;\n\n\t\t\tconst shadowNear = getScaleValue(config.sceneScale, 0.001, 0.1, 0.5);\n\t\t\tconst shadowFar = getScaleValue(config.sceneScale, 1, 100, 500);\n\n\t\t\tsunlight.shadow.camera.near = shadowNear;\n\t\t\tsunlight.shadow.camera.far = shadowFar;\n\n\t\t\tsunlight.shadow.mapSize.width = config.render.shadowMapSize || 2048;\n\t\t\tsunlight.shadow.mapSize.height = config.render.shadowMapSize || 2048;\n\n\t\t\tsunlight.shadow.bias = -0.0001;\n\t\t\tsunlight.shadow.normalBias = 0.02;\n\t\t}\n\n\t\tscene.add(sunlight);\n\t}\n}\n\nfunction addFloor(scene: THREE.Scene, config: Required<ThreeInitializerOptions>) {\n\tconst floorSize = config.floor.size;\n\tconst floorGeometry = new THREE.PlaneGeometry(floorSize, floorSize);\n\n\tconst floorColor =\n\t\ttypeof config.floor.color === 'string'\n\t\t\t? new THREE.Color(config.floor.color)\n\t\t\t: config.floor.color;\n\n\tconst floorMaterial = new THREE.MeshStandardMaterial({\n\t\tcolor: floorColor,\n\t\troughness: config.floor.roughness,\n\t\tmetalness: config.floor.metalness,\n\t\tside: THREE.DoubleSide\n\t});\n\n\tconst floor = new THREE.Mesh(floorGeometry, floorMaterial);\n\tfloor.userData.id = 'floor';\n\tfloor.name = 'floor';\n\tfloor.rotation.x = -Math.PI / 2;\n\tfloor.position.y = 0;\n\n\tif (config.floor.receiveShadow && config.render.enableShadows) {\n\t\tfloor.receiveShadow = true;\n\t}\n\n\tscene.add(floor);\n}\n\nfunction createCamera(\n\tconfig: Required<ThreeInitializerOptions>,\n\tcanvas: HTMLCanvasElement\n): THREE.PerspectiveCamera {\n\tconst parent = canvas.parentElement;\n\tconst width = parent ? parent.clientWidth : window.innerWidth;\n\tconst height = parent ? parent.clientHeight : window.innerHeight;\n\n\tconst camera = new THREE.PerspectiveCamera(\n\t\tconfig.camera.fov,\n\t\twidth / height,\n\t\tconfig.camera.near,\n\t\tconfig.camera.far\n\t);\n\n\tconst pos = config.camera.position;\n\tif (pos) {\n\t\tcamera.position.set(pos.x, pos.y, pos.z);\n\t}\n\n\treturn camera;\n}\n\n// Logarithmic depth buffer improves depth precision for mixed scales (mm to km)\nfunction setupRenderer(\n\tcanvas: HTMLCanvasElement,\n\tconfig: Required<ThreeInitializerOptions>\n): THREE.WebGLRenderer {\n\tconst renderer = new THREE.WebGLRenderer({\n\t\tantialias: config.render.antialias,\n\t\tcanvas,\n\t\talpha: true,\n\t\tpowerPreference: 'high-performance',\n\t\tpreserveDrawingBuffer: config.render.preserveDrawingBuffer,\n\t\tlogarithmicDepthBuffer: true\n\t});\n\n\tconst parent = canvas.parentElement;\n\tconst width = parent ? parent.clientWidth : window.innerWidth;\n\tconst height = parent ? parent.clientHeight : window.innerHeight;\n\n\tif (parent) {\n\t\tcanvas.style.width = '100%';\n\t\tcanvas.style.height = '100%';\n\t\tcanvas.style.display = 'block';\n\t}\n\n\trenderer.setSize(width, height, false);\n\trenderer.setPixelRatio(config.render.pixelRatio || Math.min(window.devicePixelRatio, 2));\n\n\tif (config.render.enableShadows) {\n\t\trenderer.shadowMap.enabled = true;\n\t\trenderer.shadowMap.type = THREE.VSMShadowMap;\n\t}\n\n\trenderer.toneMapping = config.render.toneMapping!;\n\trenderer.toneMappingExposure = config.render.toneMappingExposure || 1.0;\n\trenderer.outputColorSpace = THREE.SRGBColorSpace;\n\n\trenderer.sortObjects = true;\n\n\treturn renderer;\n}\n\nfunction setupEventHandlers(\n\tcanvas: HTMLCanvasElement,\n\tscene: THREE.Scene,\n\tcamera: THREE.PerspectiveCamera,\n\tcontrols: OrbitControls,\n\tconfig: Required<ThreeInitializerOptions>\n): {\n\tdispose: () => void;\n\tfitToView: () => void;\n\tclearSelection: () => void;\n} {\n\tconst selectedObjects = new Set<THREE.Object3D>();\n\tconst originalMaterials = new Map<THREE.Object3D, THREE.Material | THREE.Material[]>();\n\tconst raycaster = new THREE.Raycaster();\n\tconst mouse = new THREE.Vector2();\n\tconst mouseDownPosition = new THREE.Vector2();\n\n\t// An object is hittable only if every ancestor is also visible. Three.js's\n\t// recursive intersect doesn't enforce that — it can hit a visible Mesh inside\n\t// a hidden Group.\n\tconst isFullyVisible = (object: THREE.Object3D): boolean => {\n\t\tlet current: THREE.Object3D | null = object;\n\t\twhile (current) {\n\t\t\tif (!current.visible) return false;\n\t\t\tcurrent = current.parent;\n\t\t}\n\t\treturn true;\n\t};\n\n\tconst fitToView = () => {\n\t\tconst box = new THREE.Box3();\n\n\t\tscene.traverse((object) => {\n\t\t\tif (object.visible && object.userData.id !== 'floor' && object instanceof THREE.Mesh) {\n\t\t\t\tbox.expandByObject(object);\n\t\t\t}\n\t\t});\n\n\t\tif (box.isEmpty()) {\n\t\t\tgetLogger().warn('No objects to fit to view');\n\t\t\treturn;\n\t\t}\n\n\t\tconst center = box.getCenter(new THREE.Vector3());\n\t\tconst size = box.getSize(new THREE.Vector3());\n\n\t\tconst maxDim = Math.max(size.x, size.y, size.z);\n\t\tconst fov = camera.fov * (Math.PI / 180);\n\t\tlet distance = maxDim / (2 * Math.tan(fov / 2));\n\n\t\tdistance *= 1.5;\n\n\t\tconst direction = camera.position.clone().sub(controls.target).normalize();\n\t\tcamera.position.copy(center.clone().add(direction.multiplyScalar(distance)));\n\n\t\tcontrols.target.copy(center);\n\t\tcontrols.update();\n\t};\n\n\tconst selectionColorObj =\n\t\ttypeof config.events.selectionColor === 'string'\n\t\t\t? new THREE.Color(config.events.selectionColor)\n\t\t\t: config.events.selectionColor instanceof THREE.Color\n\t\t\t\t? config.events.selectionColor\n\t\t\t\t: new THREE.Color('#ff0000');\n\n\tconst clearSelection = () => {\n\t\tselectedObjects.forEach((obj) => {\n\t\t\tif (obj instanceof THREE.Mesh && originalMaterials.has(obj)) {\n\t\t\t\tobj.material = originalMaterials.get(obj)!;\n\t\t\t\toriginalMaterials.delete(obj);\n\t\t\t}\n\t\t});\n\t\tselectedObjects.clear();\n\t};\n\n\tconst handleMouseDown = (event: MouseEvent) => {\n\t\tmouseDownPosition.set(event.clientX, event.clientY);\n\t};\n\n\tconst handleCanvasClick = (event: MouseEvent) => {\n\t\t// Ignore if mouse has moved (drag)\n\t\tconst currentMousePosition = new THREE.Vector2(event.clientX, event.clientY);\n\t\tif (mouseDownPosition.distanceTo(currentMousePosition) > 5) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst rect = canvas.getBoundingClientRect();\n\t\tmouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;\n\t\tmouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;\n\n\t\traycaster.setFromCamera(mouse, camera);\n\t\tconst intersects = raycaster\n\t\t\t.intersectObjects(scene.children, true)\n\t\t\t.filter((i) => isFullyVisible(i.object));\n\n\t\tif (intersects.length > 0) {\n\t\t\tconst clickedObject = intersects[0].object;\n\n\t\t\tif (!selectedObjects.has(clickedObject)) {\n\t\t\t\tclearSelection();\n\t\t\t\tselectedObjects.add(clickedObject);\n\n\t\t\t\t// Clone material so we don't affect other meshes\n\t\t\t\tif (\n\t\t\t\t\tclickedObject instanceof THREE.Mesh &&\n\t\t\t\t\tclickedObject.material instanceof THREE.Material\n\t\t\t\t) {\n\t\t\t\t\toriginalMaterials.set(clickedObject, clickedObject.material);\n\n\t\t\t\t\tconst clonedMaterial = clickedObject.material.clone();\n\t\t\t\t\t(clonedMaterial as any).emissive = selectionColorObj.clone();\n\t\t\t\t\tclickedObject.material = clonedMaterial;\n\t\t\t\t}\n\n\t\t\t\tconfig.events?.onObjectSelected?.(clickedObject);\n\n\t\t\t\tif (clickedObject instanceof THREE.Mesh && Object.keys(clickedObject.userData).length > 0) {\n\t\t\t\t\tconfig.events?.onMeshMetadataClicked?.(clickedObject.userData);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tclearSelection();\n\t\t\tconfig.events?.onBackgroundClicked?.({ x: mouse.x, y: mouse.y });\n\t\t}\n\t};\n\n\tconst handleDoubleClick = (event: MouseEvent) => {\n\t\tconst rect = canvas.getBoundingClientRect();\n\t\tmouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;\n\t\tmouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;\n\n\t\traycaster.setFromCamera(mouse, camera);\n\t\tconst intersects = raycaster\n\t\t\t.intersectObjects(scene.children, true)\n\t\t\t.filter((i) => isFullyVisible(i.object));\n\n\t\tif (intersects.length === 0) return;\n\n\t\tconst target = intersects[0].object;\n\t\tconfig.events?.onMeshDoubleClicked?.(target);\n\n\t\tif (!config.events?.enableDoubleClickZoom) return;\n\n\t\tconst box = new THREE.Box3().setFromObject(target);\n\t\tif (box.isEmpty()) return;\n\n\t\tconst center = box.getCenter(new THREE.Vector3());\n\t\tconst size = box.getSize(new THREE.Vector3());\n\t\tconst maxDim = Math.max(size.x, size.y, size.z);\n\t\tconst fov = camera.fov * (Math.PI / 180);\n\t\tconst distance = (maxDim / (2 * Math.tan(fov / 2))) * 1.5;\n\n\t\tconst direction = camera.position.clone().sub(controls.target).normalize();\n\t\tconst targetPosition = center.clone().add(direction.multiplyScalar(distance));\n\n\t\tanimateCameraTo(camera, controls, targetPosition, center);\n\t};\n\n\tconst handleKeydown = (event: KeyboardEvent) => {\n\t\tif (!config.events?.enableKeyboardControls) return;\n\n\t\tswitch (event.key.toLowerCase()) {\n\t\t\tcase 'f':\n\t\t\t\tevent.preventDefault();\n\t\t\t\tfitToView();\n\t\t\t\tbreak;\n\t\t\tcase 'escape':\n\t\t\t\tevent.preventDefault();\n\t\t\t\tclearSelection();\n\t\t\t\tbreak;\n\t\t\tcase ' ':\n\t\t\t\tevent.preventDefault();\n\t\t\t\tfitToView();\n\t\t\t\tbreak;\n\t\t}\n\t};\n\n\tif (config.events?.enableClickToFocus) {\n\t\tcanvas.addEventListener('mousedown', handleMouseDown);\n\t\tcanvas.addEventListener('click', handleCanvasClick);\n\t\tcanvas.addEventListener('dblclick', handleDoubleClick);\n\t}\n\n\tif (config.events?.enableKeyboardControls) {\n\t\tcanvas.setAttribute('tabindex', '0');\n\t\tcanvas.addEventListener('keydown', handleKeydown);\n\t}\n\n\tconst dispose = () => {\n\t\tcanvas.removeEventListener('mousedown', handleMouseDown);\n\t\tcanvas.removeEventListener('click', handleCanvasClick);\n\t\tcanvas.removeEventListener('dblclick', handleDoubleClick);\n\t\tcanvas.removeEventListener('keydown', handleKeydown);\n\t\tclearSelection();\n\t};\n\n\treturn { dispose, fitToView, clearSelection };\n}\n\nfunction setupControls(\n\tcamera: THREE.PerspectiveCamera,\n\tcanvas: HTMLCanvasElement,\n\tconfig: Required<ThreeInitializerOptions>\n): OrbitControls {\n\tconst controls = new OrbitControls(camera, canvas);\n\n\tconst target = config.camera.target;\n\tif (target) {\n\t\tcontrols.target.set(target.x, target.y, target.z);\n\t}\n\n\tcontrols.enableDamping = config.controls.enableDamping || false;\n\tcontrols.dampingFactor = config.controls.dampingFactor || 0.05;\n\n\tcontrols.autoRotate = config.controls.autoRotate || false;\n\tcontrols.autoRotateSpeed = config.controls.autoRotateSpeed || 0.5;\n\n\tcontrols.enableZoom = config.controls.enableZoom ?? true;\n\tcontrols.enablePan = config.controls.enablePan ?? true;\n\tcontrols.minDistance = config.controls.minDistance || 0.001;\n\tcontrols.maxDistance = config.controls.maxDistance || Infinity;\n\n\tcontrols.screenSpacePanning = false;\n\tcontrols.maxPolarAngle = Math.PI;\n\n\tcontrols.update();\n\treturn controls;\n}\n","import * as THREE from 'three';\nimport { OrbitControls } from 'three/addons/controls/OrbitControls.js';\nimport { getLogger } from '@/core';\n\n// Camera configuration constants\nconst CAMERA_CONFIG = {\n\tHUGE_THRESHOLD: 10000,\n\tLARGE_THRESHOLD: 1000,\n\tSCALE_RATIO_THRESHOLD: 100,\n\tNEAR_PLANE_FACTOR: {\n\t\tTINY: 0.0001,\n\t\tSMALL: 0.001,\n\t\tNORMAL: 0.01\n\t},\n\tFAR_PLANE_FACTOR: {\n\t\tHUGE: 100,\n\t\tLARGE: 50,\n\t\tNORMAL: 20\n\t},\n\tINITIAL_DISTANCE_MULTIPLIER: 4\n};\n\n/**\n * Updates the scene with the given meshes and camera settings.\n * If initialPositionSet is false, it positions the camera and sets the controls target based on the bounding boxes of the meshes.\n * @param scene - The THREE.Scene object to update.\n * @param meshes - An array of THREE.Mesh objects to add to the scene.\n * @param camera - The THREE.PerspectiveCamera object to position.\n * @param controls - The OrbitControls object to update.\n * @param initialPositionSet - A boolean indicating whether the initial position of the camera and controls have been set.\n */\nexport function updateScene(\n\tscene: THREE.Scene,\n\tmeshes: THREE.Mesh[],\n\tcamera: THREE.PerspectiveCamera,\n\tcontrols: OrbitControls,\n\tinitialPositionSet: boolean\n) {\n\tclearScene(scene);\n\n\tif (meshes.length === 0) return;\n\n\t// Add new meshes to scene\n\tmeshes.forEach((mesh) => {\n\t\tscene.add(mesh);\n\t});\n\n\t// Calculate bounds of the new content\n\tconst unionBoundingBox = computeCombinedBoundingBox(meshes);\n\n\t// Get the center of the union bounding box\n\tconst center = unionBoundingBox.getCenter(new THREE.Vector3());\n\tconst size = unionBoundingBox.getSize(new THREE.Vector3());\n\n\t// Calculate a distance that is slightly larger than the largest dimension of the union bounding box\n\tconst maxDim = Math.max(size.x, size.y, size.z);\n\n\t// Always update camera frustum to ensure geometry is visible\n\t// This prevents clipping when geometry size changes significantly\n\tconst scaleRatio = maxDim / Math.min(size.x || 1, size.y || 1, size.z || 1);\n\n\tif (scaleRatio > CAMERA_CONFIG.SCALE_RATIO_THRESHOLD || maxDim > CAMERA_CONFIG.HUGE_THRESHOLD) {\n\t\t// Large scale range detected - use logarithmic depth buffer approach\n\t\tcamera.near = maxDim * CAMERA_CONFIG.NEAR_PLANE_FACTOR.TINY;\n\t\tcamera.far = maxDim * CAMERA_CONFIG.FAR_PLANE_FACTOR.HUGE;\n\t} else if (maxDim > CAMERA_CONFIG.LARGE_THRESHOLD) {\n\t\t// Large scene\n\t\tcamera.near = maxDim * CAMERA_CONFIG.NEAR_PLANE_FACTOR.SMALL;\n\t\tcamera.far = maxDim * CAMERA_CONFIG.FAR_PLANE_FACTOR.LARGE;\n\t} else {\n\t\t// Normal scene\n\t\tcamera.near = Math.max(0.01, maxDim * CAMERA_CONFIG.NEAR_PLANE_FACTOR.NORMAL);\n\t\tcamera.far = Math.max(2000, maxDim * CAMERA_CONFIG.FAR_PLANE_FACTOR.NORMAL);\n\t}\n\n\tcamera.updateProjectionMatrix();\n\n\t// Only reposition camera and controls on first frame\n\tif (!initialPositionSet) {\n\t\tconst distance = maxDim * CAMERA_CONFIG.INITIAL_DISTANCE_MULTIPLIER;\n\n\t\tcamera.position.set(center.x + distance * 0.8, center.y + distance, center.z + distance * 1.2);\n\t\tcontrols.target.copy(center);\n\t\tcontrols.minDistance = camera.near * 2;\n\t\tcontrols.maxDistance = camera.far * 0.9;\n\n\t\tcontrols.update();\n\t} else {\n\t\t// Update control constraints to match new frustum\n\t\tcontrols.minDistance = camera.near * 2;\n\t\tcontrols.maxDistance = camera.far * 0.9;\n\t}\n}\n\n// =========================\n// Helper functions\n// =========================\n\n/**\n * Parses a color string in multiple formats to a THREE.Color object.\n * Supported formats:\n * - Hex: \"#C7A5A5\", \"C7A5A5\"\n * - RGB: \"199, 165, 165\"\n * - CSS named colors: \"red\", \"blue\", etc.\n * @param colorString - The color string to parse.\n * @returns A THREE.Color object.\n */\nexport function parseColor(colorString: string): THREE.Color {\n\tif (!colorString || typeof colorString !== 'string') {\n\t\tgetLogger().warn(`Invalid color input: ${colorString}, using white`);\n\t\treturn new THREE.Color(0xffffff);\n\t}\n\n\tconst trimmed = colorString.trim();\n\n\t// Try hex format (#C7A5A5 or C7A5A5)\n\tif (trimmed.startsWith('#') || /^[0-9A-Fa-f]{6}$/.test(trimmed)) {\n\t\ttry {\n\t\t\tconst hex = trimmed.startsWith('#') ? trimmed : `#${trimmed}`;\n\t\t\treturn new THREE.Color(hex);\n\t\t} catch {\n\t\t\tgetLogger().warn(`Invalid hex color: ${colorString}, using white`);\n\t\t\treturn new THREE.Color(0xffffff);\n\t\t}\n\t}\n\n\t// Try RGB format (R, G, B)\n\tif (trimmed.includes(',')) {\n\t\tconst rgb = trimmed.split(',').map((c) => parseInt(c.trim(), 10));\n\t\tif (rgb.length === 3 && rgb.every((n) => !isNaN(n) && n >= 0 && n <= 255)) {\n\t\t\treturn new THREE.Color(rgb[0] / 255, rgb[1] / 255, rgb[2] / 255);\n\t\t}\n\t}\n\n\t// Try CSS named color\n\ttry {\n\t\treturn new THREE.Color(trimmed.toLowerCase());\n\t} catch {\n\t\tgetLogger().warn(`Invalid color string: ${colorString}, using white`);\n\t\treturn new THREE.Color(0xffffff);\n\t}\n}\n\nexport function applyOffset(meshes: THREE.Mesh[], offsetY: number): void {\n\tmeshes.forEach((mesh) => {\n\t\tmesh.position.y -= offsetY;\n\t});\n}\n\n/**\n * Computes the combined world-axis-aligned bounding box of a set of meshes.\n * Correctly accounts for mesh transformations (rotation, position, scale).\n */\nexport function computeCombinedBoundingBox(meshes: THREE.Mesh[]): THREE.Box3 {\n\tconst combinedBoundingBox = new THREE.Box3();\n\tif (meshes.length === 0) return combinedBoundingBox;\n\tmeshes.forEach((mesh) => {\n\t\t// Ensure the world matrix is up to date before calculating the box\n\t\tmesh.updateMatrixWorld(true);\n\t\tconst bbox = new THREE.Box3().setFromObject(mesh);\n\t\tcombinedBoundingBox.union(bbox);\n\t});\n\treturn combinedBoundingBox;\n}\n\n/**\n * Clears the given THREE.Scene by removing all non-floor top-level children and\n * recursively disposing of their geometry and materials.\n *\n * Removes at the top level rather than traversing for meshes, so parent Groups\n * don't accumulate as ghost nodes after their mesh children are disposed.\n */\nfunction clearScene(scene: THREE.Scene): void {\n\t// Snapshot children — we mutate the array via removeFromParent during iteration\n\tconst topLevel = [...scene.children];\n\n\ttopLevel.forEach((object) => {\n\t\tif (object.userData.id === 'floor') return;\n\n\t\t// Recursively dispose all meshes in this subtree\n\t\tobject.traverse((child) => {\n\t\t\tif (!(child instanceof THREE.Mesh)) return;\n\n\t\t\tchild.geometry?.dispose();\n\n\t\t\tconst materials = Array.isArray(child.material) ? child.material : [child.material];\n\t\t\tmaterials.forEach((material) => {\n\t\t\t\t// Walk only own enumerable properties — `for...in` on a Three.js material\n\t\t\t\t// also iterates the prototype chain, which is needlessly expensive.\n\t\t\t\tfor (const value of Object.values(material)) {\n\t\t\t\t\tif (value instanceof THREE.Texture) {\n\t\t\t\t\t\tvalue.dispose();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tmaterial.dispose();\n\t\t\t});\n\t\t});\n\n\t\tobject.removeFromParent();\n\t});\n}\n"]}
1
+ {"version":3,"sources":["/home/runner/work/selva-compute/selva-compute/dist/visualization.cjs","../src/features/visualization/threejs/three-initializer.ts","../src/features/visualization/threejs/three-helpers.ts"],"names":["defaultUp","getScaleValue","scale","mmVal","cmVal","mVal","initThree","canvas","options","config","applyDefaults","scene","createScene","camera","createCamera","renderer","setupRenderer","controls","setupControls","setupEnvironment","setupLighting","addFloor","eventHandlers","setupEventHandlers","parent","getCanvasSize","animate","disposeAnimation","createAnimationLoop","sceneUp","object","material","defaults","bgColor","animateCameraTo","toPosition","toTarget","durationMs","fromPosition","fromTarget","startTime","easeOut","t","tick","elapsed","onFrame","animationId","lastTime","checkResize","width","height","pixelRatio","newW","newH","now","delta","HDRLoader","envMap","error","getLogger","ambientLight","sunlight","pos","shadowSize","shadowNear","shadowFar","floorSize","floorGeometry","floorColor","floorMaterial","floor","selectedObjects","originalMaterials","raycaster","mouse","mouseDownPosition","isFullyVisible","current","fitToView","box","center","size","maxDim","fov","distance","direction","selectionColorObj","clearSelection","obj","handleMouseDown","event","handleCanvasClick","currentMousePosition","rect","intersects","i","clickedObject","clonedMaterial","handleDoubleClick","target","targetPosition","handleKeydown","OrbitControls","CAMERA_CONFIG","updateScene","meshes","initialPositionSet","clearScene","mesh","unionBoundingBox","computeCombinedBoundingBox","parseColor","colorString","trimmed","hex"],"mappings":"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","file":"/home/runner/work/selva-compute/selva-compute/dist/visualization.cjs","sourcesContent":[null,"import * as THREE from 'three';\nimport { OrbitControls } from 'three/addons/controls/OrbitControls.js';\nimport { HDRLoader } from 'three/addons/loaders/HDRLoader.js';\n\nimport { getLogger } from '@/core';\nimport { ThreeInitializerOptions } from '../types';\n\nconst defaultUp = new THREE.Vector3(0, 0, 1);\n\n// Returns scale-specific values for mm, cm, and m scales\nconst getScaleValue = (scale: string, mmVal: number, cmVal: number, mVal: number): number => {\n\tswitch (scale) {\n\t\tcase 'mm':\n\t\t\treturn mmVal;\n\t\tcase 'cm':\n\t\t\treturn cmVal;\n\t\tdefault:\n\t\t\treturn mVal;\n\t}\n};\n\n/**\n * Initializes a Three.js environment with scene, camera, renderer, and event handling.\n */\nexport const initThree = function (\n\tcanvas: HTMLCanvasElement,\n\toptions?: ThreeInitializerOptions\n): {\n\tscene: THREE.Scene;\n\tcamera: THREE.PerspectiveCamera;\n\tcontrols: OrbitControls;\n\trenderer: THREE.WebGLRenderer;\n\tdispose: () => void;\n\tfitToView: () => void;\n\tclearSelection: () => void;\n} {\n\tconst config = applyDefaults(options || {});\n\n\tconst scene = createScene(config);\n\tconst camera = createCamera(config, canvas);\n\tconst renderer = setupRenderer(canvas, config);\n\tconst controls = setupControls(camera, canvas, config);\n\n\tsetupEnvironment(scene, config);\n\tsetupLighting(scene, config);\n\n\tif (config.floor?.enabled) {\n\t\taddFloor(scene, config);\n\t}\n\n\tconst eventHandlers =\n\t\tconfig.events.enableEventHandlers !== false\n\t\t\t? setupEventHandlers(canvas, scene, camera, controls, config)\n\t\t\t: { dispose: () => {}, fitToView: () => {}, clearSelection: () => {} };\n\n\tconst parent = canvas.parentElement;\n\tconst getCanvasSize = () =>\n\t\tparent\n\t\t\t? { width: parent.clientWidth, height: parent.clientHeight }\n\t\t\t: { width: window.innerWidth, height: window.innerHeight };\n\n\t// Resize checked every frame so buffer resize and render happen in the same frame,\n\t// preventing visible blank frames on resize\n\tconst { animate, dispose: disposeAnimation } = createAnimationLoop(\n\t\trenderer,\n\t\tscene,\n\t\tcamera,\n\t\tcontrols,\n\t\tgetCanvasSize,\n\t\tconfig.events.onFrame\n\t);\n\tanimate();\n\n\tconst sceneUp = config.environment?.sceneUp || defaultUp;\n\tscene.up.set(sceneUp.x, sceneUp.y, sceneUp.z);\n\n\tconst dispose = () => {\n\t\tdisposeAnimation();\n\t\teventHandlers.dispose();\n\t\tcontrols.dispose();\n\t\trenderer.dispose();\n\n\t\tscene.traverse((object) => {\n\t\t\tif (object instanceof THREE.Mesh) {\n\t\t\t\tobject.geometry?.dispose();\n\t\t\t\tif (Array.isArray(object.material)) {\n\t\t\t\t\tobject.material.forEach((material) => material.dispose());\n\t\t\t\t} else {\n\t\t\t\t\tobject.material?.dispose();\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t};\n\n\treturn {\n\t\tscene,\n\t\tcamera,\n\t\tcontrols,\n\t\trenderer,\n\t\tdispose,\n\t\tfitToView: eventHandlers.fitToView,\n\t\tclearSelection: eventHandlers.clearSelection\n\t};\n};\n\nfunction applyDefaults(options: ThreeInitializerOptions): Required<ThreeInitializerOptions> {\n\tconst scale = options.sceneScale || 'm';\n\n\t// All Rhino geometry is normalized to METERS (1 unit = 1 meter), sceneScale just changes the viewing perspective\n\tconst scaleDefaults = {\n\t\tmm: {\n\t\t\tcameraDistance: 20,\n\t\t\tnear: 0.1,\n\t\t\tfar: 2000,\n\t\t\tfloorSize: 100,\n\t\t\tlightDistance: 10,\n\t\t\tlightHeight: 20,\n\t\t\tminDistance: 0.1,\n\t\t\tshadowSize: 100,\n\t\t\tscaleFactor: 1000\n\t\t},\n\t\tcm: {\n\t\t\tcameraDistance: 20,\n\t\t\tnear: 0.1,\n\t\t\tfar: 2000,\n\t\t\tfloorSize: 100,\n\t\t\tlightDistance: 25,\n\t\t\tlightHeight: 50,\n\t\t\tminDistance: 0.1,\n\t\t\tshadowSize: 100,\n\t\t\tscaleFactor: 100\n\t\t},\n\t\tm: {\n\t\t\tcameraDistance: 10,\n\t\t\tnear: 0.01,\n\t\t\tfar: 2000,\n\t\t\tfloorSize: 50,\n\t\t\tlightDistance: 25,\n\t\t\tlightHeight: 50,\n\t\t\tminDistance: 0.001,\n\t\t\tshadowSize: 100,\n\t\t\tscaleFactor: 1\n\t\t},\n\t\tinches: {\n\t\t\tcameraDistance: 15,\n\t\t\tnear: 0.1,\n\t\t\tfar: 2000,\n\t\t\tfloorSize: 80,\n\t\t\tlightDistance: 20,\n\t\t\tlightHeight: 40,\n\t\t\tminDistance: 0.1,\n\t\t\tshadowSize: 80,\n\t\t\tscaleFactor: 39.37\n\t\t},\n\t\tfeet: {\n\t\t\tcameraDistance: 8,\n\t\t\tnear: 0.1,\n\t\t\tfar: 2000,\n\t\t\tfloorSize: 40,\n\t\t\tlightDistance: 15,\n\t\t\tlightHeight: 30,\n\t\t\tminDistance: 0.1,\n\t\t\tshadowSize: 60,\n\t\t\tscaleFactor: 3.28084\n\t\t}\n\t};\n\n\tconst defaults = scaleDefaults[scale];\n\n\treturn {\n\t\tsceneScale: scale,\n\t\tcamera: {\n\t\t\tposition:\n\t\t\t\toptions.camera?.position ||\n\t\t\t\tnew THREE.Vector3(\n\t\t\t\t\t-defaults.cameraDistance,\n\t\t\t\t\tdefaults.cameraDistance,\n\t\t\t\t\tdefaults.cameraDistance\n\t\t\t\t),\n\t\t\tfov: options.camera?.fov || 20,\n\t\t\tnear: options.camera?.near || defaults.near,\n\t\t\tfar: options.camera?.far || defaults.far,\n\t\t\ttarget: options.camera?.target || new THREE.Vector3(0, 0, 0)\n\t\t},\n\t\tlighting: {\n\t\t\tenableSunlight: options.lighting?.enableSunlight ?? true,\n\t\t\tsunlightIntensity: options.lighting?.sunlightIntensity || 1,\n\t\t\tsunlightPosition:\n\t\t\t\toptions.lighting?.sunlightPosition ||\n\t\t\t\tnew THREE.Vector3(defaults.lightDistance, defaults.lightHeight, defaults.lightDistance),\n\t\t\tambientLightColor: options.lighting?.ambientLightColor || new THREE.Color(0x404040),\n\t\t\tambientLightIntensity: options.lighting?.ambientLightIntensity || 1,\n\t\t\tsunlightColor: options.lighting?.sunlightColor || 0xffffff // Default to white sunlight\n\t\t},\n\t\tenvironment: {\n\t\t\thdrPath: options.environment?.hdrPath || '/baseHDR.hdr',\n\t\t\tbackgroundColor: options.environment?.backgroundColor || new THREE.Color(0xf0f0f0),\n\t\t\tenableEnvironmentLighting: options.environment?.enableEnvironmentLighting ?? true,\n\t\t\tsceneUp: options.environment?.sceneUp || defaultUp,\n\t\t\tshowEnvironment: options.environment?.showEnvironment ?? false\n\t\t},\n\t\tfloor: {\n\t\t\tenabled: options.floor?.enabled ?? false,\n\t\t\tsize: options.floor?.size || defaults.floorSize,\n\t\t\tcolor: options.floor?.color || new THREE.Color(0x808080),\n\t\t\troughness: options.floor?.roughness || 0.7,\n\t\t\tmetalness: options.floor?.metalness || 0.0,\n\t\t\treceiveShadow: options.floor?.receiveShadow ?? true\n\t\t},\n\t\trender: {\n\t\t\tenableShadows: options.render?.enableShadows ?? true,\n\t\t\tshadowMapSize: options.render?.shadowMapSize || 2048,\n\t\t\tantialias: options.render?.antialias ?? true,\n\t\t\tpixelRatio: options.render?.pixelRatio || Math.min(window.devicePixelRatio, 2),\n\t\t\ttoneMapping: options.render?.toneMapping || THREE.NeutralToneMapping,\n\t\t\ttoneMappingExposure: options.render?.toneMappingExposure || 1,\n\t\t\tpreserveDrawingBuffer: options.render?.preserveDrawingBuffer ?? false\n\t\t},\n\t\tcontrols: {\n\t\t\tenableDamping: options.controls?.enableDamping ?? false,\n\t\t\tdampingFactor: options.controls?.dampingFactor || 0.05,\n\t\t\tautoRotate: options.controls?.autoRotate ?? false,\n\t\t\tautoRotateSpeed: options.controls?.autoRotateSpeed || 0.5,\n\t\t\tenableZoom: options.controls?.enableZoom ?? true,\n\t\t\tenablePan: options.controls?.enablePan ?? true,\n\t\t\tminDistance: options.controls?.minDistance || defaults.minDistance,\n\t\t\tmaxDistance: options.controls?.maxDistance || Infinity\n\t\t},\n\t\tevents: {\n\t\t\tonBackgroundClicked: options.events?.onBackgroundClicked,\n\t\t\tonObjectSelected: options.events?.onObjectSelected,\n\t\t\tonMeshMetadataClicked: options.events?.onMeshMetadataClicked,\n\t\t\tonMeshDoubleClicked: options.events?.onMeshDoubleClicked,\n\t\t\tselectionColor: options.events?.selectionColor || '#ff0000', // Default to red\n\t\t\tenableEventHandlers: options.events?.enableEventHandlers ?? true,\n\t\t\tenableKeyboardControls: options.events?.enableKeyboardControls ?? true,\n\t\t\tenableClickToFocus: options.events?.enableClickToFocus ?? true,\n\t\t\tenableDoubleClickZoom: options.events?.enableDoubleClickZoom ?? true,\n\t\t\tonReady: options.events?.onReady,\n\t\t\tonFrame: options.events?.onFrame\n\t\t}\n\t};\n}\n\nfunction createScene(config: Required<ThreeInitializerOptions>): THREE.Scene {\n\tconst scene = new THREE.Scene();\n\n\tconst bgColor =\n\t\ttypeof config.environment.backgroundColor === 'string'\n\t\t\t? new THREE.Color(config.environment.backgroundColor)\n\t\t\t: config.environment.backgroundColor;\n\tscene.background = bgColor || null;\n\n\treturn scene;\n}\n\nfunction animateCameraTo(\n\tcamera: THREE.PerspectiveCamera,\n\tcontrols: OrbitControls,\n\ttoPosition: THREE.Vector3,\n\ttoTarget: THREE.Vector3,\n\tdurationMs = 200\n): void {\n\tconst fromPosition = camera.position.clone();\n\tconst fromTarget = controls.target.clone();\n\tconst startTime = performance.now();\n\n\tconst easeOut = (t: number) => 1 - Math.pow(1 - t, 3);\n\n\tconst tick = () => {\n\t\tconst elapsed = performance.now() - startTime;\n\t\tconst t = easeOut(Math.min(elapsed / durationMs, 1));\n\n\t\tcamera.position.lerpVectors(fromPosition, toPosition, t);\n\t\tcontrols.target.lerpVectors(fromTarget, toTarget, t);\n\t\tcontrols.update();\n\n\t\tif (t < 1) requestAnimationFrame(tick);\n\t};\n\n\trequestAnimationFrame(tick);\n}\n\n// Resize applied before render so buffer clear and draw happen in the same frame,\n// preventing visible blank frames when the canvas is resized\nfunction createAnimationLoop(\n\trenderer: THREE.WebGLRenderer,\n\tscene: THREE.Scene,\n\tcamera: THREE.PerspectiveCamera,\n\tcontrols: OrbitControls,\n\tgetCanvasSize: () => { width: number; height: number },\n\tonFrame?: (delta: number) => void\n): { animate: () => void; dispose: () => void } {\n\tlet animationId: number | null = null;\n\tlet lastTime = performance.now();\n\n\tconst checkResize = () => {\n\t\tconst { width, height } = getCanvasSize();\n\t\tif (width === 0 || height === 0) return;\n\n\t\tconst pixelRatio = Math.min(window.devicePixelRatio, 2);\n\t\tconst newW = Math.round(width * pixelRatio);\n\t\tconst newH = Math.round(height * pixelRatio);\n\n\t\tif (renderer.domElement.width !== newW || renderer.domElement.height !== newH) {\n\t\t\trenderer.setPixelRatio(pixelRatio);\n\t\t\trenderer.setSize(width, height, false);\n\t\t\tcamera.aspect = width / height;\n\t\t\tcamera.updateProjectionMatrix();\n\t\t}\n\t};\n\n\tconst animate = function () {\n\t\tanimationId = requestAnimationFrame(animate);\n\n\t\tconst now = performance.now();\n\t\tconst delta = (now - lastTime) / 1000;\n\t\tlastTime = now;\n\n\t\tcheckResize();\n\n\t\tif (controls.enableDamping || controls.autoRotate) {\n\t\t\tcontrols.update();\n\t\t}\n\n\t\tonFrame?.(delta);\n\n\t\trenderer.render(scene, camera);\n\t};\n\n\tconst dispose = () => {\n\t\tif (animationId !== null) {\n\t\t\tcancelAnimationFrame(animationId);\n\t\t\tanimationId = null;\n\t\t}\n\t};\n\n\treturn { animate, dispose };\n}\n\nfunction setupEnvironment(scene: THREE.Scene, config: Required<ThreeInitializerOptions>) {\n\tif (config.environment.enableEnvironmentLighting) {\n\t\tnew HDRLoader().load(\n\t\t\tconfig.environment.hdrPath || '/baseHDR.hdr',\n\t\t\tfunction (envMap) {\n\t\t\t\tenvMap.mapping = THREE.EquirectangularReflectionMapping;\n\t\t\t\tscene.environment = envMap;\n\t\t\t\tif (config.environment.showEnvironment) {\n\t\t\t\t\tscene.background = envMap;\n\t\t\t\t}\n\t\t\t\tconfig.events.onReady?.();\n\t\t\t},\n\t\t\tundefined,\n\t\t\tfunction (error) {\n\t\t\t\tgetLogger().warn('HDR texture could not be loaded, falling back to basic lighting:', error);\n\t\t\t\tconfig.events.onReady?.();\n\t\t\t}\n\t\t);\n\t} else {\n\t\tconfig.events.onReady?.();\n\t}\n}\n\nfunction setupLighting(scene: THREE.Scene, config: Required<ThreeInitializerOptions>) {\n\tconst ambientLight = new THREE.AmbientLight(\n\t\tconfig.lighting.ambientLightColor,\n\t\tconfig.lighting.ambientLightIntensity\n\t);\n\tscene.add(ambientLight);\n\n\tif (config.lighting.enableSunlight) {\n\t\tconst sunlight = new THREE.DirectionalLight(\n\t\t\tconfig.lighting.sunlightColor ?? 0xffffff,\n\t\t\tconfig.lighting.sunlightIntensity\n\t\t);\n\t\tconst pos = config.lighting.sunlightPosition;\n\t\tif (pos) {\n\t\t\tsunlight.position.set(pos.x, pos.y, pos.z);\n\t\t}\n\n\t\tif (config.render.enableShadows) {\n\t\t\tsunlight.castShadow = true;\n\t\t\tconst shadowSize = getScaleValue(config.sceneScale, 0.1, 10, 100);\n\n\t\t\tsunlight.shadow.camera.left = -shadowSize;\n\t\t\tsunlight.shadow.camera.right = shadowSize;\n\t\t\tsunlight.shadow.camera.top = shadowSize;\n\t\t\tsunlight.shadow.camera.bottom = -shadowSize;\n\n\t\t\tconst shadowNear = getScaleValue(config.sceneScale, 0.001, 0.1, 0.5);\n\t\t\tconst shadowFar = getScaleValue(config.sceneScale, 1, 100, 500);\n\n\t\t\tsunlight.shadow.camera.near = shadowNear;\n\t\t\tsunlight.shadow.camera.far = shadowFar;\n\n\t\t\tsunlight.shadow.mapSize.width = config.render.shadowMapSize || 2048;\n\t\t\tsunlight.shadow.mapSize.height = config.render.shadowMapSize || 2048;\n\n\t\t\tsunlight.shadow.bias = -0.0001;\n\t\t\tsunlight.shadow.normalBias = 0.02;\n\t\t}\n\n\t\tscene.add(sunlight);\n\t}\n}\n\nfunction addFloor(scene: THREE.Scene, config: Required<ThreeInitializerOptions>) {\n\tconst floorSize = config.floor.size;\n\tconst floorGeometry = new THREE.PlaneGeometry(floorSize, floorSize);\n\n\tconst floorColor =\n\t\ttypeof config.floor.color === 'string'\n\t\t\t? new THREE.Color(config.floor.color)\n\t\t\t: config.floor.color;\n\n\tconst floorMaterial = new THREE.MeshStandardMaterial({\n\t\tcolor: floorColor,\n\t\troughness: config.floor.roughness,\n\t\tmetalness: config.floor.metalness,\n\t\tside: THREE.DoubleSide\n\t});\n\n\tconst floor = new THREE.Mesh(floorGeometry, floorMaterial);\n\tfloor.userData.id = 'floor';\n\tfloor.name = 'floor';\n\tfloor.rotation.x = -Math.PI / 2;\n\tfloor.position.y = 0;\n\n\tif (config.floor.receiveShadow && config.render.enableShadows) {\n\t\tfloor.receiveShadow = true;\n\t}\n\n\tscene.add(floor);\n}\n\nfunction createCamera(\n\tconfig: Required<ThreeInitializerOptions>,\n\tcanvas: HTMLCanvasElement\n): THREE.PerspectiveCamera {\n\tconst parent = canvas.parentElement;\n\tconst width = parent ? parent.clientWidth : window.innerWidth;\n\tconst height = parent ? parent.clientHeight : window.innerHeight;\n\n\tconst camera = new THREE.PerspectiveCamera(\n\t\tconfig.camera.fov,\n\t\twidth / height,\n\t\tconfig.camera.near,\n\t\tconfig.camera.far\n\t);\n\n\tconst pos = config.camera.position;\n\tif (pos) {\n\t\tcamera.position.set(pos.x, pos.y, pos.z);\n\t}\n\n\treturn camera;\n}\n\n// Logarithmic depth buffer improves depth precision for mixed scales (mm to km)\nfunction setupRenderer(\n\tcanvas: HTMLCanvasElement,\n\tconfig: Required<ThreeInitializerOptions>\n): THREE.WebGLRenderer {\n\tconst renderer = new THREE.WebGLRenderer({\n\t\tantialias: config.render.antialias,\n\t\tcanvas,\n\t\talpha: true,\n\t\tpowerPreference: 'high-performance',\n\t\tpreserveDrawingBuffer: config.render.preserveDrawingBuffer,\n\t\tlogarithmicDepthBuffer: true\n\t});\n\n\tconst parent = canvas.parentElement;\n\tconst width = parent ? parent.clientWidth : window.innerWidth;\n\tconst height = parent ? parent.clientHeight : window.innerHeight;\n\n\tif (parent) {\n\t\tcanvas.style.width = '100%';\n\t\tcanvas.style.height = '100%';\n\t\tcanvas.style.display = 'block';\n\t}\n\n\trenderer.setSize(width, height, false);\n\trenderer.setPixelRatio(config.render.pixelRatio || Math.min(window.devicePixelRatio, 2));\n\n\tif (config.render.enableShadows) {\n\t\trenderer.shadowMap.enabled = true;\n\t\trenderer.shadowMap.type = THREE.VSMShadowMap;\n\t}\n\n\trenderer.toneMapping = config.render.toneMapping!;\n\trenderer.toneMappingExposure = config.render.toneMappingExposure || 1.0;\n\trenderer.outputColorSpace = THREE.SRGBColorSpace;\n\n\trenderer.sortObjects = true;\n\n\treturn renderer;\n}\n\nfunction setupEventHandlers(\n\tcanvas: HTMLCanvasElement,\n\tscene: THREE.Scene,\n\tcamera: THREE.PerspectiveCamera,\n\tcontrols: OrbitControls,\n\tconfig: Required<ThreeInitializerOptions>\n): {\n\tdispose: () => void;\n\tfitToView: () => void;\n\tclearSelection: () => void;\n} {\n\tconst selectedObjects = new Set<THREE.Object3D>();\n\tconst originalMaterials = new Map<THREE.Object3D, THREE.Material | THREE.Material[]>();\n\tconst raycaster = new THREE.Raycaster();\n\tconst mouse = new THREE.Vector2();\n\tconst mouseDownPosition = new THREE.Vector2();\n\n\t// An object is hittable only if every ancestor is also visible. Three.js's\n\t// recursive intersect doesn't enforce that — it can hit a visible Mesh inside\n\t// a hidden Group.\n\tconst isFullyVisible = (object: THREE.Object3D): boolean => {\n\t\tlet current: THREE.Object3D | null = object;\n\t\twhile (current) {\n\t\t\tif (!current.visible) return false;\n\t\t\tcurrent = current.parent;\n\t\t}\n\t\treturn true;\n\t};\n\n\tconst fitToView = () => {\n\t\tconst box = new THREE.Box3();\n\n\t\tscene.traverse((object) => {\n\t\t\tif (object.visible && object.userData.id !== 'floor' && object instanceof THREE.Mesh) {\n\t\t\t\tbox.expandByObject(object);\n\t\t\t}\n\t\t});\n\n\t\tif (box.isEmpty()) {\n\t\t\tgetLogger().warn('No objects to fit to view');\n\t\t\treturn;\n\t\t}\n\n\t\tconst center = box.getCenter(new THREE.Vector3());\n\t\tconst size = box.getSize(new THREE.Vector3());\n\n\t\tconst maxDim = Math.max(size.x, size.y, size.z);\n\t\tconst fov = camera.fov * (Math.PI / 180);\n\t\tlet distance = maxDim / (2 * Math.tan(fov / 2));\n\n\t\tdistance *= 1.5;\n\n\t\tconst direction = camera.position.clone().sub(controls.target).normalize();\n\t\tcamera.position.copy(center.clone().add(direction.multiplyScalar(distance)));\n\n\t\tcontrols.target.copy(center);\n\t\tcontrols.update();\n\t};\n\n\tconst selectionColorObj =\n\t\ttypeof config.events.selectionColor === 'string'\n\t\t\t? new THREE.Color(config.events.selectionColor)\n\t\t\t: config.events.selectionColor instanceof THREE.Color\n\t\t\t\t? config.events.selectionColor\n\t\t\t\t: new THREE.Color('#ff0000');\n\n\tconst clearSelection = () => {\n\t\tselectedObjects.forEach((obj) => {\n\t\t\tif (obj instanceof THREE.Mesh && originalMaterials.has(obj)) {\n\t\t\t\tobj.material = originalMaterials.get(obj)!;\n\t\t\t\toriginalMaterials.delete(obj);\n\t\t\t}\n\t\t});\n\t\tselectedObjects.clear();\n\t};\n\n\tconst handleMouseDown = (event: MouseEvent) => {\n\t\tmouseDownPosition.set(event.clientX, event.clientY);\n\t};\n\n\tconst handleCanvasClick = (event: MouseEvent) => {\n\t\t// Ignore if mouse has moved (drag)\n\t\tconst currentMousePosition = new THREE.Vector2(event.clientX, event.clientY);\n\t\tif (mouseDownPosition.distanceTo(currentMousePosition) > 5) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst rect = canvas.getBoundingClientRect();\n\t\tmouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;\n\t\tmouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;\n\n\t\traycaster.setFromCamera(mouse, camera);\n\t\tconst intersects = raycaster\n\t\t\t.intersectObjects(scene.children, true)\n\t\t\t.filter((i) => isFullyVisible(i.object));\n\n\t\tif (intersects.length > 0) {\n\t\t\tconst clickedObject = intersects[0].object;\n\n\t\t\tif (!selectedObjects.has(clickedObject)) {\n\t\t\t\tclearSelection();\n\t\t\t\tselectedObjects.add(clickedObject);\n\n\t\t\t\t// Clone material so we don't affect other meshes\n\t\t\t\tif (\n\t\t\t\t\tclickedObject instanceof THREE.Mesh &&\n\t\t\t\t\tclickedObject.material instanceof THREE.Material\n\t\t\t\t) {\n\t\t\t\t\toriginalMaterials.set(clickedObject, clickedObject.material);\n\n\t\t\t\t\tconst clonedMaterial = clickedObject.material.clone();\n\t\t\t\t\t(clonedMaterial as any).emissive = selectionColorObj.clone();\n\t\t\t\t\tclickedObject.material = clonedMaterial;\n\t\t\t\t}\n\n\t\t\t\tconfig.events?.onObjectSelected?.(clickedObject);\n\n\t\t\t\tif (clickedObject instanceof THREE.Mesh && Object.keys(clickedObject.userData).length > 0) {\n\t\t\t\t\tconfig.events?.onMeshMetadataClicked?.(clickedObject.userData);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tclearSelection();\n\t\t\tconfig.events?.onBackgroundClicked?.({ x: mouse.x, y: mouse.y });\n\t\t}\n\t};\n\n\tconst handleDoubleClick = (event: MouseEvent) => {\n\t\tconst rect = canvas.getBoundingClientRect();\n\t\tmouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;\n\t\tmouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;\n\n\t\traycaster.setFromCamera(mouse, camera);\n\t\tconst intersects = raycaster\n\t\t\t.intersectObjects(scene.children, true)\n\t\t\t.filter((i) => isFullyVisible(i.object));\n\n\t\tif (intersects.length === 0) return;\n\n\t\tconst target = intersects[0].object;\n\t\tconfig.events?.onMeshDoubleClicked?.(target);\n\n\t\tif (!config.events?.enableDoubleClickZoom) return;\n\n\t\tconst box = new THREE.Box3().setFromObject(target);\n\t\tif (box.isEmpty()) return;\n\n\t\tconst center = box.getCenter(new THREE.Vector3());\n\t\tconst size = box.getSize(new THREE.Vector3());\n\t\tconst maxDim = Math.max(size.x, size.y, size.z);\n\t\tconst fov = camera.fov * (Math.PI / 180);\n\t\tconst distance = (maxDim / (2 * Math.tan(fov / 2))) * 1.5;\n\n\t\tconst direction = camera.position.clone().sub(controls.target).normalize();\n\t\tconst targetPosition = center.clone().add(direction.multiplyScalar(distance));\n\n\t\tanimateCameraTo(camera, controls, targetPosition, center);\n\t};\n\n\tconst handleKeydown = (event: KeyboardEvent) => {\n\t\tif (!config.events?.enableKeyboardControls) return;\n\n\t\tswitch (event.key.toLowerCase()) {\n\t\t\tcase 'f':\n\t\t\t\tevent.preventDefault();\n\t\t\t\tfitToView();\n\t\t\t\tbreak;\n\t\t\tcase 'escape':\n\t\t\t\tevent.preventDefault();\n\t\t\t\tclearSelection();\n\t\t\t\tbreak;\n\t\t\tcase ' ':\n\t\t\t\tevent.preventDefault();\n\t\t\t\tfitToView();\n\t\t\t\tbreak;\n\t\t}\n\t};\n\n\tif (config.events?.enableClickToFocus) {\n\t\tcanvas.addEventListener('mousedown', handleMouseDown);\n\t\tcanvas.addEventListener('click', handleCanvasClick);\n\t\tcanvas.addEventListener('dblclick', handleDoubleClick);\n\t}\n\n\tif (config.events?.enableKeyboardControls) {\n\t\tcanvas.setAttribute('tabindex', '0');\n\t\tcanvas.addEventListener('keydown', handleKeydown);\n\t}\n\n\tconst dispose = () => {\n\t\tcanvas.removeEventListener('mousedown', handleMouseDown);\n\t\tcanvas.removeEventListener('click', handleCanvasClick);\n\t\tcanvas.removeEventListener('dblclick', handleDoubleClick);\n\t\tcanvas.removeEventListener('keydown', handleKeydown);\n\t\tclearSelection();\n\t};\n\n\treturn { dispose, fitToView, clearSelection };\n}\n\nfunction setupControls(\n\tcamera: THREE.PerspectiveCamera,\n\tcanvas: HTMLCanvasElement,\n\tconfig: Required<ThreeInitializerOptions>\n): OrbitControls {\n\tconst controls = new OrbitControls(camera, canvas);\n\n\tconst target = config.camera.target;\n\tif (target) {\n\t\tcontrols.target.set(target.x, target.y, target.z);\n\t}\n\n\tcontrols.enableDamping = config.controls.enableDamping || false;\n\tcontrols.dampingFactor = config.controls.dampingFactor || 0.05;\n\n\tcontrols.autoRotate = config.controls.autoRotate || false;\n\tcontrols.autoRotateSpeed = config.controls.autoRotateSpeed || 0.5;\n\n\tcontrols.enableZoom = config.controls.enableZoom ?? true;\n\tcontrols.enablePan = config.controls.enablePan ?? true;\n\tcontrols.minDistance = config.controls.minDistance || 0.001;\n\tcontrols.maxDistance = config.controls.maxDistance || Infinity;\n\n\tcontrols.screenSpacePanning = false;\n\tcontrols.maxPolarAngle = Math.PI;\n\n\tcontrols.update();\n\treturn controls;\n}\n","import * as THREE from 'three';\nimport { OrbitControls } from 'three/addons/controls/OrbitControls.js';\nimport { getLogger } from '@/core';\n\n// Camera configuration constants\nconst CAMERA_CONFIG = {\n\tHUGE_THRESHOLD: 10000,\n\tLARGE_THRESHOLD: 1000,\n\tSCALE_RATIO_THRESHOLD: 100,\n\tNEAR_PLANE_FACTOR: {\n\t\tTINY: 0.0001,\n\t\tSMALL: 0.001,\n\t\tNORMAL: 0.01\n\t},\n\tFAR_PLANE_FACTOR: {\n\t\tHUGE: 100,\n\t\tLARGE: 50,\n\t\tNORMAL: 20\n\t},\n\tINITIAL_DISTANCE_MULTIPLIER: 4\n};\n\n/**\n * Updates the scene with the given meshes and camera settings.\n * If initialPositionSet is false, it positions the camera and sets the controls target based on the bounding boxes of the meshes.\n * @param scene - The THREE.Scene object to update.\n * @param meshes - An array of THREE.Mesh objects to add to the scene.\n * @param camera - The THREE.PerspectiveCamera object to position.\n * @param controls - The OrbitControls object to update.\n * @param initialPositionSet - A boolean indicating whether the initial position of the camera and controls have been set.\n */\nexport function updateScene(\n\tscene: THREE.Scene,\n\tmeshes: THREE.Mesh[],\n\tcamera: THREE.PerspectiveCamera,\n\tcontrols: OrbitControls,\n\tinitialPositionSet: boolean\n) {\n\tclearScene(scene);\n\n\tif (meshes.length === 0) return;\n\n\t// Add new meshes to scene\n\tmeshes.forEach((mesh) => {\n\t\tscene.add(mesh);\n\t});\n\n\t// Calculate bounds of the new content\n\tconst unionBoundingBox = computeCombinedBoundingBox(meshes);\n\n\t// Get the center of the union bounding box\n\tconst center = unionBoundingBox.getCenter(new THREE.Vector3());\n\tconst size = unionBoundingBox.getSize(new THREE.Vector3());\n\n\t// Calculate a distance that is slightly larger than the largest dimension of the union bounding box\n\tconst maxDim = Math.max(size.x, size.y, size.z);\n\n\t// Always update camera frustum to ensure geometry is visible\n\t// This prevents clipping when geometry size changes significantly\n\tconst scaleRatio = maxDim / Math.min(size.x || 1, size.y || 1, size.z || 1);\n\n\tif (scaleRatio > CAMERA_CONFIG.SCALE_RATIO_THRESHOLD || maxDim > CAMERA_CONFIG.HUGE_THRESHOLD) {\n\t\t// Large scale range detected - use logarithmic depth buffer approach\n\t\tcamera.near = maxDim * CAMERA_CONFIG.NEAR_PLANE_FACTOR.TINY;\n\t\tcamera.far = maxDim * CAMERA_CONFIG.FAR_PLANE_FACTOR.HUGE;\n\t} else if (maxDim > CAMERA_CONFIG.LARGE_THRESHOLD) {\n\t\t// Large scene\n\t\tcamera.near = maxDim * CAMERA_CONFIG.NEAR_PLANE_FACTOR.SMALL;\n\t\tcamera.far = maxDim * CAMERA_CONFIG.FAR_PLANE_FACTOR.LARGE;\n\t} else {\n\t\t// Normal scene\n\t\tcamera.near = Math.max(0.01, maxDim * CAMERA_CONFIG.NEAR_PLANE_FACTOR.NORMAL);\n\t\tcamera.far = Math.max(2000, maxDim * CAMERA_CONFIG.FAR_PLANE_FACTOR.NORMAL);\n\t}\n\n\tcamera.updateProjectionMatrix();\n\n\t// Only reposition camera and controls on first frame\n\tif (!initialPositionSet) {\n\t\tconst distance = maxDim * CAMERA_CONFIG.INITIAL_DISTANCE_MULTIPLIER;\n\n\t\tcamera.position.set(center.x + distance * 0.8, center.y + distance, center.z + distance * 1.2);\n\t\tcontrols.target.copy(center);\n\t\tcontrols.minDistance = camera.near * 2;\n\t\tcontrols.maxDistance = camera.far * 0.9;\n\n\t\tcontrols.update();\n\t} else {\n\t\t// Update control constraints to match new frustum\n\t\tcontrols.minDistance = camera.near * 2;\n\t\tcontrols.maxDistance = camera.far * 0.9;\n\t}\n}\n\n// =========================\n// Helper functions\n// =========================\n\n/**\n * Parses a color string in multiple formats to a THREE.Color object.\n * Supported formats:\n * - Hex: \"#C7A5A5\", \"C7A5A5\"\n * - RGB: \"199, 165, 165\"\n * - CSS named colors: \"red\", \"blue\", etc.\n * @param colorString - The color string to parse.\n * @returns A THREE.Color object.\n */\nexport function parseColor(colorString: string): THREE.Color {\n\tif (!colorString || typeof colorString !== 'string') {\n\t\tgetLogger().warn(`Invalid color input: ${colorString}, using white`);\n\t\treturn new THREE.Color(0xffffff);\n\t}\n\n\tconst trimmed = colorString.trim();\n\n\t// Try hex format (#C7A5A5 or C7A5A5) — require exactly 6 hex chars\n\tif (/^#?[0-9A-Fa-f]{6}$/.test(trimmed)) {\n\t\ttry {\n\t\t\tconst hex = trimmed.startsWith('#') ? trimmed : `#${trimmed}`;\n\t\t\treturn new THREE.Color(hex);\n\t\t} catch {\n\t\t\tgetLogger().warn(`Invalid hex color: ${colorString}, using white`);\n\t\t\treturn new THREE.Color(0xffffff);\n\t\t}\n\t}\n\n\t// Try RGB format (R, G, B)\n\tif (trimmed.includes(',')) {\n\t\tconst rgb = trimmed.split(',').map((c) => parseInt(c.trim(), 10));\n\t\tif (rgb.length === 3 && rgb.every((n) => !isNaN(n) && n >= 0 && n <= 255)) {\n\t\t\treturn new THREE.Color(rgb[0] / 255, rgb[1] / 255, rgb[2] / 255);\n\t\t}\n\t}\n\n\t// Try CSS named color\n\ttry {\n\t\treturn new THREE.Color(trimmed.toLowerCase());\n\t} catch {\n\t\tgetLogger().warn(`Invalid color string: ${colorString}, using white`);\n\t\treturn new THREE.Color(0xffffff);\n\t}\n}\n\nexport function applyOffset(meshes: THREE.Mesh[], offsetY: number): void {\n\tmeshes.forEach((mesh) => {\n\t\tmesh.position.y -= offsetY;\n\t});\n}\n\n/**\n * Computes the combined world-axis-aligned bounding box of a set of meshes.\n * Correctly accounts for mesh transformations (rotation, position, scale).\n */\nexport function computeCombinedBoundingBox(meshes: THREE.Mesh[]): THREE.Box3 {\n\tconst combinedBoundingBox = new THREE.Box3();\n\tif (meshes.length === 0) return combinedBoundingBox;\n\tmeshes.forEach((mesh) => {\n\t\t// Ensure the world matrix is up to date before calculating the box\n\t\tmesh.updateMatrixWorld(true);\n\t\tconst bbox = new THREE.Box3().setFromObject(mesh);\n\t\tcombinedBoundingBox.union(bbox);\n\t});\n\treturn combinedBoundingBox;\n}\n\n/**\n * Clears the given THREE.Scene by removing all non-floor top-level children and\n * recursively disposing of their geometry and materials.\n *\n * Removes at the top level rather than traversing for meshes, so parent Groups\n * don't accumulate as ghost nodes after their mesh children are disposed.\n */\nfunction clearScene(scene: THREE.Scene): void {\n\t// Snapshot children — we mutate the array via removeFromParent during iteration\n\tconst topLevel = [...scene.children];\n\n\ttopLevel.forEach((object) => {\n\t\tif (object.userData.id === 'floor') return;\n\n\t\t// Recursively dispose all meshes in this subtree\n\t\tobject.traverse((child) => {\n\t\t\tif (!(child instanceof THREE.Mesh)) return;\n\n\t\t\tchild.geometry?.dispose();\n\n\t\t\tconst materials = Array.isArray(child.material) ? child.material : [child.material];\n\t\t\tmaterials.forEach((material) => {\n\t\t\t\t// Walk only own enumerable properties — `for...in` on a Three.js material\n\t\t\t\t// also iterates the prototype chain, which is needlessly expensive.\n\t\t\t\tfor (const value of Object.values(material)) {\n\t\t\t\t\tif (value instanceof THREE.Texture) {\n\t\t\t\t\t\tvalue.dispose();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tmaterial.dispose();\n\t\t\t});\n\t\t});\n\n\t\tobject.removeFromParent();\n\t});\n}\n"]}
@@ -1,2 +1,2 @@
1
- import{c as G}from"./chunk-PZ4HZLFJ.js";import{a as te,c as O,d as H,e as p}from"./chunk-VK2TSW7S.js";import*as i from"three";import{OrbitControls as ne}from"three/addons/controls/OrbitControls.js";import{HDRLoader as re}from"three/addons/loaders/HDRLoader.js";var W=new i.Vector3(0,0,1),P=(e,r,t,n)=>{switch(e){case"mm":return r;case"cm":return t;default:return n}},$=function(e,r){let t=oe(r||{}),n=ae(t),o=de(t,e),s=he(e,t),a=ue(o,e,t);ce(n,t),le(n,t),t.floor?.enabled&&fe(n,t);let l=t.events.enableEventHandlers!==!1?me(e,n,o,a,t):{dispose:()=>{},fitToView:()=>{},clearSelection:()=>{}},c=e.parentElement,g=()=>c?{width:c.clientWidth,height:c.clientHeight}:{width:window.innerWidth,height:window.innerHeight},{animate:u,dispose:d}=ie(s,n,o,a,g,t.events.onFrame);u();let m=t.environment?.sceneUp||W;return n.up.set(m.x,m.y,m.z),{scene:n,camera:o,controls:a,renderer:s,dispose:()=>{d(),l.dispose(),a.dispose(),s.dispose(),n.traverse(h=>{h instanceof i.Mesh&&(h.geometry?.dispose(),Array.isArray(h.material)?h.material.forEach(x=>x.dispose()):h.material?.dispose())})},fitToView:l.fitToView,clearSelection:l.clearSelection}};function oe(e){let r=e.sceneScale||"m",n={mm:{cameraDistance:20,near:.1,far:2e3,floorSize:100,lightDistance:10,lightHeight:20,minDistance:.1,shadowSize:100,scaleFactor:1e3},cm:{cameraDistance:20,near:.1,far:2e3,floorSize:100,lightDistance:25,lightHeight:50,minDistance:.1,shadowSize:100,scaleFactor:100},m:{cameraDistance:10,near:.01,far:2e3,floorSize:50,lightDistance:25,lightHeight:50,minDistance:.001,shadowSize:100,scaleFactor:1},inches:{cameraDistance:15,near:.1,far:2e3,floorSize:80,lightDistance:20,lightHeight:40,minDistance:.1,shadowSize:80,scaleFactor:39.37},feet:{cameraDistance:8,near:.1,far:2e3,floorSize:40,lightDistance:15,lightHeight:30,minDistance:.1,shadowSize:60,scaleFactor:3.28084}}[r];return{sceneScale:r,camera:{position:e.camera?.position||new i.Vector3(-n.cameraDistance,n.cameraDistance,n.cameraDistance),fov:e.camera?.fov||20,near:e.camera?.near||n.near,far:e.camera?.far||n.far,target:e.camera?.target||new i.Vector3(0,0,0)},lighting:{enableSunlight:e.lighting?.enableSunlight??!0,sunlightIntensity:e.lighting?.sunlightIntensity||1,sunlightPosition:e.lighting?.sunlightPosition||new i.Vector3(n.lightDistance,n.lightHeight,n.lightDistance),ambientLightColor:e.lighting?.ambientLightColor||new i.Color(4210752),ambientLightIntensity:e.lighting?.ambientLightIntensity||1,sunlightColor:e.lighting?.sunlightColor||16777215},environment:{hdrPath:e.environment?.hdrPath||"/baseHDR.hdr",backgroundColor:e.environment?.backgroundColor||new i.Color(15790320),enableEnvironmentLighting:e.environment?.enableEnvironmentLighting??!0,sceneUp:e.environment?.sceneUp||W,showEnvironment:e.environment?.showEnvironment??!1},floor:{enabled:e.floor?.enabled??!1,size:e.floor?.size||n.floorSize,color:e.floor?.color||new i.Color(8421504),roughness:e.floor?.roughness||.7,metalness:e.floor?.metalness||0,receiveShadow:e.floor?.receiveShadow??!0},render:{enableShadows:e.render?.enableShadows??!0,shadowMapSize:e.render?.shadowMapSize||2048,antialias:e.render?.antialias??!0,pixelRatio:e.render?.pixelRatio||Math.min(window.devicePixelRatio,2),toneMapping:e.render?.toneMapping||i.NeutralToneMapping,toneMappingExposure:e.render?.toneMappingExposure||1,preserveDrawingBuffer:e.render?.preserveDrawingBuffer??!1},controls:{enableDamping:e.controls?.enableDamping??!1,dampingFactor:e.controls?.dampingFactor||.05,autoRotate:e.controls?.autoRotate??!1,autoRotateSpeed:e.controls?.autoRotateSpeed||.5,enableZoom:e.controls?.enableZoom??!0,enablePan:e.controls?.enablePan??!0,minDistance:e.controls?.minDistance||n.minDistance,maxDistance:e.controls?.maxDistance||1/0},events:{onBackgroundClicked:e.events?.onBackgroundClicked,onObjectSelected:e.events?.onObjectSelected,onMeshMetadataClicked:e.events?.onMeshMetadataClicked,onMeshDoubleClicked:e.events?.onMeshDoubleClicked,selectionColor:e.events?.selectionColor||"#ff0000",enableEventHandlers:e.events?.enableEventHandlers??!0,enableKeyboardControls:e.events?.enableKeyboardControls??!0,enableClickToFocus:e.events?.enableClickToFocus??!0,enableDoubleClickZoom:e.events?.enableDoubleClickZoom??!0,onReady:e.events?.onReady,onFrame:e.events?.onFrame}}}function ae(e){let r=new i.Scene,t=typeof e.environment.backgroundColor=="string"?new i.Color(e.environment.backgroundColor):e.environment.backgroundColor;return r.background=t||null,r}function se(e,r,t,n,o=200){let s=e.position.clone(),a=r.target.clone(),l=performance.now(),c=u=>1-Math.pow(1-u,3),g=()=>{let u=performance.now()-l,d=c(Math.min(u/o,1));e.position.lerpVectors(s,t,d),r.target.lerpVectors(a,n,d),r.update(),d<1&&requestAnimationFrame(g)};requestAnimationFrame(g)}function ie(e,r,t,n,o,s){let a=null,l=performance.now(),c=()=>{let{width:d,height:m}=o();if(d===0||m===0)return;let w=Math.min(window.devicePixelRatio,2),h=Math.round(d*w),x=Math.round(m*w);(e.domElement.width!==h||e.domElement.height!==x)&&(e.setPixelRatio(w),e.setSize(d,m,!1),t.aspect=d/m,t.updateProjectionMatrix())},g=function(){a=requestAnimationFrame(g);let d=performance.now(),m=(d-l)/1e3;l=d,c(),(n.enableDamping||n.autoRotate)&&n.update(),s?.(m),e.render(r,t)};return{animate:g,dispose:()=>{a!==null&&(cancelAnimationFrame(a),a=null)}}}function ce(e,r){r.environment.enableEnvironmentLighting?new re().load(r.environment.hdrPath||"/baseHDR.hdr",function(t){t.mapping=i.EquirectangularReflectionMapping,e.environment=t,r.environment.showEnvironment&&(e.background=t),r.events.onReady?.()},void 0,function(t){p().warn("HDR texture could not be loaded, falling back to basic lighting:",t),r.events.onReady?.()}):r.events.onReady?.()}function le(e,r){let t=new i.AmbientLight(r.lighting.ambientLightColor,r.lighting.ambientLightIntensity);if(e.add(t),r.lighting.enableSunlight){let n=new i.DirectionalLight(r.lighting.sunlightColor??16777215,r.lighting.sunlightIntensity),o=r.lighting.sunlightPosition;if(o&&n.position.set(o.x,o.y,o.z),r.render.enableShadows){n.castShadow=!0;let s=P(r.sceneScale,.1,10,100);n.shadow.camera.left=-s,n.shadow.camera.right=s,n.shadow.camera.top=s,n.shadow.camera.bottom=-s;let a=P(r.sceneScale,.001,.1,.5),l=P(r.sceneScale,1,100,500);n.shadow.camera.near=a,n.shadow.camera.far=l,n.shadow.mapSize.width=r.render.shadowMapSize||2048,n.shadow.mapSize.height=r.render.shadowMapSize||2048,n.shadow.bias=-1e-4,n.shadow.normalBias=.02}e.add(n)}}function fe(e,r){let t=r.floor.size,n=new i.PlaneGeometry(t,t),o=typeof r.floor.color=="string"?new i.Color(r.floor.color):r.floor.color,s=new i.MeshStandardMaterial({color:o,roughness:r.floor.roughness,metalness:r.floor.metalness,side:i.DoubleSide}),a=new i.Mesh(n,s);a.userData.id="floor",a.name="floor",a.rotation.x=-Math.PI/2,a.position.y=0,r.floor.receiveShadow&&r.render.enableShadows&&(a.receiveShadow=!0),e.add(a)}function de(e,r){let t=r.parentElement,n=t?t.clientWidth:window.innerWidth,o=t?t.clientHeight:window.innerHeight,s=new i.PerspectiveCamera(e.camera.fov,n/o,e.camera.near,e.camera.far),a=e.camera.position;return a&&s.position.set(a.x,a.y,a.z),s}function he(e,r){let t=new i.WebGLRenderer({antialias:r.render.antialias,canvas:e,alpha:!0,powerPreference:"high-performance",preserveDrawingBuffer:r.render.preserveDrawingBuffer,logarithmicDepthBuffer:!0}),n=e.parentElement,o=n?n.clientWidth:window.innerWidth,s=n?n.clientHeight:window.innerHeight;return n&&(e.style.width="100%",e.style.height="100%",e.style.display="block"),t.setSize(o,s,!1),t.setPixelRatio(r.render.pixelRatio||Math.min(window.devicePixelRatio,2)),r.render.enableShadows&&(t.shadowMap.enabled=!0,t.shadowMap.type=i.VSMShadowMap),t.toneMapping=r.render.toneMapping,t.toneMappingExposure=r.render.toneMappingExposure||1,t.outputColorSpace=i.SRGBColorSpace,t.sortObjects=!0,t}function me(e,r,t,n,o){let s=new Set,a=new Map,l=new i.Raycaster,c=new i.Vector2,g=new i.Vector2,u=f=>{let R=f;for(;R;){if(!R.visible)return!1;R=R.parent}return!0},d=()=>{let f=new i.Box3;if(r.traverse(D=>{D.visible&&D.userData.id!=="floor"&&D instanceof i.Mesh&&f.expandByObject(D)}),f.isEmpty()){p().warn("No objects to fit to view");return}let R=f.getCenter(new i.Vector3),M=f.getSize(new i.Vector3),A=Math.max(M.x,M.y,M.z),T=t.fov*(Math.PI/180),v=A/(2*Math.tan(T/2));v*=1.5;let B=t.position.clone().sub(n.target).normalize();t.position.copy(R.clone().add(B.multiplyScalar(v))),n.target.copy(R),n.update()},m=typeof o.events.selectionColor=="string"?new i.Color(o.events.selectionColor):o.events.selectionColor instanceof i.Color?o.events.selectionColor:new i.Color("#ff0000"),w=()=>{s.forEach(f=>{f instanceof i.Mesh&&a.has(f)&&(f.material=a.get(f),a.delete(f))}),s.clear()},h=f=>{g.set(f.clientX,f.clientY)},x=f=>{let R=new i.Vector2(f.clientX,f.clientY);if(g.distanceTo(R)>5)return;let M=e.getBoundingClientRect();c.x=(f.clientX-M.left)/M.width*2-1,c.y=-((f.clientY-M.top)/M.height)*2+1,l.setFromCamera(c,t);let A=l.intersectObjects(r.children,!0).filter(T=>u(T.object));if(A.length>0){let T=A[0].object;if(!s.has(T)){if(w(),s.add(T),T instanceof i.Mesh&&T.material instanceof i.Material){a.set(T,T.material);let v=T.material.clone();v.emissive=m.clone(),T.material=v}o.events?.onObjectSelected?.(T),T instanceof i.Mesh&&Object.keys(T.userData).length>0&&o.events?.onMeshMetadataClicked?.(T.userData)}}else w(),o.events?.onBackgroundClicked?.({x:c.x,y:c.y})},I=f=>{let R=e.getBoundingClientRect();c.x=(f.clientX-R.left)/R.width*2-1,c.y=-((f.clientY-R.top)/R.height)*2+1,l.setFromCamera(c,t);let M=l.intersectObjects(r.children,!0).filter(ee=>u(ee.object));if(M.length===0)return;let A=M[0].object;if(o.events?.onMeshDoubleClicked?.(A),!o.events?.enableDoubleClickZoom)return;let T=new i.Box3().setFromObject(A);if(T.isEmpty())return;let v=T.getCenter(new i.Vector3),B=T.getSize(new i.Vector3),D=Math.max(B.x,B.y,B.z),K=t.fov*(Math.PI/180),X=D/(2*Math.tan(K/2))*1.5,J=t.position.clone().sub(n.target).normalize(),Q=v.clone().add(J.multiplyScalar(X));se(t,n,Q,v)},L=f=>{if(o.events?.enableKeyboardControls)switch(f.key.toLowerCase()){case"f":f.preventDefault(),d();break;case"escape":f.preventDefault(),w();break;case" ":f.preventDefault(),d();break}};return o.events?.enableClickToFocus&&(e.addEventListener("mousedown",h),e.addEventListener("click",x),e.addEventListener("dblclick",I)),o.events?.enableKeyboardControls&&(e.setAttribute("tabindex","0"),e.addEventListener("keydown",L)),{dispose:()=>{e.removeEventListener("mousedown",h),e.removeEventListener("click",x),e.removeEventListener("dblclick",I),e.removeEventListener("keydown",L),w()},fitToView:d,clearSelection:w}}function ue(e,r,t){let n=new ne(e,r),o=t.camera.target;return o&&n.target.set(o.x,o.y,o.z),n.enableDamping=t.controls.enableDamping||!1,n.dampingFactor=t.controls.dampingFactor||.05,n.autoRotate=t.controls.autoRotate||!1,n.autoRotateSpeed=t.controls.autoRotateSpeed||.5,n.enableZoom=t.controls.enableZoom??!0,n.enablePan=t.controls.enablePan??!0,n.minDistance=t.controls.minDistance||.001,n.maxDistance=t.controls.maxDistance||1/0,n.screenSpacePanning=!1,n.maxPolarAngle=Math.PI,n.update(),n}import*as y from"three";var C={HUGE_THRESHOLD:1e4,LARGE_THRESHOLD:1e3,SCALE_RATIO_THRESHOLD:100,NEAR_PLANE_FACTOR:{TINY:1e-4,SMALL:.001,NORMAL:.01},FAR_PLANE_FACTOR:{HUGE:100,LARGE:50,NORMAL:20},INITIAL_DISTANCE_MULTIPLIER:4};function j(e,r,t,n,o){if(Ee(e),r.length===0)return;r.forEach(u=>{e.add(u)});let s=F(r),a=s.getCenter(new y.Vector3),l=s.getSize(new y.Vector3),c=Math.max(l.x,l.y,l.z);if(c/Math.min(l.x||1,l.y||1,l.z||1)>C.SCALE_RATIO_THRESHOLD||c>C.HUGE_THRESHOLD?(t.near=c*C.NEAR_PLANE_FACTOR.TINY,t.far=c*C.FAR_PLANE_FACTOR.HUGE):c>C.LARGE_THRESHOLD?(t.near=c*C.NEAR_PLANE_FACTOR.SMALL,t.far=c*C.FAR_PLANE_FACTOR.LARGE):(t.near=Math.max(.01,c*C.NEAR_PLANE_FACTOR.NORMAL),t.far=Math.max(2e3,c*C.FAR_PLANE_FACTOR.NORMAL)),t.updateProjectionMatrix(),o)n.minDistance=t.near*2,n.maxDistance=t.far*.9;else{let u=c*C.INITIAL_DISTANCE_MULTIPLIER;t.position.set(a.x+u*.8,a.y+u,a.z+u*1.2),n.target.copy(a),n.minDistance=t.near*2,n.maxDistance=t.far*.9,n.update()}}function z(e){if(!e||typeof e!="string")return p().warn(`Invalid color input: ${e}, using white`),new y.Color(16777215);let r=e.trim();if(r.startsWith("#")||/^[0-9A-Fa-f]{6}$/.test(r))try{let t=r.startsWith("#")?r:`#${r}`;return new y.Color(t)}catch{return p().warn(`Invalid hex color: ${e}, using white`),new y.Color(16777215)}if(r.includes(",")){let t=r.split(",").map(n=>parseInt(n.trim(),10));if(t.length===3&&t.every(n=>!isNaN(n)&&n>=0&&n<=255))return new y.Color(t[0]/255,t[1]/255,t[2]/255)}try{return new y.Color(r.toLowerCase())}catch{return p().warn(`Invalid color string: ${e}, using white`),new y.Color(16777215)}}function _(e,r){e.forEach(t=>{t.position.y-=r})}function F(e){let r=new y.Box3;return e.length===0||e.forEach(t=>{t.updateMatrixWorld(!0);let n=new y.Box3().setFromObject(t);r.union(n)}),r}function Ee(e){[...e.children].forEach(t=>{t.userData.id!=="floor"&&(t.traverse(n=>{if(!(n instanceof y.Mesh))return;n.geometry?.dispose(),(Array.isArray(n.material)?n.material:[n.material]).forEach(s=>{for(let a of Object.values(s))a instanceof y.Texture&&a.dispose();s.dispose()})}),t.removeFromParent())})}var V={};te(V,{CONCRETE_MATERIAL:()=>Re,EMISSIVE_MATERIAL:()=>pe,GLASS_MATERIAL:()=>ye,METAL_MATERIAL:()=>ge,PLASTIC_MATERIAL:()=>Te,RUBBER_MATERIAL:()=>we,WOOD_MATERIAL:()=>be});import*as E from"three";var pe=new E.MeshPhysicalMaterial({color:0,emissive:new E.Color(16777215),emissiveIntensity:5,metalness:0,roughness:.2,clearcoat:.3,clearcoatRoughness:.2,depthWrite:!0,depthTest:!0,transparent:!1,alphaTest:0,polygonOffset:!0,side:E.FrontSide,dithering:!0}),ge=new E.MeshPhysicalMaterial({color:new E.Color(0),metalness:.9,roughness:.3,envMapIntensity:1.2,clearcoat:.3,clearcoatRoughness:.2,reflectivity:1,ior:2.5,thickness:1,depthWrite:!0,transparent:!1,alphaTest:0,depthTest:!0,polygonOffset:!0,side:E.FrontSide,dithering:!0}),Re=new E.MeshPhysicalMaterial({color:new E.Color(13421772),metalness:0,roughness:.92,envMapIntensity:.15,clearcoat:.05,clearcoatRoughness:.9,reflectivity:.15,transmission:0,ior:1.45,thickness:0,depthWrite:!0,transparent:!1,alphaTest:.5,depthTest:!0,polygonOffset:!0,side:E.FrontSide,dithering:!0}),Te=new E.MeshPhysicalMaterial({color:new E.Color(16777215),metalness:0,roughness:.3,envMapIntensity:.5,clearcoat:.5,clearcoatRoughness:.1,reflectivity:.5,ior:1.4,transmission:0,transparent:!1,depthWrite:!0,side:E.FrontSide,dithering:!0,polygonOffset:!0,polygonOffsetFactor:1,polygonOffsetUnits:1}),ye=new E.MeshPhysicalMaterial({color:new E.Color(16777215),metalness:0,roughness:0,transmission:.95,transparent:!0,opacity:.3,envMapIntensity:1,clearcoat:1,clearcoatRoughness:0,ior:1.52,reflectivity:.9,thickness:1,side:E.DoubleSide,polygonOffset:!0,polygonOffsetFactor:1,polygonOffsetUnits:1}),we=new E.MeshPhysicalMaterial({color:new E.Color(1710618),metalness:0,roughness:.9,envMapIntensity:.2,clearcoat:.1,clearcoatRoughness:.8,reflectivity:.2,ior:1.3,transmission:0,depthWrite:!0,side:E.FrontSide,polygonOffset:!0,polygonOffsetFactor:1,polygonOffsetUnits:1}),be=new E.MeshPhysicalMaterial({color:new E.Color(8934707),metalness:0,roughness:.7,envMapIntensity:.3,clearcoat:.3,clearcoatRoughness:.4,reflectivity:.3,ior:1.3,transmission:0,depthWrite:!0,side:E.FrontSide,dithering:!0,polygonOffset:!0,polygonOffsetFactor:1,polygonOffsetUnits:1});import*as b from"three";import*as q from"fflate";async function Y(e){return new Promise((r,t)=>{try{let n=()=>{try{let o=G(e),s=q.gunzipSync(o),a=Me(s);r(a)}catch(o){t(new H(o instanceof H?o.message:`Failed to decompress batched data: ${o instanceof Error?o.message:String(o)}`,o instanceof H?o.code:O.VALIDATION_ERROR,{context:{base64StringLength:e.length},originalError:o instanceof Error?o:new Error(String(o))}))}};"requestIdleCallback"in globalThis?globalThis.requestIdleCallback(n,{timeout:5e3}):setTimeout(n,0)}catch(n){t(new H(`Failed to schedule decompression: ${n instanceof Error?n.message:String(n)}`,O.VALIDATION_ERROR,{originalError:n instanceof Error?n:new Error(String(n))}))}})}function Me(e){let r=new DataView(e.buffer,e.byteOffset,e.byteLength),t=0;if(t+4>r.byteLength)throw new H("Insufficient data to read the number of vertex floats.",O.VALIDATION_ERROR,{context:{expectedBytes:4,availableBytes:r.byteLength,offset:t}});let n=r.getUint32(t,!0);if(t+=4,n%3!==0)throw new H("Invalid number of vertex floats; should be divisible by 3.",O.VALIDATION_ERROR,{context:{numVertexFloats:n,remainder:n%3,totalBytes:r.byteLength}});let o=n*Float32Array.BYTES_PER_ELEMENT;if(t+o>r.byteLength)throw new H("Insufficient data to read vertices.",O.VALIDATION_ERROR,{context:{expectedBytes:o,availableBytes:r.byteLength-t,offset:t}});let s=new Float32Array(e.buffer.slice(e.byteOffset+t,e.byteOffset+t+o));if(t+=o,t+4>r.byteLength)throw new H("Insufficient data to read the number of face indices.",O.VALIDATION_ERROR,{context:{expectedBytes:4,availableBytes:r.byteLength-t,offset:t}});let a=r.getUint32(t,!0);t+=4;let l=a*Uint32Array.BYTES_PER_ELEMENT;if(t+l>r.byteLength)throw new H("Insufficient data to read face indices.",O.VALIDATION_ERROR,{context:{expectedBytes:l,availableBytes:r.byteLength-t,offset:t}});let c=new Uint32Array(e.buffer.slice(e.byteOffset+t,e.byteOffset+t+l));return{vertices:s,faces:c}}async function N(e,r){let{mergeByMaterial:t=!0,applyTransforms:n=!0,debug:o=!1}=r??{},s=o?performance.now():0,a=0;try{let l=performance.now(),c=JSON.parse(e);return a=performance.now()-l,await k(c,{mergeByMaterial:t,applyTransforms:n,debug:o,parseTime:a,perfStart:s})}catch(l){return p().error("Error parsing mesh batch:",l),[]}}async function k(e,r){let{mergeByMaterial:t=!0,applyTransforms:n=!0,scaleFactor:o=1,debug:s=!1,parseTime:a=0,perfStart:l=s?performance.now():0}=r??{},c=0,g=0;try{let u=performance.now(),{vertices:d,faces:m}=await Y(e.compressedData);c=performance.now()-u;let w=(e.compressedData.length*.75/1024/1024).toFixed(2),h=((d.byteLength+m.byteLength)/1024/1024).toFixed(2),x=((1-parseFloat(w)/parseFloat(h))*100).toFixed(1);s&&(p().debug("Mesh Batch Stats:"),p().debug(` Materials: ${e.materials.length} | Groups: ${e.groups.length}`),p().debug(` Vertices: ${(d.length/3).toLocaleString()} | Faces: ${(m.length/3).toLocaleString()}`),p().debug(` Compressed: ${w} MB | Uncompressed: ${h} MB`),p().debug(` Compression Ratio: ${x}%`)),n&&ve(d);let I=performance.now(),L=e.materials.map(xe),S=[];for(let f of e.groups)if(t&&f.meshes.length>1){let R=He(f,d,m,L);R.userData.sourceComponentId=e.sourceComponentId??null,S.push(R)}else{let R=Ce(f,d,m,L);for(let M of R)M.userData.sourceComponentId=e.sourceComponentId??null;S.push(...R)}if(o!==1)for(let f of S)f.scale.set(o,o,o);if(g=performance.now()-I,s){let f=performance.now()-l;p().debug("Performance:"),a>0&&p().debug(` Parse JSON: ${a.toFixed(2)}ms`),p().debug(` Decompress: ${c.toFixed(2)}ms`),p().debug(` Create Meshes: ${g.toFixed(2)}ms`),p().debug(` Total: ${f.toFixed(2)}ms`)}return S}catch(u){return p().error("Error parsing mesh batch object:",u),[]}}function xe(e){let r=z(e.color);return new b.MeshPhysicalMaterial({color:r,metalness:e.metalness,roughness:e.roughness,opacity:e.opacity,transparent:e.transparent,side:b.DoubleSide,polygonOffset:!0,polygonOffsetFactor:.5,polygonOffsetUnits:.5,depthWrite:!0,depthTest:!0})}function He(e,r,t,n){let o=new b.BufferGeometry,s=0,a=0;for(let h of e.meshes)s+=h.vertexCount,a+=h.faceCount;let l=new Float32Array(s),c=new Uint32Array(a),g=0,u=0;for(let h of e.meshes){l.set(r.subarray(h.vertexOffset,h.vertexOffset+h.vertexCount),g);let x=t.subarray(h.faceOffset,h.faceOffset+h.faceCount),I=Math.floor(h.vertexOffset/3),S=Math.floor(g/3)-I;for(let f=0;f<x.length;f++)c[u+f]=x[f]+S;g+=h.vertexCount,u+=h.faceCount}o.setAttribute("position",new b.BufferAttribute(l,3)),o.setIndex(new b.BufferAttribute(c,1)),o.computeVertexNormals();let d=new b.Mesh(o,n[e.materialId]),m=e.meshes[0],w=e.meshes.map(h=>h.name).filter(h=>h&&h.length>0);return d.name=w.length>0?w[0]:`merged_material_${e.materialId}`,d.castShadow=!0,d.receiveShadow=!0,d.userData={name:d.name,layer:m?.layer??"",originalIndex:m?.originalIndex??0,metadata:m?.metadata??{},mergedFrom:e.meshes.slice(1).map(h=>({name:h.name,layer:h.layer,originalIndex:h.originalIndex}))},d}function Ce(e,r,t,n){let o=[];for(let s of e.meshes){let a=new b.BufferGeometry,l=r.subarray(s.vertexOffset,s.vertexOffset+s.vertexCount),c=t.subarray(s.faceOffset,s.faceOffset+s.faceCount),g=Math.floor(s.vertexOffset/3),u=new Uint32Array(c.length);for(let m=0;m<c.length;m++)u[m]=c[m]-g;a.setAttribute("position",new b.BufferAttribute(l,3)),a.setIndex(new b.BufferAttribute(u,1)),a.computeVertexNormals();let d=new b.Mesh(a,n[e.materialId]);d.name=s.name,d.userData={name:s.name,layer:s.layer??"",originalIndex:s.originalIndex,metadata:s.metadata??{}},d.castShadow=!0,d.receiveShadow=!0,o.push(d)}return o}function ve(e){let r=Math.cos(-Math.PI/2),t=Math.sin(-Math.PI/2);for(let n=0;n<e.length;n+=3){let o=e[n],s=e[n+1],a=e[n+2];e[n]=o,e[n+1]=s*r-a*t,e[n+2]=s*t+a*r}}var U={Millimeters:1/1e3,Centimeters:1/100,Meters:1,Inches:1/39.37,Feet:1/3.28084},Oe="Display";async function Z(e,r){let t=performance.now(),n=[],{allowScaling:o=!0,allowAutoPosition:s=!0,debug:a=!1,parsing:l={}}=r??{};try{let c=o?Se(e.modelunits):1;return await Ae(e,n,c,l,a),s&&Le(n),n}catch(c){throw De(c,n),c}finally{a&&Fe(t)}}function Se(e){return U[e]??1}async function Ae(e,r,t,n,o){for(let s of e.values){let a=s.InnerTree;for(let l in a){let c=a[l];c&&await Ie(c,r,t,n,o)}}}async function Ie(e,r,t,n,o){for(let s of e)if(s.type.includes(Oe)){let a={mergeByMaterial:!0,applyTransforms:!0,debug:!1,...n},l=await N(s.data,a);if(t!==1)for(let c of l)c.scale.set(t,t,t);r.push(...l),o&&p().debug(`Extracted ${l.length} meshes from batch`)}}function Le(e){if(e.length===0)return;let t=F(e).min.y;_(e,t)}function De(e,r){p().error("An unexpected error occurred:",e),Be(r)}function Be(e){for(let r of e)r.geometry&&r.geometry.dispose(),r.material&&(Array.isArray(r.material)?r.material.forEach(t=>t.dispose()):r.material.dispose())}function Fe(e){let r=performance.now()-e;p().info("Time to process meshes:",`${r.toFixed(2)}ms`)}export{V as Materials,U as SCALE_FACTORS,Z as getThreeMeshesFromComputeResponse,$ as initThree,k as parseMeshBatchObject,j as updateScene};
1
+ import{c as W}from"./chunk-XZUTU46G.js";import{a as te,c as O,d as H,e as p}from"./chunk-CZCPL35F.js";import*as i from"three";import{OrbitControls as ne}from"three/addons/controls/OrbitControls.js";import{HDRLoader as re}from"three/addons/loaders/HDRLoader.js";var $=new i.Vector3(0,0,1),z=(e,r,t,n)=>{switch(e){case"mm":return r;case"cm":return t;default:return n}},j=function(e,r){let t=oe(r||{}),n=ae(t),o=de(t,e),s=he(e,t),a=ue(o,e,t);ce(n,t),le(n,t),t.floor?.enabled&&fe(n,t);let l=t.events.enableEventHandlers!==!1?me(e,n,o,a,t):{dispose:()=>{},fitToView:()=>{},clearSelection:()=>{}},c=e.parentElement,g=()=>c?{width:c.clientWidth,height:c.clientHeight}:{width:window.innerWidth,height:window.innerHeight},{animate:u,dispose:d}=ie(s,n,o,a,g,t.events.onFrame);u();let m=t.environment?.sceneUp||$;return n.up.set(m.x,m.y,m.z),{scene:n,camera:o,controls:a,renderer:s,dispose:()=>{d(),l.dispose(),a.dispose(),s.dispose(),n.traverse(h=>{h instanceof i.Mesh&&(h.geometry?.dispose(),Array.isArray(h.material)?h.material.forEach(x=>x.dispose()):h.material?.dispose())})},fitToView:l.fitToView,clearSelection:l.clearSelection}};function oe(e){let r=e.sceneScale||"m",n={mm:{cameraDistance:20,near:.1,far:2e3,floorSize:100,lightDistance:10,lightHeight:20,minDistance:.1,shadowSize:100,scaleFactor:1e3},cm:{cameraDistance:20,near:.1,far:2e3,floorSize:100,lightDistance:25,lightHeight:50,minDistance:.1,shadowSize:100,scaleFactor:100},m:{cameraDistance:10,near:.01,far:2e3,floorSize:50,lightDistance:25,lightHeight:50,minDistance:.001,shadowSize:100,scaleFactor:1},inches:{cameraDistance:15,near:.1,far:2e3,floorSize:80,lightDistance:20,lightHeight:40,minDistance:.1,shadowSize:80,scaleFactor:39.37},feet:{cameraDistance:8,near:.1,far:2e3,floorSize:40,lightDistance:15,lightHeight:30,minDistance:.1,shadowSize:60,scaleFactor:3.28084}}[r];return{sceneScale:r,camera:{position:e.camera?.position||new i.Vector3(-n.cameraDistance,n.cameraDistance,n.cameraDistance),fov:e.camera?.fov||20,near:e.camera?.near||n.near,far:e.camera?.far||n.far,target:e.camera?.target||new i.Vector3(0,0,0)},lighting:{enableSunlight:e.lighting?.enableSunlight??!0,sunlightIntensity:e.lighting?.sunlightIntensity||1,sunlightPosition:e.lighting?.sunlightPosition||new i.Vector3(n.lightDistance,n.lightHeight,n.lightDistance),ambientLightColor:e.lighting?.ambientLightColor||new i.Color(4210752),ambientLightIntensity:e.lighting?.ambientLightIntensity||1,sunlightColor:e.lighting?.sunlightColor||16777215},environment:{hdrPath:e.environment?.hdrPath||"/baseHDR.hdr",backgroundColor:e.environment?.backgroundColor||new i.Color(15790320),enableEnvironmentLighting:e.environment?.enableEnvironmentLighting??!0,sceneUp:e.environment?.sceneUp||$,showEnvironment:e.environment?.showEnvironment??!1},floor:{enabled:e.floor?.enabled??!1,size:e.floor?.size||n.floorSize,color:e.floor?.color||new i.Color(8421504),roughness:e.floor?.roughness||.7,metalness:e.floor?.metalness||0,receiveShadow:e.floor?.receiveShadow??!0},render:{enableShadows:e.render?.enableShadows??!0,shadowMapSize:e.render?.shadowMapSize||2048,antialias:e.render?.antialias??!0,pixelRatio:e.render?.pixelRatio||Math.min(window.devicePixelRatio,2),toneMapping:e.render?.toneMapping||i.NeutralToneMapping,toneMappingExposure:e.render?.toneMappingExposure||1,preserveDrawingBuffer:e.render?.preserveDrawingBuffer??!1},controls:{enableDamping:e.controls?.enableDamping??!1,dampingFactor:e.controls?.dampingFactor||.05,autoRotate:e.controls?.autoRotate??!1,autoRotateSpeed:e.controls?.autoRotateSpeed||.5,enableZoom:e.controls?.enableZoom??!0,enablePan:e.controls?.enablePan??!0,minDistance:e.controls?.minDistance||n.minDistance,maxDistance:e.controls?.maxDistance||1/0},events:{onBackgroundClicked:e.events?.onBackgroundClicked,onObjectSelected:e.events?.onObjectSelected,onMeshMetadataClicked:e.events?.onMeshMetadataClicked,onMeshDoubleClicked:e.events?.onMeshDoubleClicked,selectionColor:e.events?.selectionColor||"#ff0000",enableEventHandlers:e.events?.enableEventHandlers??!0,enableKeyboardControls:e.events?.enableKeyboardControls??!0,enableClickToFocus:e.events?.enableClickToFocus??!0,enableDoubleClickZoom:e.events?.enableDoubleClickZoom??!0,onReady:e.events?.onReady,onFrame:e.events?.onFrame}}}function ae(e){let r=new i.Scene,t=typeof e.environment.backgroundColor=="string"?new i.Color(e.environment.backgroundColor):e.environment.backgroundColor;return r.background=t||null,r}function se(e,r,t,n,o=200){let s=e.position.clone(),a=r.target.clone(),l=performance.now(),c=u=>1-Math.pow(1-u,3),g=()=>{let u=performance.now()-l,d=c(Math.min(u/o,1));e.position.lerpVectors(s,t,d),r.target.lerpVectors(a,n,d),r.update(),d<1&&requestAnimationFrame(g)};requestAnimationFrame(g)}function ie(e,r,t,n,o,s){let a=null,l=performance.now(),c=()=>{let{width:d,height:m}=o();if(d===0||m===0)return;let y=Math.min(window.devicePixelRatio,2),h=Math.round(d*y),x=Math.round(m*y);(e.domElement.width!==h||e.domElement.height!==x)&&(e.setPixelRatio(y),e.setSize(d,m,!1),t.aspect=d/m,t.updateProjectionMatrix())},g=function(){a=requestAnimationFrame(g);let d=performance.now(),m=(d-l)/1e3;l=d,c(),(n.enableDamping||n.autoRotate)&&n.update(),s?.(m),e.render(r,t)};return{animate:g,dispose:()=>{a!==null&&(cancelAnimationFrame(a),a=null)}}}function ce(e,r){r.environment.enableEnvironmentLighting?new re().load(r.environment.hdrPath||"/baseHDR.hdr",function(t){t.mapping=i.EquirectangularReflectionMapping,e.environment=t,r.environment.showEnvironment&&(e.background=t),r.events.onReady?.()},void 0,function(t){p().warn("HDR texture could not be loaded, falling back to basic lighting:",t),r.events.onReady?.()}):r.events.onReady?.()}function le(e,r){let t=new i.AmbientLight(r.lighting.ambientLightColor,r.lighting.ambientLightIntensity);if(e.add(t),r.lighting.enableSunlight){let n=new i.DirectionalLight(r.lighting.sunlightColor??16777215,r.lighting.sunlightIntensity),o=r.lighting.sunlightPosition;if(o&&n.position.set(o.x,o.y,o.z),r.render.enableShadows){n.castShadow=!0;let s=z(r.sceneScale,.1,10,100);n.shadow.camera.left=-s,n.shadow.camera.right=s,n.shadow.camera.top=s,n.shadow.camera.bottom=-s;let a=z(r.sceneScale,.001,.1,.5),l=z(r.sceneScale,1,100,500);n.shadow.camera.near=a,n.shadow.camera.far=l,n.shadow.mapSize.width=r.render.shadowMapSize||2048,n.shadow.mapSize.height=r.render.shadowMapSize||2048,n.shadow.bias=-1e-4,n.shadow.normalBias=.02}e.add(n)}}function fe(e,r){let t=r.floor.size,n=new i.PlaneGeometry(t,t),o=typeof r.floor.color=="string"?new i.Color(r.floor.color):r.floor.color,s=new i.MeshStandardMaterial({color:o,roughness:r.floor.roughness,metalness:r.floor.metalness,side:i.DoubleSide}),a=new i.Mesh(n,s);a.userData.id="floor",a.name="floor",a.rotation.x=-Math.PI/2,a.position.y=0,r.floor.receiveShadow&&r.render.enableShadows&&(a.receiveShadow=!0),e.add(a)}function de(e,r){let t=r.parentElement,n=t?t.clientWidth:window.innerWidth,o=t?t.clientHeight:window.innerHeight,s=new i.PerspectiveCamera(e.camera.fov,n/o,e.camera.near,e.camera.far),a=e.camera.position;return a&&s.position.set(a.x,a.y,a.z),s}function he(e,r){let t=new i.WebGLRenderer({antialias:r.render.antialias,canvas:e,alpha:!0,powerPreference:"high-performance",preserveDrawingBuffer:r.render.preserveDrawingBuffer,logarithmicDepthBuffer:!0}),n=e.parentElement,o=n?n.clientWidth:window.innerWidth,s=n?n.clientHeight:window.innerHeight;return n&&(e.style.width="100%",e.style.height="100%",e.style.display="block"),t.setSize(o,s,!1),t.setPixelRatio(r.render.pixelRatio||Math.min(window.devicePixelRatio,2)),r.render.enableShadows&&(t.shadowMap.enabled=!0,t.shadowMap.type=i.VSMShadowMap),t.toneMapping=r.render.toneMapping,t.toneMappingExposure=r.render.toneMappingExposure||1,t.outputColorSpace=i.SRGBColorSpace,t.sortObjects=!0,t}function me(e,r,t,n,o){let s=new Set,a=new Map,l=new i.Raycaster,c=new i.Vector2,g=new i.Vector2,u=f=>{let R=f;for(;R;){if(!R.visible)return!1;R=R.parent}return!0},d=()=>{let f=new i.Box3;if(r.traverse(D=>{D.visible&&D.userData.id!=="floor"&&D instanceof i.Mesh&&f.expandByObject(D)}),f.isEmpty()){p().warn("No objects to fit to view");return}let R=f.getCenter(new i.Vector3),M=f.getSize(new i.Vector3),A=Math.max(M.x,M.y,M.z),T=t.fov*(Math.PI/180),C=A/(2*Math.tan(T/2));C*=1.5;let B=t.position.clone().sub(n.target).normalize();t.position.copy(R.clone().add(B.multiplyScalar(C))),n.target.copy(R),n.update()},m=typeof o.events.selectionColor=="string"?new i.Color(o.events.selectionColor):o.events.selectionColor instanceof i.Color?o.events.selectionColor:new i.Color("#ff0000"),y=()=>{s.forEach(f=>{f instanceof i.Mesh&&a.has(f)&&(f.material=a.get(f),a.delete(f))}),s.clear()},h=f=>{g.set(f.clientX,f.clientY)},x=f=>{let R=new i.Vector2(f.clientX,f.clientY);if(g.distanceTo(R)>5)return;let M=e.getBoundingClientRect();c.x=(f.clientX-M.left)/M.width*2-1,c.y=-((f.clientY-M.top)/M.height)*2+1,l.setFromCamera(c,t);let A=l.intersectObjects(r.children,!0).filter(T=>u(T.object));if(A.length>0){let T=A[0].object;if(!s.has(T)){if(y(),s.add(T),T instanceof i.Mesh&&T.material instanceof i.Material){a.set(T,T.material);let C=T.material.clone();C.emissive=m.clone(),T.material=C}o.events?.onObjectSelected?.(T),T instanceof i.Mesh&&Object.keys(T.userData).length>0&&o.events?.onMeshMetadataClicked?.(T.userData)}}else y(),o.events?.onBackgroundClicked?.({x:c.x,y:c.y})},L=f=>{let R=e.getBoundingClientRect();c.x=(f.clientX-R.left)/R.width*2-1,c.y=-((f.clientY-R.top)/R.height)*2+1,l.setFromCamera(c,t);let M=l.intersectObjects(r.children,!0).filter(ee=>u(ee.object));if(M.length===0)return;let A=M[0].object;if(o.events?.onMeshDoubleClicked?.(A),!o.events?.enableDoubleClickZoom)return;let T=new i.Box3().setFromObject(A);if(T.isEmpty())return;let C=T.getCenter(new i.Vector3),B=T.getSize(new i.Vector3),D=Math.max(B.x,B.y,B.z),K=t.fov*(Math.PI/180),X=D/(2*Math.tan(K/2))*1.5,J=t.position.clone().sub(n.target).normalize(),Q=C.clone().add(J.multiplyScalar(X));se(t,n,Q,C)},I=f=>{if(o.events?.enableKeyboardControls)switch(f.key.toLowerCase()){case"f":f.preventDefault(),d();break;case"escape":f.preventDefault(),y();break;case" ":f.preventDefault(),d();break}};return o.events?.enableClickToFocus&&(e.addEventListener("mousedown",h),e.addEventListener("click",x),e.addEventListener("dblclick",L)),o.events?.enableKeyboardControls&&(e.setAttribute("tabindex","0"),e.addEventListener("keydown",I)),{dispose:()=>{e.removeEventListener("mousedown",h),e.removeEventListener("click",x),e.removeEventListener("dblclick",L),e.removeEventListener("keydown",I),y()},fitToView:d,clearSelection:y}}function ue(e,r,t){let n=new ne(e,r),o=t.camera.target;return o&&n.target.set(o.x,o.y,o.z),n.enableDamping=t.controls.enableDamping||!1,n.dampingFactor=t.controls.dampingFactor||.05,n.autoRotate=t.controls.autoRotate||!1,n.autoRotateSpeed=t.controls.autoRotateSpeed||.5,n.enableZoom=t.controls.enableZoom??!0,n.enablePan=t.controls.enablePan??!0,n.minDistance=t.controls.minDistance||.001,n.maxDistance=t.controls.maxDistance||1/0,n.screenSpacePanning=!1,n.maxPolarAngle=Math.PI,n.update(),n}import*as w from"three";var v={HUGE_THRESHOLD:1e4,LARGE_THRESHOLD:1e3,SCALE_RATIO_THRESHOLD:100,NEAR_PLANE_FACTOR:{TINY:1e-4,SMALL:.001,NORMAL:.01},FAR_PLANE_FACTOR:{HUGE:100,LARGE:50,NORMAL:20},INITIAL_DISTANCE_MULTIPLIER:4};function q(e,r,t,n,o){if(Ee(e),r.length===0)return;r.forEach(u=>{e.add(u)});let s=F(r),a=s.getCenter(new w.Vector3),l=s.getSize(new w.Vector3),c=Math.max(l.x,l.y,l.z);if(c/Math.min(l.x||1,l.y||1,l.z||1)>v.SCALE_RATIO_THRESHOLD||c>v.HUGE_THRESHOLD?(t.near=c*v.NEAR_PLANE_FACTOR.TINY,t.far=c*v.FAR_PLANE_FACTOR.HUGE):c>v.LARGE_THRESHOLD?(t.near=c*v.NEAR_PLANE_FACTOR.SMALL,t.far=c*v.FAR_PLANE_FACTOR.LARGE):(t.near=Math.max(.01,c*v.NEAR_PLANE_FACTOR.NORMAL),t.far=Math.max(2e3,c*v.FAR_PLANE_FACTOR.NORMAL)),t.updateProjectionMatrix(),o)n.minDistance=t.near*2,n.maxDistance=t.far*.9;else{let u=c*v.INITIAL_DISTANCE_MULTIPLIER;t.position.set(a.x+u*.8,a.y+u,a.z+u*1.2),n.target.copy(a),n.minDistance=t.near*2,n.maxDistance=t.far*.9,n.update()}}function _(e){if(!e||typeof e!="string")return p().warn(`Invalid color input: ${e}, using white`),new w.Color(16777215);let r=e.trim();if(/^#?[0-9A-Fa-f]{6}$/.test(r))try{let t=r.startsWith("#")?r:`#${r}`;return new w.Color(t)}catch{return p().warn(`Invalid hex color: ${e}, using white`),new w.Color(16777215)}if(r.includes(",")){let t=r.split(",").map(n=>parseInt(n.trim(),10));if(t.length===3&&t.every(n=>!isNaN(n)&&n>=0&&n<=255))return new w.Color(t[0]/255,t[1]/255,t[2]/255)}try{return new w.Color(r.toLowerCase())}catch{return p().warn(`Invalid color string: ${e}, using white`),new w.Color(16777215)}}function V(e,r){e.forEach(t=>{t.position.y-=r})}function F(e){let r=new w.Box3;return e.length===0||e.forEach(t=>{t.updateMatrixWorld(!0);let n=new w.Box3().setFromObject(t);r.union(n)}),r}function Ee(e){[...e.children].forEach(t=>{t.userData.id!=="floor"&&(t.traverse(n=>{if(!(n instanceof w.Mesh))return;n.geometry?.dispose(),(Array.isArray(n.material)?n.material:[n.material]).forEach(s=>{for(let a of Object.values(s))a instanceof w.Texture&&a.dispose();s.dispose()})}),t.removeFromParent())})}var N={};te(N,{CONCRETE_MATERIAL:()=>Re,EMISSIVE_MATERIAL:()=>pe,GLASS_MATERIAL:()=>ye,METAL_MATERIAL:()=>ge,PLASTIC_MATERIAL:()=>Te,RUBBER_MATERIAL:()=>we,WOOD_MATERIAL:()=>be});import*as E from"three";var pe=new E.MeshPhysicalMaterial({color:0,emissive:new E.Color(16777215),emissiveIntensity:5,metalness:0,roughness:.2,clearcoat:.3,clearcoatRoughness:.2,depthWrite:!0,depthTest:!0,transparent:!1,alphaTest:0,polygonOffset:!0,side:E.FrontSide,dithering:!0}),ge=new E.MeshPhysicalMaterial({color:new E.Color(0),metalness:.9,roughness:.3,envMapIntensity:1.2,clearcoat:.3,clearcoatRoughness:.2,reflectivity:1,ior:2.5,thickness:1,depthWrite:!0,transparent:!1,alphaTest:0,depthTest:!0,polygonOffset:!0,side:E.FrontSide,dithering:!0}),Re=new E.MeshPhysicalMaterial({color:new E.Color(13421772),metalness:0,roughness:.92,envMapIntensity:.15,clearcoat:.05,clearcoatRoughness:.9,reflectivity:.15,transmission:0,ior:1.45,thickness:0,depthWrite:!0,transparent:!1,alphaTest:.5,depthTest:!0,polygonOffset:!0,side:E.FrontSide,dithering:!0}),Te=new E.MeshPhysicalMaterial({color:new E.Color(16777215),metalness:0,roughness:.3,envMapIntensity:.5,clearcoat:.5,clearcoatRoughness:.1,reflectivity:.5,ior:1.4,transmission:0,transparent:!1,depthWrite:!0,side:E.FrontSide,dithering:!0,polygonOffset:!0,polygonOffsetFactor:1,polygonOffsetUnits:1}),ye=new E.MeshPhysicalMaterial({color:new E.Color(16777215),metalness:0,roughness:0,transmission:.95,transparent:!0,opacity:.3,envMapIntensity:1,clearcoat:1,clearcoatRoughness:0,ior:1.52,reflectivity:.9,thickness:1,side:E.DoubleSide,polygonOffset:!0,polygonOffsetFactor:1,polygonOffsetUnits:1}),we=new E.MeshPhysicalMaterial({color:new E.Color(1710618),metalness:0,roughness:.9,envMapIntensity:.2,clearcoat:.1,clearcoatRoughness:.8,reflectivity:.2,ior:1.3,transmission:0,depthWrite:!0,side:E.FrontSide,polygonOffset:!0,polygonOffsetFactor:1,polygonOffsetUnits:1}),be=new E.MeshPhysicalMaterial({color:new E.Color(8934707),metalness:0,roughness:.7,envMapIntensity:.3,clearcoat:.3,clearcoatRoughness:.4,reflectivity:.3,ior:1.3,transmission:0,depthWrite:!0,side:E.FrontSide,dithering:!0,polygonOffset:!0,polygonOffsetFactor:1,polygonOffsetUnits:1});import*as b from"three";import*as P from"fflate";var Me=typeof globalThis<"u"&&typeof globalThis.window<"u"&&typeof globalThis.document<"u";async function Y(e,r=!1){let t=W(e),n;try{n=Me?await new Promise((o,s)=>{P.gunzip(t,(a,l)=>{a?s(a):o(l)})}):P.gunzipSync(t)}catch(o){throw new H(`Failed to decompress batched data: ${o instanceof Error?o.message:String(o)}`,O.VALIDATION_ERROR,{context:{base64StringLength:e.length},originalError:o instanceof Error?o:new Error(String(o))})}try{return xe(n,r)}catch(o){throw new H(o instanceof H?o.message:`Failed to parse decompressed batched data: ${o instanceof Error?o.message:String(o)}`,o instanceof H?o.code:O.VALIDATION_ERROR,{context:{base64StringLength:e.length},originalError:o instanceof Error?o:new Error(String(o))})}}function xe(e,r){let t=new DataView(e.buffer,e.byteOffset,e.byteLength),n=0;if(n+4>t.byteLength)throw new H("Insufficient data to read the number of vertex floats.",O.VALIDATION_ERROR,{context:{expectedBytes:4,availableBytes:t.byteLength,offset:n}});let o=t.getUint32(n,!0);if(n+=4,o%3!==0)throw new H("Invalid number of vertex floats; should be divisible by 3.",O.VALIDATION_ERROR,{context:{numVertexFloats:o,remainder:o%3,totalBytes:t.byteLength}});let s=o*Float32Array.BYTES_PER_ELEMENT;if(n+s>t.byteLength)throw new H("Insufficient data to read vertices.",O.VALIDATION_ERROR,{context:{expectedBytes:s,availableBytes:t.byteLength-n,offset:n}});let a=e.byteOffset+n,l;if(r){let d=new Float32Array(e.buffer,a,o);l=new Float32Array(o);for(let m=0;m<o;m+=3){let y=d[m+1],h=d[m+2];l[m]=d[m],l[m+1]=h,l[m+2]=-y}}else l=new Float32Array(e.buffer,a,o);if(n+=s,n+4>t.byteLength)throw new H("Insufficient data to read the number of face indices.",O.VALIDATION_ERROR,{context:{expectedBytes:4,availableBytes:t.byteLength-n,offset:n}});let c=t.getUint32(n,!0);n+=4;let g=c*Uint32Array.BYTES_PER_ELEMENT;if(n+g>t.byteLength)throw new H("Insufficient data to read face indices.",O.VALIDATION_ERROR,{context:{expectedBytes:g,availableBytes:t.byteLength-n,offset:n}});let u=new Uint32Array(e.buffer,e.byteOffset+n,c);return{vertices:l,faces:u}}async function k(e,r){let{mergeByMaterial:t=!0,applyTransforms:n=!0,debug:o=!1}=r??{},s=o?performance.now():0,a=0;try{let l=performance.now(),c=JSON.parse(e);return a=performance.now()-l,await U(c,{mergeByMaterial:t,applyTransforms:n,debug:o,parseTime:a,perfStart:s})}catch(l){return p().error("Error parsing mesh batch:",l),[]}}async function U(e,r){let{mergeByMaterial:t=!0,applyTransforms:n=!0,scaleFactor:o=1,debug:s=!1,parseTime:a=0,perfStart:l=s?performance.now():0}=r??{},c=0,g=0;try{let u=performance.now(),{vertices:d,faces:m}=await Y(e.compressedData,n);c=performance.now()-u;let y=(e.compressedData.length*.75/1024/1024).toFixed(2),h=((d.byteLength+m.byteLength)/1024/1024).toFixed(2),x=((1-parseFloat(y)/parseFloat(h))*100).toFixed(1);s&&(p().debug("Mesh Batch Stats:"),p().debug(` Materials: ${e.materials.length} | Groups: ${e.groups.length}`),p().debug(` Vertices: ${(d.length/3).toLocaleString()} | Faces: ${(m.length/3).toLocaleString()}`),p().debug(` Compressed: ${y} MB | Uncompressed: ${h} MB`),p().debug(` Compression Ratio: ${x}%`));let L=performance.now(),I=e.materials.map(He),S=[];for(let f of e.groups)if(t&&f.meshes.length>1){let R=ve(f,d,m,I);R.userData.sourceComponentId=e.sourceComponentId??null,S.push(R)}else{let R=Ce(f,d,m,I);for(let M of R)M.userData.sourceComponentId=e.sourceComponentId??null;S.push(...R)}if(o!==1)for(let f of S)f.scale.set(o,o,o);if(g=performance.now()-L,s){let f=performance.now()-l;p().debug("Performance:"),a>0&&p().debug(` Parse JSON: ${a.toFixed(2)}ms`),p().debug(` Decompress: ${c.toFixed(2)}ms`),p().debug(` Create Meshes: ${g.toFixed(2)}ms`),p().debug(` Total: ${f.toFixed(2)}ms`)}return S}catch(u){return p().error("Error parsing mesh batch object:",u),[]}}function He(e){let r=_(e.color);return new b.MeshPhysicalMaterial({color:r,metalness:e.metalness,roughness:e.roughness,opacity:e.opacity,transparent:e.transparent,side:b.DoubleSide,polygonOffset:!0,polygonOffsetFactor:.5,polygonOffsetUnits:.5,depthWrite:!0,depthTest:!0})}function ve(e,r,t,n){let o=new b.BufferGeometry,s=0,a=0;for(let h of e.meshes)s+=h.vertexCount,a+=h.faceCount;let l=new Float32Array(s),c=new Uint32Array(a),g=0,u=0;for(let h of e.meshes){l.set(r.subarray(h.vertexOffset,h.vertexOffset+h.vertexCount),g);let x=t.subarray(h.faceOffset,h.faceOffset+h.faceCount),L=Math.floor(h.vertexOffset/3),S=Math.floor(g/3)-L;for(let f=0;f<x.length;f++)c[u+f]=x[f]+S;g+=h.vertexCount,u+=h.faceCount}o.setAttribute("position",new b.BufferAttribute(l,3)),o.setIndex(new b.BufferAttribute(c,1)),o.computeVertexNormals();let d=new b.Mesh(o,n[e.materialId]),m=e.meshes[0],y=e.meshes.map(h=>h.name).filter(h=>h&&h.length>0);return d.name=y.length>0?y[0]:`merged_material_${e.materialId}`,d.castShadow=!0,d.receiveShadow=!0,d.userData={name:d.name,layer:m?.layer??"",originalIndex:m?.originalIndex??0,metadata:m?.metadata??{},mergedFrom:e.meshes.slice(1).map(h=>({name:h.name,layer:h.layer,originalIndex:h.originalIndex}))},d}function Ce(e,r,t,n){let o=[];for(let s of e.meshes){let a=new b.BufferGeometry,l=r.subarray(s.vertexOffset,s.vertexOffset+s.vertexCount),c=t.subarray(s.faceOffset,s.faceOffset+s.faceCount),g=Math.floor(s.vertexOffset/3),u=new Uint32Array(c.length);for(let m=0;m<c.length;m++)u[m]=c[m]-g;a.setAttribute("position",new b.BufferAttribute(l,3)),a.setIndex(new b.BufferAttribute(u,1)),a.computeVertexNormals();let d=new b.Mesh(a,n[e.materialId]);d.name=s.name,d.userData={name:s.name,layer:s.layer??"",originalIndex:s.originalIndex,metadata:s.metadata??{}},d.castShadow=!0,d.receiveShadow=!0,o.push(d)}return o}var G={Millimeters:1/1e3,Centimeters:1/100,Meters:1,Inches:1/39.37,Feet:1/3.28084},Oe="Display";async function Z(e,r){let t=performance.now(),n=[],{allowScaling:o=!0,allowAutoPosition:s=!0,debug:a=!1,parsing:l={}}=r??{};try{let c=o?Se(e.modelunits):1;return await Ae(e,n,c,l,a),s&&Ie(n),n}catch(c){throw De(c,n),c}finally{a&&Fe(t)}}function Se(e){return G[e]??1}async function Ae(e,r,t,n,o){for(let s of e.values){let a=s.InnerTree;for(let l in a){let c=a[l];c&&await Le(c,r,t,n,o)}}}async function Le(e,r,t,n,o){for(let s of e)if(s.type.includes(Oe)){let a={mergeByMaterial:!0,applyTransforms:!0,debug:!1,...n},l=await k(s.data,a);if(t!==1)for(let c of l)c.scale.set(t,t,t);r.push(...l),o&&p().debug(`Extracted ${l.length} meshes from batch`)}}function Ie(e){if(e.length===0)return;let t=F(e).min.y;V(e,t)}function De(e,r){p().error("An unexpected error occurred:",e),Be(r)}function Be(e){for(let r of e)r.geometry&&r.geometry.dispose(),r.material&&(Array.isArray(r.material)?r.material.forEach(t=>t.dispose()):r.material.dispose())}function Fe(e){let r=performance.now()-e;p().info("Time to process meshes:",`${r.toFixed(2)}ms`)}export{N as Materials,G as SCALE_FACTORS,Z as getThreeMeshesFromComputeResponse,j as initThree,U as parseMeshBatchObject,q as updateScene};
2
2
  //# sourceMappingURL=visualization.js.map