@selvajs/visualization 1.0.0-beta.2 → 1.0.0-beta.3

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.
package/dist/render.d.cts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { i as MaterialAppearanceOptions, n as Look, r as LookPreset, t as LOOKS } from "./types-Di80Y609.cjs";
2
2
  import * as THREE from "three";
3
3
  import { OrbitControls } from "three/addons/controls/OrbitControls.js";
4
- import "three/addons/renderers/CSS2DRenderer.js";
4
+ import { CSS2DObject } from "three/addons/renderers/CSS2DRenderer.js";
5
5
  //#region src/shared/errors.d.ts
6
6
  /**
7
7
  * Errors for the visualization package. Replaces `@selvajs/compute`'s `RhinoComputeError`, which
@@ -307,6 +307,21 @@ interface Grid {
307
307
  dispose(): void;
308
308
  }
309
309
  //#endregion
310
+ //#region src/render/label-layer.d.ts
311
+ interface LabelHandle {
312
+ readonly object: CSS2DObject;
313
+ setPosition(position: THREE.Vector3): void;
314
+ setText(text: string): void;
315
+ remove(): void;
316
+ }
317
+ interface LabelLayer {
318
+ addLabel(text: string, position: THREE.Vector3, className?: string): LabelHandle;
319
+ /** Call each frame after the WebGL render, with the active camera. */
320
+ render(scene: THREE.Scene, camera: THREE.Camera): void;
321
+ setSize(width: number, height: number): void;
322
+ dispose(): void;
323
+ }
324
+ //#endregion
310
325
  //#region src/render/measure.d.ts
311
326
  /**
312
327
  * Two-click distance measurement. Click a point, click a second, read the distance off a label on
@@ -330,6 +345,74 @@ interface MeasureTool {
330
345
  clear(): void;
331
346
  dispose(): void;
332
347
  }
348
+ /**
349
+ * Raycast threshold for picking lines/points, as a fixed fraction of view size so the grab band
350
+ * stays constant on screen while zooming. Perspective uses camera→target distance (see
351
+ * `MeasureDeps.getViewTarget`); orthographic uses frustum height `(top − bottom) / zoom`, since
352
+ * ortho zoom changes `camera.zoom` rather than position.
353
+ *
354
+ * Shared with any tool doing its own picking, so grab bands stay consistent across tools.
355
+ */
356
+ declare function pickThreshold(camera: THREE.Camera, viewTarget?: THREE.Vector3): number;
357
+ /** Snap a raycast hit to the nearest geometry vertex within `snapPixels` on screen, else the raw hit point. */
358
+ declare function snapToVertex(hit: THREE.Intersection, camera: THREE.Camera, screenSize: {
359
+ width: number;
360
+ height: number;
361
+ }, snapPixels: number): THREE.Vector3;
362
+ //#endregion
363
+ //#region src/render/tool-registry.d.ts
364
+ /**
365
+ * A tool that can claim canvas pointer input.
366
+ *
367
+ * `handleClick` returning true means the tool consumed the event and the host stops dispatching —
368
+ * no further tool sees it, and object selection doesn't run. `handleMove` never consumes: it runs
369
+ * on every move regardless of which tool is active, so previews can't block orbit or pan.
370
+ */
371
+ interface PointerTool {
372
+ setEnabled?(enabled: boolean): void;
373
+ isEnabled?(): boolean;
374
+ /** Returns true if this tool consumed the click. */
375
+ handleClick(event: MouseEvent): boolean;
376
+ /** Preview only — must not consume. */
377
+ handleMove?(event: MouseEvent): void;
378
+ clear?(): void;
379
+ dispose?(): void;
380
+ }
381
+ interface ToolRegistration {
382
+ /** Unique within the registry; registering the same id twice replaces the earlier tool. */
383
+ id: string;
384
+ tool: PointerTool;
385
+ /**
386
+ * Higher runs first. The built-ins sit at 0 (measure) and -100 (gizmo); register above 0 to
387
+ * claim clicks before measuring, below -100 to act only as a fallback.
388
+ */
389
+ priority?: number;
390
+ }
391
+ interface ToolRegistry {
392
+ /** Returns an unregister function. Does not dispose the tool — the registrant still owns it. */
393
+ register(registration: ToolRegistration): () => void;
394
+ unregister(id: string): void;
395
+ get(id: string): PointerTool | null;
396
+ /**
397
+ * Enables one tool and disables every other registered one. Pass null to disable all.
398
+ * Tools without `setEnabled` are always live and unaffected.
399
+ */
400
+ setActive(id: string | null): void;
401
+ /** The id passed to the last `setActive`, or null. */
402
+ getActive(): string | null;
403
+ /** @internal — `initThree` forwards DOM events here. */
404
+ handleClick(event: MouseEvent): boolean;
405
+ /** @internal */
406
+ handleMove(event: MouseEvent): void;
407
+ }
408
+ /**
409
+ * Screen-space ray from a canvas mouse event, for tools doing their own picking. Handles the
410
+ * canvas's position and size, so it stays correct under CSS scaling and in fullscreen.
411
+ */
412
+ declare function pointerToNdc(event: MouseEvent, canvas: HTMLCanvasElement): {
413
+ x: number;
414
+ y: number;
415
+ };
333
416
  //#endregion
334
417
  //#region src/render/view-gizmo.d.ts
335
418
  /**
@@ -365,6 +448,13 @@ interface ThreeViewer {
365
448
  gizmo: ViewGizmo | null;
366
449
  /** Null unless `measure.enabled`. */
367
450
  measureTool: MeasureTool | null;
451
+ /** CSS2D annotation overlay. Always present — labels render above the canvas and don't take input. */
452
+ labelLayer: LabelLayer;
453
+ /**
454
+ * Pointer tools competing for canvas clicks, ahead of object selection. Built-ins are already
455
+ * registered as `'measure'` and `'gizmo'`; register your own and drive it with `setActive`.
456
+ */
457
+ tools: ToolRegistry;
368
458
  /**
369
459
  * No-op unless `edges.enabled`. Extraction runs off-thread for large meshes, so overlays can
370
460
  * attach a beat later; meshes over `edges.maxTriangles` fall back to the screen-space edge shader.
@@ -414,19 +504,48 @@ interface ThreeViewer {
414
504
  dispose: () => void;
415
505
  fitToView: () => void;
416
506
  clearSelection: () => void;
417
- /** Tagged `userData.source = 'user'` so it survives `updateScene` solves and counts for fit-to-view. */
418
- addUserGeometry: (object: THREE.Object3D) => void;
507
+ /**
508
+ * Adds host-owned geometry that survives `updateScene` solves and counts for fit-to-view.
509
+ * Pass `appId` to scope it to one app (`userData.source = 'app:<id>'`) so `clearUserGeometry`
510
+ * can clear that app alone; without one it's tagged `'user'` and only a global clear removes it.
511
+ *
512
+ * Not restyled by `setLook` — the caller owns these materials.
513
+ */
514
+ addUserGeometry: (object: THREE.Object3D, appId?: string) => void;
419
515
  removeUserGeometry: (object: THREE.Object3D) => void;
420
- /** Removes and disposes everything added via `addUserGeometry`. */
421
- clearUserGeometry: () => void;
516
+ /** Removes and disposes geometry added via `addUserGeometry` — one app's, or all of it. */
517
+ clearUserGeometry: (appId?: string) => void;
422
518
  }
423
519
  //#endregion
424
520
  //#region src/render/scene-setup/init-three.d.ts
425
521
  declare const initThree: (canvas: HTMLCanvasElement, options?: ThreeInitializerOptions) => ThreeViewer;
426
522
  //#endregion
523
+ //#region src/render/scene-ownership.d.ts
524
+ /** Geometry produced by a solve. Replaced wholesale on the next one. */
525
+ declare const SOURCE_COMPUTE = "compute";
526
+ /**
527
+ * Host-added geometry with no owner id. Predates scoped ownership and still honoured everywhere
528
+ * an `app:` scope is — new code should prefer {@link appSource}.
529
+ */
530
+ declare const SOURCE_USER = "user";
531
+ /** The `userData.source` tag for geometry owned by app `id` (`'pointcloud'` → `'app:pointcloud'`). */
532
+ declare function appSource(id: string): string;
533
+ /** The app id from a source tag, or null if the tag isn't app-owned. */
534
+ declare function appIdFromSource(source: unknown): string | null;
535
+ /**
536
+ * True for anything a host added rather than the solve — `'user'` or any `app:` scope. This is
537
+ * the predicate `clearScene` uses, so it decides what survives a solve.
538
+ */
539
+ declare function isHostOwned(object: THREE.Object3D): boolean;
540
+ /**
541
+ * True for objects owned by `id`. Passing no id matches every host-owned object, which is what
542
+ * `clearUserGeometry()` does.
543
+ */
544
+ declare function isOwnedBy(object: THREE.Object3D, id?: string): boolean;
545
+ //#endregion
427
546
  //#region src/render/three-helpers.d.ts
428
547
  /** Replaces scene content with `meshes`, rescales the camera frustum to fit, and (first call only) positions the camera/controls. */
429
548
  declare function updateScene(scene: THREE.Scene, meshes: THREE.Object3D[], camera: THREE.PerspectiveCamera, controls: OrbitControls, initialPositionSet: boolean): void;
430
549
  //#endregion
431
- export { type CameraConfig, type CameraController, type CameraProjection, type ControlsConfig, DEFAULT_LOOK, type EdgesConfig, type EnvironmentConfig, type ErrorCode, ErrorCodes, type EventConfig, type FloorConfig, type GizmoConfig, type Grid, type GridConfig, LOOKS, LOOK_PRESETS, type LightingConfig, type Logger, type Look, type LookPreset, type MaterialAppearanceOptions, type MeasureConfig, type MeasureTool, type RenderConfig, type ThreeInitializerOptions, type ThreeViewer, type ViewGizmo, type ViewPreset, VisualizationError, enableDebugLogging, getLogger, initThree, materialAppearanceForLook, setLogger, updateScene };
550
+ export { type CameraConfig, type CameraController, type CameraProjection, type ControlsConfig, DEFAULT_LOOK, type EdgesConfig, type EnvironmentConfig, type ErrorCode, ErrorCodes, type EventConfig, type FloorConfig, type GizmoConfig, type Grid, type GridConfig, LOOKS, LOOK_PRESETS, type LabelHandle, type LabelLayer, type LightingConfig, type Logger, type Look, type LookPreset, type MaterialAppearanceOptions, type MeasureConfig, type MeasureTool, type PointerTool, type RenderConfig, SOURCE_COMPUTE, SOURCE_USER, type ThreeInitializerOptions, type ThreeViewer, type ToolRegistration, type ToolRegistry, type ViewGizmo, type ViewPreset, VisualizationError, appIdFromSource, appSource, enableDebugLogging, getLogger, initThree, isHostOwned, isOwnedBy, materialAppearanceForLook, pickThreshold, pointerToNdc, setLogger, snapToVertex, updateScene };
432
551
  //# sourceMappingURL=render.d.cts.map
package/dist/render.d.ts CHANGED
@@ -307,6 +307,21 @@ interface Grid {
307
307
  dispose(): void;
308
308
  }
309
309
  //#endregion
310
+ //#region src/render/label-layer.d.ts
311
+ interface LabelHandle {
312
+ readonly object: CSS2DObject;
313
+ setPosition(position: THREE.Vector3): void;
314
+ setText(text: string): void;
315
+ remove(): void;
316
+ }
317
+ interface LabelLayer {
318
+ addLabel(text: string, position: THREE.Vector3, className?: string): LabelHandle;
319
+ /** Call each frame after the WebGL render, with the active camera. */
320
+ render(scene: THREE.Scene, camera: THREE.Camera): void;
321
+ setSize(width: number, height: number): void;
322
+ dispose(): void;
323
+ }
324
+ //#endregion
310
325
  //#region src/render/measure.d.ts
311
326
  /**
312
327
  * Two-click distance measurement. Click a point, click a second, read the distance off a label on
@@ -330,6 +345,74 @@ interface MeasureTool {
330
345
  clear(): void;
331
346
  dispose(): void;
332
347
  }
348
+ /**
349
+ * Raycast threshold for picking lines/points, as a fixed fraction of view size so the grab band
350
+ * stays constant on screen while zooming. Perspective uses camera→target distance (see
351
+ * `MeasureDeps.getViewTarget`); orthographic uses frustum height `(top − bottom) / zoom`, since
352
+ * ortho zoom changes `camera.zoom` rather than position.
353
+ *
354
+ * Shared with any tool doing its own picking, so grab bands stay consistent across tools.
355
+ */
356
+ declare function pickThreshold(camera: THREE.Camera, viewTarget?: THREE.Vector3): number;
357
+ /** Snap a raycast hit to the nearest geometry vertex within `snapPixels` on screen, else the raw hit point. */
358
+ declare function snapToVertex(hit: THREE.Intersection, camera: THREE.Camera, screenSize: {
359
+ width: number;
360
+ height: number;
361
+ }, snapPixels: number): THREE.Vector3;
362
+ //#endregion
363
+ //#region src/render/tool-registry.d.ts
364
+ /**
365
+ * A tool that can claim canvas pointer input.
366
+ *
367
+ * `handleClick` returning true means the tool consumed the event and the host stops dispatching —
368
+ * no further tool sees it, and object selection doesn't run. `handleMove` never consumes: it runs
369
+ * on every move regardless of which tool is active, so previews can't block orbit or pan.
370
+ */
371
+ interface PointerTool {
372
+ setEnabled?(enabled: boolean): void;
373
+ isEnabled?(): boolean;
374
+ /** Returns true if this tool consumed the click. */
375
+ handleClick(event: MouseEvent): boolean;
376
+ /** Preview only — must not consume. */
377
+ handleMove?(event: MouseEvent): void;
378
+ clear?(): void;
379
+ dispose?(): void;
380
+ }
381
+ interface ToolRegistration {
382
+ /** Unique within the registry; registering the same id twice replaces the earlier tool. */
383
+ id: string;
384
+ tool: PointerTool;
385
+ /**
386
+ * Higher runs first. The built-ins sit at 0 (measure) and -100 (gizmo); register above 0 to
387
+ * claim clicks before measuring, below -100 to act only as a fallback.
388
+ */
389
+ priority?: number;
390
+ }
391
+ interface ToolRegistry {
392
+ /** Returns an unregister function. Does not dispose the tool — the registrant still owns it. */
393
+ register(registration: ToolRegistration): () => void;
394
+ unregister(id: string): void;
395
+ get(id: string): PointerTool | null;
396
+ /**
397
+ * Enables one tool and disables every other registered one. Pass null to disable all.
398
+ * Tools without `setEnabled` are always live and unaffected.
399
+ */
400
+ setActive(id: string | null): void;
401
+ /** The id passed to the last `setActive`, or null. */
402
+ getActive(): string | null;
403
+ /** @internal — `initThree` forwards DOM events here. */
404
+ handleClick(event: MouseEvent): boolean;
405
+ /** @internal */
406
+ handleMove(event: MouseEvent): void;
407
+ }
408
+ /**
409
+ * Screen-space ray from a canvas mouse event, for tools doing their own picking. Handles the
410
+ * canvas's position and size, so it stays correct under CSS scaling and in fullscreen.
411
+ */
412
+ declare function pointerToNdc(event: MouseEvent, canvas: HTMLCanvasElement): {
413
+ x: number;
414
+ y: number;
415
+ };
333
416
  //#endregion
334
417
  //#region src/render/view-gizmo.d.ts
335
418
  /**
@@ -365,6 +448,13 @@ interface ThreeViewer {
365
448
  gizmo: ViewGizmo | null;
366
449
  /** Null unless `measure.enabled`. */
367
450
  measureTool: MeasureTool | null;
451
+ /** CSS2D annotation overlay. Always present — labels render above the canvas and don't take input. */
452
+ labelLayer: LabelLayer;
453
+ /**
454
+ * Pointer tools competing for canvas clicks, ahead of object selection. Built-ins are already
455
+ * registered as `'measure'` and `'gizmo'`; register your own and drive it with `setActive`.
456
+ */
457
+ tools: ToolRegistry;
368
458
  /**
369
459
  * No-op unless `edges.enabled`. Extraction runs off-thread for large meshes, so overlays can
370
460
  * attach a beat later; meshes over `edges.maxTriangles` fall back to the screen-space edge shader.
@@ -414,19 +504,48 @@ interface ThreeViewer {
414
504
  dispose: () => void;
415
505
  fitToView: () => void;
416
506
  clearSelection: () => void;
417
- /** Tagged `userData.source = 'user'` so it survives `updateScene` solves and counts for fit-to-view. */
418
- addUserGeometry: (object: THREE.Object3D) => void;
507
+ /**
508
+ * Adds host-owned geometry that survives `updateScene` solves and counts for fit-to-view.
509
+ * Pass `appId` to scope it to one app (`userData.source = 'app:<id>'`) so `clearUserGeometry`
510
+ * can clear that app alone; without one it's tagged `'user'` and only a global clear removes it.
511
+ *
512
+ * Not restyled by `setLook` — the caller owns these materials.
513
+ */
514
+ addUserGeometry: (object: THREE.Object3D, appId?: string) => void;
419
515
  removeUserGeometry: (object: THREE.Object3D) => void;
420
- /** Removes and disposes everything added via `addUserGeometry`. */
421
- clearUserGeometry: () => void;
516
+ /** Removes and disposes geometry added via `addUserGeometry` — one app's, or all of it. */
517
+ clearUserGeometry: (appId?: string) => void;
422
518
  }
423
519
  //#endregion
424
520
  //#region src/render/scene-setup/init-three.d.ts
425
521
  declare const initThree: (canvas: HTMLCanvasElement, options?: ThreeInitializerOptions) => ThreeViewer;
426
522
  //#endregion
523
+ //#region src/render/scene-ownership.d.ts
524
+ /** Geometry produced by a solve. Replaced wholesale on the next one. */
525
+ declare const SOURCE_COMPUTE = "compute";
526
+ /**
527
+ * Host-added geometry with no owner id. Predates scoped ownership and still honoured everywhere
528
+ * an `app:` scope is — new code should prefer {@link appSource}.
529
+ */
530
+ declare const SOURCE_USER = "user";
531
+ /** The `userData.source` tag for geometry owned by app `id` (`'pointcloud'` → `'app:pointcloud'`). */
532
+ declare function appSource(id: string): string;
533
+ /** The app id from a source tag, or null if the tag isn't app-owned. */
534
+ declare function appIdFromSource(source: unknown): string | null;
535
+ /**
536
+ * True for anything a host added rather than the solve — `'user'` or any `app:` scope. This is
537
+ * the predicate `clearScene` uses, so it decides what survives a solve.
538
+ */
539
+ declare function isHostOwned(object: THREE.Object3D): boolean;
540
+ /**
541
+ * True for objects owned by `id`. Passing no id matches every host-owned object, which is what
542
+ * `clearUserGeometry()` does.
543
+ */
544
+ declare function isOwnedBy(object: THREE.Object3D, id?: string): boolean;
545
+ //#endregion
427
546
  //#region src/render/three-helpers.d.ts
428
547
  /** Replaces scene content with `meshes`, rescales the camera frustum to fit, and (first call only) positions the camera/controls. */
429
548
  declare function updateScene(scene: THREE.Scene, meshes: THREE.Object3D[], camera: THREE.PerspectiveCamera, controls: OrbitControls, initialPositionSet: boolean): void;
430
549
  //#endregion
431
- export { type CameraConfig, type CameraController, type CameraProjection, type ControlsConfig, DEFAULT_LOOK, type EdgesConfig, type EnvironmentConfig, type ErrorCode, ErrorCodes, type EventConfig, type FloorConfig, type GizmoConfig, type Grid, type GridConfig, LOOKS, LOOK_PRESETS, type LightingConfig, type Logger, type Look, type LookPreset, type MaterialAppearanceOptions, type MeasureConfig, type MeasureTool, type RenderConfig, type ThreeInitializerOptions, type ThreeViewer, type ViewGizmo, type ViewPreset, VisualizationError, enableDebugLogging, getLogger, initThree, materialAppearanceForLook, setLogger, updateScene };
550
+ export { type CameraConfig, type CameraController, type CameraProjection, type ControlsConfig, DEFAULT_LOOK, type EdgesConfig, type EnvironmentConfig, type ErrorCode, ErrorCodes, type EventConfig, type FloorConfig, type GizmoConfig, type Grid, type GridConfig, LOOKS, LOOK_PRESETS, type LabelHandle, type LabelLayer, type LightingConfig, type Logger, type Look, type LookPreset, type MaterialAppearanceOptions, type MeasureConfig, type MeasureTool, type PointerTool, type RenderConfig, SOURCE_COMPUTE, SOURCE_USER, type ThreeInitializerOptions, type ThreeViewer, type ToolRegistration, type ToolRegistry, type ViewGizmo, type ViewPreset, VisualizationError, appIdFromSource, appSource, enableDebugLogging, getLogger, initThree, isHostOwned, isOwnedBy, materialAppearanceForLook, pickThreshold, pointerToNdc, setLogger, snapToVertex, updateScene };
432
551
  //# sourceMappingURL=render.d.ts.map
package/dist/render.js CHANGED
@@ -1,5 +1,5 @@
1
- import{a as e,c as t,d as n,l as r,r as i,s as a,t as o,u as s}from"./gpu-dispose-Dkj-BKt4.js";import*as c from"three";import{Line2 as l}from"three/addons/lines/Line2.js";import{LineGeometry as u}from"three/addons/lines/LineGeometry.js";import{LineMaterial as d}from"three/addons/lines/LineMaterial.js";import{LineSegments2 as f}from"three/addons/lines/LineSegments2.js";import{LineSegmentsGeometry as p}from"three/addons/lines/LineSegmentsGeometry.js";import{CSS2DObject as m,CSS2DRenderer as h}from"three/addons/renderers/CSS2DRenderer.js";import{ViewHelper as g}from"three/addons/helpers/ViewHelper.js";import{EffectComposer as _}from"three/addons/postprocessing/EffectComposer.js";import{RenderPass as v}from"three/addons/postprocessing/RenderPass.js";import{GTAOPass as y}from"three/addons/postprocessing/GTAOPass.js";import{SMAAPass as b}from"three/addons/postprocessing/SMAAPass.js";import{OutputPass as x}from"three/addons/postprocessing/OutputPass.js";import{FullScreenQuad as S,Pass as C}from"three/addons/postprocessing/Pass.js";import{OrbitControls as w}from"three/addons/controls/OrbitControls.js";import{HDRLoader as T}from"three/addons/loaders/HDRLoader.js";const E=[`technical`,`studio`,`showcase`],D=`technical`,O={studio:{toneMapping:c.ACESFilmicToneMapping,toneMappingExposure:1,envMapIntensity:1,environmentIntensity:1,hemisphereIntensity:.75,ambientIntensity:.4,cullBackfaces:!1,ambientOcclusion:!1},technical:{toneMapping:c.NeutralToneMapping,toneMappingExposure:1,envMapIntensity:.9,environmentIntensity:1,hemisphereIntensity:.35,ambientIntensity:.25,cullBackfaces:!1,ambientOcclusion:!1},showcase:{toneMapping:c.ACESFilmicToneMapping,toneMappingExposure:1.15,envMapIntensity:1.4,environmentIntensity:1.25,hemisphereIntensity:.35,ambientIntensity:.15,cullBackfaces:!1,ambientOcclusion:!1}};function k(e){let t=O[e];return{envMapIntensity:t.envMapIntensity,cullBackfaces:t.cullBackfaces}}function A(e){let t=e.clone().normalize(),n=new c.Vector3(0,0,1),r=new c.Vector3(0,1,0),i=Math.abs(t.dot(n))>.9?r:n,a=new c.Vector3().crossVectors(i,t).normalize();return{up:t,forward:new c.Vector3().crossVectors(t,a).normalize(),right:a}}function j(e,t){let{forward:n,right:r,up:i}=A(e);return n.clone().multiplyScalar(-1).add(r.clone().multiplyScalar(-1)).add(i).normalize().multiplyScalar(t)}function M(e,t,n){let{forward:r,right:i,up:a}=A(e);return i.clone().multiplyScalar(t).add(r.clone().multiplyScalar(t)).add(a.clone().multiplyScalar(n))}function ee(e){let t=e.clone().normalize(),n=new c.Vector3(0,1,0);if(t.dot(n)>.9999)return new c.Euler;if(t.dot(n)<-.9999)return new c.Euler(Math.PI,0,0);let r=new c.Quaternion().setFromUnitVectors(n,t);return new c.Euler().setFromQuaternion(r)}function te(e){let t=Math.abs(e.x),n=Math.abs(e.y),r=Math.abs(e.z);return t>=n&&t>=r?`x`:n>=r?`y`:`z`}const N={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 P(t,n,r,i,a){if(z(t),n.length===0)return;n.forEach(e=>{t.add(e)});let o=e(n),s=o.getCenter(new c.Vector3),l=o.getSize(new c.Vector3),u=Math.max(l.x,l.y,l.z);if(u/Math.min(l.x||1,l.y||1,l.z||1)>N.SCALE_RATIO_THRESHOLD||u>N.HUGE_THRESHOLD?(r.near=u*N.NEAR_PLANE_FACTOR.TINY,r.far=u*N.FAR_PLANE_FACTOR.HUGE):u>N.LARGE_THRESHOLD?(r.near=u*N.NEAR_PLANE_FACTOR.SMALL,r.far=u*N.FAR_PLANE_FACTOR.LARGE):(r.near=Math.max(.01,u*N.NEAR_PLANE_FACTOR.NORMAL),r.far=Math.max(2e3,u*N.FAR_PLANE_FACTOR.NORMAL)),r.updateProjectionMatrix(),!a){let e=u*N.INITIAL_DISTANCE_MULTIPLIER;r.position.copy(s).add(j(r.up,e)),i.target.copy(s),i.update()}}const F=new Set([`grid`,`floor`,`label-layer`,`measure`]);function I(e){let t=e;for(;t;){if(typeof t.userData.id==`string`&&F.has(t.userData.id))return!0;t=t.parent}return!1}function L(e){e.updateMatrixWorld(!0);let t=new c.Box3;return e.traverse(e=>{let n=e;e.visible&&!I(e)&&n.geometry&&t.expandByObject(e)}),t}const R=new Set([`floor`,`grid`,`label-layer`]);function z(e){[...e.children].forEach(e=>{R.has(e.userData.id)||e.userData.source!==`user`&&(o(e),e.removeFromParent())})}function B(e){let{up:t,forward:n,right:r}=A(e),i=n.clone().negate(),a=r.clone();return{top:t.clone(),bottom:t.clone().negate(),front:i.clone(),back:i.clone().negate(),right:a.clone(),left:a.clone().negate(),iso:i.clone().multiplyScalar(1.2).add(a.clone()).add(t.clone()).normalize()}}function ne(e){let{scene:t,perspective:n,controls:r,onActiveCameraChange:i}=e,a=(e.up??n.up).clone().normalize(),o=B(a),s=new c.OrthographicCamera(-1,1,1,-1,n.near,n.far);s.up.copy(a);let l=`perspective`,u=n.aspect,d=()=>l===`perspective`?n:s,f=null,p=()=>{f?.cancel(),f=null},m=()=>{let e=(l===`orthographic`?s:n).position.distanceTo(r.target)*Math.tan(n.fov*Math.PI/360),t=e*u;s.left=-t,s.right=t,s.top=e,s.bottom=-e,s.near=n.near,s.far=n.far,s.updateProjectionMatrix()},h=e=>{if(e!==l){if(p(),e===`orthographic`)s.position.copy(n.position),s.up.copy(n.up),s.lookAt(r.target),s.zoom=1,m();else{let e=(s.top-s.bottom)/(2*s.zoom)/Math.tan(n.fov*Math.PI/360),t=s.position.clone().sub(r.target);t.lengthSq()<1e-12&&t.copy(a),t.normalize(),n.position.copy(r.target).add(t.multiplyScalar(e))}l=e,r.object=d(),r.update(),i(d())}},g=(e,t,i,o)=>{let c=n.fov*(Math.PI/180),u=t/(2*Math.tan(c/2))*1.5,h=V(i,a),g=e.clone().add(h.clone().multiplyScalar(u)),_=d();l===`orthographic`&&(s.zoom=1),p(),o?f=U(_,r,g,e,()=>{l===`orthographic`&&m()}):(_.position.copy(g),r.target.copy(e),l===`orthographic`&&m(),r.update())},_=(e,n=!0)=>{let i=L(t),a=i.isEmpty()?r.target.clone():i.getCenter(new c.Vector3),o=i.isEmpty()?new c.Vector3(1,1,1):i.getSize(new c.Vector3),s=Math.max(o.x,o.y,o.z)||1;g(a,s,e,n)};return{getActiveCamera:d,getProjection:()=>l,setProjection:h,toggleProjection:()=>(h(l===`perspective`?`orthographic`:`perspective`),l),setView:(e,t=!0)=>{_(o[e],t)},setViewDirection:_,frameBounds:(e,t=!0)=>{if(e.isEmpty())return;let n=e.getCenter(new c.Vector3),i=e.getSize(new c.Vector3),a=Math.max(i.x,i.y,i.z)||1,s=d().position.clone().sub(r.target);s.lengthSq()<1e-12&&s.copy(o.iso),g(n,a,s.normalize(),t)},setRotateEnabled:e=>{r.enableRotate=e},isRotateEnabled:()=>r.enableRotate,updateAspect:(e,t)=>{u=t===0?u:e/t,l===`orthographic`&&m()},dispose:p}}function V(e,t){let{up:n,forward:r}=A(t),i=e.clone().normalize();if(Math.abs(i.dot(n))<.9999)return e;let a=r.clone().negate(),o=.5*Math.PI/180;return i.multiplyScalar(Math.cos(o)).add(a.multiplyScalar(Math.sin(o))).normalize()}const H=e=>1-(1-e)**3;function U(e,t,n,r,i,a=250){let o=e.position.clone(),s=t.target.clone(),c=performance.now(),l=null,u=()=>{l=null;let d=H(Math.min((performance.now()-c)/a,1));e.position.lerpVectors(o,n,d),t.target.lerpVectors(s,r,d),i(),t.update(),d<1&&(l=requestAnimationFrame(u))};return l=requestAnimationFrame(u),{cancel:()=>{l!==null&&(cancelAnimationFrame(l),l=null)}}}function W(e){let t=Math.floor(e.length/6);if(t===0)return 1/0;let n=Math.max(1,Math.ceil(t/4096)),r=[];for(let i=0;i<t;i+=n){let t=i*6,n=Math.hypot(e[t+3]-e[t],e[t+4]-e[t+1],e[t+5]-e[t+2]);n>0&&r.push(n)}return r.length===0?1/0:(r.sort((e,t)=>e-t),r[Math.min(r.length-1,Math.floor(r.length*.15))])}function G(e){let t=new p;return t.setPositions(e),{geometry:t,segmentCount:e.length/6,edgeSpacing:W(e)}}function K(e,t,n){let r=1e4,i=67108864,a=Math.cos(Math.PI/180*n),o=e.length/3;if(o>=i)throw Error(`extractEdgeSegments: ${o} vertices exceeds 2^26 limit`);let s=new Float64Array(o),c=new Float64Array(o),l=new Float64Array(o);for(let t=0;t<o;t++)s[t]=Math.round(e[3*t]*r),c[t]=Math.round(e[3*t+1]*r),l[t]=Math.round(e[3*t+2]*r);let u=16;for(;u<o*2;)u<<=1;let d=u-1,f=new Int32Array(u).fill(-1),p=new Int32Array(o);for(let e=0;e<o;e++){let t=(Math.imul(s[e]|0,73856093)^Math.imul(c[e]|0,19349663)^Math.imul(l[e]|0,83492791))&d;for(;;){let n=f[t];if(n===-1){f[t]=e,p[e]=e;break}if(s[n]===s[e]&&c[n]===c[e]&&l[n]===l[e]){p[e]=n;break}t=t+1&d}}let m=new Float32Array(4096),h=0,g=(t,n)=>{if(h+6>m.length){let e=new Float32Array(m.length*2);e.set(m),m=e}m[h++]=e[3*t],m[h++]=e[3*t+1],m[h++]=e[3*t+2],m[h++]=e[3*n],m[h++]=e[3*n+1],m[h++]=e[3*n+2]},_=new Map,v=[],y=[],b=[],x=(t?t.length:o)/3;for(let n=0;n<x;n++){let r=t?t[3*n]:3*n,o=t?t[3*n+1]:3*n+1,s=t?t[3*n+2]:3*n+2,c=p[r],l=p[o],u=p[s];if(c===l||l===u||u===c)continue;let d=e[3*s]-e[3*o],f=e[3*s+1]-e[3*o+1],m=e[3*s+2]-e[3*o+2],h=e[3*r]-e[3*o],x=e[3*r+1]-e[3*o+1],S=e[3*r+2]-e[3*o+2],C=f*S-m*x,w=m*h-d*S,T=d*x-f*h,E=C*C+w*w+T*T;if(E>0){let e=1/Math.sqrt(E);C*=e,w*=e,T*=e}else C=0,w=0,T=0;for(let e=0;e<3;e++){let t,n,d,f;e===0?(t=r,n=o,d=c,f=l):e===1?(t=o,n=s,d=l,f=u):(t=s,n=r,d=u,f=c);let p=f*i+d,m=_.get(p);if(m!==void 0&&m!==-1)C*b[3*m]+w*b[3*m+1]+T*b[3*m+2]<=a&&g(t,n),_.set(p,-1);else{let e=d*i+f;if(!_.has(e)){let r=v.length;_.set(e,r),v.push(t),y.push(n),b.push(C,w,T)}}}}for(let e of _.values())e!==-1&&g(v[e],y[e]);return m.slice(0,h)}function re(){return[`const extract = ${K.toString()};`,`self.onmessage = (event) => {`,` const { id, positions, index, thresholdAngle } = event.data;`,` try {`,` const segments = extract(positions, index, thresholdAngle);`,` self.postMessage({ id, segments }, [segments.buffer]);`,` } catch (error) {`,` self.postMessage({ id, error: String((error && error.message) || error) });`,` }`,`};`].join(`
2
- `)}const ie=`edge-overlay`;function ae(e){return{forcedColor:e.color==null?null:new c.Color(e.color),darken:c.MathUtils.clamp(e.darken??.75,0,1),width:e.width??1.5,thresholdAngle:e.thresholdAngle??44,distanceFade:e.distanceFade??!0,maxTriangles:e.maxTriangles??4e6,maxSegments:e.maxSegments??2e6}}function q(e){let t=e.getAttribute(`position`);return t?(e.index?e.index.count:t.count)/3:0}function oe(e){let t=e.getAttribute(`position`);if(!t||t.isInterleavedBufferAttribute||t.itemSize!==3||!(t.array instanceof Float32Array)||t.count>=67108864)return null;let n=e.index;return n&&!(n.array instanceof Uint32Array)&&!(n.array instanceof Uint16Array)?null:{positions:t.array,index:n?n.array:null}}function se(e,t){let n=4096,r=2166136261,i=e=>{r^=e,r=Math.imul(r,16777619)},a=new Uint32Array(e.positions.buffer,e.positions.byteOffset,e.positions.length),o=Math.min(n,a.length);for(let e=0;e<o;e++)i(a[e]);for(let e=Math.max(o,a.length-n);e<a.length;e++)i(a[e]);let s=0;if(e.index){s=e.index.length;let t=Math.min(n,s);for(let n=0;n<t;n++)i(e.index[n]);for(let r=Math.max(t,s-n);r<s;r++)i(e.index[r])}return`${t}:${e.positions.length}:${s}:${r>>>0}`}function ce(e,t){let n=new c.EdgesGeometry(e,t),r=n.attributes.position?n.attributes.position.array:new Float32Array;return n.dispose(),r}function le(e,t){let n=oe(e);return n?K(n.positions,n.index,t):ce(e,t)}let J;const Y=new Map;let ue=1;function de(){if(J!==void 0)return J;if(typeof Worker>`u`||typeof Blob>`u`||typeof URL>`u`||typeof URL.createObjectURL!=`function`)return J=null,null;try{let e=URL.createObjectURL(new Blob([re()],{type:`text/javascript`})),t=new Worker(e);t.onmessage=e=>{let{id:t,segments:n,error:r}=e.data,i=Y.get(t);i&&(Y.delete(t),n?i.resolve(n):i.reject(Error(r??`edge extraction failed in worker`)))},t.onerror=()=>{for(let e of Y.values())e.reject(Error(`edge extraction worker crashed`));Y.clear(),t.terminate(),J=null},J=t}catch{J=null}return J}function fe(e,t,n){return new Promise((r,i)=>{let a=ue++;Y.set(a,{resolve:r,reject:i});let o=t.positions.slice(),s=t.index?t.index.slice():null,c=[o.buffer];s&&c.push(s.buffer),e.postMessage({id:a,positions:o,index:s,thresholdAngle:n},c)})}const X=new Map;function pe(e,t){let n=oe(e);if(!n||q(e)<25e3)return Promise.resolve(le(e,t));let r=se(n,t),i=X.get(r);if(i)return i;let a=de();if(!a)return Promise.resolve(le(e,t));let o=fe(a,n,t).catch(()=>K(n.positions,n.index,t)).finally(()=>{X.delete(r)});return X.set(r,o),o}function me(e,t){let n=(Array.isArray(e.material)?e.material[0]:e.material)?.color;return n?n.clone().multiplyScalar(1-t):new c.Color(2236962)}var he=class{options;byKey=new Map;constructor(e){this.options=e}for(e,t){let n=this.options.forcedColor??me(e,this.options.darken),r=n.getHex()*2+ +!!t,i=this.byKey.get(r);return i||(i=ge(n,this.options.width,t),this.byKey.set(r,i)),i}disposeUnused(e){let t=new Set(e.map(e=>e.material));for(let e of this.byKey.values())t.has(e)||e.dispose()}};function ge(e,t,n){let r=new d({color:e});return r.linewidth=t,r.polygonOffset=!0,r.polygonOffsetFactor=0,r.polygonOffsetUnits=-1,n&&(r.transparent=!0),r}function _e(e,t,n){let r=new f(e.geometry,t);return r.userData.kind=ie,r.raycast=()=>{},n&&xe(r,e.edgeSpacing),r}const ve=new c.Vector3,ye=new c.Vector3;function be(e,t,n){e.geometry.boundingSphere||e.geometry.computeBoundingSphere();let r=e.geometry.boundingSphere;if(!r)return 1/0;if(t.isPerspectiveCamera){let i=t;ve.copy(r.center).applyMatrix4(e.matrixWorld);let a=ye.setFromMatrixPosition(t.matrixWorld).distanceTo(ve);if(a<=r.radius*e.matrixWorld.getMaxScaleOnAxis())return 1/0;let o=Math.tan(c.MathUtils.degToRad(i.fov)*.5),s=2*a*o;return s>0?n/s:1/0}if(t.isOrthographicCamera){let e=t,r=(e.top-e.bottom)/e.zoom;return r>0?n/r:1/0}return 1/0}function xe(e,t){e.onBeforeRender=(n,r,i)=>{f.prototype.onBeforeRender.call(e,n);let a=e.material,o=t*be(e,i,a.resolution.y);a.opacity=c.MathUtils.clamp((o-1)/3,0,1)}}function Se(e){return e.userData?.kind===ie}function Ce(e,t){let n=[];return e.traverse(e=>{if(e instanceof c.Mesh&&e.userData.id!==`floor`&&e.userData.id!==`grid`&&e.userData.kind!==`edge-overlay`&&!e.children.some(e=>e.userData?.kind===`edge-overlay`)&&e.geometry){if(q(e.geometry)>t){e.userData.edgesSkipped=`triangle-cap`,console.debug(`[edges] skipping mesh over triangle cap (${q(e.geometry)} > ${t})`);return}delete e.userData.edgesSkipped,n.push(e)}}),n}function we(e,t,n,r){let i=r.distanceFade&&t.segmentCount<=r.maxSegments,a=_e(t,n.for(e,i),i);return e.add(a),a}const Te=new WeakMap;function Z(e){return Te.get(e)??0}function Ee(e,t){for(let n=e;n;n=n.parent)if(n===t)return!0;return!1}async function De(e,t={}){let n=ae(t),r=new he(n),i=Z(e),a=[],o=Ce(e,n.maxTriangles).map(async t=>{let o=await pe(t.geometry,n.thresholdAngle);Z(e)===i&&Ee(t,e)&&(t.children.some(e=>e.userData?.kind===`edge-overlay`)||a.push(we(t,G(o),r,n)))});return await Promise.all(o),r.disposeUnused(a),a}function Oe(e){Te.set(e,Z(e)+1);let t=[];e.traverse(e=>{e instanceof f&&Se(e)&&t.push(e)});let n=new Set;for(let e of t)e.geometry.dispose(),n.add(e.material),e.removeFromParent();return n.forEach(e=>e.dispose()),t.length}function ke(e){if(!(e>0)||!Number.isFinite(e))return 1;let t=10**Math.floor(Math.log10(e)),n=e/t;return(n>=5?5:n>=2?2:1)*t}function Ae(e={}){let{cellSize:t=1,majorEvery:n=10,cellColor:r=8947848,majorColor:i=4473924,fadeDistance:a=100,plane:o=`y`}=e,s=o===`y`?new c.Vector2(0,2):o===`z`?new c.Vector2(0,1):new c.Vector2(1,2),l=2.5,u=new c.PlaneGeometry(1,1);o===`y`?u.rotateX(-Math.PI/2):o===`x`&&u.rotateY(Math.PI/2);let d=new c.ShaderMaterial({vertexShader:`
1
+ import{a as e,c as t,d as n,l as r,r as i,s as a,t as o,u as s}from"./gpu-dispose-Dkj-BKt4.js";import*as c from"three";import{Line2 as l}from"three/addons/lines/Line2.js";import{LineGeometry as u}from"three/addons/lines/LineGeometry.js";import{LineMaterial as d}from"three/addons/lines/LineMaterial.js";import{LineSegments2 as f}from"three/addons/lines/LineSegments2.js";import{LineSegmentsGeometry as p}from"three/addons/lines/LineSegmentsGeometry.js";import{CSS2DObject as m,CSS2DRenderer as h}from"three/addons/renderers/CSS2DRenderer.js";import{ViewHelper as g}from"three/addons/helpers/ViewHelper.js";import{EffectComposer as _}from"three/addons/postprocessing/EffectComposer.js";import{RenderPass as v}from"three/addons/postprocessing/RenderPass.js";import{GTAOPass as y}from"three/addons/postprocessing/GTAOPass.js";import{SMAAPass as b}from"three/addons/postprocessing/SMAAPass.js";import{OutputPass as x}from"three/addons/postprocessing/OutputPass.js";import{FullScreenQuad as S,Pass as C}from"three/addons/postprocessing/Pass.js";import{OrbitControls as w}from"three/addons/controls/OrbitControls.js";import{HDRLoader as T}from"three/addons/loaders/HDRLoader.js";const E=[`technical`,`studio`,`showcase`],D=`technical`,O={studio:{toneMapping:c.ACESFilmicToneMapping,toneMappingExposure:1,envMapIntensity:1,environmentIntensity:1,hemisphereIntensity:.75,ambientIntensity:.4,cullBackfaces:!1,ambientOcclusion:!1},technical:{toneMapping:c.NeutralToneMapping,toneMappingExposure:1,envMapIntensity:.9,environmentIntensity:1,hemisphereIntensity:.35,ambientIntensity:.25,cullBackfaces:!1,ambientOcclusion:!1},showcase:{toneMapping:c.ACESFilmicToneMapping,toneMappingExposure:1.15,envMapIntensity:1.4,environmentIntensity:1.25,hemisphereIntensity:.35,ambientIntensity:.15,cullBackfaces:!1,ambientOcclusion:!1}};function k(e){let t=O[e];return{envMapIntensity:t.envMapIntensity,cullBackfaces:t.cullBackfaces}}const A=`compute`,j=`user`,M=`app:`;function N(e){return`${M}${e}`}function P(e){return typeof e!=`string`||!e.startsWith(M)?null:e.slice(4)||null}function F(e){let t=e.userData?.source;return t===`user`||P(t)!==null}function ee(e,t){return t===void 0?F(e):e.userData?.source===N(t)}function I(e){let t=e.clone().normalize(),n=new c.Vector3(0,0,1),r=new c.Vector3(0,1,0),i=Math.abs(t.dot(n))>.9?r:n,a=new c.Vector3().crossVectors(i,t).normalize();return{up:t,forward:new c.Vector3().crossVectors(t,a).normalize(),right:a}}function L(e,t){let{forward:n,right:r,up:i}=I(e);return n.clone().multiplyScalar(-1).add(r.clone().multiplyScalar(-1)).add(i).normalize().multiplyScalar(t)}function R(e,t,n){let{forward:r,right:i,up:a}=I(e);return i.clone().multiplyScalar(t).add(r.clone().multiplyScalar(t)).add(a.clone().multiplyScalar(n))}function te(e){let t=e.clone().normalize(),n=new c.Vector3(0,1,0);if(t.dot(n)>.9999)return new c.Euler;if(t.dot(n)<-.9999)return new c.Euler(Math.PI,0,0);let r=new c.Quaternion().setFromUnitVectors(n,t);return new c.Euler().setFromQuaternion(r)}function ne(e){let t=Math.abs(e.x),n=Math.abs(e.y),r=Math.abs(e.z);return t>=n&&t>=r?`x`:n>=r?`y`:`z`}const z={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 re(t,n,r,i,a){if(W(t),n.length===0)return;n.forEach(e=>{t.add(e)});let o=e(n),s=o.getCenter(new c.Vector3),l=o.getSize(new c.Vector3),u=Math.max(l.x,l.y,l.z);if(u/Math.min(l.x||1,l.y||1,l.z||1)>z.SCALE_RATIO_THRESHOLD||u>z.HUGE_THRESHOLD?(r.near=u*z.NEAR_PLANE_FACTOR.TINY,r.far=u*z.FAR_PLANE_FACTOR.HUGE):u>z.LARGE_THRESHOLD?(r.near=u*z.NEAR_PLANE_FACTOR.SMALL,r.far=u*z.FAR_PLANE_FACTOR.LARGE):(r.near=Math.max(.01,u*z.NEAR_PLANE_FACTOR.NORMAL),r.far=Math.max(2e3,u*z.FAR_PLANE_FACTOR.NORMAL)),r.updateProjectionMatrix(),!a){let e=u*z.INITIAL_DISTANCE_MULTIPLIER;r.position.copy(s).add(L(r.up,e)),i.target.copy(s),i.update()}}const B=new Set([`grid`,`floor`,`label-layer`,`measure`]);function V(e){let t=e;for(;t;){if(typeof t.userData.id==`string`&&B.has(t.userData.id))return!0;t=t.parent}return!1}function H(e){e.updateMatrixWorld(!0);let t=new c.Box3;return e.traverse(e=>{let n=e;e.visible&&!V(e)&&n.geometry&&t.expandByObject(e)}),t}const U=new Set([`floor`,`grid`,`label-layer`]);function W(e){[...e.children].forEach(e=>{U.has(e.userData.id)||F(e)||(o(e),e.removeFromParent())})}function ie(e){let{up:t,forward:n,right:r}=I(e),i=n.clone().negate(),a=r.clone();return{top:t.clone(),bottom:t.clone().negate(),front:i.clone(),back:i.clone().negate(),right:a.clone(),left:a.clone().negate(),iso:i.clone().multiplyScalar(1.2).add(a.clone()).add(t.clone()).normalize()}}function ae(e){let{scene:t,perspective:n,controls:r,onActiveCameraChange:i}=e,a=(e.up??n.up).clone().normalize(),o=ie(a),s=new c.OrthographicCamera(-1,1,1,-1,n.near,n.far);s.up.copy(a);let l=`perspective`,u=n.aspect,d=()=>l===`perspective`?n:s,f=null,p=()=>{f?.cancel(),f=null},m=()=>{let e=(l===`orthographic`?s:n).position.distanceTo(r.target)*Math.tan(n.fov*Math.PI/360),t=e*u;s.left=-t,s.right=t,s.top=e,s.bottom=-e,s.near=n.near,s.far=n.far,s.updateProjectionMatrix()},h=e=>{if(e!==l){if(p(),e===`orthographic`)s.position.copy(n.position),s.up.copy(n.up),s.lookAt(r.target),s.zoom=1,m();else{let e=(s.top-s.bottom)/(2*s.zoom)/Math.tan(n.fov*Math.PI/360),t=s.position.clone().sub(r.target);t.lengthSq()<1e-12&&t.copy(a),t.normalize(),n.position.copy(r.target).add(t.multiplyScalar(e))}l=e,r.object=d(),r.update(),i(d())}},g=(e,t,i,o)=>{let c=n.fov*(Math.PI/180),u=t/(2*Math.tan(c/2))*1.5,h=oe(i,a),g=e.clone().add(h.clone().multiplyScalar(u)),_=d();l===`orthographic`&&(s.zoom=1),p(),o?f=se(_,r,g,e,()=>{l===`orthographic`&&m()}):(_.position.copy(g),r.target.copy(e),l===`orthographic`&&m(),r.update())},_=(e,n=!0)=>{let i=H(t),a=i.isEmpty()?r.target.clone():i.getCenter(new c.Vector3),o=i.isEmpty()?new c.Vector3(1,1,1):i.getSize(new c.Vector3),s=Math.max(o.x,o.y,o.z)||1;g(a,s,e,n)};return{getActiveCamera:d,getProjection:()=>l,setProjection:h,toggleProjection:()=>(h(l===`perspective`?`orthographic`:`perspective`),l),setView:(e,t=!0)=>{_(o[e],t)},setViewDirection:_,frameBounds:(e,t=!0)=>{if(e.isEmpty())return;let n=e.getCenter(new c.Vector3),i=e.getSize(new c.Vector3),a=Math.max(i.x,i.y,i.z)||1,s=d().position.clone().sub(r.target);s.lengthSq()<1e-12&&s.copy(o.iso),g(n,a,s.normalize(),t)},setRotateEnabled:e=>{r.enableRotate=e},isRotateEnabled:()=>r.enableRotate,updateAspect:(e,t)=>{u=t===0?u:e/t,l===`orthographic`&&m()},dispose:p}}function oe(e,t){let{up:n,forward:r}=I(t),i=e.clone().normalize();if(Math.abs(i.dot(n))<.9999)return e;let a=r.clone().negate(),o=.5*Math.PI/180;return i.multiplyScalar(Math.cos(o)).add(a.multiplyScalar(Math.sin(o))).normalize()}const G=e=>1-(1-e)**3;function se(e,t,n,r,i,a=250){let o=e.position.clone(),s=t.target.clone(),c=performance.now(),l=null,u=()=>{l=null;let d=G(Math.min((performance.now()-c)/a,1));e.position.lerpVectors(o,n,d),t.target.lerpVectors(s,r,d),i(),t.update(),d<1&&(l=requestAnimationFrame(u))};return l=requestAnimationFrame(u),{cancel:()=>{l!==null&&(cancelAnimationFrame(l),l=null)}}}function ce(e){let t=Math.floor(e.length/6);if(t===0)return 1/0;let n=Math.max(1,Math.ceil(t/4096)),r=[];for(let i=0;i<t;i+=n){let t=i*6,n=Math.hypot(e[t+3]-e[t],e[t+4]-e[t+1],e[t+5]-e[t+2]);n>0&&r.push(n)}return r.length===0?1/0:(r.sort((e,t)=>e-t),r[Math.min(r.length-1,Math.floor(r.length*.15))])}function le(e){let t=new p;return t.setPositions(e),{geometry:t,segmentCount:e.length/6,edgeSpacing:ce(e)}}function K(e,t,n){let r=1e4,i=67108864,a=Math.cos(Math.PI/180*n),o=e.length/3;if(o>=i)throw Error(`extractEdgeSegments: ${o} vertices exceeds 2^26 limit`);let s=new Float64Array(o),c=new Float64Array(o),l=new Float64Array(o);for(let t=0;t<o;t++)s[t]=Math.round(e[3*t]*r),c[t]=Math.round(e[3*t+1]*r),l[t]=Math.round(e[3*t+2]*r);let u=16;for(;u<o*2;)u<<=1;let d=u-1,f=new Int32Array(u).fill(-1),p=new Int32Array(o);for(let e=0;e<o;e++){let t=(Math.imul(s[e]|0,73856093)^Math.imul(c[e]|0,19349663)^Math.imul(l[e]|0,83492791))&d;for(;;){let n=f[t];if(n===-1){f[t]=e,p[e]=e;break}if(s[n]===s[e]&&c[n]===c[e]&&l[n]===l[e]){p[e]=n;break}t=t+1&d}}let m=new Float32Array(4096),h=0,g=(t,n)=>{if(h+6>m.length){let e=new Float32Array(m.length*2);e.set(m),m=e}m[h++]=e[3*t],m[h++]=e[3*t+1],m[h++]=e[3*t+2],m[h++]=e[3*n],m[h++]=e[3*n+1],m[h++]=e[3*n+2]},_=new Map,v=[],y=[],b=[],x=(t?t.length:o)/3;for(let n=0;n<x;n++){let r=t?t[3*n]:3*n,o=t?t[3*n+1]:3*n+1,s=t?t[3*n+2]:3*n+2,c=p[r],l=p[o],u=p[s];if(c===l||l===u||u===c)continue;let d=e[3*s]-e[3*o],f=e[3*s+1]-e[3*o+1],m=e[3*s+2]-e[3*o+2],h=e[3*r]-e[3*o],x=e[3*r+1]-e[3*o+1],S=e[3*r+2]-e[3*o+2],C=f*S-m*x,w=m*h-d*S,T=d*x-f*h,E=C*C+w*w+T*T;if(E>0){let e=1/Math.sqrt(E);C*=e,w*=e,T*=e}else C=0,w=0,T=0;for(let e=0;e<3;e++){let t,n,d,f;e===0?(t=r,n=o,d=c,f=l):e===1?(t=o,n=s,d=l,f=u):(t=s,n=r,d=u,f=c);let p=f*i+d,m=_.get(p);if(m!==void 0&&m!==-1)C*b[3*m]+w*b[3*m+1]+T*b[3*m+2]<=a&&g(t,n),_.set(p,-1);else{let e=d*i+f;if(!_.has(e)){let r=v.length;_.set(e,r),v.push(t),y.push(n),b.push(C,w,T)}}}}for(let e of _.values())e!==-1&&g(v[e],y[e]);return m.slice(0,h)}function ue(){return[`const extract = ${K.toString()};`,`self.onmessage = (event) => {`,` const { id, positions, index, thresholdAngle } = event.data;`,` try {`,` const segments = extract(positions, index, thresholdAngle);`,` self.postMessage({ id, segments }, [segments.buffer]);`,` } catch (error) {`,` self.postMessage({ id, error: String((error && error.message) || error) });`,` }`,`};`].join(`
2
+ `)}const de=`edge-overlay`;function fe(e){return{forcedColor:e.color==null?null:new c.Color(e.color),darken:c.MathUtils.clamp(e.darken??.75,0,1),width:e.width??1.5,thresholdAngle:e.thresholdAngle??44,distanceFade:e.distanceFade??!0,maxTriangles:e.maxTriangles??4e6,maxSegments:e.maxSegments??2e6}}function q(e){let t=e.getAttribute(`position`);return t?(e.index?e.index.count:t.count)/3:0}function pe(e){let t=e.getAttribute(`position`);if(!t||t.isInterleavedBufferAttribute||t.itemSize!==3||!(t.array instanceof Float32Array)||t.count>=67108864)return null;let n=e.index;return n&&!(n.array instanceof Uint32Array)&&!(n.array instanceof Uint16Array)?null:{positions:t.array,index:n?n.array:null}}function me(e,t){let n=4096,r=2166136261,i=e=>{r^=e,r=Math.imul(r,16777619)},a=new Uint32Array(e.positions.buffer,e.positions.byteOffset,e.positions.length),o=Math.min(n,a.length);for(let e=0;e<o;e++)i(a[e]);for(let e=Math.max(o,a.length-n);e<a.length;e++)i(a[e]);let s=0;if(e.index){s=e.index.length;let t=Math.min(n,s);for(let n=0;n<t;n++)i(e.index[n]);for(let r=Math.max(t,s-n);r<s;r++)i(e.index[r])}return`${t}:${e.positions.length}:${s}:${r>>>0}`}function he(e,t){let n=new c.EdgesGeometry(e,t),r=n.attributes.position?n.attributes.position.array:new Float32Array;return n.dispose(),r}function ge(e,t){let n=pe(e);return n?K(n.positions,n.index,t):he(e,t)}let J;const Y=new Map;let _e=1;function ve(){if(J!==void 0)return J;if(typeof Worker>`u`||typeof Blob>`u`||typeof URL>`u`||typeof URL.createObjectURL!=`function`)return J=null,null;try{let e=URL.createObjectURL(new Blob([ue()],{type:`text/javascript`})),t=new Worker(e);t.onmessage=e=>{let{id:t,segments:n,error:r}=e.data,i=Y.get(t);i&&(Y.delete(t),n?i.resolve(n):i.reject(Error(r??`edge extraction failed in worker`)))},t.onerror=()=>{for(let e of Y.values())e.reject(Error(`edge extraction worker crashed`));Y.clear(),t.terminate(),J=null},J=t}catch{J=null}return J}function ye(e,t,n){return new Promise((r,i)=>{let a=_e++;Y.set(a,{resolve:r,reject:i});let o=t.positions.slice(),s=t.index?t.index.slice():null,c=[o.buffer];s&&c.push(s.buffer),e.postMessage({id:a,positions:o,index:s,thresholdAngle:n},c)})}const X=new Map;function be(e,t){let n=pe(e);if(!n||q(e)<25e3)return Promise.resolve(ge(e,t));let r=me(n,t),i=X.get(r);if(i)return i;let a=ve();if(!a)return Promise.resolve(ge(e,t));let o=ye(a,n,t).catch(()=>K(n.positions,n.index,t)).finally(()=>{X.delete(r)});return X.set(r,o),o}function xe(e,t){let n=(Array.isArray(e.material)?e.material[0]:e.material)?.color;return n?n.clone().multiplyScalar(1-t):new c.Color(2236962)}var Se=class{options;byKey=new Map;constructor(e){this.options=e}for(e,t){let n=this.options.forcedColor??xe(e,this.options.darken),r=n.getHex()*2+ +!!t,i=this.byKey.get(r);return i||(i=Ce(n,this.options.width,t),this.byKey.set(r,i)),i}disposeUnused(e){let t=new Set(e.map(e=>e.material));for(let e of this.byKey.values())t.has(e)||e.dispose()}};function Ce(e,t,n){let r=new d({color:e});return r.linewidth=t,r.polygonOffset=!0,r.polygonOffsetFactor=0,r.polygonOffsetUnits=-1,n&&(r.transparent=!0),r}function we(e,t,n){let r=new f(e.geometry,t);return r.userData.kind=de,r.raycast=()=>{},n&&Oe(r,e.edgeSpacing),r}const Te=new c.Vector3,Ee=new c.Vector3;function De(e,t,n){e.geometry.boundingSphere||e.geometry.computeBoundingSphere();let r=e.geometry.boundingSphere;if(!r)return 1/0;if(t.isPerspectiveCamera){let i=t;Te.copy(r.center).applyMatrix4(e.matrixWorld);let a=Ee.setFromMatrixPosition(t.matrixWorld).distanceTo(Te);if(a<=r.radius*e.matrixWorld.getMaxScaleOnAxis())return 1/0;let o=Math.tan(c.MathUtils.degToRad(i.fov)*.5),s=2*a*o;return s>0?n/s:1/0}if(t.isOrthographicCamera){let e=t,r=(e.top-e.bottom)/e.zoom;return r>0?n/r:1/0}return 1/0}function Oe(e,t){e.onBeforeRender=(n,r,i)=>{f.prototype.onBeforeRender.call(e,n);let a=e.material,o=t*De(e,i,a.resolution.y);a.opacity=c.MathUtils.clamp((o-1)/3,0,1)}}function ke(e){return e.userData?.kind===de}function Ae(e,t){let n=[];return e.traverse(e=>{if(e instanceof c.Mesh&&e.userData.id!==`floor`&&e.userData.id!==`grid`&&e.userData.kind!==`edge-overlay`&&!e.children.some(e=>e.userData?.kind===`edge-overlay`)&&e.geometry){if(q(e.geometry)>t){e.userData.edgesSkipped=`triangle-cap`,console.debug(`[edges] skipping mesh over triangle cap (${q(e.geometry)} > ${t})`);return}delete e.userData.edgesSkipped,n.push(e)}}),n}function je(e,t,n,r){let i=r.distanceFade&&t.segmentCount<=r.maxSegments,a=we(t,n.for(e,i),i);return e.add(a),a}const Me=new WeakMap;function Z(e){return Me.get(e)??0}function Ne(e,t){for(let n=e;n;n=n.parent)if(n===t)return!0;return!1}async function Pe(e,t={}){let n=fe(t),r=new Se(n),i=Z(e),a=[],o=Ae(e,n.maxTriangles).map(async t=>{let o=await be(t.geometry,n.thresholdAngle);Z(e)===i&&Ne(t,e)&&(t.children.some(e=>e.userData?.kind===`edge-overlay`)||a.push(je(t,le(o),r,n)))});return await Promise.all(o),r.disposeUnused(a),a}function Fe(e){Me.set(e,Z(e)+1);let t=[];e.traverse(e=>{e instanceof f&&ke(e)&&t.push(e)});let n=new Set;for(let e of t)e.geometry.dispose(),n.add(e.material),e.removeFromParent();return n.forEach(e=>e.dispose()),t.length}function Ie(e){if(!(e>0)||!Number.isFinite(e))return 1;let t=10**Math.floor(Math.log10(e)),n=e/t;return(n>=5?5:n>=2?2:1)*t}function Le(e={}){let{cellSize:t=1,majorEvery:n=10,cellColor:r=8947848,majorColor:i=4473924,fadeDistance:a=100,plane:o=`y`}=e,s=o===`y`?new c.Vector2(0,2):o===`z`?new c.Vector2(0,1):new c.Vector2(1,2),l=2.5,u=new c.PlaneGeometry(1,1);o===`y`?u.rotateX(-Math.PI/2):o===`x`&&u.rotateY(Math.PI/2);let d=new c.ShaderMaterial({vertexShader:`
3
3
  varying vec3 vWorldPos;
4
4
  void main() {
5
5
  vec4 world = modelMatrix * vec4(position, 1.0);
@@ -50,7 +50,7 @@ import{a as e,c as t,d as n,l as r,r as i,s as a,t as o,u as s}from"./gpu-dispos
50
50
  if (alpha < 0.001) discard;
51
51
  gl_FragColor = vec4(color, alpha);
52
52
  }
53
- `,transparent:!0,depthWrite:!1,side:c.DoubleSide,uniforms:{uAxes:{value:s},uCell:{value:t},uMajor:{value:n},uCellColor:{value:new c.Color(r)},uMajorColor:{value:new c.Color(i)},uCenter:{value:new c.Vector3},uFade:{value:a}}}),f=new c.Mesh(u,d);f.name=`grid`,f.userData.id=`grid`,f.renderOrder=-1;let p=a,m=a*l,h=new c.Vector3;return{object:f,update:e=>{o===`y`?(f.position.set(e.x,0,e.z),h.set(e.x,0,e.z)):o===`z`?(f.position.set(e.x,e.y,0),h.set(e.x,e.y,0)):(f.position.set(0,e.y,e.z),h.set(0,e.y,e.z)),d.uniforms.uCenter.value.copy(h),f.scale.setScalar(m)},fitToContent:e=>{if(e.isEmpty())return;let t=e.getSize(new c.Vector3),n=(e,t)=>t===0?e.x:t===1?e.y:e.z,r=Math.max(n(t,s.x),n(t,s.y));!(r>0)||!Number.isFinite(r)||(d.uniforms.uCell.value=ke(r/20),p=r*2,d.uniforms.uFade.value=p,m=p*l)},setVisible:e=>{f.visible=e},dispose:()=>{f.removeFromParent(),u.dispose(),d.dispose()}}}function je(e,t){let n=new h,r=n.domElement;r.style.position=`absolute`,r.style.top=`0`,r.style.left=`0`,r.style.overflow=`hidden`,r.style.pointerEvents=`none`,r.style.zIndex=`30`,getComputedStyle(e).position===`static`&&(e.style.position=`relative`),e.appendChild(r);let i={width:e.clientWidth||1,height:e.clientHeight||1};n.setSize(i.width,i.height);let a=new c.Group;a.name=`label-layer`,a.userData.id=`label-layer`,t.add(a);let o=new Set;return{addLabel:(e,t,n)=>{let r=document.createElement(`div`);r.textContent=e,n?r.className=n:Object.assign(r.style,{padding:`2px 6px`,borderRadius:`4px`,background:`rgba(20, 20, 20, 0.78)`,color:`#fff`,font:`12px/1.3 system-ui, sans-serif`,whiteSpace:`pre`,textAlign:`center`,userSelect:`none`}),r.style.pointerEvents=`none`;let i=new m(r);return i.position.copy(t),a.add(i),o.add(i),{object:i,setPosition:e=>i.position.copy(e),setText:e=>{r.textContent=e},remove:()=>{i.removeFromParent(),r.remove(),o.delete(i)}}},render:(e,t)=>n.render(e,t),setSize:(e,t)=>n.setSize(e,t),dispose:()=>{o.forEach(e=>{e.removeFromParent(),e.element.remove()}),o.clear(),a.removeFromParent(),r.remove()}}}const Me=.015,Ne={Millimeters:{metersPerUnit:1/1e3,suffix:`mm`},Centimeters:{metersPerUnit:1/100,suffix:`cm`},Meters:{metersPerUnit:1,suffix:`m`},Inches:{metersPerUnit:1/39.37,suffix:`in`},Feet:{metersPerUnit:1/3.28084,suffix:`ft`}};function Pe(e){let t=e&&Ne[e]||Ne.Meters;return e=>`${(e/t.metersPerUnit).toPrecision(3)} ${t.suffix}`}function Fe(e,t){if(e.isOrthographicCamera){let t=e;return Math.abs(t.top-t.bottom)/(t.zoom||1)*Me}return((t?e.position.distanceTo(t):e.position.length())||1)*Me}function Ie(e){let t=e.object;if(t instanceof c.Mesh)return e.face?[e.face.a,e.face.b,e.face.c]:null;if(t instanceof c.Points)return e.index==null?null:[e.index];if(t instanceof c.Line){if(e.index==null)return null;let n=t.geometry.index;return n?e.index+1>=n.count?null:[n.getX(e.index),n.getX(e.index+1)]:[e.index,e.index+1]}return null}function Le(e,t,n,r){let i=e.point.clone(),a=e.object,o=Ie(e);if(!o||!a.geometry)return i;let s=a.geometry.attributes.position;if(!s)return i;let l=e=>{let r=e.clone().project(t);return new c.Vector2((r.x+1)/2*n.width,(1-r.y)/2*n.height)},u=l(i),d=i,f=r;for(let e of o){if(e>=s.count)continue;let t=new c.Vector3().fromBufferAttribute(s,e).applyMatrix4(a.matrixWorld),n=l(t).distanceTo(u);n<f&&(f=n,d=t)}return d}function Re(e){let{canvas:t,scene:n,getActiveCamera:r,getViewTarget:i,labelLayer:a,options:o={}}=e,s=o.snapPixels??12,f=new c.Color(o.color??16763904),p=Pe(o.displayUnit),m=o.format??((e,t)=>`${p(e)}\nΔx ${p(t.x)} Δy ${p(t.y)} Δz ${p(t.z)}`),h=new c.Raycaster,g=new c.Vector2,_=!1,v=[],y=[],b=null,x=null,S=new c.PointsMaterial({color:f,size:8,sizeAttenuation:!1,depthTest:!1}),C=new c.PointsMaterial({color:f,size:11,sizeAttenuation:!1,depthTest:!1,transparent:!0,opacity:.5}),w=null,T=e=>{if(!e){w&&(w.visible=!1);return}if(!w){let e=new c.BufferGeometry;e.setAttribute(`position`,new c.Float32BufferAttribute([0,0,0],3)),w=new c.Points(e,C),w.renderOrder=1e3,w.userData.id=`measure`,w.raycast=()=>{},n.add(w)}w.position.copy(e),w.visible=!0},E=e=>{let t=new c.BufferGeometry;t.setAttribute(`position`,new c.Float32BufferAttribute([e.x,e.y,e.z],3));let r=new c.Points(t,S);return r.renderOrder=999,r.userData.id=`measure`,r.raycast=()=>{},n.add(r),r},D=()=>{v.length=0,y.forEach(e=>{e.geometry.dispose(),e.removeFromParent()}),y.length=0,b&&=(b.geometry.dispose(),b.material.dispose(),b.removeFromParent(),null),x?.remove(),x=null},O=()=>{if(v.length!==2)return;let[e,t]=v,r=new u;r.setPositions([e.x,e.y,e.z,t.x,t.y,t.z]);let i=new d({color:f});i.linewidth=2,i.depthTest=!1,b=new l(r,i),b.renderOrder=998,b.userData.id=`measure`,b.raycast=()=>{},n.add(b);let s=e.clone().add(t).multiplyScalar(.5),p=new c.Vector3(Math.abs(t.x-e.x),Math.abs(t.y-e.y),Math.abs(t.z-e.z));x=a.addLabel(m(e.distanceTo(t),p),s,o.labelClassName)},k=e=>{let a=t.getBoundingClientRect();g.x=(e.clientX-a.left)/a.width*2-1,g.y=-((e.clientY-a.top)/a.height)*2+1;let o=r();h.setFromCamera(g,o);let c=Fe(o,i?.());h.params.Line.threshold=c,h.params.Points.threshold=c;let l=h.intersectObjects(n.children,!0).filter(e=>e.object.userData.id!==`measure`&&e.object.userData.id!==`grid`);return l.length===0?null:Le(l[0],o,{width:a.width,height:a.height},s)},A=null,j=0,M=()=>{j&&=(cancelAnimationFrame(j),0),A=null};return{setEnabled:e=>{_=e,e||(M(),D(),T(null))},isEnabled:()=>_,handleClick:e=>{if(!_)return!1;v.length===2&&D();let t=k(e);return t===null||(v.push(t),y.push(E(t)),v.length===2&&O(),!0)},handleMove:e=>{_&&(A=e,!j&&(j=requestAnimationFrame(()=>{j=0;let e=A;A=null,!(!_||!e)&&T(k(e))})))},clear:D,dispose:()=>{M(),D(),w&&=(w.geometry.dispose(),w.removeFromParent(),null),S.dispose(),C.dispose()}}}const ze=[];function Be({camera:e,scene:t,groundNormals:n=()=>ze}){let r=e.near,i=e.near,a=new c.Vector3,o=new c.Vector3;return{update:()=>{e.near!==i&&(r=e.near);let s=L(t),l=r;if(!s.isEmpty()){let t=s.getSize(o).length()*.5,i=e.position.distanceTo(s.getCenter(a))-t;for(let t of n())i=Math.min(i,Math.abs(e.position.dot(t)));l=c.MathUtils.clamp(i*.5,r,e.far*.01)}Math.abs(l-i)>i*.05&&(e.near=l,e.updateProjectionMatrix(),i=l)}}}function Ve(e){let{camera:t,domElement:n,controller:r}=e,i=new g(t,n);i.setLabels(`X`,`Y`,`Z`);let a=!0,o=new c.Raycaster,s=new c.OrthographicCamera(-2,2,2,-2,0,4);s.position.set(0,0,2),s.updateMatrixWorld();let l={posX:new c.Vector3(1,0,0),negX:new c.Vector3(-1,0,0),posY:new c.Vector3(0,1,0),negY:new c.Vector3(0,-1,0),posZ:new c.Vector3(0,0,1),negZ:new c.Vector3(0,0,-1)},u=e=>{let r=n.getBoundingClientRect(),a=r.left+n.offsetWidth-128-i.location.right,u=r.top+n.offsetHeight-128-i.location.bottom,d=new c.Vector2((e.clientX-a)/128*2-1,-((e.clientY-u)/128)*2+1);if(Math.abs(d.x)>1||Math.abs(d.y)>1)return null;i.quaternion.copy(t.quaternion).invert(),i.updateMatrixWorld(),o.setFromCamera(d,s);let f=o.intersectObjects(i.children,!1);for(let e of f){let t=e.object.userData?.type;if(typeof t==`string`&&t in l)return t}return null};return{render:e=>{if(!a)return;let t=e.autoClear;e.autoClear=!1,i.render(e),e.autoClear=t},handleClick:e=>{if(!a)return!1;let t=u(e);return t?(r.getProjection()===`orthographic`&&r.setProjection(`perspective`),r.setViewDirection(l[t],!1),!0):!1},setVisible:e=>{a=e},isVisible:()=>a,dispose:()=>i.dispose()}}function He(e,t,n,r,i,a,o,s,l,u,d,f,p,m,h=!0){let g=null,_=performance.now(),v=!0,y=0,b=new c.Matrix4,x=new c.Matrix4,S=null,C=()=>{v=!0},w=e=>{e.updateMatrixWorld();let t=S!==e||!b.equals(e.matrixWorld)||!x.equals(e.projectionMatrix);return t&&(S=e,b.copy(e.matrixWorld),x.copy(e.projectionMatrix)),t},T=e.domElement,E=[`pointerdown`,`pointerup`,`wheel`];if(h)for(let e of E)T.addEventListener(e,C,{passive:!0});let D=()=>{let{width:t,height:r}=o();if(t===0||r===0)return;let a=Math.floor(t*s),c=Math.floor(r*s);(e.domElement.width!==a||e.domElement.height!==c)&&(e.setPixelRatio(s),e.setSize(t,r,!1),n.aspect=t/r,n.updateProjectionMatrix(),i.updateAspect(t,r),f?.()?.setSize(t,r,s),p?.setSize(t,r),C())},O=function(){g=requestAnimationFrame(O);let n=performance.now(),i=(n-_)/1e3;_=n,D(),(a.enableDamping||a.autoRotate)&&a.update(),u&&u.update(r().position),m&&m.update(),l?.(i);let o=r();if(h){if(!(v||w(o)||n-y>=500))return;v=!1,y=n}let s=f?.();s?(s.setCamera(o),s.render(i)):e.render(t,o),p&&p.render(t,o),d&&d.render(e)};return{animate:O,dispose:()=>{if(g!==null&&(cancelAnimationFrame(g),g=null),h)for(let e of E)T.removeEventListener(e,C)},invalidate:C}}const Q=new c.Vector3(0,0,1);function Ue(e){let t=e.sceneScale||`m`,n={mm:{cameraDistance:20,near:.1,far:2e3,floorSize:100,lightDistance:10,lightHeight:20,minDistance:.1,shadowSize:100,scaleFactor:1e3},cm:{cameraDistance:20,near:.1,far:2e3,floorSize:100,lightDistance:25,lightHeight:50,minDistance:.1,shadowSize:100,scaleFactor:100},m:{cameraDistance:10,near:.01,far:2e3,floorSize:50,lightDistance:25,lightHeight:50,minDistance:.001,shadowSize:100,scaleFactor:1},inches:{cameraDistance:15,near:.1,far:2e3,floorSize:80,lightDistance:20,lightHeight:40,minDistance:.1,shadowSize:80,scaleFactor:39.37},feet:{cameraDistance:8,near:.1,far:2e3,floorSize:40,lightDistance:15,lightHeight:30,minDistance:.1,shadowSize:60,scaleFactor:3.28084}}[t],r=e.look??`technical`,i=O[r];return{sceneScale:t,look:r,camera:{position:e.camera?.position||j(e.environment?.sceneUp??Q,n.cameraDistance*Math.sqrt(3)),fov:e.camera?.fov||20,near:e.camera?.near||n.near,far:e.camera?.far||n.far,target:e.camera?.target||new c.Vector3(0,0,0),dynamicNear:e.camera?.dynamicNear??!0},lighting:{enableSunlight:e.lighting?.enableSunlight??!0,sunlightIntensity:e.lighting?.sunlightIntensity??1,sunlightPosition:e.lighting?.sunlightPosition||M(e.environment?.sceneUp??Q,n.lightDistance,n.lightHeight),ambientLightColor:e.lighting?.ambientLightColor||new c.Color(4210752),ambientLightIntensity:e.lighting?.ambientLightIntensity??i.ambientIntensity,sunlightColor:e.lighting?.sunlightColor||16777215,enableHemisphereLight:e.lighting?.enableHemisphereLight??i.hemisphereIntensity>0,hemisphereSkyColor:e.lighting?.hemisphereSkyColor??14673663,hemisphereGroundColor:e.lighting?.hemisphereGroundColor??7036754,hemisphereIntensity:e.lighting?.hemisphereIntensity??i.hemisphereIntensity},environment:{hdrPath:e.environment?.hdrPath||`/baseHDR.hdr`,backgroundColor:e.environment?.backgroundColor||new c.Color(15790320),enableEnvironmentLighting:e.environment?.enableEnvironmentLighting??!0,sceneUp:e.environment?.sceneUp||Q,showEnvironment:e.environment?.showEnvironment??!1,environmentIntensity:e.environment?.environmentIntensity??i.environmentIntensity},floor:{enabled:e.floor?.enabled??!1,size:e.floor?.size||n.floorSize,color:e.floor?.color||new c.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.toneMapping,toneMappingExposure:e.render?.toneMappingExposure??i.toneMappingExposure,preserveDrawingBuffer:e.render?.preserveDrawingBuffer??!1,ambientOcclusion:e.render?.ambientOcclusion??i.ambientOcclusion,aoIntensity:e.render?.aoIntensity??1,aoPixelRatio:e.render?.aoPixelRatio??1,onDemand:e.render?.onDemand??!0},controls:{enableDamping:e.controls?.enableDamping??!1,dampingFactor:e.controls?.dampingFactor||.05,autoRotate:e.controls?.autoRotate??!1,autoRotateSpeed:e.controls?.autoRotateSpeed||.5,enableZoom:e.controls?.enableZoom??!0,enablePan:e.controls?.enablePan??!0,minDistance:e.controls?.minDistance||n.minDistance,maxDistance:e.controls?.maxDistance||1/0},grid:{enabled:e.grid?.enabled??!1,cellSize:e.grid?.cellSize??1,majorEvery:e.grid?.majorEvery??10,cellColor:e.grid?.cellColor??8947848,majorColor:e.grid?.majorColor??4473924,fadeDistance:e.grid?.fadeDistance??100,plane:e.grid?.plane??te(e.environment?.sceneUp??Q)},gizmo:{enabled:e.gizmo?.enabled??!1},edges:{enabled:e.edges?.enabled??!1,color:e.edges?.color,darken:e.edges?.darken,width:e.edges?.width??1.5,thresholdAngle:e.edges?.thresholdAngle??44,distanceFade:e.edges?.distanceFade??!0,maxTriangles:e.edges?.maxTriangles,maxSegments:e.edges?.maxSegments,screenSpaceFallback:e.edges?.screenSpaceFallback},measure:{enabled:e.measure?.enabled??!1,snapPixels:e.measure?.snapPixels,color:e.measure?.color,labelClassName:e.measure?.labelClassName,displayUnit:e.measure?.displayUnit,format:e.measure?.format},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},onMaxAnisotropy:e.onMaxAnisotropy}}function We(e){let{scene:t,renderer:n,lights:r,config:i,pipeline:a,requestRender:o}=e,s=i.look,l=e=>{e.ambientIntensity!==void 0&&(r.ambient.intensity=e.ambientIntensity),e.hemisphereIntensity!==void 0&&!r.hemisphere&&e.hemisphereIntensity>0&&(r.hemisphere=new c.HemisphereLight(e.hemisphereSkyColor??i.lighting.hemisphereSkyColor,e.hemisphereGroundColor??i.lighting.hemisphereGroundColor,e.hemisphereIntensity),r.hemisphere.position.copy(i.environment.sceneUp??Q),t.add(r.hemisphere)),r.hemisphere&&(e.hemisphereIntensity!==void 0&&(r.hemisphere.intensity=e.hemisphereIntensity),e.hemisphereSkyColor!==void 0&&r.hemisphere.color.set(e.hemisphereSkyColor),e.hemisphereGroundColor!==void 0&&r.hemisphere.groundColor.set(e.hemisphereGroundColor)),o()},u=e=>{i.environment.environmentIntensity=e,t.environmentIntensity=e,o()};return{setFillLights:l,setEnvironmentIntensity:u,setToneMappingExposure:e=>{i.render.toneMappingExposure=e,n.toneMappingExposure=e,a.get()&&a.rebuild()},setAoIntensity:e=>{i.render.aoIntensity=e,a.get()&&a.rebuild()},setLook:e=>{let r=O[e];s=e,n.toneMapping=r.toneMapping,n.toneMappingExposure=r.toneMappingExposure,i.render.toneMapping=r.toneMapping,i.render.toneMappingExposure=r.toneMappingExposure,l({hemisphereIntensity:r.hemisphereIntensity,ambientIntensity:r.ambientIntensity}),u(r.environmentIntensity);let c=a.get()!==null;a.setAmbientOcclusion(r.ambientOcclusion),c&&a.rebuild(),t.traverse(e=>{if(e.userData.source!==`compute`)return;let t=e,n=Array.isArray(t.material)?t.material:t.material?[t.material]:[];for(let e of n)`envMapIntensity`in e&&(e.envMapIntensity=r.envMapIntensity)}),o()},getMaterialAppearance:()=>k(s)}}function Ge(e,t){let n=t.parentElement,r=n?n.clientWidth:window.innerWidth,i=n?n.clientHeight:window.innerHeight,a=new c.PerspectiveCamera(e.camera.fov,r/i,e.camera.near,e.camera.far),o=e.camera.position;return o&&a.position.set(o.x,o.y,o.z),a}function Ke(e){let t=new c.Scene;return t.background=(typeof e.environment.backgroundColor==`string`?new c.Color(e.environment.backgroundColor):e.environment.backgroundColor)||null,t}function qe(e,t){o(e,t),e.environment?.dispose(),e.background instanceof c.Texture&&e.background.dispose()}const $={uniforms:{tDiffuse:{value:null},tNormal:{value:null},tDepth:{value:null},uResolution:{value:new c.Vector2(1,1)},uColor:{value:new c.Color(2236962)},uOpacity:{value:1},uNormalThreshold:{value:.4},uDepthThreshold:{value:.02},uThickness:{value:1},uNear:{value:.1},uFar:{value:1e3},uPerspective:{value:1}},vertexShader:`
53
+ `,transparent:!0,depthWrite:!1,side:c.DoubleSide,uniforms:{uAxes:{value:s},uCell:{value:t},uMajor:{value:n},uCellColor:{value:new c.Color(r)},uMajorColor:{value:new c.Color(i)},uCenter:{value:new c.Vector3},uFade:{value:a}}}),f=new c.Mesh(u,d);f.name=`grid`,f.userData.id=`grid`,f.renderOrder=-1;let p=a,m=a*l,h=new c.Vector3;return{object:f,update:e=>{o===`y`?(f.position.set(e.x,0,e.z),h.set(e.x,0,e.z)):o===`z`?(f.position.set(e.x,e.y,0),h.set(e.x,e.y,0)):(f.position.set(0,e.y,e.z),h.set(0,e.y,e.z)),d.uniforms.uCenter.value.copy(h),f.scale.setScalar(m)},fitToContent:e=>{if(e.isEmpty())return;let t=e.getSize(new c.Vector3),n=(e,t)=>t===0?e.x:t===1?e.y:e.z,r=Math.max(n(t,s.x),n(t,s.y));!(r>0)||!Number.isFinite(r)||(d.uniforms.uCell.value=Ie(r/20),p=r*2,d.uniforms.uFade.value=p,m=p*l)},setVisible:e=>{f.visible=e},dispose:()=>{f.removeFromParent(),u.dispose(),d.dispose()}}}function Re(e,t){let n=new h,r=n.domElement;r.style.position=`absolute`,r.style.top=`0`,r.style.left=`0`,r.style.overflow=`hidden`,r.style.pointerEvents=`none`,r.style.zIndex=`30`,getComputedStyle(e).position===`static`&&(e.style.position=`relative`),e.appendChild(r);let i={width:e.clientWidth||1,height:e.clientHeight||1};n.setSize(i.width,i.height);let a=new c.Group;a.name=`label-layer`,a.userData.id=`label-layer`,t.add(a);let o=new Set;return{addLabel:(e,t,n)=>{let r=document.createElement(`div`);r.textContent=e,n?r.className=n:Object.assign(r.style,{padding:`2px 6px`,borderRadius:`4px`,background:`rgba(20, 20, 20, 0.78)`,color:`#fff`,font:`12px/1.3 system-ui, sans-serif`,whiteSpace:`pre`,textAlign:`center`,userSelect:`none`}),r.style.pointerEvents=`none`;let i=new m(r);return i.position.copy(t),a.add(i),o.add(i),{object:i,setPosition:e=>i.position.copy(e),setText:e=>{r.textContent=e},remove:()=>{i.removeFromParent(),r.remove(),o.delete(i)}}},render:(e,t)=>n.render(e,t),setSize:(e,t)=>n.setSize(e,t),dispose:()=>{o.forEach(e=>{e.removeFromParent(),e.element.remove()}),o.clear(),a.removeFromParent(),r.remove()}}}const ze=.015,Be={Millimeters:{metersPerUnit:1/1e3,suffix:`mm`},Centimeters:{metersPerUnit:1/100,suffix:`cm`},Meters:{metersPerUnit:1,suffix:`m`},Inches:{metersPerUnit:1/39.37,suffix:`in`},Feet:{metersPerUnit:1/3.28084,suffix:`ft`}};function Ve(e){let t=e&&Be[e]||Be.Meters;return e=>`${(e/t.metersPerUnit).toPrecision(3)} ${t.suffix}`}function He(e,t){if(e.isOrthographicCamera){let t=e;return Math.abs(t.top-t.bottom)/(t.zoom||1)*ze}return((t?e.position.distanceTo(t):e.position.length())||1)*ze}function Ue(e){let t=e.object;if(t instanceof c.Mesh)return e.face?[e.face.a,e.face.b,e.face.c]:null;if(t instanceof c.Points)return e.index==null?null:[e.index];if(t instanceof c.Line){if(e.index==null)return null;let n=t.geometry.index;return n?e.index+1>=n.count?null:[n.getX(e.index),n.getX(e.index+1)]:[e.index,e.index+1]}return null}function We(e,t,n,r){let i=e.point.clone(),a=e.object,o=Ue(e);if(!o||!a.geometry)return i;let s=a.geometry.attributes.position;if(!s)return i;let l=e=>{let r=e.clone().project(t);return new c.Vector2((r.x+1)/2*n.width,(1-r.y)/2*n.height)},u=l(i),d=i,f=r;for(let e of o){if(e>=s.count)continue;let t=new c.Vector3().fromBufferAttribute(s,e).applyMatrix4(a.matrixWorld),n=l(t).distanceTo(u);n<f&&(f=n,d=t)}return d}function Ge(e){let{canvas:t,scene:n,getActiveCamera:r,getViewTarget:i,labelLayer:a,options:o={}}=e,s=o.snapPixels??12,f=new c.Color(o.color??16763904),p=Ve(o.displayUnit),m=o.format??((e,t)=>`${p(e)}\nΔx ${p(t.x)} Δy ${p(t.y)} Δz ${p(t.z)}`),h=new c.Raycaster,g=new c.Vector2,_=!1,v=[],y=[],b=null,x=null,S=new c.PointsMaterial({color:f,size:8,sizeAttenuation:!1,depthTest:!1}),C=new c.PointsMaterial({color:f,size:11,sizeAttenuation:!1,depthTest:!1,transparent:!0,opacity:.5}),w=null,T=e=>{if(!e){w&&(w.visible=!1);return}if(!w){let e=new c.BufferGeometry;e.setAttribute(`position`,new c.Float32BufferAttribute([0,0,0],3)),w=new c.Points(e,C),w.renderOrder=1e3,w.userData.id=`measure`,w.raycast=()=>{},n.add(w)}w.position.copy(e),w.visible=!0},E=e=>{let t=new c.BufferGeometry;t.setAttribute(`position`,new c.Float32BufferAttribute([e.x,e.y,e.z],3));let r=new c.Points(t,S);return r.renderOrder=999,r.userData.id=`measure`,r.raycast=()=>{},n.add(r),r},D=()=>{v.length=0,y.forEach(e=>{e.geometry.dispose(),e.removeFromParent()}),y.length=0,b&&=(b.geometry.dispose(),b.material.dispose(),b.removeFromParent(),null),x?.remove(),x=null},O=()=>{if(v.length!==2)return;let[e,t]=v,r=new u;r.setPositions([e.x,e.y,e.z,t.x,t.y,t.z]);let i=new d({color:f});i.linewidth=2,i.depthTest=!1,b=new l(r,i),b.renderOrder=998,b.userData.id=`measure`,b.raycast=()=>{},n.add(b);let s=e.clone().add(t).multiplyScalar(.5),p=new c.Vector3(Math.abs(t.x-e.x),Math.abs(t.y-e.y),Math.abs(t.z-e.z));x=a.addLabel(m(e.distanceTo(t),p),s,o.labelClassName)},k=e=>{let a=t.getBoundingClientRect();g.x=(e.clientX-a.left)/a.width*2-1,g.y=-((e.clientY-a.top)/a.height)*2+1;let o=r();h.setFromCamera(g,o);let c=He(o,i?.());h.params.Line.threshold=c,h.params.Points.threshold=c;let l=h.intersectObjects(n.children,!0).filter(e=>e.object.userData.id!==`measure`&&e.object.userData.id!==`grid`);return l.length===0?null:We(l[0],o,{width:a.width,height:a.height},s)},A=null,j=0,M=()=>{j&&=(cancelAnimationFrame(j),0),A=null};return{setEnabled:e=>{_=e,e||(M(),D(),T(null))},isEnabled:()=>_,handleClick:e=>{if(!_)return!1;v.length===2&&D();let t=k(e);return t===null||(v.push(t),y.push(E(t)),v.length===2&&O(),!0)},handleMove:e=>{_&&(A=e,!j&&(j=requestAnimationFrame(()=>{j=0;let e=A;A=null,!(!_||!e)&&T(k(e))})))},clear:D,dispose:()=>{M(),D(),w&&=(w.geometry.dispose(),w.removeFromParent(),null),S.dispose(),C.dispose()}}}const Ke=[];function qe({camera:e,scene:t,groundNormals:n=()=>Ke}){let r=e.near,i=e.near,a=new c.Vector3,o=new c.Vector3;return{update:()=>{e.near!==i&&(r=e.near);let s=H(t),l=r;if(!s.isEmpty()){let t=s.getSize(o).length()*.5,i=e.position.distanceTo(s.getCenter(a))-t;for(let t of n())i=Math.min(i,Math.abs(e.position.dot(t)));l=c.MathUtils.clamp(i*.5,r,e.far*.01)}Math.abs(l-i)>i*.05&&(e.near=l,e.updateProjectionMatrix(),i=l)}}}function Je(){let e=[],t=null,n=()=>e.sort((e,t)=>t.priority-e.priority),r=t=>e.findIndex(e=>e.id===t),i=n=>{let i=r(n);i!==-1&&(e.splice(i,1),t===n&&(t=null))};return{register:({id:t,tool:r,priority:a=0})=>(i(t),e.push({id:t,tool:r,priority:a}),n(),()=>i(t)),unregister:i,get:t=>e[r(t)]?.tool??null,setActive:n=>{t=n;for(let t of e)t.tool.setEnabled?.(t.id===n)},getActive:()=>t,handleClick:t=>{for(let n of[...e])if(n.tool.handleClick(t))return!0;return!1},handleMove:t=>{for(let n of[...e])n.tool.handleMove?.(t)}}}function Ye(e,t){let n=t.getBoundingClientRect();return{x:(e.clientX-n.left)/n.width*2-1,y:-((e.clientY-n.top)/n.height)*2+1}}function Xe(e){let{camera:t,domElement:n,controller:r}=e,i=new g(t,n);i.setLabels(`X`,`Y`,`Z`);let a=!0,o=new c.Raycaster,s=new c.OrthographicCamera(-2,2,2,-2,0,4);s.position.set(0,0,2),s.updateMatrixWorld();let l={posX:new c.Vector3(1,0,0),negX:new c.Vector3(-1,0,0),posY:new c.Vector3(0,1,0),negY:new c.Vector3(0,-1,0),posZ:new c.Vector3(0,0,1),negZ:new c.Vector3(0,0,-1)},u=e=>{let r=n.getBoundingClientRect(),a=r.left+n.offsetWidth-128-i.location.right,u=r.top+n.offsetHeight-128-i.location.bottom,d=new c.Vector2((e.clientX-a)/128*2-1,-((e.clientY-u)/128)*2+1);if(Math.abs(d.x)>1||Math.abs(d.y)>1)return null;i.quaternion.copy(t.quaternion).invert(),i.updateMatrixWorld(),o.setFromCamera(d,s);let f=o.intersectObjects(i.children,!1);for(let e of f){let t=e.object.userData?.type;if(typeof t==`string`&&t in l)return t}return null};return{render:e=>{if(!a)return;let t=e.autoClear;e.autoClear=!1,i.render(e),e.autoClear=t},handleClick:e=>{if(!a)return!1;let t=u(e);return t?(r.getProjection()===`orthographic`&&r.setProjection(`perspective`),r.setViewDirection(l[t],!1),!0):!1},setVisible:e=>{a=e},isVisible:()=>a,dispose:()=>i.dispose()}}function Ze(e,t,n,r,i,a,o,s,l,u,d,f,p,m,h=!0){let g=null,_=performance.now(),v=!0,y=0,b=new c.Matrix4,x=new c.Matrix4,S=null,C=()=>{v=!0},w=e=>{e.updateMatrixWorld();let t=S!==e||!b.equals(e.matrixWorld)||!x.equals(e.projectionMatrix);return t&&(S=e,b.copy(e.matrixWorld),x.copy(e.projectionMatrix)),t},T=e.domElement,E=[`pointerdown`,`pointerup`,`wheel`];if(h)for(let e of E)T.addEventListener(e,C,{passive:!0});let D=()=>{let{width:t,height:r}=o();if(t===0||r===0)return;let a=Math.floor(t*s),c=Math.floor(r*s);(e.domElement.width!==a||e.domElement.height!==c)&&(e.setPixelRatio(s),e.setSize(t,r,!1),n.aspect=t/r,n.updateProjectionMatrix(),i.updateAspect(t,r),f?.()?.setSize(t,r,s),p?.setSize(t,r),C())},O=function(){g=requestAnimationFrame(O);let n=performance.now(),i=(n-_)/1e3;_=n,D(),(a.enableDamping||a.autoRotate)&&a.update(),u&&u.update(r().position),m&&m.update(),l?.(i);let o=r();if(h){if(!(v||w(o)||n-y>=500))return;v=!1,y=n}let s=f?.();s?(s.setCamera(o),s.render(i)):e.render(t,o),p&&p.render(t,o),d&&d.render(e)};return{animate:O,dispose:()=>{if(g!==null&&(cancelAnimationFrame(g),g=null),h)for(let e of E)T.removeEventListener(e,C)},invalidate:C}}const Q=new c.Vector3(0,0,1);function Qe(e){let t=e.sceneScale||`m`,n={mm:{cameraDistance:20,near:.1,far:2e3,floorSize:100,lightDistance:10,lightHeight:20,minDistance:.1,shadowSize:100,scaleFactor:1e3},cm:{cameraDistance:20,near:.1,far:2e3,floorSize:100,lightDistance:25,lightHeight:50,minDistance:.1,shadowSize:100,scaleFactor:100},m:{cameraDistance:10,near:.01,far:2e3,floorSize:50,lightDistance:25,lightHeight:50,minDistance:.001,shadowSize:100,scaleFactor:1},inches:{cameraDistance:15,near:.1,far:2e3,floorSize:80,lightDistance:20,lightHeight:40,minDistance:.1,shadowSize:80,scaleFactor:39.37},feet:{cameraDistance:8,near:.1,far:2e3,floorSize:40,lightDistance:15,lightHeight:30,minDistance:.1,shadowSize:60,scaleFactor:3.28084}}[t],r=e.look??`technical`,i=O[r];return{sceneScale:t,look:r,camera:{position:e.camera?.position||L(e.environment?.sceneUp??Q,n.cameraDistance*Math.sqrt(3)),fov:e.camera?.fov||20,near:e.camera?.near||n.near,far:e.camera?.far||n.far,target:e.camera?.target||new c.Vector3(0,0,0),dynamicNear:e.camera?.dynamicNear??!0},lighting:{enableSunlight:e.lighting?.enableSunlight??!0,sunlightIntensity:e.lighting?.sunlightIntensity??1,sunlightPosition:e.lighting?.sunlightPosition||R(e.environment?.sceneUp??Q,n.lightDistance,n.lightHeight),ambientLightColor:e.lighting?.ambientLightColor||new c.Color(4210752),ambientLightIntensity:e.lighting?.ambientLightIntensity??i.ambientIntensity,sunlightColor:e.lighting?.sunlightColor||16777215,enableHemisphereLight:e.lighting?.enableHemisphereLight??i.hemisphereIntensity>0,hemisphereSkyColor:e.lighting?.hemisphereSkyColor??14673663,hemisphereGroundColor:e.lighting?.hemisphereGroundColor??7036754,hemisphereIntensity:e.lighting?.hemisphereIntensity??i.hemisphereIntensity},environment:{hdrPath:e.environment?.hdrPath||`/baseHDR.hdr`,backgroundColor:e.environment?.backgroundColor||new c.Color(15790320),enableEnvironmentLighting:e.environment?.enableEnvironmentLighting??!0,sceneUp:e.environment?.sceneUp||Q,showEnvironment:e.environment?.showEnvironment??!1,environmentIntensity:e.environment?.environmentIntensity??i.environmentIntensity},floor:{enabled:e.floor?.enabled??!1,size:e.floor?.size||n.floorSize,color:e.floor?.color||new c.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.toneMapping,toneMappingExposure:e.render?.toneMappingExposure??i.toneMappingExposure,preserveDrawingBuffer:e.render?.preserveDrawingBuffer??!1,ambientOcclusion:e.render?.ambientOcclusion??i.ambientOcclusion,aoIntensity:e.render?.aoIntensity??1,aoPixelRatio:e.render?.aoPixelRatio??1,onDemand:e.render?.onDemand??!0},controls:{enableDamping:e.controls?.enableDamping??!1,dampingFactor:e.controls?.dampingFactor||.05,autoRotate:e.controls?.autoRotate??!1,autoRotateSpeed:e.controls?.autoRotateSpeed||.5,enableZoom:e.controls?.enableZoom??!0,enablePan:e.controls?.enablePan??!0,minDistance:e.controls?.minDistance||n.minDistance,maxDistance:e.controls?.maxDistance||1/0},grid:{enabled:e.grid?.enabled??!1,cellSize:e.grid?.cellSize??1,majorEvery:e.grid?.majorEvery??10,cellColor:e.grid?.cellColor??8947848,majorColor:e.grid?.majorColor??4473924,fadeDistance:e.grid?.fadeDistance??100,plane:e.grid?.plane??ne(e.environment?.sceneUp??Q)},gizmo:{enabled:e.gizmo?.enabled??!1},edges:{enabled:e.edges?.enabled??!1,color:e.edges?.color,darken:e.edges?.darken,width:e.edges?.width??1.5,thresholdAngle:e.edges?.thresholdAngle??44,distanceFade:e.edges?.distanceFade??!0,maxTriangles:e.edges?.maxTriangles,maxSegments:e.edges?.maxSegments,screenSpaceFallback:e.edges?.screenSpaceFallback},measure:{enabled:e.measure?.enabled??!1,snapPixels:e.measure?.snapPixels,color:e.measure?.color,labelClassName:e.measure?.labelClassName,displayUnit:e.measure?.displayUnit,format:e.measure?.format},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},onMaxAnisotropy:e.onMaxAnisotropy}}function $e(e){let{scene:t,renderer:n,lights:r,config:i,pipeline:a,requestRender:o}=e,s=i.look,l=e=>{e.ambientIntensity!==void 0&&(r.ambient.intensity=e.ambientIntensity),e.hemisphereIntensity!==void 0&&!r.hemisphere&&e.hemisphereIntensity>0&&(r.hemisphere=new c.HemisphereLight(e.hemisphereSkyColor??i.lighting.hemisphereSkyColor,e.hemisphereGroundColor??i.lighting.hemisphereGroundColor,e.hemisphereIntensity),r.hemisphere.position.copy(i.environment.sceneUp??Q),t.add(r.hemisphere)),r.hemisphere&&(e.hemisphereIntensity!==void 0&&(r.hemisphere.intensity=e.hemisphereIntensity),e.hemisphereSkyColor!==void 0&&r.hemisphere.color.set(e.hemisphereSkyColor),e.hemisphereGroundColor!==void 0&&r.hemisphere.groundColor.set(e.hemisphereGroundColor)),o()},u=e=>{i.environment.environmentIntensity=e,t.environmentIntensity=e,o()};return{setFillLights:l,setEnvironmentIntensity:u,setToneMappingExposure:e=>{i.render.toneMappingExposure=e,n.toneMappingExposure=e,a.get()&&a.rebuild()},setAoIntensity:e=>{i.render.aoIntensity=e,a.get()&&a.rebuild()},setLook:e=>{let r=O[e];s=e,n.toneMapping=r.toneMapping,n.toneMappingExposure=r.toneMappingExposure,i.render.toneMapping=r.toneMapping,i.render.toneMappingExposure=r.toneMappingExposure,l({hemisphereIntensity:r.hemisphereIntensity,ambientIntensity:r.ambientIntensity}),u(r.environmentIntensity);let c=a.get()!==null;a.setAmbientOcclusion(r.ambientOcclusion),c&&a.rebuild(),t.traverse(e=>{if(e.userData.source!==`compute`)return;let t=e,n=Array.isArray(t.material)?t.material:t.material?[t.material]:[];for(let e of n)`envMapIntensity`in e&&(e.envMapIntensity=r.envMapIntensity)}),o()},getMaterialAppearance:()=>k(s)}}function et(e,t){let n=t.parentElement,r=n?n.clientWidth:window.innerWidth,i=n?n.clientHeight:window.innerHeight,a=new c.PerspectiveCamera(e.camera.fov,r/i,e.camera.near,e.camera.far),o=e.camera.position;return o&&a.position.set(o.x,o.y,o.z),a}function tt(e){let t=new c.Scene;return t.background=(typeof e.environment.backgroundColor==`string`?new c.Color(e.environment.backgroundColor):e.environment.backgroundColor)||null,t}function nt(e,t){o(e,t),e.environment?.dispose(),e.background instanceof c.Texture&&e.background.dispose()}const $={uniforms:{tDiffuse:{value:null},tNormal:{value:null},tDepth:{value:null},uResolution:{value:new c.Vector2(1,1)},uColor:{value:new c.Color(2236962)},uOpacity:{value:1},uNormalThreshold:{value:.4},uDepthThreshold:{value:.02},uThickness:{value:1},uNear:{value:.1},uFar:{value:1e3},uPerspective:{value:1}},vertexShader:`
54
54
  varying vec2 vUv;
55
55
  void main() {
56
56
  vUv = uv;
@@ -104,5 +104,5 @@ import{a as e,c as t,d as n,l as r,r as i,s as a,t as o,u as s}from"./gpu-dispos
104
104
  float edge = max(depthEdge, normalEdge) * uOpacity;
105
105
  gl_FragColor = vec4(mix(color.rgb, uColor, edge), color.a);
106
106
  }
107
- `};var Je=class extends C{camera;scene;normalMaterial;edgeMaterial;fsQuad;normalTarget=null;width;height;constructor(e,t,n,r,i={}){super(),this.scene=e,this.camera=t,this.width=Math.max(1,n),this.height=Math.max(1,r),this.normalMaterial=new c.MeshNormalMaterial,this.normalMaterial.blending=c.NoBlending,this.edgeMaterial=new c.ShaderMaterial({uniforms:c.UniformsUtils.clone($.uniforms),vertexShader:$.vertexShader,fragmentShader:$.fragmentShader});let a=this.edgeMaterial.uniforms;a.uColor.value=new c.Color(i.color??2236962),a.uOpacity.value=i.opacity??1,a.uNormalThreshold.value=i.normalThreshold??.4,a.uDepthThreshold.value=i.depthThreshold??.02,a.uThickness.value=i.thickness??1,this.fsQuad=new S(this.edgeMaterial),this.needsSwap=!0}acquireNormalTarget(){if(!this.normalTarget){let e=new c.DepthTexture(this.width,this.height);this.normalTarget=new c.WebGLRenderTarget(this.width,this.height,{minFilter:c.NearestFilter,magFilter:c.NearestFilter,depthTexture:e})}return this.normalTarget}setSize(e,t){this.width=Math.max(1,e),this.height=Math.max(1,t),this.normalTarget?.setSize(this.width,this.height)}render(e,t,n){let r=this.acquireNormalTarget(),i=e.getRenderTarget(),a=e.autoClear,o=e.getClearColor(new c.Color),s=e.getClearAlpha(),l=this.scene.overrideMaterial;e.setRenderTarget(r),e.setClearColor(7829503,1),e.autoClear=!0,this.scene.overrideMaterial=this.normalMaterial,e.render(this.scene,this.camera),this.scene.overrideMaterial=l,e.setClearColor(o,s),e.autoClear=a;let u=this.edgeMaterial.uniforms;u.tDiffuse.value=n.texture,u.tNormal.value=r.texture,u.tDepth.value=r.depthTexture,u.uResolution.value.set(this.width,this.height);let d=this.camera;u.uPerspective.value=+!!d.isPerspectiveCamera,u.uNear.value=this.camera.near??.1,u.uFar.value=this.camera.far??1e3,e.setRenderTarget(this.renderToScreen?null:t),this.fsQuad.render(e),e.setRenderTarget(i)}dispose(){this.normalTarget?.dispose(),this.normalMaterial.dispose(),this.edgeMaterial.dispose(),this.fsQuad.dispose()}};function Ye(e,t,n,r,i,a){let o=new _(e),s=new v(t,n);o.addPass(s);let c=null;(a.ambientOcclusion??!0)&&(c=new y(t,n,r,i),c.blendIntensity=a.aoIntensity??1,c.updateGtaoMaterial({screenSpaceRadius:!0}),o.addPass(c));let l=new Je(t,n,r,i,typeof a.edgeDetection==`object`?a.edgeDetection:{});l.enabled=!!a.edgeDetection,o.addPass(l);let u=new b;o.addPass(u);let d=new x;o.addPass(d),e.toneMapping=a.toneMapping,e.toneMappingExposure=a.toneMappingExposure;let f=a.aoPixelRatio??1;return o.setSize(r,i),{render:e=>o.render(e),setSize:(e,t,n)=>{o.setPixelRatio(Math.min(n,f)),o.setSize(e,t)},setCamera:e=>{if(s.camera=e,l.camera=e,!c)return;c.camera=e;let t=+!!e.isPerspectiveCamera;c.gtaoMaterial.defines.PERSPECTIVE_CAMERA!==t&&(c.gtaoMaterial.defines.PERSPECTIVE_CAMERA=t,c.gtaoMaterial.needsUpdate=!0)},setEdgeDetection:e=>{l.enabled=e},edgeDetectionEnabled:()=>l.enabled,dispose:()=>{o.dispose(),c?.dispose(),l.dispose(),u.dispose(),d.dispose()}}}function Xe(e){let{renderer:t,scene:n,getActiveCamera:r,getCanvasSize:i,pixelRatio:a,config:o,requestRender:s}=e,l=null,u=!!o.render.ambientOcclusion,d=!1,f=!1,p=e=>{let{width:s,height:l}=i(),u=Ye(t,n,r(),Math.max(1,s),Math.max(1,l),{toneMapping:o.render.toneMapping??c.NeutralToneMapping,toneMappingExposure:o.render.toneMappingExposure??1,ambientOcclusion:e,aoIntensity:o.render.aoIntensity,aoPixelRatio:o.render.aoPixelRatio,edgeDetection:!1});return u.setSize(Math.max(1,s),Math.max(1,l),a),u},m=()=>{if(!(u||d)){l?.dispose(),l=null,s();return}(!l||f!==u)&&(l?.dispose(),l=p(u),f=u),l.setEdgeDetection(d),s()};return{get:()=>l,sync:m,rebuild:()=>{l?.dispose(),l=null,m()},setAmbientOcclusion:e=>{u=e,m()},setEdgeFallback:e=>{e!==d&&(d=e,m())},isEdgeFallbackActive:()=>d,dispose:()=>{l?.dispose(),l=null}}}function Ze(e,t,n){let r=new w(e,t),i=n.camera.target;return i&&r.target.set(i.x,i.y,i.z),r.enableDamping=n.controls.enableDamping||!1,r.dampingFactor=n.controls.dampingFactor||.05,r.autoRotate=n.controls.autoRotate||!1,r.autoRotateSpeed=n.controls.autoRotateSpeed||.5,r.enableZoom=n.controls.enableZoom??!0,r.enablePan=n.controls.enablePan??!0,r.minDistance=n.controls.minDistance||.001,r.maxDistance=n.controls.maxDistance||1/0,r.screenSpacePanning=!1,r.maxPolarAngle=Math.PI,r.update(),r}function Qe(e,n,r,i){r.environment.enableEnvironmentLighting?new T().load(r.environment.hdrPath||`/baseHDR.hdr`,function(a){if(i()){a.dispose();return}if(!a?.image){t().warn(`HDR loaded without image data; skipping environment map.`),a?.dispose(),r.events.onReady?.();return}a.mapping=c.EquirectangularReflectionMapping;let o=new c.PMREMGenerator(n);o.compileEquirectangularShader();let s=o.fromEquirectangular(a).texture;o.dispose(),e.environment=s,e.environmentIntensity=r.environment.environmentIntensity??1;let l=ee(r.environment.sceneUp??Q);e.environmentRotation.copy(l),r.environment.showEnvironment?(e.background=a,e.backgroundRotation.copy(l)):a.dispose(),r.events.onReady?.()},void 0,function(e){i()||(t().warn(`HDR texture could not be loaded, falling back to basic lighting:`,e),r.events.onReady?.())}):r.events.onReady?.()}function $e(e,t){let n=t.floor.size,r=new c.PlaneGeometry(n,n),i=typeof t.floor.color==`string`?new c.Color(t.floor.color):t.floor.color,a=new c.MeshStandardMaterial({color:i,roughness:t.floor.roughness,metalness:t.floor.metalness,side:c.DoubleSide}),o=new c.Mesh(r,a);o.userData.id=`floor`,o.name=`floor`;let s=(t.environment?.sceneUp||Q).clone().normalize();o.quaternion.setFromUnitVectors(new c.Vector3(0,0,1),s),o.position.set(0,0,0),t.floor.receiveShadow&&t.render.enableShadows&&(o.receiveShadow=!0),e.add(o)}function et(e,n,r,i){let a=new Set,o=new Map,s=new c.Raycaster,l=new c.Vector2,u=new c.Vector2,d=()=>r.getActiveCamera(),f=e=>{let t=e;for(;t;){if(!t.visible)return!1;t=t.parent}return!0},p=()=>{let e=L(n);if(e.isEmpty()){t().warn(`No objects to fit to view`);return}r.frameBounds(e,!1)},m=typeof i.events.selectionColor==`string`?new c.Color(i.events.selectionColor):i.events.selectionColor instanceof c.Color?i.events.selectionColor:new c.Color(`#ff0000`),h=()=>{a.forEach(e=>{let t=e;if(o.has(e)){let r=o.get(e),i=t.material;i instanceof c.Material?i.dispose():Array.isArray(i)&&i.forEach(e=>e.dispose()),t.material=r,o.delete(e);let a=e;for(;a.parent;)a=a.parent;a!==n&&(r instanceof c.Material?r.dispose():r.forEach(e=>e.dispose()))}}),a.clear()},g=e=>{let t=e;if(!(t.material instanceof c.Material))return!1;o.set(e,t.material);let n=t.material.clone();return e instanceof c.Mesh&&`emissive`in n?n.emissive=m.clone():`color`in n&&(n.color=m.clone()),t.material=n,!0},_=()=>{let e=L(n),t=e.isEmpty()?1:e.getSize(new c.Vector3).length();s.params.Points.threshold=t*.01},v=e=>{u.set(e.clientX,e.clientY)},y=t=>{let r=new c.Vector2(t.clientX,t.clientY);if(u.distanceTo(r)>5)return;let o=e.getBoundingClientRect();l.x=(t.clientX-o.left)/o.width*2-1,l.y=-((t.clientY-o.top)/o.height)*2+1,_(),s.setFromCamera(l,d());let p=s.intersectObjects(n.children,!0).filter(e=>f(e.object));if(p.length>0){let e=p[0].object;a.has(e)||(h(),a.add(e),g(e),i.events?.onObjectSelected?.(e),e instanceof c.Mesh&&Object.keys(e.userData).length>0&&i.events?.onMeshMetadataClicked?.(e.userData))}else h(),i.events?.onBackgroundClicked?.({x:l.x,y:l.y})},b=t=>{let a=e.getBoundingClientRect();l.x=(t.clientX-a.left)/a.width*2-1,l.y=-((t.clientY-a.top)/a.height)*2+1,_(),s.setFromCamera(l,d());let o=s.intersectObjects(n.children,!0).filter(e=>f(e.object));if(o.length===0)return;let u=o[0].object;if(i.events?.onMeshDoubleClicked?.(u),!i.events?.enableDoubleClickZoom)return;let p=new c.Box3().setFromObject(u);p.isEmpty()||r.frameBounds(p,!0)},x=e=>{if(i.events?.enableKeyboardControls)switch(e.key.toLowerCase()){case`f`:e.preventDefault(),p();break;case`escape`:e.preventDefault(),h();break;case` `:e.preventDefault(),p()}};return i.events?.enableClickToFocus&&(e.addEventListener(`mousedown`,v),e.addEventListener(`click`,y),e.addEventListener(`dblclick`,b)),i.events?.enableKeyboardControls&&(e.setAttribute(`tabindex`,`0`),e.addEventListener(`keydown`,x)),{dispose:()=>{e.removeEventListener(`mousedown`,v),e.removeEventListener(`click`,y),e.removeEventListener(`dblclick`,b),e.removeEventListener(`keydown`,x),h()},fitToView:p,clearSelection:h}}function tt(e,t){let n=new c.AmbientLight(t.lighting.ambientLightColor,t.lighting.ambientLightIntensity);e.add(n);let r=null;if(t.lighting.enableHemisphereLight){r=new c.HemisphereLight(t.lighting.hemisphereSkyColor,t.lighting.hemisphereGroundColor,t.lighting.hemisphereIntensity);let n=t.environment.sceneUp??Q;r.position.copy(n),e.add(r)}if(!t.lighting.enableSunlight)return{ambient:n,hemisphere:r,sun:null};let i=new c.DirectionalLight(t.lighting.sunlightColor??16777215,t.lighting.sunlightIntensity),a=t.lighting.sunlightPosition;return a&&i.position.set(a.x,a.y,a.z),t.render.enableShadows?(i.castShadow=!0,i.shadow.mapSize.width=t.render.shadowMapSize||2048,i.shadow.mapSize.height=t.render.shadowMapSize||2048,i.shadow.bias=-1e-4,i.shadow.normalBias=.02,i.shadow.radius=4,e.add(i),e.add(i.target),{ambient:n,hemisphere:r,sun:i}):(e.add(i),{ambient:n,hemisphere:r,sun:null})}function nt(e,t){if(t.isEmpty())return;let n=t.getCenter(new c.Vector3),r=t.getSize(new c.Vector3).length()*.5*1.2,i=e.shadow.camera;i.left=-r,i.right=r,i.top=r,i.bottom=-r,e.target.position.copy(n),e.target.updateMatrixWorld();let a=e.position.distanceTo(n);i.near=Math.max(r*.01,a-r),i.far=a+r,i.updateProjectionMatrix()}function rt(e,t,n){let r=new c.WebGLRenderer({antialias:t.render.antialias,canvas:e,alpha:!0,powerPreference:`high-performance`,preserveDrawingBuffer:t.render.preserveDrawingBuffer,logarithmicDepthBuffer:!1}),i=e.parentElement,a=i?i.clientWidth:window.innerWidth,o=i?i.clientHeight:window.innerHeight;return i&&(e.style.width=`100%`,e.style.height=`100%`,e.style.display=`block`),r.setSize(a,o,!1),r.setPixelRatio(n),t.render.enableShadows&&(r.shadowMap.enabled=!0,r.shadowMap.type=c.VSMShadowMap),r.toneMapping=t.render.toneMapping,r.toneMappingExposure=t.render.toneMappingExposure??1,r.outputColorSpace=c.SRGBColorSpace,r.sortObjects=!0,r}const it=function(e,t){let n=Ue(t||{}),r=n.environment?.sceneUp||Q,a=n.render.pixelRatio??Math.min(window.devicePixelRatio,2),s=Ke(n),l=Ge(n,e);l.up.copy(r);let u=rt(e,n,a);i(u.capabilities.getMaxAnisotropy()),t?.onMaxAnisotropy?.(u.capabilities.getMaxAnisotropy());let d=Ze(l,e,n),f=ne({scene:s,perspective:l,controls:d,onActiveCameraChange:()=>{},up:r}),p=()=>f.getActiveCamera(),m=!1;Qe(s,u,n,()=>m);let h=tt(s,n),g=h.sun,_=()=>{g&&nt(g,L(s))};n.floor?.enabled&&$e(s,n);let v=n.floor?.enabled?s.children.find(e=>e.userData.id===`floor`)??null:null,y=n.grid.enabled?Ae({cellSize:n.grid.cellSize,majorEvery:n.grid.majorEvery,cellColor:n.grid.cellColor,majorColor:n.grid.majorColor,fadeDistance:n.grid.fadeDistance,plane:n.grid.plane}):null;y&&s.add(y.object);let b=()=>{y&&y.fitToContent(L(s))},x=n.gizmo.enabled?Ve({camera:l,domElement:e,controller:f}):null,S=n.grid.plane??te(r),C=new c.Vector3(+(S===`x`),+(S===`y`),+(S===`z`)),w=r.clone().normalize(),T=n.camera.dynamicNear?Be({camera:l,scene:s,groundNormals:()=>{let e=[];return y?.object.visible&&e.push(C),n.floor.enabled&&v?.visible&&e.push(w),e}}):null,E=e.parentElement??e,D=n.measure.enabled?je(E,s):null,O=n.measure.enabled&&D?Re({canvas:e,scene:s,getActiveCamera:p,labelLayer:D,options:{snapPixels:n.measure.snapPixels,color:n.measure.color,labelClassName:n.measure.labelClassName,displayUnit:n.measure.displayUnit,format:n.measure.format}}):null,k=n.events.enableEventHandlers===!1?{dispose:()=>{},fitToView:()=>{},clearSelection:()=>{}}:et(e,s,f,n),A=0,j=0,M=e=>{A=e.clientX,j=e.clientY},ee=e=>Math.hypot(e.clientX-A,e.clientY-j)>5,N=e=>{if(!ee(e)){if(O?.handleClick(e)){e.stopImmediatePropagation();return}x?.handleClick(e)&&e.stopImmediatePropagation()}};(x||O)&&(e.addEventListener(`mousedown`,M,{capture:!0}),e.addEventListener(`click`,N,{capture:!0}));let P=e=>O?.handleMove(e);O&&e.addEventListener(`mousemove`,P,{passive:!0});let F=()=>{},I=e=>{De(e,{color:n.edges.color,darken:n.edges.darken,width:n.edges.width,thresholdAngle:n.edges.thresholdAngle,distanceFade:n.edges.distanceFade,maxTriangles:n.edges.maxTriangles,maxSegments:n.edges.maxSegments}).then(()=>{R(e),F()})},R=e=>{if(n.edges.screenSpaceFallback===!1)return;let t=!1;e.traverse(e=>{e.userData?.edgesSkipped===`triangle-cap`&&(t=!0)}),H.setEdgeFallback(t)},z=e=>{Oe(e),H.setEdgeFallback(!1),F()},B=e.parentElement,V=()=>B?{width:B.clientWidth,height:B.clientHeight}:{width:window.innerWidth,height:window.innerHeight},H=Xe({renderer:u,scene:s,getActiveCamera:p,getCanvasSize:V,pixelRatio:a,config:n,requestRender:()=>F()});H.sync();let U=We({scene:s,renderer:u,lights:h,config:n,pipeline:H,requestRender:()=>F()}),{animate:W,dispose:G,invalidate:K}=He(u,s,l,p,f,d,V,a,n.events.onFrame,y,x,()=>H.get(),D,T,n.render.onDemand??!0);return F=K,W(),s.up.set(r.x,r.y,r.z),_(),b(),{scene:s,camera:l,controls:d,renderer:u,cameraController:f,grid:y,gizmo:x,measureTool:O,applyEdges:I,clearEdges:z,invalidate:K,setAmbientOcclusion:H.setAmbientOcclusion,setLook:U.setLook,setFillLights:U.setFillLights,setEnvironmentIntensity:U.setEnvironmentIntensity,setToneMappingExposure:U.setToneMappingExposure,setAoIntensity:U.setAoIntensity,getMaterialAppearance:U.getMaterialAppearance,updateShadowBounds:_,updateGridScale:b,dispose:()=>{m||(m=!0,G(),k.dispose(),(x||O)&&(e.removeEventListener(`mousedown`,M,{capture:!0}),e.removeEventListener(`click`,N,{capture:!0})),O&&e.removeEventListener(`mousemove`,P),O?.dispose(),D?.dispose(),x?.dispose(),y?.dispose(),H.dispose(),f.dispose(),d.dispose(),u.dispose(),u.forceContextLoss(),qe(s))},fitToView:k.fitToView,clearSelection:k.clearSelection,addUserGeometry:e=>{e.userData.source=`user`,s.add(e)},removeUserGeometry:e=>{e.removeFromParent(),o(e)},clearUserGeometry:()=>{s.children.filter(e=>e.userData.source===`user`).forEach(e=>{e.removeFromParent(),o(e)})}}};export{D as DEFAULT_LOOK,s as ErrorCodes,E as LOOKS,O as LOOK_PRESETS,n as VisualizationError,a as enableDebugLogging,t as getLogger,it as initThree,k as materialAppearanceForLook,r as setLogger,P as updateScene};
107
+ `};var rt=class extends C{camera;scene;normalMaterial;edgeMaterial;fsQuad;normalTarget=null;width;height;constructor(e,t,n,r,i={}){super(),this.scene=e,this.camera=t,this.width=Math.max(1,n),this.height=Math.max(1,r),this.normalMaterial=new c.MeshNormalMaterial,this.normalMaterial.blending=c.NoBlending,this.edgeMaterial=new c.ShaderMaterial({uniforms:c.UniformsUtils.clone($.uniforms),vertexShader:$.vertexShader,fragmentShader:$.fragmentShader});let a=this.edgeMaterial.uniforms;a.uColor.value=new c.Color(i.color??2236962),a.uOpacity.value=i.opacity??1,a.uNormalThreshold.value=i.normalThreshold??.4,a.uDepthThreshold.value=i.depthThreshold??.02,a.uThickness.value=i.thickness??1,this.fsQuad=new S(this.edgeMaterial),this.needsSwap=!0}acquireNormalTarget(){if(!this.normalTarget){let e=new c.DepthTexture(this.width,this.height);this.normalTarget=new c.WebGLRenderTarget(this.width,this.height,{minFilter:c.NearestFilter,magFilter:c.NearestFilter,depthTexture:e})}return this.normalTarget}setSize(e,t){this.width=Math.max(1,e),this.height=Math.max(1,t),this.normalTarget?.setSize(this.width,this.height)}render(e,t,n){let r=this.acquireNormalTarget(),i=e.getRenderTarget(),a=e.autoClear,o=e.getClearColor(new c.Color),s=e.getClearAlpha(),l=this.scene.overrideMaterial;e.setRenderTarget(r),e.setClearColor(7829503,1),e.autoClear=!0,this.scene.overrideMaterial=this.normalMaterial,e.render(this.scene,this.camera),this.scene.overrideMaterial=l,e.setClearColor(o,s),e.autoClear=a;let u=this.edgeMaterial.uniforms;u.tDiffuse.value=n.texture,u.tNormal.value=r.texture,u.tDepth.value=r.depthTexture,u.uResolution.value.set(this.width,this.height);let d=this.camera;u.uPerspective.value=+!!d.isPerspectiveCamera,u.uNear.value=this.camera.near??.1,u.uFar.value=this.camera.far??1e3,e.setRenderTarget(this.renderToScreen?null:t),this.fsQuad.render(e),e.setRenderTarget(i)}dispose(){this.normalTarget?.dispose(),this.normalMaterial.dispose(),this.edgeMaterial.dispose(),this.fsQuad.dispose()}};function it(e,t,n,r,i,a){let o=new _(e),s=new v(t,n);o.addPass(s);let c=null;(a.ambientOcclusion??!0)&&(c=new y(t,n,r,i),c.blendIntensity=a.aoIntensity??1,c.updateGtaoMaterial({screenSpaceRadius:!0}),o.addPass(c));let l=new rt(t,n,r,i,typeof a.edgeDetection==`object`?a.edgeDetection:{});l.enabled=!!a.edgeDetection,o.addPass(l);let u=new b;o.addPass(u);let d=new x;o.addPass(d),e.toneMapping=a.toneMapping,e.toneMappingExposure=a.toneMappingExposure;let f=a.aoPixelRatio??1;return o.setSize(r,i),{render:e=>o.render(e),setSize:(e,t,n)=>{o.setPixelRatio(Math.min(n,f)),o.setSize(e,t)},setCamera:e=>{if(s.camera=e,l.camera=e,!c)return;c.camera=e;let t=+!!e.isPerspectiveCamera;c.gtaoMaterial.defines.PERSPECTIVE_CAMERA!==t&&(c.gtaoMaterial.defines.PERSPECTIVE_CAMERA=t,c.gtaoMaterial.needsUpdate=!0)},setEdgeDetection:e=>{l.enabled=e},edgeDetectionEnabled:()=>l.enabled,dispose:()=>{o.dispose(),c?.dispose(),l.dispose(),u.dispose(),d.dispose()}}}function at(e){let{renderer:t,scene:n,getActiveCamera:r,getCanvasSize:i,pixelRatio:a,config:o,requestRender:s}=e,l=null,u=!!o.render.ambientOcclusion,d=!1,f=!1,p=e=>{let{width:s,height:l}=i(),u=it(t,n,r(),Math.max(1,s),Math.max(1,l),{toneMapping:o.render.toneMapping??c.NeutralToneMapping,toneMappingExposure:o.render.toneMappingExposure??1,ambientOcclusion:e,aoIntensity:o.render.aoIntensity,aoPixelRatio:o.render.aoPixelRatio,edgeDetection:!1});return u.setSize(Math.max(1,s),Math.max(1,l),a),u},m=()=>{if(!(u||d)){l?.dispose(),l=null,s();return}(!l||f!==u)&&(l?.dispose(),l=p(u),f=u),l.setEdgeDetection(d),s()};return{get:()=>l,sync:m,rebuild:()=>{l?.dispose(),l=null,m()},setAmbientOcclusion:e=>{u=e,m()},setEdgeFallback:e=>{e!==d&&(d=e,m())},isEdgeFallbackActive:()=>d,dispose:()=>{l?.dispose(),l=null}}}function ot(e,t,n){let r=new w(e,t),i=n.camera.target;return i&&r.target.set(i.x,i.y,i.z),r.enableDamping=n.controls.enableDamping||!1,r.dampingFactor=n.controls.dampingFactor||.05,r.autoRotate=n.controls.autoRotate||!1,r.autoRotateSpeed=n.controls.autoRotateSpeed||.5,r.enableZoom=n.controls.enableZoom??!0,r.enablePan=n.controls.enablePan??!0,r.minDistance=n.controls.minDistance||.001,r.maxDistance=n.controls.maxDistance||1/0,r.screenSpacePanning=!1,r.maxPolarAngle=Math.PI,r.update(),r}function st(e,n,r,i){r.environment.enableEnvironmentLighting?new T().load(r.environment.hdrPath||`/baseHDR.hdr`,function(a){if(i()){a.dispose();return}if(!a?.image){t().warn(`HDR loaded without image data; skipping environment map.`),a?.dispose(),r.events.onReady?.();return}a.mapping=c.EquirectangularReflectionMapping;let o=new c.PMREMGenerator(n);o.compileEquirectangularShader();let s=o.fromEquirectangular(a).texture;o.dispose(),e.environment=s,e.environmentIntensity=r.environment.environmentIntensity??1;let l=te(r.environment.sceneUp??Q);e.environmentRotation.copy(l),r.environment.showEnvironment?(e.background=a,e.backgroundRotation.copy(l)):a.dispose(),r.events.onReady?.()},void 0,function(e){i()||(t().warn(`HDR texture could not be loaded, falling back to basic lighting:`,e),r.events.onReady?.())}):r.events.onReady?.()}function ct(e,t){let n=t.floor.size,r=new c.PlaneGeometry(n,n),i=typeof t.floor.color==`string`?new c.Color(t.floor.color):t.floor.color,a=new c.MeshStandardMaterial({color:i,roughness:t.floor.roughness,metalness:t.floor.metalness,side:c.DoubleSide}),o=new c.Mesh(r,a);o.userData.id=`floor`,o.name=`floor`;let s=(t.environment?.sceneUp||Q).clone().normalize();o.quaternion.setFromUnitVectors(new c.Vector3(0,0,1),s),o.position.set(0,0,0),t.floor.receiveShadow&&t.render.enableShadows&&(o.receiveShadow=!0),e.add(o)}function lt(e,n,r,i){let a=new Set,o=new Map,s=new c.Raycaster,l=new c.Vector2,u=new c.Vector2,d=()=>r.getActiveCamera(),f=e=>{let t=e;for(;t;){if(!t.visible)return!1;t=t.parent}return!0},p=()=>{let e=H(n);if(e.isEmpty()){t().warn(`No objects to fit to view`);return}r.frameBounds(e,!1)},m=typeof i.events.selectionColor==`string`?new c.Color(i.events.selectionColor):i.events.selectionColor instanceof c.Color?i.events.selectionColor:new c.Color(`#ff0000`),h=()=>{a.forEach(e=>{let t=e;if(o.has(e)){let r=o.get(e),i=t.material;i instanceof c.Material?i.dispose():Array.isArray(i)&&i.forEach(e=>e.dispose()),t.material=r,o.delete(e);let a=e;for(;a.parent;)a=a.parent;a!==n&&(r instanceof c.Material?r.dispose():r.forEach(e=>e.dispose()))}}),a.clear()},g=e=>{let t=e;if(!(t.material instanceof c.Material))return!1;o.set(e,t.material);let n=t.material.clone();return e instanceof c.Mesh&&`emissive`in n?n.emissive=m.clone():`color`in n&&(n.color=m.clone()),t.material=n,!0},_=()=>{let e=H(n),t=e.isEmpty()?1:e.getSize(new c.Vector3).length();s.params.Points.threshold=t*.01},v=e=>{u.set(e.clientX,e.clientY)},y=t=>{let r=new c.Vector2(t.clientX,t.clientY);if(u.distanceTo(r)>5)return;let o=e.getBoundingClientRect();l.x=(t.clientX-o.left)/o.width*2-1,l.y=-((t.clientY-o.top)/o.height)*2+1,_(),s.setFromCamera(l,d());let p=s.intersectObjects(n.children,!0).filter(e=>f(e.object));if(p.length>0){let e=p[0].object;a.has(e)||(h(),a.add(e),g(e),i.events?.onObjectSelected?.(e),e instanceof c.Mesh&&Object.keys(e.userData).length>0&&i.events?.onMeshMetadataClicked?.(e.userData))}else h(),i.events?.onBackgroundClicked?.({x:l.x,y:l.y})},b=t=>{let a=e.getBoundingClientRect();l.x=(t.clientX-a.left)/a.width*2-1,l.y=-((t.clientY-a.top)/a.height)*2+1,_(),s.setFromCamera(l,d());let o=s.intersectObjects(n.children,!0).filter(e=>f(e.object));if(o.length===0)return;let u=o[0].object;if(i.events?.onMeshDoubleClicked?.(u),!i.events?.enableDoubleClickZoom)return;let p=new c.Box3().setFromObject(u);p.isEmpty()||r.frameBounds(p,!0)},x=e=>{if(i.events?.enableKeyboardControls)switch(e.key.toLowerCase()){case`f`:e.preventDefault(),p();break;case`escape`:e.preventDefault(),h();break;case` `:e.preventDefault(),p()}};return i.events?.enableClickToFocus&&(e.addEventListener(`mousedown`,v),e.addEventListener(`click`,y),e.addEventListener(`dblclick`,b)),i.events?.enableKeyboardControls&&(e.setAttribute(`tabindex`,`0`),e.addEventListener(`keydown`,x)),{dispose:()=>{e.removeEventListener(`mousedown`,v),e.removeEventListener(`click`,y),e.removeEventListener(`dblclick`,b),e.removeEventListener(`keydown`,x),h()},fitToView:p,clearSelection:h}}function ut(e,t){let n=new c.AmbientLight(t.lighting.ambientLightColor,t.lighting.ambientLightIntensity);e.add(n);let r=null;if(t.lighting.enableHemisphereLight){r=new c.HemisphereLight(t.lighting.hemisphereSkyColor,t.lighting.hemisphereGroundColor,t.lighting.hemisphereIntensity);let n=t.environment.sceneUp??Q;r.position.copy(n),e.add(r)}if(!t.lighting.enableSunlight)return{ambient:n,hemisphere:r,sun:null};let i=new c.DirectionalLight(t.lighting.sunlightColor??16777215,t.lighting.sunlightIntensity),a=t.lighting.sunlightPosition;return a&&i.position.set(a.x,a.y,a.z),t.render.enableShadows?(i.castShadow=!0,i.shadow.mapSize.width=t.render.shadowMapSize||2048,i.shadow.mapSize.height=t.render.shadowMapSize||2048,i.shadow.bias=-1e-4,i.shadow.normalBias=.02,i.shadow.radius=4,e.add(i),e.add(i.target),{ambient:n,hemisphere:r,sun:i}):(e.add(i),{ambient:n,hemisphere:r,sun:null})}function dt(e,t){if(t.isEmpty())return;let n=t.getCenter(new c.Vector3),r=t.getSize(new c.Vector3).length()*.5*1.2,i=e.shadow.camera;i.left=-r,i.right=r,i.top=r,i.bottom=-r,e.target.position.copy(n),e.target.updateMatrixWorld();let a=e.position.distanceTo(n);i.near=Math.max(r*.01,a-r),i.far=a+r,i.updateProjectionMatrix()}function ft(e,t,n){let r=new c.WebGLRenderer({antialias:t.render.antialias,canvas:e,alpha:!0,powerPreference:`high-performance`,preserveDrawingBuffer:t.render.preserveDrawingBuffer,logarithmicDepthBuffer:!1}),i=e.parentElement,a=i?i.clientWidth:window.innerWidth,o=i?i.clientHeight:window.innerHeight;return i&&(e.style.width=`100%`,e.style.height=`100%`,e.style.display=`block`),r.setSize(a,o,!1),r.setPixelRatio(n),t.render.enableShadows&&(r.shadowMap.enabled=!0,r.shadowMap.type=c.VSMShadowMap),r.toneMapping=t.render.toneMapping,r.toneMappingExposure=t.render.toneMappingExposure??1,r.outputColorSpace=c.SRGBColorSpace,r.sortObjects=!0,r}const pt=function(e,t){let n=Qe(t||{}),r=n.environment?.sceneUp||Q,a=n.render.pixelRatio??Math.min(window.devicePixelRatio,2),s=tt(n),l=et(n,e);l.up.copy(r);let u=ft(e,n,a);i(u.capabilities.getMaxAnisotropy()),t?.onMaxAnisotropy?.(u.capabilities.getMaxAnisotropy());let d=ot(l,e,n),f=ae({scene:s,perspective:l,controls:d,onActiveCameraChange:()=>{},up:r}),p=()=>f.getActiveCamera(),m=!1;st(s,u,n,()=>m);let h=ut(s,n),g=h.sun,_=()=>{g&&dt(g,H(s))};n.floor?.enabled&&ct(s,n);let v=n.floor?.enabled?s.children.find(e=>e.userData.id===`floor`)??null:null,y=n.grid.enabled?Le({cellSize:n.grid.cellSize,majorEvery:n.grid.majorEvery,cellColor:n.grid.cellColor,majorColor:n.grid.majorColor,fadeDistance:n.grid.fadeDistance,plane:n.grid.plane}):null;y&&s.add(y.object);let b=()=>{y&&y.fitToContent(H(s))},x=n.gizmo.enabled?Xe({camera:l,domElement:e,controller:f}):null,S=n.grid.plane??ne(r),C=new c.Vector3(+(S===`x`),+(S===`y`),+(S===`z`)),w=r.clone().normalize(),T=n.camera.dynamicNear?qe({camera:l,scene:s,groundNormals:()=>{let e=[];return y?.object.visible&&e.push(C),n.floor.enabled&&v?.visible&&e.push(w),e}}):null,E=Re(e.parentElement??e,s),D=n.measure.enabled?Ge({canvas:e,scene:s,getActiveCamera:p,labelLayer:E,options:{snapPixels:n.measure.snapPixels,color:n.measure.color,labelClassName:n.measure.labelClassName,displayUnit:n.measure.displayUnit,format:n.measure.format}}):null,O=n.events.enableEventHandlers===!1?{dispose:()=>{},fitToView:()=>{},clearSelection:()=>{}}:lt(e,s,f,n),k=Je();D&&k.register({id:`measure`,tool:D,priority:0}),x&&k.register({id:`gizmo`,tool:x,priority:-100});let A=0,M=0,P=e=>{A=e.clientX,M=e.clientY},F=e=>Math.hypot(e.clientX-A,e.clientY-M)>5,I=e=>{F(e)||k.handleClick(e)&&e.stopImmediatePropagation()};e.addEventListener(`mousedown`,P,{capture:!0}),e.addEventListener(`click`,I,{capture:!0});let L=e=>k.handleMove(e);e.addEventListener(`mousemove`,L,{passive:!0});let R=()=>{},te=e=>{Pe(e,{color:n.edges.color,darken:n.edges.darken,width:n.edges.width,thresholdAngle:n.edges.thresholdAngle,distanceFade:n.edges.distanceFade,maxTriangles:n.edges.maxTriangles,maxSegments:n.edges.maxSegments}).then(()=>{z(e),R()})},z=e=>{if(n.edges.screenSpaceFallback===!1)return;let t=!1;e.traverse(e=>{e.userData?.edgesSkipped===`triangle-cap`&&(t=!0)}),U.setEdgeFallback(t)},re=e=>{Fe(e),U.setEdgeFallback(!1),R()},B=e.parentElement,V=()=>B?{width:B.clientWidth,height:B.clientHeight}:{width:window.innerWidth,height:window.innerHeight},U=at({renderer:u,scene:s,getActiveCamera:p,getCanvasSize:V,pixelRatio:a,config:n,requestRender:()=>R()});U.sync();let W=$e({scene:s,renderer:u,lights:h,config:n,pipeline:U,requestRender:()=>R()}),{animate:ie,dispose:oe,invalidate:G}=Ze(u,s,l,p,f,d,V,a,n.events.onFrame,y,x,()=>U.get(),E,T,n.render.onDemand??!0);return R=G,ie(),s.up.set(r.x,r.y,r.z),_(),b(),{scene:s,camera:l,controls:d,renderer:u,cameraController:f,grid:y,gizmo:x,measureTool:D,labelLayer:E,tools:k,applyEdges:te,clearEdges:re,invalidate:G,setAmbientOcclusion:U.setAmbientOcclusion,setLook:W.setLook,setFillLights:W.setFillLights,setEnvironmentIntensity:W.setEnvironmentIntensity,setToneMappingExposure:W.setToneMappingExposure,setAoIntensity:W.setAoIntensity,getMaterialAppearance:W.getMaterialAppearance,updateShadowBounds:_,updateGridScale:b,dispose:()=>{m||(m=!0,oe(),O.dispose(),e.removeEventListener(`mousedown`,P,{capture:!0}),e.removeEventListener(`click`,I,{capture:!0}),e.removeEventListener(`mousemove`,L),D?.dispose(),E?.dispose(),x?.dispose(),y?.dispose(),U.dispose(),f.dispose(),d.dispose(),u.dispose(),u.forceContextLoss(),nt(s))},fitToView:O.fitToView,clearSelection:O.clearSelection,addUserGeometry:(e,t)=>{e.userData.source=t===void 0?j:N(t),s.add(e),R()},removeUserGeometry:e=>{e.removeFromParent(),o(e),R()},clearUserGeometry:e=>{s.children.filter(t=>ee(t,e)).forEach(e=>{e.removeFromParent(),o(e)}),R()}}};export{D as DEFAULT_LOOK,s as ErrorCodes,E as LOOKS,O as LOOK_PRESETS,A as SOURCE_COMPUTE,j as SOURCE_USER,n as VisualizationError,P as appIdFromSource,N as appSource,a as enableDebugLogging,t as getLogger,pt as initThree,F as isHostOwned,ee as isOwnedBy,k as materialAppearanceForLook,He as pickThreshold,Ye as pointerToNdc,r as setLogger,We as snapToVertex,re as updateScene};
108
108
  //# sourceMappingURL=render.js.map