@selvajs/compute 3.1.0-beta.1 → 3.1.0-beta.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/dist/chunk-2KQHHQZW.js +2 -0
  2. package/dist/chunk-2KQHHQZW.js.map +1 -0
  3. package/dist/chunk-7XMD5YXP.cjs +62 -0
  4. package/dist/chunk-7XMD5YXP.cjs.map +1 -0
  5. package/dist/chunk-CUQQ3ZBV.cjs +4 -0
  6. package/dist/chunk-CUQQ3ZBV.cjs.map +1 -0
  7. package/dist/chunk-HOWV4A5D.cjs +2 -0
  8. package/dist/chunk-HOWV4A5D.cjs.map +1 -0
  9. package/dist/chunk-PX2YTSHJ.js +62 -0
  10. package/dist/chunk-PX2YTSHJ.js.map +1 -0
  11. package/dist/chunk-WPB2LKCD.js +4 -0
  12. package/dist/chunk-WPB2LKCD.js.map +1 -0
  13. package/dist/core.cjs +1 -1
  14. package/dist/core.cjs.map +1 -1
  15. package/dist/core.d.cts +40 -3
  16. package/dist/core.d.ts +40 -3
  17. package/dist/core.js +1 -1
  18. package/dist/grasshopper.cjs +1 -1
  19. package/dist/grasshopper.cjs.map +1 -1
  20. package/dist/grasshopper.d.cts +222 -32
  21. package/dist/grasshopper.d.ts +222 -32
  22. package/dist/grasshopper.js +1 -1
  23. package/dist/{handle-files-9pkEgDIp.d.ts → handle-files-BISo_wob.d.cts} +51 -67
  24. package/dist/{handle-files-9pkEgDIp.d.cts → handle-files-BISo_wob.d.ts} +51 -67
  25. package/dist/index.cjs +1 -1
  26. package/dist/index.cjs.map +1 -1
  27. package/dist/index.d.cts +4 -4
  28. package/dist/index.d.ts +4 -4
  29. package/dist/index.js +1 -1
  30. package/dist/types-BGhtYxZ-.d.cts +45 -0
  31. package/dist/types-BGhtYxZ-.d.ts +45 -0
  32. package/dist/{types-DK2-skCK.d.cts → types-C8XWc4Ab.d.cts} +92 -67
  33. package/dist/{types-jb_K_a0s.d.ts → types-Dtok-mVq.d.ts} +92 -67
  34. package/dist/visualization-4RSUYQG2.cjs +2 -0
  35. package/dist/visualization-4RSUYQG2.cjs.map +1 -0
  36. package/dist/visualization-MOYO6MDN.js +2 -0
  37. package/dist/visualization.cjs +1 -1
  38. package/dist/visualization.cjs.map +1 -1
  39. package/dist/visualization.d.cts +200 -37
  40. package/dist/visualization.d.ts +200 -37
  41. package/dist/visualization.js +1 -1
  42. package/package.json +3 -3
  43. package/dist/chunk-C2HJB4MH.js +0 -55
  44. package/dist/chunk-C2HJB4MH.js.map +0 -1
  45. package/dist/chunk-DRG5SLIP.cjs +0 -4
  46. package/dist/chunk-DRG5SLIP.cjs.map +0 -1
  47. package/dist/chunk-ESPPM542.js +0 -2
  48. package/dist/chunk-ESPPM542.js.map +0 -1
  49. package/dist/chunk-J3MFKB33.js +0 -4
  50. package/dist/chunk-J3MFKB33.js.map +0 -1
  51. package/dist/chunk-LP7LO5PR.cjs +0 -2
  52. package/dist/chunk-LP7LO5PR.cjs.map +0 -1
  53. package/dist/chunk-QZ573TYU.cjs +0 -55
  54. package/dist/chunk-QZ573TYU.cjs.map +0 -1
  55. package/dist/types-ChF690kY.d.cts +0 -88
  56. package/dist/types-ChF690kY.d.ts +0 -88
  57. package/dist/visualization-3E3Q76VG.cjs +0 -2
  58. package/dist/visualization-3E3Q76VG.cjs.map +0 -1
  59. package/dist/visualization-XBMHHG6L.js +0 -2
  60. /package/dist/{visualization-XBMHHG6L.js.map → visualization-MOYO6MDN.js.map} +0 -0
@@ -1,11 +1,11 @@
1
1
  import * as THREE from 'three';
2
2
  import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
3
+ import { M as MaterialAppearanceOptions, f as GrasshopperComputeResponse, m as MeshExtractionOptions, n as MeshBatchParsingOptions, o as DisplayBatch, p as DisplayItem } from './types-Dtok-mVq.js';
4
+ export { q as DisplayCurve, r as DisplayIdentity, s as DisplayItemBase, t as DisplayPoint, u as DisplayPosition, v as MeshBatch } from './types-Dtok-mVq.js';
3
5
  import { CSS2DObject } from 'three/addons/renderers/CSS2DRenderer.js';
4
6
  import { LineSegments2 } from 'three/addons/lines/LineSegments2.js';
5
- import { f as GrasshopperComputeResponse, M as MeshExtractionOptions, m as MeshBatchParsingOptions, n as DisplayBatch, o as DisplayItem } from './types-jb_K_a0s.js';
6
- export { p as DisplayCurve, q as DisplayIdentity, r as DisplayItemBase, s as DisplayPoint, t as DisplayPosition, u as MeshBatch } from './types-jb_K_a0s.js';
7
7
  import { RhinoModule } from 'rhino3dm';
8
- import './types-ChF690kY.js';
8
+ import './types-BGhtYxZ-.js';
9
9
 
10
10
  type CameraConfig = {
11
11
  position?: THREE.Vector3;
@@ -13,6 +13,13 @@ type CameraConfig = {
13
13
  near?: number;
14
14
  far?: number;
15
15
  target?: THREE.Vector3;
16
+ /**
17
+ * Refit the perspective camera's near plane to the camera↔content gap every frame (default true).
18
+ * Recovers depth-buffer precision when zoomed out (precision ∝ near/z²), which is what stops
19
+ * distant surfaces z-fighting. `near` stays the lower bound — the plane is only raised, never
20
+ * lowered below it.
21
+ */
22
+ dynamicNear?: boolean;
16
23
  };
17
24
  type LightingConfig = {
18
25
  enableSunlight?: boolean;
@@ -21,6 +28,20 @@ type LightingConfig = {
21
28
  ambientLightColor?: THREE.Color;
22
29
  ambientLightIntensity?: number;
23
30
  sunlightColor?: THREE.Color | number;
31
+ /**
32
+ * Add a hemisphere fill light (sky color from above, ground color from below). Unlike the flat
33
+ * ambient, this gives soft *direction-aware* fill, so downward- and side-facing surfaces never
34
+ * collapse to black when the HDR's lower hemisphere is dark. The single biggest lever for keeping
35
+ * results well-lit regardless of which HDR is loaded. Default false (opt-in) — enabling it shifts
36
+ * the look. See {@link LightingConfig.hemisphereIntensity}.
37
+ */
38
+ enableHemisphereLight?: boolean;
39
+ /** Hemisphere fill sky color (lights upward-facing surfaces). Default white. */
40
+ hemisphereSkyColor?: THREE.Color | number;
41
+ /** Hemisphere fill ground color (lights downward-facing surfaces). Default a mid grey. */
42
+ hemisphereGroundColor?: THREE.Color | number;
43
+ /** Hemisphere fill strength. Default 0.6. Only applies when {@link LightingConfig.enableHemisphereLight}. */
44
+ hemisphereIntensity?: number;
24
45
  };
25
46
  type EnvironmentConfig = {
26
47
  hdrPath?: string;
@@ -28,6 +49,13 @@ type EnvironmentConfig = {
28
49
  enableEnvironmentLighting?: boolean;
29
50
  sceneUp?: THREE.Vector3;
30
51
  showEnvironment?: boolean;
52
+ /**
53
+ * Uniform multiplier on the HDR's image-based lighting contribution (`scene.environmentIntensity`).
54
+ * Normalizes brightness across HDRs of differing exposure — raise it to lift a dim HDR, lower it to
55
+ * tame a blown-out one — so the scene doesn't render dim-or-blown purely because of the HDR chosen.
56
+ * Default 1 (three.js default, unchanged look).
57
+ */
58
+ environmentIntensity?: number;
31
59
  };
32
60
  type FloorConfig = {
33
61
  enabled?: boolean;
@@ -52,7 +80,36 @@ type RenderConfig = {
52
80
  ambientOcclusion?: boolean;
53
81
  /** AO strength 0–1 when {@link RenderConfig.ambientOcclusion} is on. Default 1. */
54
82
  aoIntensity?: number;
83
+ /**
84
+ * Device-pixel-ratio cap for the ambient-occlusion postprocessing buffers. AO is low-frequency, so
85
+ * rendering its buffers below the display DPR is nearly invisible but hugely cheaper — on a Retina
86
+ * display (DPR 2) full-resolution AO means 4× the pixels through GTAO's per-pixel sample loops,
87
+ * which can dominate frame time. Default 1 (AO buffers at 1× regardless of display DPR). Raise
88
+ * toward the display DPR for sharper AO at higher cost; only relevant when AO is enabled.
89
+ */
90
+ aoPixelRatio?: number;
55
91
  };
92
+ /**
93
+ * A ready-to-go visual look. A `look` is a named bundle of LIGHTING/MATERIAL defaults only — it is
94
+ * deliberately decoupled from the CAD overlays (edges, grid), which are driven independently by
95
+ * {@link EdgesConfig}/{@link GridConfig}. Pick one and the viewer looks professional with zero other
96
+ * config; every individual `lighting`/`environment`/`render` option still overrides the preset. Seeds
97
+ * construction defaults and can be re-applied live via `setLook`.
98
+ *
99
+ * - 'technical' (default): matte, drawing-like — neutral tone mapping, low IBL, no fill. Reads like a
100
+ * CAD shaded view (Rhino/Onshape).
101
+ * - 'studio': balanced presentation — ACES tone mapping, hemisphere fill + lifted HDR so results are
102
+ * well-lit regardless of the HDR, without washing colour out. The polished "product shot" look.
103
+ * - 'showcase': punchier presentation — ACES, stronger IBL/fill and a touch more exposure.
104
+ */
105
+ /**
106
+ * The look values as a runtime array — the single source of truth. {@link Look} is derived from it, so
107
+ * the type and the enumerable list can never drift. Consumers (e.g. a viewer's style picker) iterate
108
+ * this instead of hardcoding the names, so adding or renaming a look here updates them automatically.
109
+ * 'technical' is first because it's the default.
110
+ */
111
+ declare const LOOKS: readonly ["technical", "studio", "showcase"];
112
+ type Look = (typeof LOOKS)[number];
56
113
  /** Crisp boundary/crease edge overlays on meshes. See `addEdges`. */
57
114
  type EdgesConfig = {
58
115
  /** Auto-attach edge overlays to meshes as they load. Default false (opt-in). */
@@ -63,6 +120,8 @@ type EdgesConfig = {
63
120
  width?: number;
64
121
  /** Crease angle (degrees): keep edges where faces differ by more than this. Default 30. */
65
122
  thresholdAngle?: number;
123
+ /** Fade an overlay out as its mesh shrinks on screen, so far zoom-outs stay clean. Default true. */
124
+ distanceFade?: boolean;
66
125
  };
67
126
  type ControlsConfig = {
68
127
  enableDamping?: boolean;
@@ -122,6 +181,14 @@ type MeasureConfig = {
122
181
  };
123
182
  type ThreeInitializerOptions = {
124
183
  sceneScale?: 'mm' | 'cm' | 'm' | 'inches' | 'feet';
184
+ /**
185
+ * Pick a ready-to-go visual look up front — seeds professional lighting/material defaults (tone
186
+ * mapping, AO, IBL strength, hemisphere fill; see {@link Look}). Individual `lighting`/
187
+ * `environment`/`render` options still win when set explicitly, so this only fills in what you
188
+ * leave unspecified. A look does NOT touch edges/grid (those are independent overlays). Defaults
189
+ * to 'technical'. Re-apply later via the init result's `setLook`.
190
+ */
191
+ look?: Look;
125
192
  camera?: CameraConfig;
126
193
  lighting?: LightingConfig;
127
194
  environment?: EnvironmentConfig;
@@ -193,12 +260,20 @@ interface CameraController {
193
260
  * singularity.
194
261
  */
195
262
  setViewDirection(direction: THREE.Vector3, animate?: boolean): void;
263
+ /**
264
+ * Frame an arbitrary world-space box (e.g. a double-clicked object) from the current view
265
+ * direction, moving the *active* camera — in 2D mode that means resizing the ortho frustum, not
266
+ * just translating. No-op on an empty box.
267
+ */
268
+ frameBounds(box: THREE.Box3, animate?: boolean): void;
196
269
  /** Enable/disable orbit rotation at runtime (pan/zoom unaffected). */
197
270
  setRotateEnabled(enabled: boolean): void;
198
271
  /** Whether rotation is currently enabled. */
199
272
  isRotateEnabled(): boolean;
200
273
  /** Keep the orthographic frustum aspect in sync on canvas resize. Called by the resize loop. */
201
274
  updateAspect(width: number, height: number): void;
275
+ /** Cancel any in-flight camera tween. Call on viewer teardown so ticks can't touch disposed controls. */
276
+ dispose(): void;
202
277
  }
203
278
  interface CameraControllerDeps {
204
279
  scene: THREE.Scene;
@@ -265,14 +340,24 @@ declare function createGrid(options?: GridOptions): Grid;
265
340
  *
266
341
  * Caller responsibilities (mirror ViewHelper's own contract):
267
342
  * - call {@link ViewGizmo.render} *after* the main scene render each frame (overlay viewport),
268
- * - call {@link ViewGizmo.update} each frame (no-op now; kept for API symmetry),
269
343
  * - forward pointer clicks to {@link ViewGizmo.handleClick}.
270
344
  */
271
345
  interface ViewGizmo {
272
346
  render(renderer: THREE.WebGLRenderer): void;
347
+ /**
348
+ * @deprecated No-op, kept only for API stability. This wrapper never uses ViewHelper's
349
+ * click→animate path (see module comment) — view changes snap instantly through the camera
350
+ * controller — so there is never a gizmo animation to advance. Safe to stop calling.
351
+ */
273
352
  update(delta: number): void;
274
353
  /** Hit-test a click. Returns true if it hit the gizmo (and a view change started). */
275
354
  handleClick(event: MouseEvent): boolean;
355
+ /**
356
+ * @deprecated Always `false`, kept only for API stability. Gizmo clicks snap the view
357
+ * instantly rather than animating (deliberately — ViewHelper's built-in animation assumes a
358
+ * Y-up world and rolls the view in this Z-up scene), so there is no animation window to gate
359
+ * input on.
360
+ */
276
361
  readonly isAnimating: boolean;
277
362
  /** Show/hide the gizmo at runtime. Hidden = not rendered and not click-hittable. */
278
363
  setVisible(visible: boolean): void;
@@ -375,6 +460,14 @@ interface MeasureDeps {
375
460
  canvas: HTMLCanvasElement;
376
461
  scene: THREE.Scene;
377
462
  getActiveCamera: () => THREE.Camera;
463
+ /**
464
+ * The current orbit target (e.g. `controls.target`). Used to scale the line/point pick
465
+ * threshold with the view: the tolerance is a fraction of the camera→target distance, so it
466
+ * stays roughly constant on screen wherever the user has framed the model. Optional for
467
+ * backward compatibility — without it the perspective fallback is the camera's distance to the
468
+ * world origin, which misjudges the threshold for off-origin content. Thread it in when you can.
469
+ */
470
+ getViewTarget?: () => THREE.Vector3;
378
471
  labelLayer: LabelLayer;
379
472
  options?: MeasureOptions;
380
473
  }
@@ -412,6 +505,46 @@ declare const initThree: (canvas: HTMLCanvasElement, options?: ThreeInitializerO
412
505
  applyEdges: (root: THREE.Object3D) => void;
413
506
  /** Toggle ambient occlusion at runtime — builds or tears down the postprocessing pipeline. */
414
507
  setAmbientOcclusion: (enabled: boolean) => void;
508
+ /**
509
+ * Apply a coherent look to the already-loaded scene: 'technical' (matte/CAD — edges, grid, low
510
+ * IBL, neutral tone mapping) or 'rendered' (presentation — stronger IBL, ACES tone mapping, no
511
+ * edges). Retunes viewer-owned dials only; per-material parse choices are set via the batch
512
+ * parser's `material` option. Handy for comparing the two looks in a live viewer.
513
+ */
514
+ /**
515
+ * Switch the viewer to a ready-to-go look at runtime ('studio' | 'technical' | 'showcase'). Retunes
516
+ * lighting/material only (tone mapping, fill, IBL, AO) — never edges/grid. A straight preset apply:
517
+ * overwrites any granular lighting dials you set earlier.
518
+ */
519
+ setLook: (look: "studio" | "technical" | "showcase") => void;
520
+ /**
521
+ * Retune the fill lights at runtime: the direction-aware hemisphere fill (sky/ground) and the flat
522
+ * ambient. Raising `hemisphereIntensity` is the most effective way to lift shadowed / under-facing
523
+ * surfaces a dark HDR leaves black. A positive `hemisphereIntensity` lazily creates the hemisphere
524
+ * light if the viewer was built without one; `0` switches it off.
525
+ */
526
+ setFillLights: (opts: {
527
+ hemisphereIntensity?: number;
528
+ hemisphereSkyColor?: THREE.Color | number;
529
+ hemisphereGroundColor?: THREE.Color | number;
530
+ ambientIntensity?: number;
531
+ }) => void;
532
+ /**
533
+ * Set the uniform multiplier on the HDR's image-based lighting (`scene.environmentIntensity`) at
534
+ * runtime — normalizes brightness across HDRs of differing exposure so the scene isn't at the
535
+ * mercy of whichever HDR is loaded. Applies immediately, even before the HDR finishes decoding.
536
+ */
537
+ setEnvironmentIntensity: (intensity: number) => void;
538
+ /** Set renderer tone-mapping exposure at runtime. Higher lifts shadows and overall brightness. */
539
+ setToneMappingExposure: (exposure: number) => void;
540
+ /** Set GTAO strength at runtime (0–1). No-op when ambient occlusion isn't active. */
541
+ setAoIntensity: (intensity: number) => void;
542
+ /**
543
+ * The parse-time material options (backface culling, IBL strength) matching the active look — feed
544
+ * into the batch parser's `material` option so freshly-loaded meshes are built to match it. See
545
+ * `setLook`.
546
+ */
547
+ getMaterialAppearance: () => MaterialAppearanceOptions;
415
548
  /**
416
549
  * Refit the sun's shadow frustum to the current scene content for crisp shadows. Call after
417
550
  * loading or replacing geometry (e.g. after `updateScene`). No-op when sunlight/shadows are off.
@@ -432,25 +565,9 @@ declare const initThree: (canvas: HTMLCanvasElement, options?: ThreeInitializerO
432
565
  clearUserGeometry: () => void;
433
566
  };
434
567
 
435
- /**
436
- * Updates the scene with the given meshes and camera settings.
437
- * If initialPositionSet is false, it positions the camera and sets the controls target based on the bounding boxes of the meshes.
438
- * @param scene - The THREE.Scene object to update.
439
- * @param meshes - An array of THREE.Mesh objects to add to the scene.
440
- * @param camera - The THREE.PerspectiveCamera object to position.
441
- * @param controls - The OrbitControls object to update.
442
- * @param initialPositionSet - A boolean indicating whether the initial position of the camera and controls have been set.
443
- */
568
+ /** Updates scene with meshes and positions camera on first call. */
444
569
  declare function updateScene(scene: THREE.Scene, meshes: THREE.Object3D[], camera: THREE.PerspectiveCamera, controls: OrbitControls, initialPositionSet: boolean): void;
445
- /**
446
- * Parses a color string in multiple formats to a THREE.Color object.
447
- * Supported formats:
448
- * - Hex: "#C7A5A5", "C7A5A5"
449
- * - RGB: "199, 165, 165"
450
- * - CSS named colors: "red", "blue", etc.
451
- * @param colorString - The color string to parse.
452
- * @returns A THREE.Color object.
453
- */
570
+ /** Parses color strings (hex, RGB, CSS names). */
454
571
  declare function parseColor(colorString: string): THREE.Color;
455
572
  /**
456
573
  * Shift objects along one world axis. Defaults to `z` — the up axis of the unified Z-up scene
@@ -470,6 +587,8 @@ declare const PLASTIC_MATERIAL: THREE.MeshPhysicalMaterial;
470
587
  declare const GLASS_MATERIAL: THREE.MeshPhysicalMaterial;
471
588
  declare const RUBBER_MATERIAL: THREE.MeshPhysicalMaterial;
472
589
  declare const WOOD_MATERIAL: THREE.MeshPhysicalMaterial;
590
+ /** Shared singleton materials; must not be disposed (rebuilds shaders, frees textures). */
591
+ declare const SHARED_MATERIALS: ReadonlySet<THREE.Material>;
473
592
 
474
593
  declare const threeMaterials_CONCRETE_MATERIAL: typeof CONCRETE_MATERIAL;
475
594
  declare const threeMaterials_EMISSIVE_MATERIAL: typeof EMISSIVE_MATERIAL;
@@ -477,9 +596,10 @@ declare const threeMaterials_GLASS_MATERIAL: typeof GLASS_MATERIAL;
477
596
  declare const threeMaterials_METAL_MATERIAL: typeof METAL_MATERIAL;
478
597
  declare const threeMaterials_PLASTIC_MATERIAL: typeof PLASTIC_MATERIAL;
479
598
  declare const threeMaterials_RUBBER_MATERIAL: typeof RUBBER_MATERIAL;
599
+ declare const threeMaterials_SHARED_MATERIALS: typeof SHARED_MATERIALS;
480
600
  declare const threeMaterials_WOOD_MATERIAL: typeof WOOD_MATERIAL;
481
601
  declare namespace threeMaterials {
482
- export { threeMaterials_CONCRETE_MATERIAL as CONCRETE_MATERIAL, threeMaterials_EMISSIVE_MATERIAL as EMISSIVE_MATERIAL, threeMaterials_GLASS_MATERIAL as GLASS_MATERIAL, threeMaterials_METAL_MATERIAL as METAL_MATERIAL, threeMaterials_PLASTIC_MATERIAL as PLASTIC_MATERIAL, threeMaterials_RUBBER_MATERIAL as RUBBER_MATERIAL, threeMaterials_WOOD_MATERIAL as WOOD_MATERIAL };
602
+ export { threeMaterials_CONCRETE_MATERIAL as CONCRETE_MATERIAL, threeMaterials_EMISSIVE_MATERIAL as EMISSIVE_MATERIAL, threeMaterials_GLASS_MATERIAL as GLASS_MATERIAL, threeMaterials_METAL_MATERIAL as METAL_MATERIAL, threeMaterials_PLASTIC_MATERIAL as PLASTIC_MATERIAL, threeMaterials_RUBBER_MATERIAL as RUBBER_MATERIAL, threeMaterials_SHARED_MATERIALS as SHARED_MATERIALS, threeMaterials_WOOD_MATERIAL as WOOD_MATERIAL };
483
603
  }
484
604
 
485
605
  /**
@@ -491,6 +611,15 @@ declare namespace threeMaterials {
491
611
  * `LineMaterial` family as curves (Phase 1) — so edges get controllable thickness, not the 1px cap
492
612
  * of `THREE.LineSegments`. The overlay is added as a *child* of each mesh, so it inherits the mesh's
493
613
  * transform and is disposed when the mesh subtree is cleared.
614
+ *
615
+ * Depth strategy: edges render at TRUE depth; the mesh's own surface is pushed back a hair with
616
+ * polygonOffset instead (see {@link setSurfaceDepthOffset}). Biasing the lines toward the camera —
617
+ * the obvious alternative — needs a multi-ULP constant offset to survive glancing angles (fat-line
618
+ * quads face the screen, so the slope-scaled factor term is nil), and a depth ULP grows ~quadratically
619
+ * with distance: zoomed out, that constant becomes a meter-scale pull that makes hidden edges bleed
620
+ * through whatever mesh is in front. Offsetting the surfaces instead lets the slope-proportional
621
+ * factor term do the glancing-angle work, keeps the constant term at quantization scale, and leaves
622
+ * occlusion of hidden edges exact.
494
623
  */
495
624
  interface EdgeOptions {
496
625
  /** Edge color. Default near-black. */
@@ -502,6 +631,11 @@ interface EdgeOptions {
502
631
  * Default 30. Higher = fewer edges (only sharp creases); lower = more (catches gentle bends).
503
632
  */
504
633
  thresholdAngle?: number;
634
+ /**
635
+ * Fade an overlay out as its mesh shrinks on screen (default true). Constant-px edges on a mesh
636
+ * covering only tens of pixels alias into dark noise; fading them keeps far zoom-outs clean.
637
+ */
638
+ distanceFade?: boolean;
505
639
  }
506
640
  /** Tag on edge overlays so pick/fit/clear logic can recognize and skip or dispose them. */
507
641
  declare const EDGE_USERDATA_KIND = "edge-overlay";
@@ -526,11 +660,18 @@ declare function removeEdges(root: THREE.Object3D): number;
526
660
  * this when `render.ambientOcclusion` is enabled, and otherwise renders with a plain
527
661
  * `renderer.render` so the cheap path stays cheap (the chosen tradeoff — see cad-viewer-plan.md).
528
662
  *
529
- * Pipeline: RenderPass → GTAOPass → OutputPass. GTAO (ground-truth AO) is the modern replacement for
530
- * SSAO/SAO — better contact shadows in crevices, the "engineered" depth cue. `screenSpaceRadius` is
531
- * on so the AO radius is in screen space, which keeps it scale-robust across the viewer's mm→m
532
- * scenes without per-scene tuning. OutputPass applies tone mapping + color space (taking over the
533
- * roles the renderer did directly in the non-composer path).
663
+ * Pipeline: RenderPass → GTAOPass → SMAAPass → OutputPass. GTAO (ground-truth AO) is the modern
664
+ * replacement for SSAO/SAO — better contact shadows in crevices, the "engineered" depth cue.
665
+ * `screenSpaceRadius` is on so the AO radius is in screen space, which keeps it scale-robust across
666
+ * the viewer's mm→m scenes without per-scene tuning.
667
+ *
668
+ * SMAA restores antialiasing on this path. The EffectComposer renders into an offscreen target, so
669
+ * the WebGLRenderer's own MSAA (`antialias: true`) does nothing here — without a dedicated AA pass,
670
+ * enabling AO would visibly *worsen* edge quality. SMAA is chosen over TAA because TAA's temporal
671
+ * jitter smears during OrbitControls drags; SMAA is single-frame, cheap, and stable while orbiting.
672
+ *
673
+ * OutputPass applies tone mapping + color space last (taking over the roles the renderer did
674
+ * directly in the non-composer path), so SMAA operates on the pre-tonemapped image as intended.
534
675
  *
535
676
  * Camera swaps: the active camera can flip perspective↔ortho. Rather than rebuild the composer, we
536
677
  * retarget the passes' `camera` each render via {@link setCamera}.
@@ -548,9 +689,21 @@ interface RenderPipelineOptions {
548
689
  toneMappingExposure: number;
549
690
  /** AO strength 0–1. Default 1. */
550
691
  aoIntensity?: number;
692
+ /**
693
+ * Cap on the device-pixel-ratio used for the composer's (AO) buffers. AO is low-frequency, so
694
+ * rendering below the display DPR is nearly invisible but far cheaper. `setSize`'s incoming
695
+ * pixelRatio is clamped to this. Default 1.
696
+ */
697
+ aoPixelRatio?: number;
551
698
  }
552
699
  declare function createRenderPipeline(renderer: THREE.WebGLRenderer, scene: THREE.Scene, camera: THREE.Camera, width: number, height: number, options: RenderPipelineOptions): RenderPipeline;
553
700
 
701
+ /**
702
+ * Metres per model unit, keyed by Rhino `UnitSystem` name (the `modelunits` string on the compute
703
+ * response). Imperial factors are the exact international definitions (1 in = 0.0254 m,
704
+ * 1 ft = 0.3048 m, 1 mi = 1609.344 m). Units not in this table scale 1 and log a one-time warning
705
+ * — see {@link getScaleFactor}.
706
+ */
554
707
  declare const SCALE_FACTORS: Record<string, number>;
555
708
  /**
556
709
  * Extracts and processes display meshes from a ComputePointerResponse using the Grasshopper WebDisplay component.
@@ -558,7 +711,9 @@ declare const SCALE_FACTORS: Record<string, number>;
558
711
  * This is the primary entry point for extracting mesh geometry from Grasshopper compute responses.
559
712
  * It handles all aspects of mesh processing: decompression, coordinate transformation, scaling, and positioning.
560
713
  *
561
- * **Note:** Mesh decompression happens asynchronously in a Web Worker to prevent UI blocking.
714
+ * **Note:** The entire pipeline (base64 decode, inflate, dequantization, mesh construction) runs
715
+ * synchronously on the calling thread — large batches will block the UI for their duration. The
716
+ * function is `async` only so its shape can stay stable if parsing moves off-thread later.
562
717
  *
563
718
  * @param data - The ComputePointerResponse containing Grasshopper output trees.
564
719
  * @param options - Configuration for mesh extraction and parsing behavior. All options are optional with sensible defaults.
@@ -569,7 +724,7 @@ declare const SCALE_FACTORS: Record<string, number>;
569
724
  * - Only works with the WebDisplay component of GHHeadless.
570
725
  * - Requires changes to Rhino.Compute (see https://github.com/TheVessen/compute.rhino3d).
571
726
  * - Provides a performant way to display mesh data in Three.js.
572
- * - Decompression is performed in a Web Worker for non-blocking UI updates.
727
+ * - All decoding is synchronous on the main thread; there is no Web Worker offload today.
573
728
  * - Supports mesh metadata (names, user data) if provided in the compute response.
574
729
  *
575
730
  * @internal Internal helper: high-level extraction remains public via visualization module, but this
@@ -598,11 +753,7 @@ declare const SCALE_FACTORS: Record<string, number>;
598
753
  */
599
754
  declare function getThreeMeshesFromComputeResponse(data: GrasshopperComputeResponse, options?: MeshExtractionOptions): Promise<THREE.Object3D[]>;
600
755
 
601
- /**
602
- * Internal-only telemetry threaded from an outer entry point (e.g. the JSON
603
- * `parseMeshBatch` measuring its own `JSON.parse` cost) into the shared build
604
- * step. Never part of any public options surface — callers don't supply timings.
605
- */
756
+ /** Internal telemetry only (not exposed in public options). */
606
757
  interface ParseTelemetry {
607
758
  parseTime?: number;
608
759
  perfStart?: number;
@@ -614,9 +765,14 @@ interface ParseTelemetry {
614
765
  * over the blob. The function stays `async` so callers don't have to change shape if we move
615
766
  * parsing into a worker later.
616
767
  *
768
+ * A batch with no `compressedData` (genuinely empty/absent geometry) resolves to `[]`. A corrupt,
769
+ * truncated, or unsupported blob throws so callers get a signal instead of a silent empty scene —
770
+ * `getThreeMeshesFromComputeResponse` documents (and now delivers) exactly that rethrow.
771
+ *
617
772
  * @param batch - DisplayBatch object
618
773
  * @param options - Rendering options
619
774
  * @returns Promise resolving to array of Three.js mesh objects
775
+ * @throws {RhinoComputeError} On a corrupt/truncated/unsupported mesh blob or malformed group metadata.
620
776
  */
621
777
  declare function parseMeshBatchObject(batch: DisplayBatch, options?: MeshBatchParsingOptions,
622
778
  /** @internal Timings threaded from an outer entry point; not a caller option. */
@@ -632,13 +788,20 @@ telemetry?: ParseTelemetry): Promise<THREE.Mesh[]>;
632
788
  * @param blob - Raw blob bytes from a binary WebSocket frame.
633
789
  * @param options - Rendering options.
634
790
  * @returns Promise resolving to array of Three.js mesh objects.
791
+ * @throws {RhinoComputeError} On a corrupt/truncated/unsupported mesh blob or malformed group metadata.
635
792
  */
636
793
  declare function parseMeshBatchBlob(blob: ArrayBuffer | Uint8Array, options?: MeshBatchParsingOptions): Promise<THREE.Mesh[]>;
637
794
 
638
795
  interface DisplayItemParseOptions {
639
796
  /** rhino3dm instance for decoding curve JSON. Omit to skip curves (points still render). */
640
797
  rhino?: RhinoModule;
641
- /** Apply the Rhino Z-up → Three Y-up transform. Defaults to true (matches the mesh path). */
798
+ /**
799
+ * No-op. Historically toggled the Rhino Z-up → Three Y-up rotation, but the pipeline now keeps
800
+ * one coordinate frame end to end ({@link rhinoToThree} is the identity), so this flag no longer
801
+ * changes the result. Do NOT pre-rotate your own geometry to compensate — none is applied.
802
+ *
803
+ * @deprecated Retained only so existing call sites compile unchanged; has no effect.
804
+ */
642
805
  applyTransforms?: boolean;
643
806
  }
644
807
  /**
@@ -648,4 +811,4 @@ interface DisplayItemParseOptions {
648
811
  */
649
812
  declare function parseDisplayItems(items: DisplayItem[] | undefined, options?: DisplayItemParseOptions): THREE.Object3D[];
650
813
 
651
- export { type CameraConfig, type CameraController, type CameraProjection, type ControlsConfig, DisplayBatch, DisplayItem, type DisplayItemParseOptions, EDGE_USERDATA_KIND, type EdgeOptions, type EdgesConfig, type EnvironmentConfig, type EventConfig, type FloorConfig, type GizmoConfig, type Grid, type GridConfig, type GridOptions, type LabelHandle, type LabelLayer, type LightingConfig, threeMaterials as Materials, type MeasureConfig, type MeasureOptions, type MeasureTool, MeshExtractionOptions, type RenderConfig, type RenderPipeline, type RenderPipelineOptions, SCALE_FACTORS, type ThreeInitializerOptions, type ViewGizmo, type ViewPreset, addEdges, applyOffset, computeCombinedBoundingBox, createCameraController, createGrid, createLabelLayer, createMeasureTool, createRenderPipeline, createViewGizmo, getThreeMeshesFromComputeResponse, initThree, isEdgeOverlay, parseColor, parseDisplayItems, parseMeshBatchBlob, parseMeshBatchObject, removeEdges, snapToVertex, updateScene };
814
+ export { type CameraConfig, type CameraController, type CameraProjection, type ControlsConfig, DisplayBatch, DisplayItem, type DisplayItemParseOptions, EDGE_USERDATA_KIND, type EdgeOptions, type EdgesConfig, type EnvironmentConfig, type EventConfig, type FloorConfig, type GizmoConfig, type Grid, type GridConfig, type GridOptions, LOOKS, type LabelHandle, type LabelLayer, type LightingConfig, type Look, threeMaterials as Materials, type MeasureConfig, type MeasureOptions, type MeasureTool, MeshExtractionOptions, type RenderConfig, type RenderPipeline, type RenderPipelineOptions, SCALE_FACTORS, type ThreeInitializerOptions, type ViewGizmo, type ViewPreset, addEdges, applyOffset, computeCombinedBoundingBox, createCameraController, createGrid, createLabelLayer, createMeasureTool, createRenderPipeline, createViewGizmo, getThreeMeshesFromComputeResponse, initThree, isEdgeOverlay, parseColor, parseDisplayItems, parseMeshBatchBlob, parseMeshBatchObject, removeEdges, snapToVertex, updateScene };
@@ -1,2 +1,2 @@
1
- import{B as h,C as c,D as v,E as j,a as e,b as r,c as t,d as o,e as i,f as a,g as s,h as p,i as n,j as l,k as f,l as m,m as y,n as u,o as d,p as x,q as C,r as g}from"./chunk-C2HJB4MH.js";import"./chunk-J3MFKB33.js";export{p as EDGE_USERDATA_KIND,C as Materials,v as SCALE_FACTORS,n as addEdges,t as applyOffset,o as computeCombinedBoundingBox,i as createCameraController,a as createGrid,y as createLabelLayer,d as createMeasureTool,m as createRenderPipeline,s as createViewGizmo,j as getThreeMeshesFromComputeResponse,x as initThree,l as isEdgeOverlay,r as parseColor,g as parseDisplayItems,c as parseMeshBatchBlob,h as parseMeshBatchObject,f as removeEdges,u as snapToVertex,e as updateScene};
1
+ import{K as v,L as c,M as j,N as z,a as e,b as r,c as t,d as o,e as i,f as a,g as s,h as p,i as n,j as l,k as f,l as m,m as y,n as u,o as x,p as d,u as C,v as g,w as h}from"./chunk-PX2YTSHJ.js";import"./chunk-WPB2LKCD.js";export{n as EDGE_USERDATA_KIND,g as LOOKS,e as Materials,j as SCALE_FACTORS,l as addEdges,o as applyOffset,i as computeCombinedBoundingBox,a as createCameraController,s as createGrid,u as createLabelLayer,d as createMeasureTool,y as createRenderPipeline,p as createViewGizmo,z as getThreeMeshesFromComputeResponse,C as initThree,f as isEdgeOverlay,t as parseColor,h as parseDisplayItems,c as parseMeshBatchBlob,v as parseMeshBatchObject,m as removeEdges,x as snapToVertex,r as updateScene};
2
2
  //# sourceMappingURL=visualization.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@selvajs/compute",
3
- "version": "3.1.0-beta.1",
3
+ "version": "3.1.0-beta.10",
4
4
  "description": "TypeScript library for Rhino Compute Server - Grasshopper and RhinoCommon",
5
5
  "author": "VektorNode",
6
6
  "license": "MIT",
@@ -84,7 +84,7 @@
84
84
  "devDependencies": {
85
85
  "@changesets/cli": "^2.30.0",
86
86
  "@eslint/js": "^10.0.1",
87
- "@types/node": "^25.3.3",
87
+ "@types/node": "^26.1.0",
88
88
  "@types/three": "^0.184.1",
89
89
  "@vitest/coverage-v8": "^3.2.4",
90
90
  "eslint": "^10.4.1",
@@ -97,7 +97,7 @@
97
97
  "prettier-plugin-svelte": "^4.1.0",
98
98
  "prettier-plugin-tailwindcss": "^0.8.0",
99
99
  "svelte": "^5.53.7",
100
- "three": "^0.184.0",
100
+ "three": "^0.185.1",
101
101
  "tsup": "^8.5.1",
102
102
  "typedoc": "^0.28.17",
103
103
  "typedoc-plugin-extras": "^4.0.1",
@@ -1,55 +0,0 @@
1
- import{a as ke,c as ie,d as se,e as M,j as fe}from"./chunk-J3MFKB33.js";import*as _ from"three";var $={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 Xr(e,n,t,r,o){if(Ge(e),n.length===0)return;n.forEach(u=>{e.add(u)});let a=K(n),i=a.getCenter(new _.Vector3),s=a.getSize(new _.Vector3),l=Math.max(s.x,s.y,s.z);if(l/Math.min(s.x||1,s.y||1,s.z||1)>$.SCALE_RATIO_THRESHOLD||l>$.HUGE_THRESHOLD?(t.near=l*$.NEAR_PLANE_FACTOR.TINY,t.far=l*$.FAR_PLANE_FACTOR.HUGE):l>$.LARGE_THRESHOLD?(t.near=l*$.NEAR_PLANE_FACTOR.SMALL,t.far=l*$.FAR_PLANE_FACTOR.LARGE):(t.near=Math.max(.01,l*$.NEAR_PLANE_FACTOR.NORMAL),t.far=Math.max(2e3,l*$.FAR_PLANE_FACTOR.NORMAL)),t.updateProjectionMatrix(),o)r.minDistance=t.near*2,r.maxDistance=t.far*.9;else{let u=l*$.INITIAL_DISTANCE_MULTIPLIER;t.position.set(i.x+u*.8,i.y+u,i.z+u*1.2),r.target.copy(i),r.minDistance=t.near*2,r.maxDistance=t.far*.9,r.update()}}function pe(e){if(!e||typeof e!="string")return M().warn(`Invalid color input: ${e}, using white`),new _.Color(16777215);let n=e.trim();if(/^#?[0-9A-Fa-f]{6}$/.test(n))try{let t=n.startsWith("#")?n:`#${n}`;return new _.Color(t)}catch{return M().warn(`Invalid hex color: ${e}, using white`),new _.Color(16777215)}if(n.includes(",")){let t=n.split(",").map(r=>parseInt(r.trim(),10));if(t.length===3&&t.every(r=>!isNaN(r)&&r>=0&&r<=255))return new _.Color(t[0]/255,t[1]/255,t[2]/255)}try{return new _.Color(n.toLowerCase())}catch{return M().warn(`Invalid color string: ${e}, using white`),new _.Color(16777215)}}function Ee(e,n,t="z"){e.forEach(r=>{r.position[t]-=n})}function K(e){let n=new _.Box3;return e.length===0||e.forEach(t=>{t.updateMatrixWorld(!0);let r=new _.Box3().setFromObject(t);n.union(r)}),n}var je=new Set(["floor","grid","label-layer"]);function Ge(e){[...e.children].forEach(t=>{je.has(t.userData.id)||t.userData.source!=="user"&&(t.traverse(r=>{let o=r;if(!o.geometry&&!o.material)return;o.geometry?.dispose();let a=o.material;if(!a)return;(Array.isArray(a)?a:[a]).forEach(s=>{for(let l of Object.values(s))l instanceof _.Texture&&l.dispose();s.dispose()})}),t.removeFromParent())})}import*as k from"three";function Ne(e){let n=e.clone().normalize(),t=new k.Vector3(0,0,1),r=new k.Vector3(0,1,0),o=Math.abs(n.dot(t))>.9?r:t,a=new k.Vector3().crossVectors(n,o).normalize(),i=new k.Vector3().crossVectors(a,n).normalize();return{top:n.clone(),bottom:n.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(n.clone()).normalize()}}function he(e){let{scene:n,perspective:t,controls:r,onActiveCameraChange:o}=e,a=(e.up??t.up).clone().normalize(),i=Ne(a),s=new k.OrthographicCamera(-1,1,1,-1,t.near,t.far);s.up.copy(a);let l="perspective",c=t.aspect,u=()=>l==="perspective"?t:s,d=()=>{let p=t.position.distanceTo(r.target)*Math.tan(t.fov*Math.PI/360),T=p*c;s.left=-T,s.right=T,s.top=p,s.bottom=-p,s.near=t.near,s.far=t.far,s.updateProjectionMatrix()},m=g=>{g!==l&&(g==="orthographic"?(s.position.copy(t.position),s.up.copy(t.up),s.lookAt(r.target),d()):t.position.copy(s.position),l=g,r.object=u(),r.update(),o(u()))},f=(g,p=!0)=>{let T=Ye(n),v=T.isEmpty()?r.target.clone():T.getCenter(new k.Vector3),O=T.isEmpty()?new k.Vector3(1,1,1):T.getSize(new k.Vector3),w=Math.max(O.x,O.y,O.z)||1,R=t.fov*(Math.PI/180),A=w/(2*Math.tan(R/2))*1.5,P=Xe(g,a),D=v.clone().add(P.clone().multiplyScalar(A)),F=u();p?Ze(F,r,D,v,()=>{l==="orthographic"&&d()}):(F.position.copy(D),r.target.copy(v),l==="orthographic"&&d(),r.update())};return{getActiveCamera:u,getProjection:()=>l,setProjection:m,toggleProjection:()=>(m(l==="perspective"?"orthographic":"perspective"),l),setView:(g,p=!0)=>{f(i[g],p)},setViewDirection:f,setRotateEnabled:g=>{r.enableRotate=g},isRotateEnabled:()=>r.enableRotate,updateAspect:(g,p)=>{c=p===0?c:g/p,l==="orthographic"&&d()}}}var We=new Set(["grid","floor","label-layer","measure"]);function $e(e){let n=e;for(;n;){if(typeof n.userData.id=="string"&&We.has(n.userData.id))return!0;n=n.parent}return!1}function Ye(e){let n=[];return e.traverse(t=>{let r=t;t.visible&&!$e(t)&&r.geometry&&n.push(t)}),K(n)}function Xe(e,n){let t=n.clone().normalize(),r=e.clone().normalize();if(Math.abs(r.dot(t))<.9999)return e;let o=Math.abs(t.dot(new k.Vector3(0,0,1)))>.9?new k.Vector3(0,1,0):new k.Vector3(0,0,1),a=new k.Vector3().crossVectors(t,o).normalize(),i=.5*Math.PI/180;return r.multiplyScalar(Math.cos(i)).add(a.multiplyScalar(Math.sin(i))).normalize()}var qe=e=>1-Math.pow(1-e,3);function Ze(e,n,t,r,o,a=250){let i=e.position.clone(),s=n.target.clone(),l=performance.now(),c=()=>{let u=qe(Math.min((performance.now()-l)/a,1));e.position.lerpVectors(i,t,u),n.target.lerpVectors(s,r,u),o(),n.update(),u<1&&requestAnimationFrame(c)};requestAnimationFrame(c)}import*as B from"three";var Je=`
2
- varying vec3 vWorldPos;
3
- void main() {
4
- vec4 world = modelMatrix * vec4(position, 1.0);
5
- vWorldPos = world.xyz;
6
- gl_Position = projectionMatrix * viewMatrix * world;
7
- }
8
- `,Ke=`
9
- precision highp float;
10
- varying vec3 vWorldPos;
11
-
12
- uniform vec2 uAxes; // indices (0=x,1=y,2=z) of the two in-plane world axes
13
- uniform float uCell;
14
- uniform float uMajor;
15
- uniform vec3 uCellColor;
16
- uniform vec3 uMajorColor;
17
- uniform vec3 uCenter; // fade center (camera position), projected onto plane
18
- uniform float uFade;
19
-
20
- // Antialiased grid line intensity for a given spacing, using screen-space derivatives so lines
21
- // stay ~1px regardless of zoom (the standard "pristine grid" technique).
22
- float gridLine(vec2 coord, float spacing) {
23
- vec2 c = coord / spacing;
24
- vec2 d = fwidth(c);
25
- vec2 g = abs(fract(c - 0.5) - 0.5) / max(d, 1e-6);
26
- float line = min(g.x, g.y);
27
- return 1.0 - clamp(line, 0.0, 1.0);
28
- }
29
-
30
- // Index a vec3 by a float axis id (0/1/2) without dynamic indexing (WebGL1-safe).
31
- float axis(vec3 v, float i) {
32
- return i < 0.5 ? v.x : (i < 1.5 ? v.y : v.z);
33
- }
34
-
35
- void main() {
36
- // Pick the two in-plane world coordinates.
37
- vec2 coord = vec2(axis(vWorldPos, uAxes.x), axis(vWorldPos, uAxes.y));
38
-
39
- float minor = gridLine(coord, uCell);
40
- float major = gridLine(coord, uCell * uMajor);
41
-
42
- vec3 color = mix(uCellColor, uMajorColor, major);
43
- float alpha = max(minor, major);
44
-
45
- // Radial fade from the camera-projected center.
46
- float dist = distance(vWorldPos, uCenter);
47
- float fade = 1.0 - clamp(dist / uFade, 0.0, 1.0);
48
- alpha *= fade * fade;
49
-
50
- if (alpha < 0.001) discard;
51
- gl_FragColor = vec4(color, alpha);
52
- }
53
- `;function ge(e={}){let{cellSize:n=1,majorEvery:t=10,cellColor:r=8947848,majorColor:o=4473924,fadeDistance:a=100,plane:i="y"}=e,s=i==="y"?new B.Vector2(0,2):i==="z"?new B.Vector2(0,1):new B.Vector2(1,2),l=a*2.5,c=new B.PlaneGeometry(l,l);i==="y"?c.rotateX(-Math.PI/2):i==="x"&&c.rotateY(Math.PI/2);let u=new B.ShaderMaterial({vertexShader:Je,fragmentShader:Ke,transparent:!0,depthWrite:!1,side:B.DoubleSide,uniforms:{uAxes:{value:s},uCell:{value:n},uMajor:{value:t},uCellColor:{value:new B.Color(r)},uMajorColor:{value:new B.Color(o)},uCenter:{value:new B.Vector3},uFade:{value:a}}}),d=new B.Mesh(c,u);d.name="grid",d.userData.id="grid",d.renderOrder=-1;let m=new B.Vector3;return{object:d,update:f=>{i==="y"?(d.position.set(f.x,0,f.z),m.set(f.x,0,f.z)):i==="z"?(d.position.set(f.x,f.y,0),m.set(f.x,f.y,0)):(d.position.set(0,f.y,f.z),m.set(0,f.y,f.z)),u.uniforms.uCenter.value.copy(m)},setVisible:f=>{d.visible=f},dispose:()=>{c.dispose(),u.dispose()}}}import*as G from"three";import{ViewHelper as Qe}from"three/addons/helpers/ViewHelper.js";function ye(e){let{camera:n,domElement:t,controller:r}=e,o=new Qe(n,t);o.setLabels("X","Y","Z");let a=!0,i=128,s=new G.Raycaster,l=new G.OrthographicCamera(-2,2,2,-2,0,4);l.position.set(0,0,2);let c={posX:new G.Vector3(1,0,0),negX:new G.Vector3(-1,0,0),posY:new G.Vector3(0,1,0),negY:new G.Vector3(0,-1,0),posZ:new G.Vector3(0,0,1),negZ:new G.Vector3(0,0,-1)},u=m=>{let f=t.getBoundingClientRect(),b=f.left+t.offsetWidth-i-o.location.right,H=f.top+t.offsetHeight-i-o.location.bottom,h=new G.Vector2((m.clientX-b)/i*2-1,-((m.clientY-H)/i)*2+1);if(Math.abs(h.x)>1||Math.abs(h.y)>1)return null;o.quaternion.copy(n.quaternion).invert(),o.updateMatrixWorld(),s.setFromCamera(h,l);let g=s.intersectObjects(o.children,!1);for(let p of g){let T=p.object.userData?.type;if(typeof T=="string"&&T in c)return T}return null};return{render:m=>{if(!a)return;let f=m.autoClear;m.autoClear=!1,o.render(m),m.autoClear=f},update:m=>{o.animating&&o.update(m)},handleClick:m=>{if(!a)return!1;let f=u(m);return f?(r.getProjection()==="orthographic"&&r.setProjection("perspective"),r.setViewDirection(c[f],!1),!0):!1},get isAnimating(){return o.animating},setVisible:m=>{a=m},isVisible:()=>a,dispose:()=>o.dispose()}}import*as J from"three";import{LineSegmentsGeometry as et}from"three/addons/lines/LineSegmentsGeometry.js";import{LineSegments2 as be}from"three/addons/lines/LineSegments2.js";import{LineMaterial as tt}from"three/addons/lines/LineMaterial.js";var te="edge-overlay",rt=2236962,nt=1.5,ot=30;function Te(e,n={}){let t=new J.Color(n.color??rt),r=n.width??nt,o=n.thresholdAngle??ot,a=[];return e.traverse(i=>{if(!(i instanceof J.Mesh)||i.userData.id==="floor"||i.userData.id==="grid"||i.userData.kind===te||i.children.some(l=>l.userData?.kind===te)||!i.geometry)return;let s=at(i.geometry,t,r,o);i.add(s),a.push(s)}),a}function at(e,n,t,r){let o=new J.EdgesGeometry(e,r),a=new et;a.setPositions(Array.from(o.attributes.position.array)),o.dispose();let i=new tt({color:n});i.linewidth=t,i.polygonOffset=!0,i.polygonOffsetFactor=-1,i.polygonOffsetUnits=-1;let s=new be(a,i);return s.userData.kind=te,s.raycast=()=>{},s}function it(e){return e.userData?.kind===te}function on(e){let n=[];e.traverse(t=>{t instanceof be&&it(t)&&n.push(t)});for(let t of n)t.geometry.dispose(),t.material.dispose(),t.removeFromParent();return n.length}import{EffectComposer as st}from"three/addons/postprocessing/EffectComposer.js";import{RenderPass as lt}from"three/addons/postprocessing/RenderPass.js";import{GTAOPass as ct}from"three/addons/postprocessing/GTAOPass.js";import{OutputPass as ut}from"three/addons/postprocessing/OutputPass.js";function Re(e,n,t,r,o,a){let i=new st(e),s=new lt(n,t);i.addPass(s);let l=new ct(n,t,r,o);l.blendIntensity=a.aoIntensity??1,l.updateGtaoMaterial({screenSpaceRadius:!0}),i.addPass(l);let c=new ut;return i.addPass(c),e.toneMapping=a.toneMapping,e.toneMappingExposure=a.toneMappingExposure,i.setSize(r,o),{render:u=>i.render(u),setSize:(u,d,m)=>{i.setPixelRatio(m),i.setSize(u,d),l.setSize(u,d)},setCamera:u=>{s.camera=u,l.camera=u},dispose:()=>{i.dispose(),l.dispose(),c.dispose()}}}import*as we from"three";import{CSS2DRenderer as dt,CSS2DObject as mt}from"three/addons/renderers/CSS2DRenderer.js";function He(e,n){let t=new dt,r=t.domElement;r.style.position="absolute",r.style.top="0",r.style.left="0",r.style.width="100%",r.style.height="100%",r.style.overflow="hidden",r.style.pointerEvents="none",r.style.zIndex="30",getComputedStyle(e).position==="static"&&(e.style.position="relative"),e.appendChild(r);let o={width:e.clientWidth||1,height:e.clientHeight||1};t.setSize(o.width,o.height);let a=new we.Group;a.name="label-layer",a.userData.id="label-layer",n.add(a);let i=new Set;return{addLabel:(l,c,u)=>{let d=document.createElement("div");d.textContent=l,u?d.className=u:Object.assign(d.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"}),d.style.pointerEvents="none";let m=new mt(d);return m.position.copy(c),a.add(m),i.add(m),{object:m,setPosition:f=>m.position.copy(f),setText:f=>{d.textContent=f},remove:()=>{m.removeFromParent(),d.remove(),i.delete(m)}}},render:(l,c)=>t.render(l,c),setSize:(l,c)=>t.setSize(l,c),dispose:()=>{i.forEach(l=>{l.removeFromParent(),l.element.remove()}),i.clear(),a.removeFromParent(),r.remove()}}}import*as S from"three";import{Line2 as ft}from"three/addons/lines/Line2.js";import{LineGeometry as pt}from"three/addons/lines/LineGeometry.js";import{LineMaterial as Et}from"three/addons/lines/LineMaterial.js";var ht=12,gt=16763904,yt=.015,ve={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 bt(e){let n=e&&ve[e]||ve.Meters;return t=>`${(t/n.metersPerUnit).toPrecision(3)} ${n.suffix}`}function Tt(e){let n=e.object;return n instanceof S.Mesh?e.face?[e.face.a,e.face.b,e.face.c]:null:n instanceof S.Points?e.index!=null?[e.index]:null:n instanceof S.Line&&e.index!=null?[e.index,e.index+1]:null}function Rt(e,n,t,r){let o=e.point.clone(),a=e.object,i=Tt(e);if(!i||!a.geometry)return o;let s=a.geometry.attributes.position;if(!s)return o;let l=m=>{let f=m.clone().project(n);return new S.Vector2((f.x+1)/2*t.width,(1-f.y)/2*t.height)},c=l(o),u=o,d=r;for(let m of i){if(m>=s.count)continue;let b=new S.Vector3().fromBufferAttribute(s,m).applyMatrix4(a.matrixWorld),H=l(b).distanceTo(c);H<d&&(d=H,u=b)}return u}function xe(e){let{canvas:n,scene:t,getActiveCamera:r,labelLayer:o,options:a={}}=e,i=a.snapPixels??ht,s=new S.Color(a.color??gt),l=bt(a.displayUnit),c=(y,x)=>`${l(y)}
54
- \u0394x ${l(x.x)} \u0394y ${l(x.y)} \u0394z ${l(x.z)}`,u=a.format??c,d=new S.Raycaster,m=new S.Vector2,f=!1,b=[],H=[],h=null,g=null,p=new S.PointsMaterial({color:s,size:8,sizeAttenuation:!1,depthTest:!1}),T=new S.PointsMaterial({color:s,size:11,sizeAttenuation:!1,depthTest:!1,transparent:!0,opacity:.5}),v=null,O=y=>{if(!y){v&&(v.visible=!1);return}if(!v){let x=new S.BufferGeometry;x.setAttribute("position",new S.Float32BufferAttribute([0,0,0],3)),v=new S.Points(x,T),v.renderOrder=1e3,v.userData.id="measure",v.raycast=()=>{},t.add(v)}v.position.copy(y),v.visible=!0},w=y=>{let x=new S.BufferGeometry;x.setAttribute("position",new S.Float32BufferAttribute([y.x,y.y,y.z],3));let I=new S.Points(x,p);return I.renderOrder=999,I.userData.id="measure",I.raycast=()=>{},t.add(I),I},R=()=>{b.length=0,H.forEach(y=>{y.geometry.dispose(),y.removeFromParent()}),H.length=0,h&&(h.geometry.dispose(),h.material.dispose(),h.removeFromParent(),h=null),g?.remove(),g=null},A=()=>{if(b.length!==2)return;let[y,x]=b,I=new pt;I.setPositions([y.x,y.y,y.z,x.x,x.y,x.z]);let z=new Et({color:s});z.linewidth=2,z.depthTest=!1,h=new ft(I,z),h.renderOrder=998,h.userData.id="measure",h.raycast=()=>{},t.add(h);let q=y.clone().add(x).multiplyScalar(.5),X=new S.Vector3(Math.abs(x.x-y.x),Math.abs(x.y-y.y),Math.abs(x.z-y.z));g=o.addLabel(u(y.distanceTo(x),X),q,a.labelClassName)},P=y=>{let x=n.getBoundingClientRect();m.x=(y.clientX-x.left)/x.width*2-1,m.y=-((y.clientY-x.top)/x.height)*2+1;let I=r();d.setFromCamera(m,I);let q=I.position.length()*yt;d.params.Line.threshold=q,d.params.Points.threshold=q;let X=d.intersectObjects(t.children,!0).filter(Z=>Z.object.userData.id!=="measure"&&Z.object.userData.id!=="grid");return X.length===0?null:Rt(X[0],I,{width:x.width,height:x.height},i)};return{setEnabled:y=>{f=y,y||(R(),O(null))},isEnabled:()=>f,handleClick:y=>{if(!f)return!1;b.length===2&&R();let x=P(y);return x===null||(b.push(x),H.push(w(x)),b.length===2&&A()),!0},handleMove:y=>{f&&O(P(y))},clear:R,dispose:()=>{R(),v&&(v.geometry.dispose(),v.removeFromParent(),v=null),p.dispose(),T.dispose()}}}import*as E from"three";import{OrbitControls as wt}from"three/addons/controls/OrbitControls.js";import{HDRLoader as Ht}from"three/addons/loaders/HDRLoader.js";var re=new E.Vector3(0,0,1);function vt(e){let n=Math.abs(e.x),t=Math.abs(e.y),r=Math.abs(e.z);return r>=n&&r>=t?"z":t>=n&&t>=r?"y":"x"}var An=function(e,n){let t=xt(n||{}),r=t.environment?.sceneUp||re,o=St(t),a=Vt(t,e);a.up.copy(r);let i=Bt(e,t),s=Ut(a,e,t),l=he({scene:o,perspective:a,controls:s,onActiveCameraChange:()=>{},up:r}),c=()=>l.getActiveCamera();Pt(o,t);let u=Ot(o,t),d=()=>{u&&At(u,le(o))};t.floor?.enabled&&It(o,t);let m=t.grid.enabled?ge({cellSize:t.grid.cellSize,majorEvery:t.grid.majorEvery,cellColor:t.grid.cellColor,majorColor:t.grid.majorColor,fadeDistance:t.grid.fadeDistance,plane:t.grid.plane}):null;m&&o.add(m.object);let f=t.gizmo.enabled?ye({camera:a,domElement:e,controller:l}):null,b=e.parentElement??e,H=t.measure.enabled?He(b,o):null,h=t.measure.enabled&&H?xe({canvas:e,scene:o,getActiveCamera:c,labelLayer:H,options:{snapPixels:t.measure.snapPixels,color:t.measure.color,labelClassName:t.measure.labelClassName,displayUnit:t.measure.displayUnit,format:t.measure.format}}):null,g=t.events.enableEventHandlers!==!1?Ft(e,o,c,a,s,t):{dispose:()=>{},fitToView:()=>{},clearSelection:()=>{}},p=5,T=0,v=0,O=C=>{T=C.clientX,v=C.clientY},w=C=>Math.hypot(C.clientX-T,C.clientY-v)>p,R=C=>{if(!w(C)){if(h?.handleClick(C)){C.stopImmediatePropagation();return}f?.handleClick(C)&&C.stopImmediatePropagation()}};(f||h)&&(e.addEventListener("mousedown",O,{capture:!0}),e.addEventListener("click",R,{capture:!0}));let A=C=>h?.handleMove(C);h&&e.addEventListener("mousemove",A,{passive:!0});let P=C=>{Te(C,{color:t.edges.color,width:t.edges.width,thresholdAngle:t.edges.thresholdAngle})},D=e.parentElement,F=()=>D?{width:D.clientWidth,height:D.clientHeight}:{width:window.innerWidth,height:window.innerHeight},y=null,x=()=>{let{width:C,height:U}=F(),W=Math.min(window.devicePixelRatio,2),ee=Re(i,o,c(),Math.max(1,C),Math.max(1,U),{toneMapping:t.render.toneMapping??E.NeutralToneMapping,toneMappingExposure:t.render.toneMappingExposure??1,aoIntensity:t.render.aoIntensity});return ee.setSize(Math.max(1,C),Math.max(1,U),W),ee},I=C=>{C&&!y?y=x():!C&&y&&(y.dispose(),y=null)};t.render.ambientOcclusion&&(y=x());let{animate:z,dispose:q}=Lt(i,o,a,c,l,s,F,t.events.onFrame,m,f,()=>y,H);z(),o.up.set(r.x,r.y,r.z),d();let X=C=>{C.traverse(U=>{let W=U;!W.geometry&&!W.material||(W.geometry?.dispose(),Array.isArray(W.material)?W.material.forEach(ee=>ee.dispose()):W.material?.dispose())})},Z=C=>{C.userData.source="user",o.add(C)},ze=C=>{C.removeFromParent(),X(C)},_e=()=>{o.children.filter(U=>U.userData.source==="user").forEach(U=>{U.removeFromParent(),X(U)})};return{scene:o,camera:a,controls:s,renderer:i,cameraController:l,grid:m,gizmo:f,measureTool:h,applyEdges:P,setAmbientOcclusion:I,updateShadowBounds:d,dispose:()=>{q(),g.dispose(),(f||h)&&(e.removeEventListener("mousedown",O,{capture:!0}),e.removeEventListener("click",R,{capture:!0})),h&&e.removeEventListener("mousemove",A),h?.dispose(),H?.dispose(),f?.dispose(),m?.dispose(),y?.dispose(),s.dispose(),i.dispose(),o.traverse(C=>{let U=C;!U.geometry&&!U.material||(U.geometry?.dispose(),Array.isArray(U.material)?U.material.forEach(W=>W.dispose()):U.material?.dispose())}),o.environment?.dispose(),o.background instanceof E.Texture&&o.background.dispose()},fitToView:g.fitToView,clearSelection:g.clearSelection,addUserGeometry:Z,removeUserGeometry:ze,clearUserGeometry:_e}};function xt(e){let n=e.sceneScale||"m",r={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}}[n];return{sceneScale:n,camera:{position:e.camera?.position||new E.Vector3(-r.cameraDistance,-r.cameraDistance,r.cameraDistance),fov:e.camera?.fov||20,near:e.camera?.near||r.near,far:e.camera?.far||r.far,target:e.camera?.target||new E.Vector3(0,0,0)},lighting:{enableSunlight:e.lighting?.enableSunlight??!0,sunlightIntensity:e.lighting?.sunlightIntensity??1,sunlightPosition:e.lighting?.sunlightPosition||new E.Vector3(r.lightDistance,r.lightDistance,r.lightHeight),ambientLightColor:e.lighting?.ambientLightColor||new E.Color(4210752),ambientLightIntensity:e.lighting?.ambientLightIntensity??1,sunlightColor:e.lighting?.sunlightColor||16777215},environment:{hdrPath:e.environment?.hdrPath||"/baseHDR.hdr",backgroundColor:e.environment?.backgroundColor||new E.Color(15790320),enableEnvironmentLighting:e.environment?.enableEnvironmentLighting??!0,sceneUp:e.environment?.sceneUp||re,showEnvironment:e.environment?.showEnvironment??!1},floor:{enabled:e.floor?.enabled??!1,size:e.floor?.size||r.floorSize,color:e.floor?.color||new E.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||E.NeutralToneMapping,toneMappingExposure:e.render?.toneMappingExposure??1,preserveDrawingBuffer:e.render?.preserveDrawingBuffer??!1,ambientOcclusion:e.render?.ambientOcclusion??!1,aoIntensity:e.render?.aoIntensity??1},controls:{enableDamping:e.controls?.enableDamping??!1,dampingFactor:e.controls?.dampingFactor||.05,autoRotate:e.controls?.autoRotate??!1,autoRotateSpeed:e.controls?.autoRotateSpeed||.5,enableZoom:e.controls?.enableZoom??!0,enablePan:e.controls?.enablePan??!0,minDistance:e.controls?.minDistance||r.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??vt(e.environment?.sceneUp??re)},gizmo:{enabled:e.gizmo?.enabled??!1},edges:{enabled:e.edges?.enabled??!1,color:e.edges?.color??2236962,width:e.edges?.width??1.5,thresholdAngle:e.edges?.thresholdAngle??30},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}}}var Mt=new Set(["grid","floor","label-layer","measure"]);function Ct(e){let n=e;for(;n;){if(typeof n.userData.id=="string"&&Mt.has(n.userData.id))return!0;n=n.parent}return!1}function le(e){let n=new E.Box3;return e.traverse(t=>{let r=t;t.visible&&!Ct(t)&&r.geometry&&n.expandByObject(t)}),n}function At(e,n){if(n.isEmpty())return;let t=n.getCenter(new E.Vector3),r=n.getSize(new E.Vector3).length()*.5*1.2,o=e.shadow.camera;o.left=-r,o.right=r,o.top=r,o.bottom=-r,e.target.position.copy(t),e.target.updateMatrixWorld();let a=e.position.distanceTo(t);o.near=Math.max(r*.01,a-r),o.far=a+r,o.updateProjectionMatrix()}function St(e){let n=new E.Scene,t=typeof e.environment.backgroundColor=="string"?new E.Color(e.environment.backgroundColor):e.environment.backgroundColor;return n.background=t||null,n}function Dt(e,n,t,r,o=200){let a=e.position.clone(),i=n.target.clone(),s=performance.now(),l=u=>1-Math.pow(1-u,3),c=()=>{let u=performance.now()-s,d=l(Math.min(u/o,1));e.position.lerpVectors(a,t,d),n.target.lerpVectors(i,r,d),n.update(),d<1&&requestAnimationFrame(c)};requestAnimationFrame(c)}function Lt(e,n,t,r,o,a,i,s,l,c,u,d){let m=null,f=performance.now(),b=()=>{let{width:g,height:p}=i();if(g===0||p===0)return;let T=Math.min(window.devicePixelRatio,2),v=Math.round(g*T),O=Math.round(p*T);(e.domElement.width!==v||e.domElement.height!==O)&&(e.setPixelRatio(T),e.setSize(g,p,!1),t.aspect=g/p,t.updateProjectionMatrix(),o.updateAspect(g,p),u?.()?.setSize(g,p,T),d?.setSize(g,p))},H=function(){m=requestAnimationFrame(H);let g=performance.now(),p=(g-f)/1e3;f=g,b(),(a.enableDamping||a.autoRotate)&&a.update(),l&&l.update(r().position),c&&c.update(p),s?.(p);let T=r(),v=u?.();v?(v.setCamera(T),v.render(p)):e.render(n,T),d&&d.render(n,T),c&&c.render(e)};return{animate:H,dispose:()=>{m!==null&&(cancelAnimationFrame(m),m=null)}}}function Pt(e,n){n.environment.enableEnvironmentLighting?new Ht().load(n.environment.hdrPath||"/baseHDR.hdr",function(t){if(!t?.image){M().warn("HDR loaded without image data; skipping environment map."),n.events.onReady?.();return}t.mapping=E.EquirectangularReflectionMapping,e.environment=t,n.environment.showEnvironment&&(e.background=t),n.events.onReady?.()},void 0,function(t){M().warn("HDR texture could not be loaded, falling back to basic lighting:",t),n.events.onReady?.()}):n.events.onReady?.()}function Ot(e,n){let t=new E.AmbientLight(n.lighting.ambientLightColor,n.lighting.ambientLightIntensity);if(e.add(t),!n.lighting.enableSunlight)return null;let r=new E.DirectionalLight(n.lighting.sunlightColor??16777215,n.lighting.sunlightIntensity),o=n.lighting.sunlightPosition;return o&&r.position.set(o.x,o.y,o.z),n.render.enableShadows?(r.castShadow=!0,r.shadow.mapSize.width=n.render.shadowMapSize||2048,r.shadow.mapSize.height=n.render.shadowMapSize||2048,r.shadow.bias=-1e-4,r.shadow.normalBias=.02,r.shadow.radius=4,e.add(r),e.add(r.target),r):(e.add(r),null)}function It(e,n){let t=n.floor.size,r=new E.PlaneGeometry(t,t),o=typeof n.floor.color=="string"?new E.Color(n.floor.color):n.floor.color,a=new E.MeshStandardMaterial({color:o,roughness:n.floor.roughness,metalness:n.floor.metalness,side:E.DoubleSide}),i=new E.Mesh(r,a);i.userData.id="floor",i.name="floor";let s=(n.environment?.sceneUp||re).clone().normalize();i.quaternion.setFromUnitVectors(new E.Vector3(0,0,1),s),i.position.set(0,0,0),n.floor.receiveShadow&&n.render.enableShadows&&(i.receiveShadow=!0),e.add(i)}function Vt(e,n){let t=n.parentElement,r=t?t.clientWidth:window.innerWidth,o=t?t.clientHeight:window.innerHeight,a=new E.PerspectiveCamera(e.camera.fov,r/o,e.camera.near,e.camera.far),i=e.camera.position;return i&&a.position.set(i.x,i.y,i.z),a}function Bt(e,n){let t=new E.WebGLRenderer({antialias:n.render.antialias,canvas:e,alpha:!0,powerPreference:"high-performance",preserveDrawingBuffer:n.render.preserveDrawingBuffer,logarithmicDepthBuffer:!0}),r=e.parentElement,o=r?r.clientWidth:window.innerWidth,a=r?r.clientHeight:window.innerHeight;return r&&(e.style.width="100%",e.style.height="100%",e.style.display="block"),t.setSize(o,a,!1),t.setPixelRatio(n.render.pixelRatio||Math.min(window.devicePixelRatio,2)),n.render.enableShadows&&(t.shadowMap.enabled=!0,t.shadowMap.type=E.VSMShadowMap),t.toneMapping=n.render.toneMapping,t.toneMappingExposure=n.render.toneMappingExposure??1,t.outputColorSpace=E.SRGBColorSpace,t.sortObjects=!0,t}function Ft(e,n,t,r,o,a){let i=new Set,s=new Map,l=new E.Raycaster,c=new E.Vector2,u=new E.Vector2,d=w=>{let R=w;for(;R;){if(!R.visible)return!1;R=R.parent}return!0},m=()=>{let w=le(n);if(w.isEmpty()){M().warn("No objects to fit to view");return}let R=w.getCenter(new E.Vector3),A=w.getSize(new E.Vector3),P=Math.max(A.x,A.y,A.z),D=r.fov*(Math.PI/180),F=P/(2*Math.tan(D/2));F*=1.5;let y=r.position.clone().sub(o.target);y.lengthSq()<1e-12&&y.set(.8,1,1.2),y.normalize(),r.position.copy(R.clone().add(y.multiplyScalar(F))),o.target.copy(R),o.update()},f=typeof a.events.selectionColor=="string"?new E.Color(a.events.selectionColor):a.events.selectionColor instanceof E.Color?a.events.selectionColor:new E.Color("#ff0000"),b=()=>{i.forEach(w=>{let R=w;if(s.has(w)){let A=s.get(w),P=R.material;P instanceof E.Material?P.dispose():Array.isArray(P)&&P.forEach(D=>D.dispose()),R.material=A,s.delete(w)}}),i.clear()},H=w=>{let R=w;if(!(R.material instanceof E.Material))return!1;s.set(w,R.material);let A=R.material.clone();return w instanceof E.Mesh&&"emissive"in A?A.emissive=f.clone():"color"in A&&(A.color=f.clone()),R.material=A,!0},h=()=>{let w=le(n),R=w.isEmpty()?1:w.getSize(new E.Vector3).length();l.params.Points.threshold=R*.01},g=w=>{u.set(w.clientX,w.clientY)},p=w=>{let R=new E.Vector2(w.clientX,w.clientY);if(u.distanceTo(R)>5)return;let A=e.getBoundingClientRect();c.x=(w.clientX-A.left)/A.width*2-1,c.y=-((w.clientY-A.top)/A.height)*2+1,h(),l.setFromCamera(c,t());let P=l.intersectObjects(n.children,!0).filter(D=>d(D.object));if(P.length>0){let D=P[0].object;i.has(D)||(b(),i.add(D),H(D),a.events?.onObjectSelected?.(D),D instanceof E.Mesh&&Object.keys(D.userData).length>0&&a.events?.onMeshMetadataClicked?.(D.userData))}else b(),a.events?.onBackgroundClicked?.({x:c.x,y:c.y})},T=w=>{let R=e.getBoundingClientRect();c.x=(w.clientX-R.left)/R.width*2-1,c.y=-((w.clientY-R.top)/R.height)*2+1,h(),l.setFromCamera(c,t());let A=l.intersectObjects(n.children,!0).filter(Z=>d(Z.object));if(A.length===0)return;let P=A[0].object;if(a.events?.onMeshDoubleClicked?.(P),!a.events?.enableDoubleClickZoom)return;let D=new E.Box3().setFromObject(P);if(D.isEmpty())return;let F=D.getCenter(new E.Vector3),y=D.getSize(new E.Vector3),x=Math.max(y.x,y.y,y.z),I=r.fov*(Math.PI/180),z=x/(2*Math.tan(I/2))*1.5,q=r.position.clone().sub(o.target).normalize(),X=F.clone().add(q.multiplyScalar(z));Dt(r,o,X,F)},v=w=>{if(a.events?.enableKeyboardControls)switch(w.key.toLowerCase()){case"f":w.preventDefault(),m();break;case"escape":w.preventDefault(),b();break;case" ":w.preventDefault(),m();break}};return a.events?.enableClickToFocus&&(e.addEventListener("mousedown",g),e.addEventListener("click",p),e.addEventListener("dblclick",T)),a.events?.enableKeyboardControls&&(e.setAttribute("tabindex","0"),e.addEventListener("keydown",v)),{dispose:()=>{e.removeEventListener("mousedown",g),e.removeEventListener("click",p),e.removeEventListener("dblclick",T),e.removeEventListener("keydown",v),b()},fitToView:m,clearSelection:b}}function Ut(e,n,t){let r=new wt(e,n),o=t.camera.target;return o&&r.target.set(o.x,o.y,o.z),r.enableDamping=t.controls.enableDamping||!1,r.dampingFactor=t.controls.dampingFactor||.05,r.autoRotate=t.controls.autoRotate||!1,r.autoRotateSpeed=t.controls.autoRotateSpeed||.5,r.enableZoom=t.controls.enableZoom??!0,r.enablePan=t.controls.enablePan??!0,r.minDistance=t.controls.minDistance||.001,r.maxDistance=t.controls.maxDistance||1/0,r.screenSpacePanning=!1,r.maxPolarAngle=Math.PI,r.update(),r}var $t={};ke($t,{CONCRETE_MATERIAL:()=>kt,EMISSIVE_MATERIAL:()=>zt,GLASS_MATERIAL:()=>Gt,METAL_MATERIAL:()=>_t,PLASTIC_MATERIAL:()=>jt,RUBBER_MATERIAL:()=>Nt,WOOD_MATERIAL:()=>Wt});import*as L from"three";var zt=new L.MeshPhysicalMaterial({color:0,emissive:new L.Color(16777215),emissiveIntensity:5,metalness:0,roughness:.2,clearcoat:.3,clearcoatRoughness:.2,depthWrite:!0,depthTest:!0,transparent:!1,alphaTest:0,polygonOffset:!0,side:L.FrontSide,dithering:!0}),_t=new L.MeshPhysicalMaterial({color:new L.Color(0),metalness:.9,roughness:.3,envMapIntensity:1.2,clearcoat:.3,clearcoatRoughness:.2,reflectivity:1,ior:2.5,thickness:1,depthWrite:!0,transparent:!1,alphaTest:0,depthTest:!0,polygonOffset:!0,side:L.FrontSide,dithering:!0}),kt=new L.MeshPhysicalMaterial({color:new L.Color(13421772),metalness:0,roughness:.92,envMapIntensity:.15,clearcoat:.05,clearcoatRoughness:.9,reflectivity:.15,transmission:0,ior:1.45,thickness:0,depthWrite:!0,transparent:!1,alphaTest:.5,depthTest:!0,polygonOffset:!0,side:L.FrontSide,dithering:!0}),jt=new L.MeshPhysicalMaterial({color:new L.Color(16777215),metalness:0,roughness:.3,envMapIntensity:.5,clearcoat:.5,clearcoatRoughness:.1,reflectivity:.5,ior:1.4,transmission:0,transparent:!1,depthWrite:!0,side:L.FrontSide,dithering:!0,polygonOffset:!0,polygonOffsetFactor:1,polygonOffsetUnits:1}),Gt=new L.MeshPhysicalMaterial({color:new L.Color(16777215),metalness:0,roughness:0,transmission:.95,transparent:!0,opacity:.3,envMapIntensity:1,clearcoat:1,clearcoatRoughness:0,ior:1.52,reflectivity:.9,thickness:1,side:L.DoubleSide,polygonOffset:!0,polygonOffsetFactor:1,polygonOffsetUnits:1}),Nt=new L.MeshPhysicalMaterial({color:new L.Color(1710618),metalness:0,roughness:.9,envMapIntensity:.2,clearcoat:.1,clearcoatRoughness:.8,reflectivity:.2,ior:1.3,transmission:0,depthWrite:!0,side:L.FrontSide,polygonOffset:!0,polygonOffsetFactor:1,polygonOffsetUnits:1}),Wt=new L.MeshPhysicalMaterial({color:new L.Color(8934707),metalness:0,roughness:.7,envMapIntensity:.3,clearcoat:.3,clearcoatRoughness:.4,reflectivity:.3,ior:1.3,transmission:0,depthWrite:!0,side:L.FrontSide,dithering:!0,polygonOffset:!0,polygonOffsetFactor:1,polygonOffsetUnits:1});import*as N from"three";import{Line2 as Yt}from"three/addons/lines/Line2.js";import{LineGeometry as Xt}from"three/addons/lines/LineGeometry.js";import{LineMaterial as qt}from"three/addons/lines/LineMaterial.js";function ne(e,n,t,r=!0){return{x:e,y:n,z:t}}var Zt="#ffffff",Me=12,Jt=4e-4,Kt=12,Qt=.05;function Ce(e,n={}){if(!e||e.length===0)return[];let{rhino:t,applyTransforms:r=!0}=n,o=[];for(let a of e)switch(a.kind){case"curve":{let i=tr(a,t,r);i&&o.push(i);break}case"point":{o.push(rr(a,r));break}default:{let i=a;M().warn(`Skipping unknown display item kind: ${String(i.kind)}`);break}}return o}var er=2;function tr(e,n,t){if(!n)return M().warn("No rhino3dm instance provided; skipping curve display item."),null;let r=nr(e.json,n);if(!r)return null;let o=or(r,t);if(o.length<2)return null;let a=[];for(let d of o)a.push(d.x,d.y,d.z);let i=new Xt;i.setPositions(a);let s=Ae(e.color,e.opacity),l=new qt({color:s.color}),c=l;c.linewidth=e.width??er,c.transparent=s.transparent,c.opacity=s.opacity;let u=new Yt(i,l);return u.computeLineDistances(),u.name=e.name,u.userData={source:"compute",id:e.id,layer:e.layer,kind:"curve",metadata:e.metadata},u}function rr(e,n){let{x:t,y:r,z:o}=ne(e.position.X,e.position.Y,e.position.Z,n),a=new N.BufferGeometry;a.setAttribute("position",new N.Float32BufferAttribute([t,r,o],3));let i=new N.PointsMaterial({...Ae(e.color,e.opacity),size:6,sizeAttenuation:!1}),s=new N.Points(a,i);return s.name=e.name,s.userData={source:"compute",id:e.id,layer:e.layer,kind:"point",metadata:e.metadata},s}function nr(e,n){try{let t=JSON.parse(e),r=n.CommonObject.decode(t);return r&&typeof r.pointAt=="function"?r:(M().warn("Decoded display-item JSON is not a curve; skipping."),null)}catch(t){return M().warn("Failed to decode curve display item JSON:",t),null}}function or(e,n){let t=ar(e,n);return t||ir(e,n)}function ar(e,n){if(!e.isPolyline())return null;let t=e.tryGetPolyline(),r=Array.isArray(t)?t[1]:t;if(!r||typeof r.count!="number"||r.count<2)return null;let o=[];for(let a=0;a<r.count;a++){let i=r.get(a),{x:s,y:l,z:c}=ne(i[0],i[1],i[2],n);o.push(new N.Vector3(s,l,c))}return o}function ir(e,n){let t=e.domain,r=t[0],a=t[1]-r,i=d=>{let m=e.pointAt(d),{x:f,y:b,z:H}=ne(m[0],m[1],m[2],n);return new N.Vector3(f,b,H)},s=sr(e),l=r,c=i(r),u=[c];for(let d=0;d<Me;d++){let m=r+a*(d+1)/Me,f=i(m);ce(l,c,m,f,i,s,Kt,u),u.push(f),l=m,c=f}return u}function ce(e,n,t,r,o,a,i,s){if(i<=0)return;let l=(e+t)/2,c=o(l),u=cr(c,n,r),d=lr(n,c,r);u<=a&&d<=Qt||(ce(e,n,l,c,o,a,i-1,s),s.push(c),ce(l,c,t,r,o,a,i-1,s))}function sr(e){let n=e.getBoundingBox(),t=n.min,r=n.max,o=Math.hypot(r[0]-t[0],r[1]-t[1],r[2]-t[2]);return Math.max(o*Jt,1e-6)}function lr(e,n,t){let r=n.clone().sub(e),o=t.clone().sub(n),a=r.length(),i=o.length();if(a===0||i===0)return 0;let s=Math.max(-1,Math.min(1,r.dot(o)/(a*i)));return Math.acos(s)}function cr(e,n,t){let r=t.clone().sub(n),o=r.lengthSq();if(o===0)return e.distanceTo(n);let a=Math.max(0,Math.min(1,e.clone().sub(n).dot(r)/o)),i=n.clone().addScaledVector(r,a);return e.distanceTo(i)}function Ae(e,n){let t=n??1;return{color:new N.Color(e??Zt),transparent:t<1,opacity:t}}import{inflateSync as ur}from"fflate";var Se=1096174675,dr=1515605075,De=3,Le=1,de=1,mr=2,fr=4,pr=8,Er=16;var hr=1,Pe=12,Oe=56;function me(e){let n=Tr(br(e)),t=new DataView(n.buffer,n.byteOffset,n.byteLength);if(n.byteLength<Pe)throw j("Blob too small to contain SLVA header.",{expectedBytes:Pe,availableBytes:n.byteLength});let r=0,o=t.getUint32(r,!0);if(r+=4,o!==Se)throw j(`Invalid SLVA magic: 0x${o.toString(16)}`,{expectedMagic:`0x${Se.toString(16)}`,actualMagic:`0x${o.toString(16)}`});let a=t.getUint32(r,!0);if(r+=4,a<Le||a>De)throw j(`Unsupported SLVA version: ${a}`,{minSupportedVersion:Le,maxSupportedVersion:De,actualVersion:a});let i=t.getUint32(r,!0);if(r+=4,r+i>n.byteLength)throw j("Insufficient data to read metadata JSON.",{expectedBytes:i,availableBytes:n.byteLength-r,offset:r});let s=n.subarray(r,r+i);r+=i;let l;try{l=JSON.parse(Rr(s))}catch(z){throw j(`Failed to parse metadata JSON: ${z instanceof Error?z.message:String(z)}`,{metadataLen:i})}if(r+Oe>n.byteLength)throw j("Insufficient data to read geometry header.",{expectedBytes:Oe,availableBytes:n.byteLength-r,offset:r});let c=t.getUint32(r,!0);r+=4;let u=t.getFloat64(r,!0);r+=8;let d=t.getFloat64(r,!0);r+=8;let m=t.getFloat64(r,!0);r+=8;let f=t.getFloat64(r,!0);r+=8;let b=t.getFloat64(r,!0);r+=8;let H=t.getFloat64(r,!0);r+=8;let h=t.getUint32(r,!0);r+=4;let g=(c&de)!==0,p=(c&fr)!==0,T=h*3,O=T*(g?4:2);if(r+O>n.byteLength)throw j("Insufficient data to read vertices.",{expectedBytes:O,availableBytes:n.byteLength-r,offset:r,useFloat32:g,vertexCount:h});let w=n.byteOffset+r,R;if(g?R=Ve(n.buffer,w,T):p?R=vr(ue(n.buffer,w,T)):R=wr(n.buffer,w,T),r+=O,r+4>n.byteLength)throw j("Insufficient data to read index count.",{expectedBytes:4,availableBytes:n.byteLength-r,offset:r});let A=t.getUint32(r,!0);r+=4;let P=(c&mr)!==0,F=A*(P?2:4);if(r+F>n.byteLength)throw j("Insufficient data to read indices.",{expectedBytes:F,availableBytes:n.byteLength-r,offset:r,indexCount:A,useUint16Indices:P});let y=P?ue(n.buffer,n.byteOffset+r,A):Hr(n.buffer,n.byteOffset+r,A);p&&(y=y instanceof Uint16Array?xr(y):Mr(y)),r+=F;let x=null;if((c&pr)!==0){let z=gr(n,t,r,h,p);x=z.uvs,r=z.offset}let I=null;return(c&Er)!==0&&(I=yr(n,r,h,p)),{metadata:l,flags:c,vertices:R,indices:y,origin:[u,d,m],scale:[f,b,H],uvs:x,colors:I}}var Ie=36;function gr(e,n,t,r,o){if(t+Ie>e.byteLength)throw j("Insufficient data to read UV chunk header.",{expectedBytes:Ie,availableBytes:e.byteLength-t,offset:t});let a=n.getUint32(t,!0);t+=4;let i=n.getFloat64(t,!0);t+=8;let s=n.getFloat64(t,!0);t+=8;let l=n.getFloat64(t,!0);t+=8;let c=n.getFloat64(t,!0);t+=8;let u=r*2,d=a===hr,m=u*(d?4:2);if(t+m>e.byteLength)throw j("Insufficient data to read UV chunk.",{expectedBytes:m,availableBytes:e.byteLength-t,offset:t,uvFormat:a,vertexCount:r});let f=e.byteOffset+t,b;if(d)b=Ve(e.buffer,f,u).slice();else{let H=ue(e.buffer,f,u);b=new Float32Array(u);let h=0,g=0;for(let p=0;p<u;p+=2)o?(h=h+Y(H[p])&65535,g=g+Y(H[p+1])&65535):(h=H[p],g=H[p+1]),b[p]=i+h*l,b[p+1]=s+g*c}return{uvs:b,offset:t+m}}function yr(e,n,t,r){let o=t*3;if(n+o>e.byteLength)throw j("Insufficient data to read vertex-color chunk.",{expectedBytes:o,availableBytes:e.byteLength-n,offset:n,vertexCount:t});let a=e.subarray(n,n+o);if(!r)return a.slice();let i=new Uint8Array(o),s=0,l=0,c=0;for(let u=0;u<o;u+=3)s=s+Y(a[u])&255,l=l+Y(a[u+1])&255,c=c+Y(a[u+2])&255,i[u]=s,i[u+1]=l,i[u+2]=c;return i}function br(e){return typeof e=="string"?fe(e):e instanceof Uint8Array?e:new Uint8Array(e)}function Tr(e){if(e.byteLength<8)return e;let n=new DataView(e.buffer,e.byteOffset,e.byteLength);if(n.getUint32(0,!0)!==dr)return e;let t=n.getUint32(4,!0),r=e.subarray(8),o=Math.max(r.byteLength*1032+1024,1<<20);if(t>o)throw j("SLVZ header declares an implausible uncompressed length",{uncompressedLen:t,deflatedBytes:r.byteLength,maxPlausibleLen:o});try{return ur(r,{out:new Uint8Array(t)})}catch(a){throw j(`Failed to inflate SLVZ blob: ${a instanceof Error?a.message:String(a)}`,{uncompressedLen:t,deflatedBytes:r.byteLength})}}function Rr(e){if(typeof TextDecoder<"u")return new TextDecoder("utf-8").decode(e);if(typeof globalThis.Buffer<"u")return globalThis.Buffer.from(e).toString("utf-8");throw new se("No UTF-8 decoder available in this environment.",ie.INVALID_STATE)}function wr(e,n,t){if(t===0)return new Int16Array(0);if(n%2===0)return new Int16Array(e,n,t);let r=new Uint8Array(t*2);return r.set(new Uint8Array(e,n,t*2)),new Int16Array(r.buffer)}function Ve(e,n,t){if(t===0)return new Float32Array(0);if(n%4===0)return new Float32Array(e,n,t);let r=new Uint8Array(t*4);return r.set(new Uint8Array(e,n,t*4)),new Float32Array(r.buffer)}function ue(e,n,t){if(t===0)return new Uint16Array(0);if(n%2===0)return new Uint16Array(e,n,t);let r=new Uint8Array(t*2);return r.set(new Uint8Array(e,n,t*2)),new Uint16Array(r.buffer)}function Hr(e,n,t){if(t===0)return new Uint32Array(0);if(n%4===0)return new Uint32Array(e,n,t);let r=new Uint8Array(t*4);return r.set(new Uint8Array(e,n,t*4)),new Uint32Array(r.buffer)}function Y(e){return e>>>1^-(e&1)}function vr(e){let n=new Int16Array(e.length),t=0,r=0,o=0;for(let a=0;a<e.length;a+=3)t=t+Y(e[a])<<16>>16,r=r+Y(e[a+1])<<16>>16,o=o+Y(e[a+2])<<16>>16,n[a]=t,n[a+1]=r,n[a+2]=o;return n}function xr(e){let n=new Uint16Array(e.length),t=0;for(let r=0;r<e.length;r++)t=t+Y(e[r])&65535,n[r]=t;return n}function Mr(e){let n=new Uint32Array(e.length),t=0;for(let r=0;r<e.length;r++)t=t+Y(e[r])>>>0,n[r]=t;return n}function j(e,n){return new se(e,ie.VALIDATION_ERROR,{context:n})}import*as ae from"three";var oe=new Map,Q=new Map;function Be(e,n){let t=oe.get(n);if(t){e.map=t,e.needsUpdate=!0;return}typeof document>"u"||Cr(n).then(r=>{e.map=r,e.needsUpdate=!0}).catch(r=>{M().warn(`Failed to load material texture ${n}:`,r)})}function jn(){for(let e of oe.values())e.dispose();oe.clear(),Q.clear()}function Cr(e){let n=Q.get(e);return n||(n=new Promise((t,r)=>{new ae.TextureLoader().load(e,o=>{o.colorSpace=ae.SRGBColorSpace,oe.set(e,o),Q.delete(e),t(o)},void 0,o=>{Q.delete(e),r(o)})}),Q.set(e,n)),n}import*as V from"three";async function Fe(e,n){let{debug:t=!1}=n??{},r=t?performance.now():0;try{let o=performance.now(),a=JSON.parse(e),i=performance.now()-o;return await Ar(a,n,{parseTime:i,perfStart:r})}catch(o){return M().error("Error parsing mesh batch:",o),[]}}async function Ar(e,n,t){let{mergeByMaterial:r=!0,applyTransforms:o=!0,debug:a=!1}=n??{},{parseTime:i=0,perfStart:s=a?performance.now():0}=t??{};try{let l=performance.now(),c=me(e.compressedData),u=performance.now()-l,d=a?Ir(e.compressedData):0;return Ue(c,{mergeByMaterial:r,applyTransforms:o,debug:a,parseTime:i,decodeTime:u,perfStart:s,blobBytes:d,fallback:{materials:e.materials,groups:e.groups,sourceComponentId:e.sourceComponentId}})}catch(l){return M().error("Error parsing mesh batch object:",l),[]}}async function Xn(e,n){let{mergeByMaterial:t=!0,applyTransforms:r=!0,debug:o=!1}=n??{},a=o?performance.now():0;try{let i=performance.now(),s=me(e),l=performance.now()-i,c=e.byteLength;return Ue(s,{mergeByMaterial:t,applyTransforms:r,debug:o,parseTime:0,decodeTime:l,perfStart:a,blobBytes:c})}catch(i){return M().error("Error parsing mesh batch blob:",i),[]}}function Ue(e,n){let{mergeByMaterial:t,applyTransforms:r,debug:o,parseTime:a,decodeTime:i,perfStart:s,blobBytes:l,fallback:c}=n,u=e.metadata.materials??c?.materials??[],d=e.metadata.groups??c?.groups??[],m=c?.sourceComponentId??e.metadata.sourceComponentId,f=(e.flags&de)!==0,b=f?Dr(e.vertices,r):Sr(e.vertices,e.origin,e.scale,r);if(o){let T=e.vertices.byteLength+e.indices.byteLength;M().debug("Mesh Batch Stats:"),M().debug(` Materials: ${u.length} | Groups: ${d.length}`),M().debug(` Vertices: ${e.vertices.length/3} | Indices: ${e.indices.length}`),M().debug(` Format: ${f?"float32":"int16 quantized"}`),M().debug(` Blob: ${(l/1024/1024).toFixed(2)} MB | Geometry on wire: ${(T/1024/1024).toFixed(2)} MB`)}let H=performance.now(),h=u.map(T=>Lr(T,{vertexColors:e.colors!=null})),g=[];for(let T of d)if(t&&T.meshes.length>1){let v=Pr(T,b,e.indices,h,e.uvs,e.colors);v.userData.sourceComponentId=m??null,g.push(v)}else{let v=Or(T,b,e.indices,h,e.uvs,e.colors);for(let O of v)O.userData.sourceComponentId=m??null;g.push(...v)}let p=performance.now()-H;if(o){let T=performance.now()-s;M().debug("Performance:"),a>0&&M().debug(` Parse JSON: ${a.toFixed(2)}ms`),M().debug(` Decode binary: ${i.toFixed(2)}ms`),M().debug(` Create Meshes: ${p.toFixed(2)}ms`),M().debug(` Total: ${T.toFixed(2)}ms`)}return Promise.resolve(g)}function Sr(e,n,t,r){let o=new Float32Array(e.length),a=n[0],i=n[1],s=n[2],l=t[0],c=t[1],u=t[2];for(let d=0;d<e.length;d+=3)o[d]=a+(e[d]+32767)*l,o[d+1]=i+(e[d+1]+32767)*c,o[d+2]=s+(e[d+2]+32767)*u;return o}function Dr(e,n){return e}function Lr(e,n){let t=pe(e.color),r=new V.MeshPhysicalMaterial({color:t,metalness:e.metalness,roughness:e.roughness,opacity:e.opacity,transparent:e.transparent,vertexColors:n?.vertexColors??!1,side:V.DoubleSide,polygonOffset:!0,polygonOffsetFactor:.5,polygonOffsetUnits:.5,depthWrite:!0,depthTest:!0});return e.map&&Be(r,e.map),r}function Pr(e,n,t,r,o=null,a=null){let i=0,s=0;for(let p of e.meshes)i+=p.vertexCount,s+=p.indexCount;let l=new Float32Array(i*3),c=new Uint32Array(s),u=o?new Float32Array(i*2):null,d=a?new Uint8Array(i*3):null,m=0,f=0;for(let p of e.meshes){let T=p.vertexStart*3,v=p.vertexCount*3;if(l.set(n.subarray(T,T+v),m*3),u&&o){let R=p.vertexStart*2;u.set(o.subarray(R,R+p.vertexCount*2),m*2)}d&&a&&d.set(a.subarray(T,T+v),m*3);let O=t.subarray(p.indexStart,p.indexStart+p.indexCount),w=m-p.vertexStart;if(w===0)c.set(O,f);else for(let R=0;R<O.length;R++)c[f+R]=O[R]+w;m+=p.vertexCount,f+=p.indexCount}let b=new V.BufferGeometry;b.setAttribute("position",new V.BufferAttribute(l,3)),b.setIndex(new V.BufferAttribute(c,1)),u&&b.setAttribute("uv",new V.BufferAttribute(u,2)),d&&b.setAttribute("color",new V.BufferAttribute(d,3,!0)),b.computeVertexNormals();let H=new V.Mesh(b,r[e.materialId]),h=e.meshes[0],g=e.meshes.map(p=>p.name).filter(p=>p&&p.length>0);return H.name=g.length>0?g[0]:`merged_material_${e.materialId}`,H.castShadow=!0,H.receiveShadow=!0,H.userData={source:"compute",name:H.name,layer:h?.layer??"",originalIndex:h?.originalIndex??0,metadata:h?.metadata??{},mergedFrom:e.meshes.slice(1).map(p=>({name:p.name,layer:p.layer,originalIndex:p.originalIndex}))},H}function Or(e,n,t,r,o=null,a=null){let i=[];for(let s of e.meshes){let l=s.vertexStart*3,c=s.vertexCount*3,u=n.slice(l,l+c),d=t.subarray(s.indexStart,s.indexStart+s.indexCount),m=new Uint32Array(d.length),f=s.vertexStart;for(let h=0;h<d.length;h++)m[h]=d[h]-f;let b=new V.BufferGeometry;if(b.setAttribute("position",new V.BufferAttribute(u,3)),b.setIndex(new V.BufferAttribute(m,1)),o){let h=s.vertexStart*2,g=o.slice(h,h+s.vertexCount*2);b.setAttribute("uv",new V.BufferAttribute(g,2))}if(a){let h=a.slice(l,l+c);b.setAttribute("color",new V.BufferAttribute(h,3,!0))}b.computeVertexNormals();let H=new V.Mesh(b,r[e.materialId]);H.name=s.name,H.userData={source:"compute",name:s.name,layer:s.layer??"",originalIndex:s.originalIndex,metadata:s.metadata??{}},H.castShadow=!0,H.receiveShadow=!0,i.push(H)}return i}function Ir(e){return Math.floor(e.length*3/4)}var Vr={Millimeters:1/1e3,Centimeters:1/100,Meters:1,Inches:1/39.37,Feet:1/3.28084},Br="Display";async function eo(e,n){let t=performance.now(),r=[],{allowScaling:o=!0,allowAutoPosition:a=!0,rhino:i,debug:s=!1,parsing:l={}}=n??{};try{let c=o?Fr(e.modelunits):1;return await Ur(e,r,c,l,i,s),a&&jr(r),r}catch(c){throw Gr(c,r),c}finally{s&&Wr(t)}}function Fr(e){return Vr[e]??1}async function Ur(e,n,t,r,o,a){for(let i of e.values){let s=i.InnerTree;for(let l in s){let c=s[l];c&&await zr(c,n,t,r,o,a)}}}async function zr(e,n,t,r,o,a){for(let i of e){if(!i.type.includes(Br))continue;let s={mergeByMaterial:!0,applyTransforms:!0,debug:!1,...r},l=await Fe(i.data,s),c=Ce(_r(i.data),{rhino:o,applyTransforms:s.applyTransforms}),u=[...l,...c];if(t!==1)for(let d of u)d.scale.set(t,t,t);n.push(...u),a&&M().debug(`Extracted ${l.length} meshes and ${c.length} items from batch`)}}function _r(e){return(typeof e=="string"?kr(e):e)?.items}function kr(e){try{return JSON.parse(e)}catch{return}}function jr(e){if(e.length===0)return;let n=K(e);Ee(e,n.min.z,"z")}function Gr(e,n){M().error("An unexpected error occurred:",e),Nr(n)}function Nr(e){for(let n of e){let t=n;t.geometry&&t.geometry.dispose(),t.material&&(Array.isArray(t.material)?t.material.forEach(r=>r.dispose()):t.material.dispose())}}function Wr(e){let n=performance.now()-e;M().info("Time to process meshes:",`${n.toFixed(2)}ms`)}export{Xr as a,pe as b,Ee as c,K as d,he as e,ge as f,ye as g,te as h,Te as i,it as j,on as k,Re as l,He as m,Rt as n,xe as o,An as p,$t as q,Ce as r,Se as s,De as t,de as u,fr as v,pr as w,Er as x,me as y,jn as z,Fe as A,Ar as B,Xn as C,Vr as D,eo as E};
55
- //# sourceMappingURL=chunk-C2HJB4MH.js.map