@selvajs/compute 2.0.0 → 2.1.0-beta.1

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.
Files changed (35) hide show
  1. package/dist/chunk-JPXUC3P5.cjs +54 -0
  2. package/dist/chunk-JPXUC3P5.cjs.map +1 -0
  3. package/dist/{chunk-YNVXBKBY.cjs → chunk-P4SF7AKZ.cjs} +2 -2
  4. package/dist/{chunk-YNVXBKBY.cjs.map → chunk-P4SF7AKZ.cjs.map} +1 -1
  5. package/dist/{chunk-UQ3QRF72.js → chunk-SKAHIC4G.js} +2 -2
  6. package/dist/chunk-Z4TVQVMV.js +54 -0
  7. package/dist/chunk-Z4TVQVMV.js.map +1 -0
  8. package/dist/grasshopper.cjs +1 -1
  9. package/dist/grasshopper.d.cts +4 -3
  10. package/dist/grasshopper.d.ts +4 -3
  11. package/dist/grasshopper.js +1 -1
  12. package/dist/index.cjs +1 -1
  13. package/dist/index.d.cts +2 -1
  14. package/dist/index.d.ts +2 -1
  15. package/dist/index.js +1 -1
  16. package/dist/{types-CJ092lxB.d.cts → types-BuRCHPlb.d.cts} +94 -3
  17. package/dist/{types-XCUrJGby.d.ts → types-jPuWWtnU.d.ts} +94 -3
  18. package/dist/visualization-R7QUUUWV.js +2 -0
  19. package/dist/visualization-ZDXKGD2L.cjs +2 -0
  20. package/dist/visualization-ZDXKGD2L.cjs.map +1 -0
  21. package/dist/visualization.cjs +1 -1
  22. package/dist/visualization.cjs.map +1 -1
  23. package/dist/visualization.d.cts +193 -7
  24. package/dist/visualization.d.ts +193 -7
  25. package/dist/visualization.js +1 -1
  26. package/package.json +1 -1
  27. package/dist/chunk-JFLD2UCY.cjs +0 -2
  28. package/dist/chunk-JFLD2UCY.cjs.map +0 -1
  29. package/dist/chunk-MKW2KTPT.js +0 -2
  30. package/dist/chunk-MKW2KTPT.js.map +0 -1
  31. package/dist/visualization-GU7JIB4V.cjs +0 -2
  32. package/dist/visualization-GU7JIB4V.cjs.map +0 -1
  33. package/dist/visualization-WIUVT2FZ.js +0 -2
  34. /package/dist/{chunk-UQ3QRF72.js.map → chunk-SKAHIC4G.js.map} +0 -0
  35. /package/dist/{visualization-WIUVT2FZ.js.map → visualization-R7QUUUWV.js.map} +0 -0
@@ -1,6 +1,8 @@
1
1
  import * as THREE from 'three';
2
2
  import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
3
- import { f as GrasshopperComputeResponse, M as MeshExtractionOptions, m as MeshBatchParsingOptions, n as MeshBatch } from './types-XCUrJGby.js';
3
+ import { f as GrasshopperComputeResponse, M as MeshExtractionOptions, m as MeshBatchParsingOptions, n as DisplayBatch, o as DisplayItem } from './types-jPuWWtnU.js';
4
+ export { p as DisplayCurve, q as DisplayIdentity, r as DisplayItemBase, s as DisplayPoint, t as DisplayPosition, u as MeshBatch } from './types-jPuWWtnU.js';
5
+ import { RhinoModule } from 'rhino3dm';
4
6
  import './types-D1SkNje_.js';
5
7
 
6
8
  type CameraConfig = {
@@ -41,6 +43,24 @@ type RenderConfig = {
41
43
  toneMapping?: THREE.ToneMapping;
42
44
  toneMappingExposure?: number;
43
45
  preserveDrawingBuffer?: boolean;
46
+ /**
47
+ * Enable ground-truth ambient occlusion (GTAO) via a postprocessing pipeline. Default false —
48
+ * turning it on switches rendering from `renderer.render` to an EffectComposer, which costs more.
49
+ */
50
+ ambientOcclusion?: boolean;
51
+ /** AO strength 0–1 when {@link RenderConfig.ambientOcclusion} is on. Default 1. */
52
+ aoIntensity?: number;
53
+ };
54
+ /** Crisp boundary/crease edge overlays on meshes. See `addEdges`. */
55
+ type EdgesConfig = {
56
+ /** Auto-attach edge overlays to meshes as they load. Default false (opt-in). */
57
+ enabled?: boolean;
58
+ /** Edge color. Default near-black. */
59
+ color?: THREE.ColorRepresentation;
60
+ /** Edge thickness in CSS px. Default 1.5. */
61
+ width?: number;
62
+ /** Crease angle (degrees): keep edges where faces differ by more than this. Default 30. */
63
+ thresholdAngle?: number;
44
64
  };
45
65
  type ControlsConfig = {
46
66
  enableDamping?: boolean;
@@ -52,6 +72,44 @@ type ControlsConfig = {
52
72
  minDistance?: number;
53
73
  maxDistance?: number;
54
74
  };
75
+ /** Infinite distance-fading reference grid. See `createGrid`. */
76
+ type GridConfig = {
77
+ /** Show the grid. Default false (opt-in). */
78
+ enabled?: boolean;
79
+ /** Minor cell size in world units (meters). Default 1. */
80
+ cellSize?: number;
81
+ /** Minor cells per major line. Default 10. */
82
+ majorEvery?: number;
83
+ /** Minor line color. */
84
+ cellColor?: THREE.ColorRepresentation;
85
+ /** Major line color. */
86
+ majorColor?: THREE.ColorRepresentation;
87
+ /** World radius at which the grid fully fades. Default 100. */
88
+ fadeDistance?: number;
89
+ /** Plane the grid lies on. 'y' = horizontal ground. Default 'y'. */
90
+ plane?: 'x' | 'y' | 'z';
91
+ };
92
+ /** Corner nav-cube/axis gizmo that snaps to preset views. See `createViewGizmo`. */
93
+ type GizmoConfig = {
94
+ /** Show the gizmo. Default false (opt-in). */
95
+ enabled?: boolean;
96
+ };
97
+ /** Two-click distance measurement tool. See `createMeasureTool`. */
98
+ type MeasureConfig = {
99
+ /**
100
+ * Create the measurement tool. Default false. Note: this only *builds* the tool (and its label
101
+ * overlay); start measuring by calling `measureTool.setEnabled(true)` on the init result.
102
+ */
103
+ enabled?: boolean;
104
+ /** Snap to a vertex within this many screen px. Default 12. */
105
+ snapPixels?: number;
106
+ /** Marker + line color. Default yellow. */
107
+ color?: THREE.ColorRepresentation;
108
+ /** CSS class for the distance label. */
109
+ labelClassName?: string;
110
+ /** Format the distance number → label text. Default 3 sig-digits + " m". */
111
+ format?: (distance: number) => string;
112
+ };
55
113
  type ThreeInitializerOptions = {
56
114
  sceneScale?: 'mm' | 'cm' | 'm' | 'inches' | 'feet';
57
115
  camera?: CameraConfig;
@@ -60,6 +118,10 @@ type ThreeInitializerOptions = {
60
118
  floor?: FloorConfig;
61
119
  render?: RenderConfig;
62
120
  controls?: ControlsConfig;
121
+ grid?: GridConfig;
122
+ gizmo?: GizmoConfig;
123
+ edges?: EdgesConfig;
124
+ measure?: MeasureConfig;
63
125
  events?: EventConfig;
64
126
  };
65
127
  type EventConfig = {
@@ -86,6 +148,105 @@ type EventConfig = {
86
148
  onFrame?: (delta: number) => void;
87
149
  };
88
150
 
151
+ /**
152
+ * Runtime camera control for the viewer: preset views (top/front/…), a true 2D/3D toggle
153
+ * (orthographic ⇄ perspective), and a rotate lock.
154
+ *
155
+ * Why a controller and not just loose methods: all three features have to agree on *which* camera
156
+ * is active. Switching projection swaps the camera object OrbitControls drives, the animation loop
157
+ * renders, the resize handler reshapes, and the raycaster picks with. Centralizing that here keeps
158
+ * those four call sites reading one source of truth ({@link getActiveCamera}) instead of each
159
+ * branching on a `mode` flag.
160
+ *
161
+ * The perspective camera stays the primary (it's what {@link updateScene} and existing consumers
162
+ * size). The orthographic camera shadows it: same position/target, frustum derived from the
163
+ * perspective FOV + current distance so the 3D→2D switch doesn't visually jump.
164
+ */
165
+ /** The six axis-aligned presets plus the default 3/4 iso. Named in Three's Y-up frame. */
166
+ type ViewPreset = 'top' | 'bottom' | 'front' | 'back' | 'left' | 'right' | 'iso';
167
+ type CameraProjection = 'perspective' | 'orthographic';
168
+ interface CameraController {
169
+ /** The camera currently being rendered/picked with. Swaps identity on {@link setProjection}. */
170
+ getActiveCamera(): THREE.Camera;
171
+ /** Current projection mode. */
172
+ getProjection(): CameraProjection;
173
+ /** Switch between perspective (3D) and orthographic (2D). No-op if already in that mode. */
174
+ setProjection(projection: CameraProjection): void;
175
+ /** Convenience toggle for a 2D/3D button. */
176
+ toggleProjection(): CameraProjection;
177
+ /** Move the camera to a preset orientation, framing current scene content. Animated. */
178
+ setView(preset: ViewPreset, animate?: boolean): void;
179
+ /** Enable/disable orbit rotation at runtime (pan/zoom unaffected). */
180
+ setRotateEnabled(enabled: boolean): void;
181
+ /** Whether rotation is currently enabled. */
182
+ isRotateEnabled(): boolean;
183
+ /** Keep the orthographic frustum aspect in sync on canvas resize. Called by the resize loop. */
184
+ updateAspect(width: number, height: number): void;
185
+ }
186
+
187
+ interface Grid {
188
+ /** The grid mesh; add to the scene. Tagged `userData.id = 'grid'` so pick/fit code skips it. */
189
+ readonly object: THREE.Mesh;
190
+ /** Keep the fade centered on the camera so the grid feels infinite as you move. Call per frame. */
191
+ update(cameraPosition: THREE.Vector3): void;
192
+ setVisible(visible: boolean): void;
193
+ dispose(): void;
194
+ }
195
+
196
+ /**
197
+ * The corner nav-cube/axis gizmo. Wraps three's {@link ViewHelper} (the standard, well-tested
198
+ * widget) and uses its built-in click → animate behavior, which we keep rather than reimplement:
199
+ * ViewHelper's hit-test depends on private internals (`dim`, `interactiveObjects`, viewport math),
200
+ * so replicating it is fragile. We let it drive the perspective camera directly.
201
+ *
202
+ * Two integration points with the viewer's dual-camera setup:
203
+ * 1. Before each click we point `helper.center` at the live orbit target, so the snap rotates about
204
+ * what the user is looking at (not the world origin).
205
+ * 2. ViewHelper only drives the perspective camera. The nav cube is inherently a 3D-orientation
206
+ * tool, so if the viewer is in orthographic (2D) mode when the gizmo is clicked, we first flip
207
+ * back to perspective — then ViewHelper animates as usual. Using the cube returns you to 3D.
208
+ *
209
+ * Caller responsibilities (mirror ViewHelper's own contract):
210
+ * - call {@link ViewGizmo.render} *after* the main scene render each frame (overlay viewport),
211
+ * - call {@link ViewGizmo.update} each frame with the frame delta (drives the snap animation),
212
+ * - forward pointer clicks to {@link ViewGizmo.handleClick}.
213
+ */
214
+ interface ViewGizmo {
215
+ render(renderer: THREE.WebGLRenderer): void;
216
+ update(delta: number): void;
217
+ /** Hit-test a click. Returns true if it hit the gizmo (and a view change started). */
218
+ handleClick(event: MouseEvent): boolean;
219
+ readonly isAnimating: boolean;
220
+ /** Show/hide the gizmo at runtime. Hidden = not rendered and not click-hittable. */
221
+ setVisible(visible: boolean): void;
222
+ isVisible(): boolean;
223
+ dispose(): void;
224
+ }
225
+
226
+ /**
227
+ * A two-click distance measurement tool — the CAD verb users expect. Click a point, click a second,
228
+ * read the distance off a label on the connecting line; a third click starts a new measurement.
229
+ *
230
+ * Picking snaps to geometry so measurements are exact, not "wherever the ray happened to land":
231
+ * on a mesh hit we snap to the nearest vertex of the struck triangle if it's within
232
+ * {@link MeasureOptions.snapPixels} on screen, else use the raw hit point. This is a cheap local
233
+ * snap (three candidate vertices), no spatial index — enough for clean vertex-to-vertex measurement
234
+ * without the cost/complexity of full edge/midpoint snapping (a later refinement).
235
+ *
236
+ * The tool is dormant until {@link MeasureTool.setEnabled}(true). While enabled it intercepts clicks
237
+ * (the caller forwards them and swallows the event when {@link MeasureTool.handleClick} returns
238
+ * true) so measuring doesn't also select objects.
239
+ */
240
+ interface MeasureTool {
241
+ setEnabled(enabled: boolean): void;
242
+ isEnabled(): boolean;
243
+ /** Process a click. Returns true if the tool consumed it (caller should not also select). */
244
+ handleClick(event: MouseEvent): boolean;
245
+ /** Clear the current measurement (markers, line, label). */
246
+ clear(): void;
247
+ dispose(): void;
248
+ }
249
+
89
250
  /**
90
251
  * Initializes a Three.js environment with scene, camera, renderer, and event handling.
91
252
  */
@@ -94,6 +255,18 @@ declare const initThree: (canvas: HTMLCanvasElement, options?: ThreeInitializerO
94
255
  camera: THREE.PerspectiveCamera;
95
256
  controls: OrbitControls;
96
257
  renderer: THREE.WebGLRenderer;
258
+ cameraController: CameraController;
259
+ grid: Grid | null;
260
+ gizmo: ViewGizmo | null;
261
+ /** Two-click distance measurement tool. Null unless `measure.enabled`; `setEnabled(true)` to use. */
262
+ measureTool: MeasureTool | null;
263
+ /**
264
+ * Attach edge overlays to the meshes under `root` (no-op unless `edges.enabled`). Call after
265
+ * loading meshes via `updateScene`, since meshes arrive after init.
266
+ */
267
+ applyEdges: (root: THREE.Object3D) => void;
268
+ /** Toggle ambient occlusion at runtime — builds or tears down the postprocessing pipeline. */
269
+ setAmbientOcclusion: (enabled: boolean) => void;
97
270
  dispose: () => void;
98
271
  fitToView: () => void;
99
272
  clearSelection: () => void;
@@ -108,7 +281,7 @@ declare const initThree: (canvas: HTMLCanvasElement, options?: ThreeInitializerO
108
281
  * @param controls - The OrbitControls object to update.
109
282
  * @param initialPositionSet - A boolean indicating whether the initial position of the camera and controls have been set.
110
283
  */
111
- declare function updateScene(scene: THREE.Scene, meshes: THREE.Mesh[], camera: THREE.PerspectiveCamera, controls: OrbitControls, initialPositionSet: boolean): void;
284
+ declare function updateScene(scene: THREE.Scene, meshes: THREE.Object3D[], camera: THREE.PerspectiveCamera, controls: OrbitControls, initialPositionSet: boolean): void;
112
285
 
113
286
  declare const EMISSIVE_MATERIAL: THREE.MeshPhysicalMaterial;
114
287
  declare const METAL_MATERIAL: THREE.MeshPhysicalMaterial;
@@ -174,7 +347,7 @@ declare const SCALE_FACTORS: Record<string, number>;
174
347
  * });
175
348
  * ```
176
349
  */
177
- declare function getThreeMeshesFromComputeResponse(data: GrasshopperComputeResponse, options?: MeshExtractionOptions): Promise<THREE.Mesh[]>;
350
+ declare function getThreeMeshesFromComputeResponse(data: GrasshopperComputeResponse, options?: MeshExtractionOptions): Promise<THREE.Object3D[]>;
178
351
 
179
352
  /**
180
353
  * Internal-only telemetry threaded from an outer entry point (e.g. the JSON
@@ -186,17 +359,17 @@ interface ParseTelemetry {
186
359
  perfStart?: number;
187
360
  }
188
361
  /**
189
- * Parses a MeshBatch object and creates Three.js meshes.
362
+ * Parses a DisplayBatch object and creates Three.js meshes from its mesh blob.
190
363
  *
191
364
  * The path is synchronous internally — `parseBinaryMeshBatch` does no IO, just typed-array views
192
365
  * over the blob. The function stays `async` so callers don't have to change shape if we move
193
366
  * parsing into a worker later.
194
367
  *
195
- * @param batch - MeshBatch object
368
+ * @param batch - DisplayBatch object
196
369
  * @param options - Rendering options
197
370
  * @returns Promise resolving to array of Three.js mesh objects
198
371
  */
199
- declare function parseMeshBatchObject(batch: MeshBatch, options?: MeshBatchParsingOptions & {
372
+ declare function parseMeshBatchObject(batch: DisplayBatch, options?: MeshBatchParsingOptions & {
200
373
  /** Scale factor to apply to meshes (e.g., for unit conversion) */
201
374
  scaleFactor?: number;
202
375
  },
@@ -219,4 +392,17 @@ declare function parseMeshBatchBlob(blob: ArrayBuffer | Uint8Array, options?: Me
219
392
  scaleFactor?: number;
220
393
  }): Promise<THREE.Mesh[]>;
221
394
 
222
- export { type CameraConfig, type ControlsConfig, type EnvironmentConfig, type EventConfig, type FloorConfig, type LightingConfig, threeMaterials as Materials, MeshBatch, MeshExtractionOptions, type RenderConfig, SCALE_FACTORS, type ThreeInitializerOptions, getThreeMeshesFromComputeResponse, initThree, parseMeshBatchBlob, parseMeshBatchObject, updateScene };
395
+ interface DisplayItemParseOptions {
396
+ /** rhino3dm instance for decoding curve JSON. Omit to skip curves (points still render). */
397
+ rhino?: RhinoModule;
398
+ /** Apply the Rhino Z-up → Three Y-up transform. Defaults to true (matches the mesh path). */
399
+ applyTransforms?: boolean;
400
+ }
401
+ /**
402
+ * Parse a batch's `items` into renderable THREE objects. Returns an empty array when there are no
403
+ * items. Unknown kinds are skipped with a warning (forward-compatible with future label/icon kinds
404
+ * a viewer hasn't taught itself to render yet).
405
+ */
406
+ declare function parseDisplayItems(items: DisplayItem[] | undefined, options?: DisplayItemParseOptions): THREE.Object3D[];
407
+
408
+ export { type CameraConfig, type ControlsConfig, DisplayBatch, DisplayItem, type DisplayItemParseOptions, type EnvironmentConfig, type EventConfig, type FloorConfig, type LightingConfig, threeMaterials as Materials, MeshExtractionOptions, type RenderConfig, SCALE_FACTORS, type ThreeInitializerOptions, getThreeMeshesFromComputeResponse, initThree, parseDisplayItems, parseMeshBatchBlob, parseMeshBatchObject, updateScene };
@@ -1,2 +1,2 @@
1
- import{a as e,b as o,f as t,l as r,m as i,n,o as s}from"./chunk-MKW2KTPT.js";import"./chunk-GTTKNF4G.js";export{t as Materials,n as SCALE_FACTORS,s as getThreeMeshesFromComputeResponse,e as initThree,i as parseMeshBatchBlob,r as parseMeshBatchObject,o as updateScene};
1
+ import{A as p,a as e,p as t,q as i,r as s,x as o,y as a,z as r}from"./chunk-Z4TVQVMV.js";import"./chunk-GTTKNF4G.js";export{i as Materials,r as SCALE_FACTORS,p as getThreeMeshesFromComputeResponse,t as initThree,s as parseDisplayItems,a as parseMeshBatchBlob,o as parseMeshBatchObject,e as updateScene};
2
2
  //# sourceMappingURL=visualization.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@selvajs/compute",
3
- "version": "2.0.0",
3
+ "version": "2.1.0-beta.1",
4
4
  "description": "TypeScript library for Rhino Compute Server - Grasshopper and RhinoCommon",
5
5
  "author": "VektorNode",
6
6
  "license": "MIT",
@@ -1,2 +0,0 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }var _chunkMA6YB3YZcjs = require('./chunk-MA6YB3YZ.cjs');var _three = require('three'); var i = _interopRequireWildcard(_three); var w = _interopRequireWildcard(_three); var b = _interopRequireWildcard(_three); var M = _interopRequireWildcard(_three);var _OrbitControlsjs = require('three/addons/controls/OrbitControls.js');var _HDRLoaderjs = require('three/addons/loaders/HDRLoader.js');var V=new i.Vector3(0,0,1),P=(e,r,n,t)=>{switch(e){case"mm":return r;case"cm":return n;default:return t}},Ze= exports.a =function(e,r){let n=oe(r||{}),t=ae(n),o=de(n,e),s=me(e,n),a=he(o,e,n);ce(t,n),le(t,n),_optionalChain([n, 'access', _2 => _2.floor, 'optionalAccess', _3 => _3.enabled])&&ue(t,n);let u=n.events.enableEventHandlers!==!1?fe(e,t,o,a,n):{dispose:()=>{},fitToView:()=>{},clearSelection:()=>{}},c=e.parentElement,h=()=>c?{width:c.clientWidth,height:c.clientHeight}:{width:window.innerWidth,height:window.innerHeight},{animate:m,dispose:l}=ie(s,t,o,a,h,n.events.onFrame);m();let E=_optionalChain([n, 'access', _4 => _4.environment, 'optionalAccess', _5 => _5.sceneUp])||V;return t.up.set(E.x,E.y,E.z),{scene:t,camera:o,controls:a,renderer:s,dispose:()=>{l(),u.dispose(),a.dispose(),s.dispose(),t.traverse(d=>{d instanceof i.Mesh&&(_optionalChain([d, 'access', _6 => _6.geometry, 'optionalAccess', _7 => _7.dispose, 'call', _8 => _8()]),Array.isArray(d.material)?d.material.forEach(H=>H.dispose()):_optionalChain([d, 'access', _9 => _9.material, 'optionalAccess', _10 => _10.dispose, 'call', _11 => _11()]))})},fitToView:u.fitToView,clearSelection:u.clearSelection}};function oe(e){let r=e.sceneScale||"m",t={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:_optionalChain([e, 'access', _12 => _12.camera, 'optionalAccess', _13 => _13.position])||new i.Vector3(-t.cameraDistance,t.cameraDistance,t.cameraDistance),fov:_optionalChain([e, 'access', _14 => _14.camera, 'optionalAccess', _15 => _15.fov])||20,near:_optionalChain([e, 'access', _16 => _16.camera, 'optionalAccess', _17 => _17.near])||t.near,far:_optionalChain([e, 'access', _18 => _18.camera, 'optionalAccess', _19 => _19.far])||t.far,target:_optionalChain([e, 'access', _20 => _20.camera, 'optionalAccess', _21 => _21.target])||new i.Vector3(0,0,0)},lighting:{enableSunlight:_nullishCoalesce(_optionalChain([e, 'access', _22 => _22.lighting, 'optionalAccess', _23 => _23.enableSunlight]), () => (!0)),sunlightIntensity:_optionalChain([e, 'access', _24 => _24.lighting, 'optionalAccess', _25 => _25.sunlightIntensity])||1,sunlightPosition:_optionalChain([e, 'access', _26 => _26.lighting, 'optionalAccess', _27 => _27.sunlightPosition])||new i.Vector3(t.lightDistance,t.lightHeight,t.lightDistance),ambientLightColor:_optionalChain([e, 'access', _28 => _28.lighting, 'optionalAccess', _29 => _29.ambientLightColor])||new i.Color(4210752),ambientLightIntensity:_optionalChain([e, 'access', _30 => _30.lighting, 'optionalAccess', _31 => _31.ambientLightIntensity])||1,sunlightColor:_optionalChain([e, 'access', _32 => _32.lighting, 'optionalAccess', _33 => _33.sunlightColor])||16777215},environment:{hdrPath:_optionalChain([e, 'access', _34 => _34.environment, 'optionalAccess', _35 => _35.hdrPath])||"/baseHDR.hdr",backgroundColor:_optionalChain([e, 'access', _36 => _36.environment, 'optionalAccess', _37 => _37.backgroundColor])||new i.Color(15790320),enableEnvironmentLighting:_nullishCoalesce(_optionalChain([e, 'access', _38 => _38.environment, 'optionalAccess', _39 => _39.enableEnvironmentLighting]), () => (!0)),sceneUp:_optionalChain([e, 'access', _40 => _40.environment, 'optionalAccess', _41 => _41.sceneUp])||V,showEnvironment:_nullishCoalesce(_optionalChain([e, 'access', _42 => _42.environment, 'optionalAccess', _43 => _43.showEnvironment]), () => (!1))},floor:{enabled:_nullishCoalesce(_optionalChain([e, 'access', _44 => _44.floor, 'optionalAccess', _45 => _45.enabled]), () => (!1)),size:_optionalChain([e, 'access', _46 => _46.floor, 'optionalAccess', _47 => _47.size])||t.floorSize,color:_optionalChain([e, 'access', _48 => _48.floor, 'optionalAccess', _49 => _49.color])||new i.Color(8421504),roughness:_optionalChain([e, 'access', _50 => _50.floor, 'optionalAccess', _51 => _51.roughness])||.7,metalness:_optionalChain([e, 'access', _52 => _52.floor, 'optionalAccess', _53 => _53.metalness])||0,receiveShadow:_nullishCoalesce(_optionalChain([e, 'access', _54 => _54.floor, 'optionalAccess', _55 => _55.receiveShadow]), () => (!0))},render:{enableShadows:_nullishCoalesce(_optionalChain([e, 'access', _56 => _56.render, 'optionalAccess', _57 => _57.enableShadows]), () => (!0)),shadowMapSize:_optionalChain([e, 'access', _58 => _58.render, 'optionalAccess', _59 => _59.shadowMapSize])||2048,antialias:_nullishCoalesce(_optionalChain([e, 'access', _60 => _60.render, 'optionalAccess', _61 => _61.antialias]), () => (!0)),pixelRatio:_optionalChain([e, 'access', _62 => _62.render, 'optionalAccess', _63 => _63.pixelRatio])||Math.min(window.devicePixelRatio,2),toneMapping:_optionalChain([e, 'access', _64 => _64.render, 'optionalAccess', _65 => _65.toneMapping])||i.NeutralToneMapping,toneMappingExposure:_optionalChain([e, 'access', _66 => _66.render, 'optionalAccess', _67 => _67.toneMappingExposure])||1,preserveDrawingBuffer:_nullishCoalesce(_optionalChain([e, 'access', _68 => _68.render, 'optionalAccess', _69 => _69.preserveDrawingBuffer]), () => (!1))},controls:{enableDamping:_nullishCoalesce(_optionalChain([e, 'access', _70 => _70.controls, 'optionalAccess', _71 => _71.enableDamping]), () => (!1)),dampingFactor:_optionalChain([e, 'access', _72 => _72.controls, 'optionalAccess', _73 => _73.dampingFactor])||.05,autoRotate:_nullishCoalesce(_optionalChain([e, 'access', _74 => _74.controls, 'optionalAccess', _75 => _75.autoRotate]), () => (!1)),autoRotateSpeed:_optionalChain([e, 'access', _76 => _76.controls, 'optionalAccess', _77 => _77.autoRotateSpeed])||.5,enableZoom:_nullishCoalesce(_optionalChain([e, 'access', _78 => _78.controls, 'optionalAccess', _79 => _79.enableZoom]), () => (!0)),enablePan:_nullishCoalesce(_optionalChain([e, 'access', _80 => _80.controls, 'optionalAccess', _81 => _81.enablePan]), () => (!0)),minDistance:_optionalChain([e, 'access', _82 => _82.controls, 'optionalAccess', _83 => _83.minDistance])||t.minDistance,maxDistance:_optionalChain([e, 'access', _84 => _84.controls, 'optionalAccess', _85 => _85.maxDistance])||1/0},events:{onBackgroundClicked:_optionalChain([e, 'access', _86 => _86.events, 'optionalAccess', _87 => _87.onBackgroundClicked]),onObjectSelected:_optionalChain([e, 'access', _88 => _88.events, 'optionalAccess', _89 => _89.onObjectSelected]),onMeshMetadataClicked:_optionalChain([e, 'access', _90 => _90.events, 'optionalAccess', _91 => _91.onMeshMetadataClicked]),onMeshDoubleClicked:_optionalChain([e, 'access', _92 => _92.events, 'optionalAccess', _93 => _93.onMeshDoubleClicked]),selectionColor:_optionalChain([e, 'access', _94 => _94.events, 'optionalAccess', _95 => _95.selectionColor])||"#ff0000",enableEventHandlers:_nullishCoalesce(_optionalChain([e, 'access', _96 => _96.events, 'optionalAccess', _97 => _97.enableEventHandlers]), () => (!0)),enableKeyboardControls:_nullishCoalesce(_optionalChain([e, 'access', _98 => _98.events, 'optionalAccess', _99 => _99.enableKeyboardControls]), () => (!0)),enableClickToFocus:_nullishCoalesce(_optionalChain([e, 'access', _100 => _100.events, 'optionalAccess', _101 => _101.enableClickToFocus]), () => (!0)),enableDoubleClickZoom:_nullishCoalesce(_optionalChain([e, 'access', _102 => _102.events, 'optionalAccess', _103 => _103.enableDoubleClickZoom]), () => (!0)),onReady:_optionalChain([e, 'access', _104 => _104.events, 'optionalAccess', _105 => _105.onReady]),onFrame:_optionalChain([e, 'access', _106 => _106.events, 'optionalAccess', _107 => _107.onFrame])}}}function ae(e){let r=new i.Scene,n=typeof e.environment.backgroundColor=="string"?new i.Color(e.environment.backgroundColor):e.environment.backgroundColor;return r.background=n||null,r}function se(e,r,n,t,o=200){let s=e.position.clone(),a=r.target.clone(),u=performance.now(),c=m=>1-Math.pow(1-m,3),h=()=>{let m=performance.now()-u,l=c(Math.min(m/o,1));e.position.lerpVectors(s,n,l),r.target.lerpVectors(a,t,l),r.update(),l<1&&requestAnimationFrame(h)};requestAnimationFrame(h)}function ie(e,r,n,t,o,s){let a=null,u=performance.now(),c=()=>{let{width:l,height:E}=o();if(l===0||E===0)return;let g=Math.min(window.devicePixelRatio,2),d=Math.round(l*g),H=Math.round(E*g);(e.domElement.width!==d||e.domElement.height!==H)&&(e.setPixelRatio(g),e.setSize(l,E,!1),n.aspect=l/E,n.updateProjectionMatrix())},h=function(){a=requestAnimationFrame(h);let l=performance.now(),E=(l-u)/1e3;u=l,c(),(t.enableDamping||t.autoRotate)&&t.update(),_optionalChain([s, 'optionalCall', _108 => _108(E)]),e.render(r,n)};return{animate:h,dispose:()=>{a!==null&&(cancelAnimationFrame(a),a=null)}}}function ce(e,r){r.environment.enableEnvironmentLighting?new (0, _HDRLoaderjs.HDRLoader)().load(r.environment.hdrPath||"/baseHDR.hdr",function(n){n.mapping=i.EquirectangularReflectionMapping,e.environment=n,r.environment.showEnvironment&&(e.background=n),_optionalChain([r, 'access', _109 => _109.events, 'access', _110 => _110.onReady, 'optionalCall', _111 => _111()])},void 0,function(n){_chunkMA6YB3YZcjs.e.call(void 0, ).warn("HDR texture could not be loaded, falling back to basic lighting:",n),_optionalChain([r, 'access', _112 => _112.events, 'access', _113 => _113.onReady, 'optionalCall', _114 => _114()])}):_optionalChain([r, 'access', _115 => _115.events, 'access', _116 => _116.onReady, 'optionalCall', _117 => _117()])}function le(e,r){let n=new i.AmbientLight(r.lighting.ambientLightColor,r.lighting.ambientLightIntensity);if(e.add(n),r.lighting.enableSunlight){let t=new i.DirectionalLight(_nullishCoalesce(r.lighting.sunlightColor, () => (16777215)),r.lighting.sunlightIntensity),o=r.lighting.sunlightPosition;if(o&&t.position.set(o.x,o.y,o.z),r.render.enableShadows){t.castShadow=!0;let s=P(r.sceneScale,.1,10,100);t.shadow.camera.left=-s,t.shadow.camera.right=s,t.shadow.camera.top=s,t.shadow.camera.bottom=-s;let a=P(r.sceneScale,.001,.1,.5),u=P(r.sceneScale,1,100,500);t.shadow.camera.near=a,t.shadow.camera.far=u,t.shadow.mapSize.width=r.render.shadowMapSize||2048,t.shadow.mapSize.height=r.render.shadowMapSize||2048,t.shadow.bias=-1e-4,t.shadow.normalBias=.02}e.add(t)}}function ue(e,r){let n=r.floor.size,t=new i.PlaneGeometry(n,n),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(t,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 n=r.parentElement,t=n?n.clientWidth:window.innerWidth,o=n?n.clientHeight:window.innerHeight,s=new i.PerspectiveCamera(e.camera.fov,t/o,e.camera.near,e.camera.far),a=e.camera.position;return a&&s.position.set(a.x,a.y,a.z),s}function me(e,r){let n=new i.WebGLRenderer({antialias:r.render.antialias,canvas:e,alpha:!0,powerPreference:"high-performance",preserveDrawingBuffer:r.render.preserveDrawingBuffer,logarithmicDepthBuffer:!0}),t=e.parentElement,o=t?t.clientWidth:window.innerWidth,s=t?t.clientHeight:window.innerHeight;return t&&(e.style.width="100%",e.style.height="100%",e.style.display="block"),n.setSize(o,s,!1),n.setPixelRatio(r.render.pixelRatio||Math.min(window.devicePixelRatio,2)),r.render.enableShadows&&(n.shadowMap.enabled=!0,n.shadowMap.type=i.VSMShadowMap),n.toneMapping=r.render.toneMapping,n.toneMappingExposure=r.render.toneMappingExposure||1,n.outputColorSpace=i.SRGBColorSpace,n.sortObjects=!0,n}function fe(e,r,n,t,o){let s=new Set,a=new Map,u=new i.Raycaster,c=new i.Vector2,h=new i.Vector2,m=f=>{let p=f;for(;p;){if(!p.visible)return!1;p=p.parent}return!0},l=()=>{let f=new i.Box3;if(r.traverse(A=>{A.visible&&A.userData.id!=="floor"&&A instanceof i.Mesh&&f.expandByObject(A)}),f.isEmpty()){_chunkMA6YB3YZcjs.e.call(void 0, ).warn("No objects to fit to view");return}let p=f.getCenter(new i.Vector3),T=f.getSize(new i.Vector3),v=Math.max(T.x,T.y,T.z),R=n.fov*(Math.PI/180),S=v/(2*Math.tan(R/2));S*=1.5;let O=n.position.clone().sub(t.target).normalize();n.position.copy(p.clone().add(O.multiplyScalar(S))),t.target.copy(p),t.update()},E=typeof o.events.selectionColor=="string"?new i.Color(o.events.selectionColor):o.events.selectionColor instanceof i.Color?o.events.selectionColor:new i.Color("#ff0000"),g=()=>{s.forEach(f=>{f instanceof i.Mesh&&a.has(f)&&(f.material=a.get(f),a.delete(f))}),s.clear()},d=f=>{h.set(f.clientX,f.clientY)},H=f=>{let p=new i.Vector2(f.clientX,f.clientY);if(h.distanceTo(p)>5)return;let T=e.getBoundingClientRect();c.x=(f.clientX-T.left)/T.width*2-1,c.y=-((f.clientY-T.top)/T.height)*2+1,u.setFromCamera(c,n);let v=u.intersectObjects(r.children,!0).filter(R=>m(R.object));if(v.length>0){let R=v[0].object;if(!s.has(R)){if(g(),s.add(R),R instanceof i.Mesh&&R.material instanceof i.Material){a.set(R,R.material);let S=R.material.clone();S.emissive=E.clone(),R.material=S}_optionalChain([o, 'access', _118 => _118.events, 'optionalAccess', _119 => _119.onObjectSelected, 'optionalCall', _120 => _120(R)]),R instanceof i.Mesh&&Object.keys(R.userData).length>0&&_optionalChain([o, 'access', _121 => _121.events, 'optionalAccess', _122 => _122.onMeshMetadataClicked, 'optionalCall', _123 => _123(R.userData)])}}else g(),_optionalChain([o, 'access', _124 => _124.events, 'optionalAccess', _125 => _125.onBackgroundClicked, 'optionalCall', _126 => _126({x:c.x,y:c.y})])},L=f=>{let p=e.getBoundingClientRect();c.x=(f.clientX-p.left)/p.width*2-1,c.y=-((f.clientY-p.top)/p.height)*2+1,u.setFromCamera(c,n);let T=u.intersectObjects(r.children,!0).filter(ee=>m(ee.object));if(T.length===0)return;let v=T[0].object;if(_optionalChain([o, 'access', _127 => _127.events, 'optionalAccess', _128 => _128.onMeshDoubleClicked, 'optionalCall', _129 => _129(v)]),!_optionalChain([o, 'access', _130 => _130.events, 'optionalAccess', _131 => _131.enableDoubleClickZoom]))return;let R=new i.Box3().setFromObject(v);if(R.isEmpty())return;let S=R.getCenter(new i.Vector3),O=R.getSize(new i.Vector3),A=Math.max(O.x,O.y,O.z),K=n.fov*(Math.PI/180),X=A/(2*Math.tan(K/2))*1.5,J=n.position.clone().sub(t.target).normalize(),Q=S.clone().add(J.multiplyScalar(X));se(n,t,Q,S)},x=f=>{if(_optionalChain([o, 'access', _132 => _132.events, 'optionalAccess', _133 => _133.enableKeyboardControls]))switch(f.key.toLowerCase()){case"f":f.preventDefault(),l();break;case"escape":f.preventDefault(),g();break;case" ":f.preventDefault(),l();break}};return _optionalChain([o, 'access', _134 => _134.events, 'optionalAccess', _135 => _135.enableClickToFocus])&&(e.addEventListener("mousedown",d),e.addEventListener("click",H),e.addEventListener("dblclick",L)),_optionalChain([o, 'access', _136 => _136.events, 'optionalAccess', _137 => _137.enableKeyboardControls])&&(e.setAttribute("tabindex","0"),e.addEventListener("keydown",x)),{dispose:()=>{e.removeEventListener("mousedown",d),e.removeEventListener("click",H),e.removeEventListener("dblclick",L),e.removeEventListener("keydown",x),g()},fitToView:l,clearSelection:g}}function he(e,r,n){let t=new (0, _OrbitControlsjs.OrbitControls)(e,r),o=n.camera.target;return o&&t.target.set(o.x,o.y,o.z),t.enableDamping=n.controls.enableDamping||!1,t.dampingFactor=n.controls.dampingFactor||.05,t.autoRotate=n.controls.autoRotate||!1,t.autoRotateSpeed=n.controls.autoRotateSpeed||.5,t.enableZoom=_nullishCoalesce(n.controls.enableZoom, () => (!0)),t.enablePan=_nullishCoalesce(n.controls.enablePan, () => (!0)),t.minDistance=n.controls.minDistance||.001,t.maxDistance=n.controls.maxDistance||1/0,t.screenSpacePanning=!1,t.maxPolarAngle=Math.PI,t.update(),t}var B={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 Xe(e,r,n,t,o){if(Ee(e),r.length===0)return;r.forEach(m=>{e.add(m)});let s=z(r),a=s.getCenter(new w.Vector3),u=s.getSize(new w.Vector3),c=Math.max(u.x,u.y,u.z);if(c/Math.min(u.x||1,u.y||1,u.z||1)>B.SCALE_RATIO_THRESHOLD||c>B.HUGE_THRESHOLD?(n.near=c*B.NEAR_PLANE_FACTOR.TINY,n.far=c*B.FAR_PLANE_FACTOR.HUGE):c>B.LARGE_THRESHOLD?(n.near=c*B.NEAR_PLANE_FACTOR.SMALL,n.far=c*B.FAR_PLANE_FACTOR.LARGE):(n.near=Math.max(.01,c*B.NEAR_PLANE_FACTOR.NORMAL),n.far=Math.max(2e3,c*B.FAR_PLANE_FACTOR.NORMAL)),n.updateProjectionMatrix(),o)t.minDistance=n.near*2,t.maxDistance=n.far*.9;else{let m=c*B.INITIAL_DISTANCE_MULTIPLIER;n.position.set(a.x+m*.8,a.y+m,a.z+m*1.2),t.target.copy(a),t.minDistance=n.near*2,t.maxDistance=n.far*.9,t.update()}}function N(e){if(!e||typeof e!="string")return _chunkMA6YB3YZcjs.e.call(void 0, ).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 n=r.startsWith("#")?r:`#${r}`;return new w.Color(n)}catch (e2){return _chunkMA6YB3YZcjs.e.call(void 0, ).warn(`Invalid hex color: ${e}, using white`),new w.Color(16777215)}if(r.includes(",")){let n=r.split(",").map(t=>parseInt(t.trim(),10));if(n.length===3&&n.every(t=>!isNaN(t)&&t>=0&&t<=255))return new w.Color(n[0]/255,n[1]/255,n[2]/255)}try{return new w.Color(r.toLowerCase())}catch (e3){return _chunkMA6YB3YZcjs.e.call(void 0, ).warn(`Invalid color string: ${e}, using white`),new w.Color(16777215)}}function G(e,r){e.forEach(n=>{n.position.y-=r})}function z(e){let r=new w.Box3;return e.length===0||e.forEach(n=>{n.updateMatrixWorld(!0);let t=new w.Box3().setFromObject(n);r.union(t)}),r}function Ee(e){[...e.children].forEach(n=>{n.userData.id!=="floor"&&(n.traverse(t=>{if(!(t instanceof w.Mesh))return;_optionalChain([t, 'access', _138 => _138.geometry, 'optionalAccess', _139 => _139.dispose, 'call', _140 => _140()]),(Array.isArray(t.material)?t.material:[t.material]).forEach(s=>{for(let a of Object.values(s))a instanceof w.Texture&&a.dispose();s.dispose()})}),n.removeFromParent())})}var Me={};_chunkMA6YB3YZcjs.a.call(void 0, Me,{CONCRETE_MATERIAL:()=>ye,EMISSIVE_MATERIAL:()=>pe,GLASS_MATERIAL:()=>Re,METAL_MATERIAL:()=>ge,PLASTIC_MATERIAL:()=>be,RUBBER_MATERIAL:()=>Te,WOOD_MATERIAL:()=>we});var pe=new b.MeshPhysicalMaterial({color:0,emissive:new b.Color(16777215),emissiveIntensity:5,metalness:0,roughness:.2,clearcoat:.3,clearcoatRoughness:.2,depthWrite:!0,depthTest:!0,transparent:!1,alphaTest:0,polygonOffset:!0,side:b.FrontSide,dithering:!0}),ge=new b.MeshPhysicalMaterial({color:new b.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:b.FrontSide,dithering:!0}),ye=new b.MeshPhysicalMaterial({color:new b.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:b.FrontSide,dithering:!0}),be=new b.MeshPhysicalMaterial({color:new b.Color(16777215),metalness:0,roughness:.3,envMapIntensity:.5,clearcoat:.5,clearcoatRoughness:.1,reflectivity:.5,ior:1.4,transmission:0,transparent:!1,depthWrite:!0,side:b.FrontSide,dithering:!0,polygonOffset:!0,polygonOffsetFactor:1,polygonOffsetUnits:1}),Re=new b.MeshPhysicalMaterial({color:new b.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:b.DoubleSide,polygonOffset:!0,polygonOffsetFactor:1,polygonOffsetUnits:1}),Te=new b.MeshPhysicalMaterial({color:new b.Color(1710618),metalness:0,roughness:.9,envMapIntensity:.2,clearcoat:.1,clearcoatRoughness:.8,reflectivity:.2,ior:1.3,transmission:0,depthWrite:!0,side:b.FrontSide,polygonOffset:!0,polygonOffsetFactor:1,polygonOffsetUnits:1}),we=new b.MeshPhysicalMaterial({color:new b.Color(8934707),metalness:0,roughness:.7,envMapIntensity:.3,clearcoat:.3,clearcoatRoughness:.4,reflectivity:.3,ior:1.3,transmission:0,depthWrite:!0,side:b.FrontSide,dithering:!0,polygonOffset:!0,polygonOffsetFactor:1,polygonOffsetUnits:1});var $=1096174675,W= exports.h =1,k= exports.i =1,Y=12,j=56;function _(e){let r=He(e),n=new DataView(r.buffer,r.byteOffset,r.byteLength);if(r.byteLength<Y)throw I("Blob too small to contain SLVA header.",{expectedBytes:Y,availableBytes:r.byteLength});let t=0,o=n.getUint32(t,!0);if(t+=4,o!==$)throw I(`Invalid SLVA magic: 0x${o.toString(16)}`,{expectedMagic:`0x${$.toString(16)}`,actualMagic:`0x${o.toString(16)}`});let s=n.getUint32(t,!0);if(t+=4,s!==W)throw I(`Unsupported SLVA version: ${s}`,{expectedVersion:W,actualVersion:s});let a=n.getUint32(t,!0);if(t+=4,t+a>r.byteLength)throw I("Insufficient data to read metadata JSON.",{expectedBytes:a,availableBytes:r.byteLength-t,offset:t});let u=r.subarray(t,t+a);t+=a;let c;try{c=JSON.parse(xe(u))}catch(A){throw I(`Failed to parse metadata JSON: ${A instanceof Error?A.message:String(A)}`,{metadataLen:a})}if(t+j>r.byteLength)throw I("Insufficient data to read geometry header.",{expectedBytes:j,availableBytes:r.byteLength-t,offset:t});let h=n.getUint32(t,!0);t+=4;let m=n.getFloat64(t,!0);t+=8;let l=n.getFloat64(t,!0);t+=8;let E=n.getFloat64(t,!0);t+=8;let g=n.getFloat64(t,!0);t+=8;let d=n.getFloat64(t,!0);t+=8;let H=n.getFloat64(t,!0);t+=8;let L=n.getUint32(t,!0);t+=4;let x=(h&k)!==0,C=L*3,p=C*(x?4:2);if(t+p>r.byteLength)throw I("Insufficient data to read vertices.",{expectedBytes:p,availableBytes:r.byteLength-t,offset:t,useFloat32:x,vertexCount:L});let T=r.byteOffset+t,v=x?ve(r.buffer,T,C):Ce(r.buffer,T,C);if(t+=p,t+4>r.byteLength)throw I("Insufficient data to read index count.",{expectedBytes:4,availableBytes:r.byteLength-t,offset:t});let R=n.getUint32(t,!0);t+=4;let S=R*4;if(t+S>r.byteLength)throw I("Insufficient data to read indices.",{expectedBytes:S,availableBytes:r.byteLength-t,offset:t,indexCount:R});let O=Se(r.buffer,r.byteOffset+t,R);return{metadata:c,flags:h,vertices:v,indices:O,origin:[m,l,E],scale:[g,d,H]}}function He(e){return typeof e=="string"?_chunkMA6YB3YZcjs.o.call(void 0, e):e instanceof Uint8Array?e:new Uint8Array(e)}function xe(e){if(typeof TextDecoder<"u")return new TextDecoder("utf-8").decode(e);if(typeof globalThis.Buffer<"u")return globalThis.Buffer.from(e).toString("utf-8");throw new (0, _chunkMA6YB3YZcjs.d)("No UTF-8 decoder available in this environment.",_chunkMA6YB3YZcjs.c.INVALID_STATE)}function Ce(e,r,n){if(n===0)return new Int16Array(0);if(r%2===0)return new Int16Array(e,r,n);let t=new Uint8Array(n*2);return t.set(new Uint8Array(e,r,n*2)),new Int16Array(t.buffer)}function ve(e,r,n){if(n===0)return new Float32Array(0);if(r%4===0)return new Float32Array(e,r,n);let t=new Uint8Array(n*4);return t.set(new Uint8Array(e,r,n*4)),new Float32Array(t.buffer)}function Se(e,r,n){if(n===0)return new Uint32Array(0);if(r%4===0)return new Uint32Array(e,r,n);let t=new Uint8Array(n*4);return t.set(new Uint8Array(e,r,n*4)),new Uint32Array(t.buffer)}function I(e,r){return new (0, _chunkMA6YB3YZcjs.d)(e,_chunkMA6YB3YZcjs.c.VALIDATION_ERROR,{context:r})}async function Z(e,r){let{debug:n=!1}=_nullishCoalesce(r, () => ({})),t=n?performance.now():0;try{let o=performance.now(),s=JSON.parse(e),a=performance.now()-o;return await Ae(s,r,{parseTime:a,perfStart:t})}catch(o){return _chunkMA6YB3YZcjs.e.call(void 0, ).error("Error parsing mesh batch:",o),[]}}async function Ae(e,r,n){let{mergeByMaterial:t=!0,applyTransforms:o=!0,scaleFactor:s=1,debug:a=!1}=_nullishCoalesce(r, () => ({})),{parseTime:u=0,perfStart:c=a?performance.now():0}=_nullishCoalesce(n, () => ({}));try{let h=performance.now(),m=_(e.compressedData),l=performance.now()-h,E=a?Fe(e.compressedData):0;return q(m,{mergeByMaterial:t,applyTransforms:o,scaleFactor:s,debug:a,parseTime:u,decodeTime:l,perfStart:c,blobBytes:E,fallback:{materials:e.materials,groups:e.groups,sourceComponentId:e.sourceComponentId}})}catch(h){return _chunkMA6YB3YZcjs.e.call(void 0, ).error("Error parsing mesh batch object:",h),[]}}async function at(e,r){let{mergeByMaterial:n=!0,applyTransforms:t=!0,scaleFactor:o=1,debug:s=!1}=_nullishCoalesce(r, () => ({})),a=s?performance.now():0;try{let u=performance.now(),c=_(e),h=performance.now()-u,m=e.byteLength;return q(c,{mergeByMaterial:n,applyTransforms:t,scaleFactor:o,debug:s,parseTime:0,decodeTime:h,perfStart:a,blobBytes:m})}catch(u){return _chunkMA6YB3YZcjs.e.call(void 0, ).error("Error parsing mesh batch blob:",u),[]}}function q(e,r){let{mergeByMaterial:n,applyTransforms:t,scaleFactor:o,debug:s,parseTime:a,decodeTime:u,perfStart:c,blobBytes:h,fallback:m}=r,l=_nullishCoalesce(_nullishCoalesce(e.metadata.materials, () => (_optionalChain([m, 'optionalAccess', _141 => _141.materials]))), () => ([])),E=_nullishCoalesce(_nullishCoalesce(e.metadata.groups, () => (_optionalChain([m, 'optionalAccess', _142 => _142.groups]))), () => ([])),g=_nullishCoalesce(e.metadata.sourceComponentId, () => (_optionalChain([m, 'optionalAccess', _143 => _143.sourceComponentId]))),d=(e.flags&k)!==0,H=d?Le(e.vertices,t):Be(e.vertices,e.origin,e.scale,t);if(s){let p=e.vertices.byteLength+e.indices.byteLength;_chunkMA6YB3YZcjs.e.call(void 0, ).debug("Mesh Batch Stats:"),_chunkMA6YB3YZcjs.e.call(void 0, ).debug(` Materials: ${l.length} | Groups: ${E.length}`),_chunkMA6YB3YZcjs.e.call(void 0, ).debug(` Vertices: ${e.vertices.length/3} | Indices: ${e.indices.length}`),_chunkMA6YB3YZcjs.e.call(void 0, ).debug(` Format: ${d?"float32":"int16 quantized"}`),_chunkMA6YB3YZcjs.e.call(void 0, ).debug(` Blob: ${(h/1024/1024).toFixed(2)} MB | Geometry on wire: ${(p/1024/1024).toFixed(2)} MB`)}let L=performance.now(),x=l.map(Ie),C=[];for(let p of E)if(n&&p.meshes.length>1){let T=Oe(p,H,e.indices,x);T.userData.sourceComponentId=_nullishCoalesce(g, () => (null)),C.push(T)}else{let T=De(p,H,e.indices,x);for(let v of T)v.userData.sourceComponentId=_nullishCoalesce(g, () => (null));C.push(...T)}if(o!==1)for(let p of C)p.scale.set(o,o,o);let f=performance.now()-L;if(s){let p=performance.now()-c;_chunkMA6YB3YZcjs.e.call(void 0, ).debug("Performance:"),a>0&&_chunkMA6YB3YZcjs.e.call(void 0, ).debug(` Parse JSON: ${a.toFixed(2)}ms`),_chunkMA6YB3YZcjs.e.call(void 0, ).debug(` Decode binary: ${u.toFixed(2)}ms`),_chunkMA6YB3YZcjs.e.call(void 0, ).debug(` Create Meshes: ${f.toFixed(2)}ms`),_chunkMA6YB3YZcjs.e.call(void 0, ).debug(` Total: ${p.toFixed(2)}ms`)}return Promise.resolve(C)}function Be(e,r,n,t){let o=new Float32Array(e.length),s=r[0],a=r[1],u=r[2],c=n[0],h=n[1],m=n[2];if(t)for(let l=0;l<e.length;l+=3){let E=s+(e[l]+32767)*c,g=a+(e[l+1]+32767)*h,d=u+(e[l+2]+32767)*m;o[l]=E,o[l+1]=d,o[l+2]=-g}else for(let l=0;l<e.length;l+=3)o[l]=s+(e[l]+32767)*c,o[l+1]=a+(e[l+1]+32767)*h,o[l+2]=u+(e[l+2]+32767)*m;return o}function Le(e,r){if(!r)return e;let n=new Float32Array(e.length);for(let t=0;t<e.length;t+=3){let o=e[t],s=e[t+1],a=e[t+2];n[t]=o,n[t+1]=a,n[t+2]=-s}return n}function Ie(e){let r=N(e.color);return new M.MeshPhysicalMaterial({color:r,metalness:e.metalness,roughness:e.roughness,opacity:e.opacity,transparent:e.transparent,side:M.DoubleSide,polygonOffset:!0,polygonOffsetFactor:.5,polygonOffsetUnits:.5,depthWrite:!0,depthTest:!0})}function Oe(e,r,n,t){let o=0,s=0;for(let d of e.meshes)o+=d.vertexCount,s+=d.indexCount;let a=new Float32Array(o*3),u=new Uint32Array(s),c=0,h=0;for(let d of e.meshes){let H=d.vertexStart*3,L=d.vertexCount*3;a.set(r.subarray(H,H+L),c*3);let x=n.subarray(d.indexStart,d.indexStart+d.indexCount),C=c-d.vertexStart;if(C===0)u.set(x,h);else for(let f=0;f<x.length;f++)u[h+f]=x[f]+C;c+=d.vertexCount,h+=d.indexCount}let m=new M.BufferGeometry;m.setAttribute("position",new M.BufferAttribute(a,3)),m.setIndex(new M.BufferAttribute(u,1)),m.computeVertexNormals();let l=new M.Mesh(m,t[e.materialId]),E=e.meshes[0],g=e.meshes.map(d=>d.name).filter(d=>d&&d.length>0);return l.name=g.length>0?g[0]:`merged_material_${e.materialId}`,l.castShadow=!0,l.receiveShadow=!0,l.userData={name:l.name,layer:_nullishCoalesce(_optionalChain([E, 'optionalAccess', _144 => _144.layer]), () => ("")),originalIndex:_nullishCoalesce(_optionalChain([E, 'optionalAccess', _145 => _145.originalIndex]), () => (0)),metadata:_nullishCoalesce(_optionalChain([E, 'optionalAccess', _146 => _146.metadata]), () => ({})),mergedFrom:e.meshes.slice(1).map(d=>({name:d.name,layer:d.layer,originalIndex:d.originalIndex}))},l}function De(e,r,n,t){let o=[];for(let s of e.meshes){let a=s.vertexStart*3,u=s.vertexCount*3,c=r.slice(a,a+u),h=n.subarray(s.indexStart,s.indexStart+s.indexCount),m=new Uint32Array(h.length),l=s.vertexStart;for(let d=0;d<h.length;d++)m[d]=h[d]-l;let E=new M.BufferGeometry;E.setAttribute("position",new M.BufferAttribute(c,3)),E.setIndex(new M.BufferAttribute(m,1)),E.computeVertexNormals();let g=new M.Mesh(E,t[e.materialId]);g.name=s.name,g.userData={name:s.name,layer:_nullishCoalesce(s.layer, () => ("")),originalIndex:s.originalIndex,metadata:_nullishCoalesce(s.metadata, () => ({}))},g.castShadow=!0,g.receiveShadow=!0,o.push(g)}return o}function Fe(e){return Math.floor(e.length*3/4)}var Pe={Millimeters:1/1e3,Centimeters:1/100,Meters:1,Inches:1/39.37,Feet:1/3.28084},ze="Display";async function ut(e,r){let n=performance.now(),t=[],{allowScaling:o=!0,allowAutoPosition:s=!0,debug:a=!1,parsing:u={}}=_nullishCoalesce(r, () => ({}));try{let c=o?ke(e.modelunits):1;return await _e(e,t,c,u,a),s&&Ve(t),t}catch(c){throw Ne(c,t),c}finally{a&&$e(n)}}function ke(e){return _nullishCoalesce(Pe[e], () => (1))}async function _e(e,r,n,t,o){for(let s of e.values){let a=s.InnerTree;for(let u in a){let c=a[u];c&&await Ue(c,r,n,t,o)}}}async function Ue(e,r,n,t,o){for(let s of e)if(s.type.includes(ze)){let a={mergeByMaterial:!0,applyTransforms:!0,debug:!1,...t},u=await Z(s.data,a);if(n!==1)for(let c of u)c.scale.set(n,n,n);r.push(...u),o&&_chunkMA6YB3YZcjs.e.call(void 0, ).debug(`Extracted ${u.length} meshes from batch`)}}function Ve(e){if(e.length===0)return;let n=z(e).min.y;G(e,n)}function Ne(e,r){_chunkMA6YB3YZcjs.e.call(void 0, ).error("An unexpected error occurred:",e),Ge(r)}function Ge(e){for(let r of e)r.geometry&&r.geometry.dispose(),r.material&&(Array.isArray(r.material)?r.material.forEach(n=>n.dispose()):r.material.dispose())}function $e(e){let r=performance.now()-e;_chunkMA6YB3YZcjs.e.call(void 0, ).info("Time to process meshes:",`${r.toFixed(2)}ms`)}exports.a = Ze; exports.b = Xe; exports.c = N; exports.d = G; exports.e = z; exports.f = Me; exports.g = $; exports.h = W; exports.i = k; exports.j = _; exports.k = Z; exports.l = Ae; exports.m = at; exports.n = Pe; exports.o = ut;
2
- //# sourceMappingURL=chunk-JFLD2UCY.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["/home/runner/work/selva-compute/selva-compute/dist/chunk-JFLD2UCY.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/chunk-JFLD2UCY.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 +0,0 @@
1
- import{a as te,c as D,d as F,e as y,o as U}from"./chunk-GTTKNF4G.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 V=new i.Vector3(0,0,1),P=(e,r,n,t)=>{switch(e){case"mm":return r;case"cm":return n;default:return t}},Ze=function(e,r){let n=oe(r||{}),t=ae(n),o=de(n,e),s=me(e,n),a=he(o,e,n);ce(t,n),le(t,n),n.floor?.enabled&&ue(t,n);let u=n.events.enableEventHandlers!==!1?fe(e,t,o,a,n):{dispose:()=>{},fitToView:()=>{},clearSelection:()=>{}},c=e.parentElement,h=()=>c?{width:c.clientWidth,height:c.clientHeight}:{width:window.innerWidth,height:window.innerHeight},{animate:m,dispose:l}=ie(s,t,o,a,h,n.events.onFrame);m();let E=n.environment?.sceneUp||V;return t.up.set(E.x,E.y,E.z),{scene:t,camera:o,controls:a,renderer:s,dispose:()=>{l(),u.dispose(),a.dispose(),s.dispose(),t.traverse(d=>{d instanceof i.Mesh&&(d.geometry?.dispose(),Array.isArray(d.material)?d.material.forEach(H=>H.dispose()):d.material?.dispose())})},fitToView:u.fitToView,clearSelection:u.clearSelection}};function oe(e){let r=e.sceneScale||"m",t={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(-t.cameraDistance,t.cameraDistance,t.cameraDistance),fov:e.camera?.fov||20,near:e.camera?.near||t.near,far:e.camera?.far||t.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(t.lightDistance,t.lightHeight,t.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||V,showEnvironment:e.environment?.showEnvironment??!1},floor:{enabled:e.floor?.enabled??!1,size:e.floor?.size||t.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||t.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,n=typeof e.environment.backgroundColor=="string"?new i.Color(e.environment.backgroundColor):e.environment.backgroundColor;return r.background=n||null,r}function se(e,r,n,t,o=200){let s=e.position.clone(),a=r.target.clone(),u=performance.now(),c=m=>1-Math.pow(1-m,3),h=()=>{let m=performance.now()-u,l=c(Math.min(m/o,1));e.position.lerpVectors(s,n,l),r.target.lerpVectors(a,t,l),r.update(),l<1&&requestAnimationFrame(h)};requestAnimationFrame(h)}function ie(e,r,n,t,o,s){let a=null,u=performance.now(),c=()=>{let{width:l,height:E}=o();if(l===0||E===0)return;let g=Math.min(window.devicePixelRatio,2),d=Math.round(l*g),H=Math.round(E*g);(e.domElement.width!==d||e.domElement.height!==H)&&(e.setPixelRatio(g),e.setSize(l,E,!1),n.aspect=l/E,n.updateProjectionMatrix())},h=function(){a=requestAnimationFrame(h);let l=performance.now(),E=(l-u)/1e3;u=l,c(),(t.enableDamping||t.autoRotate)&&t.update(),s?.(E),e.render(r,n)};return{animate:h,dispose:()=>{a!==null&&(cancelAnimationFrame(a),a=null)}}}function ce(e,r){r.environment.enableEnvironmentLighting?new re().load(r.environment.hdrPath||"/baseHDR.hdr",function(n){n.mapping=i.EquirectangularReflectionMapping,e.environment=n,r.environment.showEnvironment&&(e.background=n),r.events.onReady?.()},void 0,function(n){y().warn("HDR texture could not be loaded, falling back to basic lighting:",n),r.events.onReady?.()}):r.events.onReady?.()}function le(e,r){let n=new i.AmbientLight(r.lighting.ambientLightColor,r.lighting.ambientLightIntensity);if(e.add(n),r.lighting.enableSunlight){let t=new i.DirectionalLight(r.lighting.sunlightColor??16777215,r.lighting.sunlightIntensity),o=r.lighting.sunlightPosition;if(o&&t.position.set(o.x,o.y,o.z),r.render.enableShadows){t.castShadow=!0;let s=P(r.sceneScale,.1,10,100);t.shadow.camera.left=-s,t.shadow.camera.right=s,t.shadow.camera.top=s,t.shadow.camera.bottom=-s;let a=P(r.sceneScale,.001,.1,.5),u=P(r.sceneScale,1,100,500);t.shadow.camera.near=a,t.shadow.camera.far=u,t.shadow.mapSize.width=r.render.shadowMapSize||2048,t.shadow.mapSize.height=r.render.shadowMapSize||2048,t.shadow.bias=-1e-4,t.shadow.normalBias=.02}e.add(t)}}function ue(e,r){let n=r.floor.size,t=new i.PlaneGeometry(n,n),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(t,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 n=r.parentElement,t=n?n.clientWidth:window.innerWidth,o=n?n.clientHeight:window.innerHeight,s=new i.PerspectiveCamera(e.camera.fov,t/o,e.camera.near,e.camera.far),a=e.camera.position;return a&&s.position.set(a.x,a.y,a.z),s}function me(e,r){let n=new i.WebGLRenderer({antialias:r.render.antialias,canvas:e,alpha:!0,powerPreference:"high-performance",preserveDrawingBuffer:r.render.preserveDrawingBuffer,logarithmicDepthBuffer:!0}),t=e.parentElement,o=t?t.clientWidth:window.innerWidth,s=t?t.clientHeight:window.innerHeight;return t&&(e.style.width="100%",e.style.height="100%",e.style.display="block"),n.setSize(o,s,!1),n.setPixelRatio(r.render.pixelRatio||Math.min(window.devicePixelRatio,2)),r.render.enableShadows&&(n.shadowMap.enabled=!0,n.shadowMap.type=i.VSMShadowMap),n.toneMapping=r.render.toneMapping,n.toneMappingExposure=r.render.toneMappingExposure||1,n.outputColorSpace=i.SRGBColorSpace,n.sortObjects=!0,n}function fe(e,r,n,t,o){let s=new Set,a=new Map,u=new i.Raycaster,c=new i.Vector2,h=new i.Vector2,m=f=>{let p=f;for(;p;){if(!p.visible)return!1;p=p.parent}return!0},l=()=>{let f=new i.Box3;if(r.traverse(A=>{A.visible&&A.userData.id!=="floor"&&A instanceof i.Mesh&&f.expandByObject(A)}),f.isEmpty()){y().warn("No objects to fit to view");return}let p=f.getCenter(new i.Vector3),T=f.getSize(new i.Vector3),v=Math.max(T.x,T.y,T.z),R=n.fov*(Math.PI/180),S=v/(2*Math.tan(R/2));S*=1.5;let O=n.position.clone().sub(t.target).normalize();n.position.copy(p.clone().add(O.multiplyScalar(S))),t.target.copy(p),t.update()},E=typeof o.events.selectionColor=="string"?new i.Color(o.events.selectionColor):o.events.selectionColor instanceof i.Color?o.events.selectionColor:new i.Color("#ff0000"),g=()=>{s.forEach(f=>{f instanceof i.Mesh&&a.has(f)&&(f.material=a.get(f),a.delete(f))}),s.clear()},d=f=>{h.set(f.clientX,f.clientY)},H=f=>{let p=new i.Vector2(f.clientX,f.clientY);if(h.distanceTo(p)>5)return;let T=e.getBoundingClientRect();c.x=(f.clientX-T.left)/T.width*2-1,c.y=-((f.clientY-T.top)/T.height)*2+1,u.setFromCamera(c,n);let v=u.intersectObjects(r.children,!0).filter(R=>m(R.object));if(v.length>0){let R=v[0].object;if(!s.has(R)){if(g(),s.add(R),R instanceof i.Mesh&&R.material instanceof i.Material){a.set(R,R.material);let S=R.material.clone();S.emissive=E.clone(),R.material=S}o.events?.onObjectSelected?.(R),R instanceof i.Mesh&&Object.keys(R.userData).length>0&&o.events?.onMeshMetadataClicked?.(R.userData)}}else g(),o.events?.onBackgroundClicked?.({x:c.x,y:c.y})},L=f=>{let p=e.getBoundingClientRect();c.x=(f.clientX-p.left)/p.width*2-1,c.y=-((f.clientY-p.top)/p.height)*2+1,u.setFromCamera(c,n);let T=u.intersectObjects(r.children,!0).filter(ee=>m(ee.object));if(T.length===0)return;let v=T[0].object;if(o.events?.onMeshDoubleClicked?.(v),!o.events?.enableDoubleClickZoom)return;let R=new i.Box3().setFromObject(v);if(R.isEmpty())return;let S=R.getCenter(new i.Vector3),O=R.getSize(new i.Vector3),A=Math.max(O.x,O.y,O.z),K=n.fov*(Math.PI/180),X=A/(2*Math.tan(K/2))*1.5,J=n.position.clone().sub(t.target).normalize(),Q=S.clone().add(J.multiplyScalar(X));se(n,t,Q,S)},x=f=>{if(o.events?.enableKeyboardControls)switch(f.key.toLowerCase()){case"f":f.preventDefault(),l();break;case"escape":f.preventDefault(),g();break;case" ":f.preventDefault(),l();break}};return o.events?.enableClickToFocus&&(e.addEventListener("mousedown",d),e.addEventListener("click",H),e.addEventListener("dblclick",L)),o.events?.enableKeyboardControls&&(e.setAttribute("tabindex","0"),e.addEventListener("keydown",x)),{dispose:()=>{e.removeEventListener("mousedown",d),e.removeEventListener("click",H),e.removeEventListener("dblclick",L),e.removeEventListener("keydown",x),g()},fitToView:l,clearSelection:g}}function he(e,r,n){let t=new ne(e,r),o=n.camera.target;return o&&t.target.set(o.x,o.y,o.z),t.enableDamping=n.controls.enableDamping||!1,t.dampingFactor=n.controls.dampingFactor||.05,t.autoRotate=n.controls.autoRotate||!1,t.autoRotateSpeed=n.controls.autoRotateSpeed||.5,t.enableZoom=n.controls.enableZoom??!0,t.enablePan=n.controls.enablePan??!0,t.minDistance=n.controls.minDistance||.001,t.maxDistance=n.controls.maxDistance||1/0,t.screenSpacePanning=!1,t.maxPolarAngle=Math.PI,t.update(),t}import*as w from"three";var B={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 Xe(e,r,n,t,o){if(Ee(e),r.length===0)return;r.forEach(m=>{e.add(m)});let s=z(r),a=s.getCenter(new w.Vector3),u=s.getSize(new w.Vector3),c=Math.max(u.x,u.y,u.z);if(c/Math.min(u.x||1,u.y||1,u.z||1)>B.SCALE_RATIO_THRESHOLD||c>B.HUGE_THRESHOLD?(n.near=c*B.NEAR_PLANE_FACTOR.TINY,n.far=c*B.FAR_PLANE_FACTOR.HUGE):c>B.LARGE_THRESHOLD?(n.near=c*B.NEAR_PLANE_FACTOR.SMALL,n.far=c*B.FAR_PLANE_FACTOR.LARGE):(n.near=Math.max(.01,c*B.NEAR_PLANE_FACTOR.NORMAL),n.far=Math.max(2e3,c*B.FAR_PLANE_FACTOR.NORMAL)),n.updateProjectionMatrix(),o)t.minDistance=n.near*2,t.maxDistance=n.far*.9;else{let m=c*B.INITIAL_DISTANCE_MULTIPLIER;n.position.set(a.x+m*.8,a.y+m,a.z+m*1.2),t.target.copy(a),t.minDistance=n.near*2,t.maxDistance=n.far*.9,t.update()}}function N(e){if(!e||typeof e!="string")return y().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 n=r.startsWith("#")?r:`#${r}`;return new w.Color(n)}catch{return y().warn(`Invalid hex color: ${e}, using white`),new w.Color(16777215)}if(r.includes(",")){let n=r.split(",").map(t=>parseInt(t.trim(),10));if(n.length===3&&n.every(t=>!isNaN(t)&&t>=0&&t<=255))return new w.Color(n[0]/255,n[1]/255,n[2]/255)}try{return new w.Color(r.toLowerCase())}catch{return y().warn(`Invalid color string: ${e}, using white`),new w.Color(16777215)}}function G(e,r){e.forEach(n=>{n.position.y-=r})}function z(e){let r=new w.Box3;return e.length===0||e.forEach(n=>{n.updateMatrixWorld(!0);let t=new w.Box3().setFromObject(n);r.union(t)}),r}function Ee(e){[...e.children].forEach(n=>{n.userData.id!=="floor"&&(n.traverse(t=>{if(!(t instanceof w.Mesh))return;t.geometry?.dispose(),(Array.isArray(t.material)?t.material:[t.material]).forEach(s=>{for(let a of Object.values(s))a instanceof w.Texture&&a.dispose();s.dispose()})}),n.removeFromParent())})}var Me={};te(Me,{CONCRETE_MATERIAL:()=>ye,EMISSIVE_MATERIAL:()=>pe,GLASS_MATERIAL:()=>Re,METAL_MATERIAL:()=>ge,PLASTIC_MATERIAL:()=>be,RUBBER_MATERIAL:()=>Te,WOOD_MATERIAL:()=>we});import*as b from"three";var pe=new b.MeshPhysicalMaterial({color:0,emissive:new b.Color(16777215),emissiveIntensity:5,metalness:0,roughness:.2,clearcoat:.3,clearcoatRoughness:.2,depthWrite:!0,depthTest:!0,transparent:!1,alphaTest:0,polygonOffset:!0,side:b.FrontSide,dithering:!0}),ge=new b.MeshPhysicalMaterial({color:new b.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:b.FrontSide,dithering:!0}),ye=new b.MeshPhysicalMaterial({color:new b.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:b.FrontSide,dithering:!0}),be=new b.MeshPhysicalMaterial({color:new b.Color(16777215),metalness:0,roughness:.3,envMapIntensity:.5,clearcoat:.5,clearcoatRoughness:.1,reflectivity:.5,ior:1.4,transmission:0,transparent:!1,depthWrite:!0,side:b.FrontSide,dithering:!0,polygonOffset:!0,polygonOffsetFactor:1,polygonOffsetUnits:1}),Re=new b.MeshPhysicalMaterial({color:new b.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:b.DoubleSide,polygonOffset:!0,polygonOffsetFactor:1,polygonOffsetUnits:1}),Te=new b.MeshPhysicalMaterial({color:new b.Color(1710618),metalness:0,roughness:.9,envMapIntensity:.2,clearcoat:.1,clearcoatRoughness:.8,reflectivity:.2,ior:1.3,transmission:0,depthWrite:!0,side:b.FrontSide,polygonOffset:!0,polygonOffsetFactor:1,polygonOffsetUnits:1}),we=new b.MeshPhysicalMaterial({color:new b.Color(8934707),metalness:0,roughness:.7,envMapIntensity:.3,clearcoat:.3,clearcoatRoughness:.4,reflectivity:.3,ior:1.3,transmission:0,depthWrite:!0,side:b.FrontSide,dithering:!0,polygonOffset:!0,polygonOffsetFactor:1,polygonOffsetUnits:1});var $=1096174675,W=1,k=1,Y=12,j=56;function _(e){let r=He(e),n=new DataView(r.buffer,r.byteOffset,r.byteLength);if(r.byteLength<Y)throw I("Blob too small to contain SLVA header.",{expectedBytes:Y,availableBytes:r.byteLength});let t=0,o=n.getUint32(t,!0);if(t+=4,o!==$)throw I(`Invalid SLVA magic: 0x${o.toString(16)}`,{expectedMagic:`0x${$.toString(16)}`,actualMagic:`0x${o.toString(16)}`});let s=n.getUint32(t,!0);if(t+=4,s!==W)throw I(`Unsupported SLVA version: ${s}`,{expectedVersion:W,actualVersion:s});let a=n.getUint32(t,!0);if(t+=4,t+a>r.byteLength)throw I("Insufficient data to read metadata JSON.",{expectedBytes:a,availableBytes:r.byteLength-t,offset:t});let u=r.subarray(t,t+a);t+=a;let c;try{c=JSON.parse(xe(u))}catch(A){throw I(`Failed to parse metadata JSON: ${A instanceof Error?A.message:String(A)}`,{metadataLen:a})}if(t+j>r.byteLength)throw I("Insufficient data to read geometry header.",{expectedBytes:j,availableBytes:r.byteLength-t,offset:t});let h=n.getUint32(t,!0);t+=4;let m=n.getFloat64(t,!0);t+=8;let l=n.getFloat64(t,!0);t+=8;let E=n.getFloat64(t,!0);t+=8;let g=n.getFloat64(t,!0);t+=8;let d=n.getFloat64(t,!0);t+=8;let H=n.getFloat64(t,!0);t+=8;let L=n.getUint32(t,!0);t+=4;let x=(h&k)!==0,C=L*3,p=C*(x?4:2);if(t+p>r.byteLength)throw I("Insufficient data to read vertices.",{expectedBytes:p,availableBytes:r.byteLength-t,offset:t,useFloat32:x,vertexCount:L});let T=r.byteOffset+t,v=x?ve(r.buffer,T,C):Ce(r.buffer,T,C);if(t+=p,t+4>r.byteLength)throw I("Insufficient data to read index count.",{expectedBytes:4,availableBytes:r.byteLength-t,offset:t});let R=n.getUint32(t,!0);t+=4;let S=R*4;if(t+S>r.byteLength)throw I("Insufficient data to read indices.",{expectedBytes:S,availableBytes:r.byteLength-t,offset:t,indexCount:R});let O=Se(r.buffer,r.byteOffset+t,R);return{metadata:c,flags:h,vertices:v,indices:O,origin:[m,l,E],scale:[g,d,H]}}function He(e){return typeof e=="string"?U(e):e instanceof Uint8Array?e:new Uint8Array(e)}function xe(e){if(typeof TextDecoder<"u")return new TextDecoder("utf-8").decode(e);if(typeof globalThis.Buffer<"u")return globalThis.Buffer.from(e).toString("utf-8");throw new F("No UTF-8 decoder available in this environment.",D.INVALID_STATE)}function Ce(e,r,n){if(n===0)return new Int16Array(0);if(r%2===0)return new Int16Array(e,r,n);let t=new Uint8Array(n*2);return t.set(new Uint8Array(e,r,n*2)),new Int16Array(t.buffer)}function ve(e,r,n){if(n===0)return new Float32Array(0);if(r%4===0)return new Float32Array(e,r,n);let t=new Uint8Array(n*4);return t.set(new Uint8Array(e,r,n*4)),new Float32Array(t.buffer)}function Se(e,r,n){if(n===0)return new Uint32Array(0);if(r%4===0)return new Uint32Array(e,r,n);let t=new Uint8Array(n*4);return t.set(new Uint8Array(e,r,n*4)),new Uint32Array(t.buffer)}function I(e,r){return new F(e,D.VALIDATION_ERROR,{context:r})}import*as M from"three";async function Z(e,r){let{debug:n=!1}=r??{},t=n?performance.now():0;try{let o=performance.now(),s=JSON.parse(e),a=performance.now()-o;return await Ae(s,r,{parseTime:a,perfStart:t})}catch(o){return y().error("Error parsing mesh batch:",o),[]}}async function Ae(e,r,n){let{mergeByMaterial:t=!0,applyTransforms:o=!0,scaleFactor:s=1,debug:a=!1}=r??{},{parseTime:u=0,perfStart:c=a?performance.now():0}=n??{};try{let h=performance.now(),m=_(e.compressedData),l=performance.now()-h,E=a?Fe(e.compressedData):0;return q(m,{mergeByMaterial:t,applyTransforms:o,scaleFactor:s,debug:a,parseTime:u,decodeTime:l,perfStart:c,blobBytes:E,fallback:{materials:e.materials,groups:e.groups,sourceComponentId:e.sourceComponentId}})}catch(h){return y().error("Error parsing mesh batch object:",h),[]}}async function at(e,r){let{mergeByMaterial:n=!0,applyTransforms:t=!0,scaleFactor:o=1,debug:s=!1}=r??{},a=s?performance.now():0;try{let u=performance.now(),c=_(e),h=performance.now()-u,m=e.byteLength;return q(c,{mergeByMaterial:n,applyTransforms:t,scaleFactor:o,debug:s,parseTime:0,decodeTime:h,perfStart:a,blobBytes:m})}catch(u){return y().error("Error parsing mesh batch blob:",u),[]}}function q(e,r){let{mergeByMaterial:n,applyTransforms:t,scaleFactor:o,debug:s,parseTime:a,decodeTime:u,perfStart:c,blobBytes:h,fallback:m}=r,l=e.metadata.materials??m?.materials??[],E=e.metadata.groups??m?.groups??[],g=e.metadata.sourceComponentId??m?.sourceComponentId,d=(e.flags&k)!==0,H=d?Le(e.vertices,t):Be(e.vertices,e.origin,e.scale,t);if(s){let p=e.vertices.byteLength+e.indices.byteLength;y().debug("Mesh Batch Stats:"),y().debug(` Materials: ${l.length} | Groups: ${E.length}`),y().debug(` Vertices: ${e.vertices.length/3} | Indices: ${e.indices.length}`),y().debug(` Format: ${d?"float32":"int16 quantized"}`),y().debug(` Blob: ${(h/1024/1024).toFixed(2)} MB | Geometry on wire: ${(p/1024/1024).toFixed(2)} MB`)}let L=performance.now(),x=l.map(Ie),C=[];for(let p of E)if(n&&p.meshes.length>1){let T=Oe(p,H,e.indices,x);T.userData.sourceComponentId=g??null,C.push(T)}else{let T=De(p,H,e.indices,x);for(let v of T)v.userData.sourceComponentId=g??null;C.push(...T)}if(o!==1)for(let p of C)p.scale.set(o,o,o);let f=performance.now()-L;if(s){let p=performance.now()-c;y().debug("Performance:"),a>0&&y().debug(` Parse JSON: ${a.toFixed(2)}ms`),y().debug(` Decode binary: ${u.toFixed(2)}ms`),y().debug(` Create Meshes: ${f.toFixed(2)}ms`),y().debug(` Total: ${p.toFixed(2)}ms`)}return Promise.resolve(C)}function Be(e,r,n,t){let o=new Float32Array(e.length),s=r[0],a=r[1],u=r[2],c=n[0],h=n[1],m=n[2];if(t)for(let l=0;l<e.length;l+=3){let E=s+(e[l]+32767)*c,g=a+(e[l+1]+32767)*h,d=u+(e[l+2]+32767)*m;o[l]=E,o[l+1]=d,o[l+2]=-g}else for(let l=0;l<e.length;l+=3)o[l]=s+(e[l]+32767)*c,o[l+1]=a+(e[l+1]+32767)*h,o[l+2]=u+(e[l+2]+32767)*m;return o}function Le(e,r){if(!r)return e;let n=new Float32Array(e.length);for(let t=0;t<e.length;t+=3){let o=e[t],s=e[t+1],a=e[t+2];n[t]=o,n[t+1]=a,n[t+2]=-s}return n}function Ie(e){let r=N(e.color);return new M.MeshPhysicalMaterial({color:r,metalness:e.metalness,roughness:e.roughness,opacity:e.opacity,transparent:e.transparent,side:M.DoubleSide,polygonOffset:!0,polygonOffsetFactor:.5,polygonOffsetUnits:.5,depthWrite:!0,depthTest:!0})}function Oe(e,r,n,t){let o=0,s=0;for(let d of e.meshes)o+=d.vertexCount,s+=d.indexCount;let a=new Float32Array(o*3),u=new Uint32Array(s),c=0,h=0;for(let d of e.meshes){let H=d.vertexStart*3,L=d.vertexCount*3;a.set(r.subarray(H,H+L),c*3);let x=n.subarray(d.indexStart,d.indexStart+d.indexCount),C=c-d.vertexStart;if(C===0)u.set(x,h);else for(let f=0;f<x.length;f++)u[h+f]=x[f]+C;c+=d.vertexCount,h+=d.indexCount}let m=new M.BufferGeometry;m.setAttribute("position",new M.BufferAttribute(a,3)),m.setIndex(new M.BufferAttribute(u,1)),m.computeVertexNormals();let l=new M.Mesh(m,t[e.materialId]),E=e.meshes[0],g=e.meshes.map(d=>d.name).filter(d=>d&&d.length>0);return l.name=g.length>0?g[0]:`merged_material_${e.materialId}`,l.castShadow=!0,l.receiveShadow=!0,l.userData={name:l.name,layer:E?.layer??"",originalIndex:E?.originalIndex??0,metadata:E?.metadata??{},mergedFrom:e.meshes.slice(1).map(d=>({name:d.name,layer:d.layer,originalIndex:d.originalIndex}))},l}function De(e,r,n,t){let o=[];for(let s of e.meshes){let a=s.vertexStart*3,u=s.vertexCount*3,c=r.slice(a,a+u),h=n.subarray(s.indexStart,s.indexStart+s.indexCount),m=new Uint32Array(h.length),l=s.vertexStart;for(let d=0;d<h.length;d++)m[d]=h[d]-l;let E=new M.BufferGeometry;E.setAttribute("position",new M.BufferAttribute(c,3)),E.setIndex(new M.BufferAttribute(m,1)),E.computeVertexNormals();let g=new M.Mesh(E,t[e.materialId]);g.name=s.name,g.userData={name:s.name,layer:s.layer??"",originalIndex:s.originalIndex,metadata:s.metadata??{}},g.castShadow=!0,g.receiveShadow=!0,o.push(g)}return o}function Fe(e){return Math.floor(e.length*3/4)}var Pe={Millimeters:1/1e3,Centimeters:1/100,Meters:1,Inches:1/39.37,Feet:1/3.28084},ze="Display";async function ut(e,r){let n=performance.now(),t=[],{allowScaling:o=!0,allowAutoPosition:s=!0,debug:a=!1,parsing:u={}}=r??{};try{let c=o?ke(e.modelunits):1;return await _e(e,t,c,u,a),s&&Ve(t),t}catch(c){throw Ne(c,t),c}finally{a&&$e(n)}}function ke(e){return Pe[e]??1}async function _e(e,r,n,t,o){for(let s of e.values){let a=s.InnerTree;for(let u in a){let c=a[u];c&&await Ue(c,r,n,t,o)}}}async function Ue(e,r,n,t,o){for(let s of e)if(s.type.includes(ze)){let a={mergeByMaterial:!0,applyTransforms:!0,debug:!1,...t},u=await Z(s.data,a);if(n!==1)for(let c of u)c.scale.set(n,n,n);r.push(...u),o&&y().debug(`Extracted ${u.length} meshes from batch`)}}function Ve(e){if(e.length===0)return;let n=z(e).min.y;G(e,n)}function Ne(e,r){y().error("An unexpected error occurred:",e),Ge(r)}function Ge(e){for(let r of e)r.geometry&&r.geometry.dispose(),r.material&&(Array.isArray(r.material)?r.material.forEach(n=>n.dispose()):r.material.dispose())}function $e(e){let r=performance.now()-e;y().info("Time to process meshes:",`${r.toFixed(2)}ms`)}export{Ze as a,Xe as b,N as c,G as d,z as e,Me as f,$ as g,W as h,k as i,_ as j,Z as k,Ae as l,at as m,Pe as n,ut as o};
2
- //# sourceMappingURL=chunk-MKW2KTPT.js.map