@selvajs/compute 3.1.0-beta.9 → 3.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/chunk-FQKQISPG.cjs +2 -0
- package/dist/chunk-FQKQISPG.cjs.map +1 -0
- package/dist/chunk-H3FZW6OX.cjs +4 -0
- package/dist/chunk-H3FZW6OX.cjs.map +1 -0
- package/dist/chunk-N2WCSETE.js +120 -0
- package/dist/chunk-N2WCSETE.js.map +1 -0
- package/dist/chunk-RFE763NG.cjs +120 -0
- package/dist/chunk-RFE763NG.cjs.map +1 -0
- package/dist/chunk-S3VUIIRE.js +2 -0
- package/dist/chunk-S3VUIIRE.js.map +1 -0
- package/dist/chunk-Y3M7P3BW.js +4 -0
- package/dist/chunk-Y3M7P3BW.js.map +1 -0
- package/dist/core.cjs +1 -1
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +22 -1
- package/dist/core.d.ts +22 -1
- package/dist/core.js +1 -1
- package/dist/grasshopper.cjs +1 -1
- package/dist/grasshopper.cjs.map +1 -1
- package/dist/grasshopper.d.cts +22 -2
- package/dist/grasshopper.d.ts +22 -2
- package/dist/grasshopper.js +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/{types-Dtok-mVq.d.ts → types-4FMvnx2j.d.ts} +14 -1
- package/dist/{types-C8XWc4Ab.d.cts → types-BpOl6U02.d.cts} +14 -1
- package/dist/visualization-E6BTQZCA.cjs +2 -0
- package/dist/visualization-E6BTQZCA.cjs.map +1 -0
- package/dist/visualization-HDBKPJGQ.js +2 -0
- package/dist/visualization.cjs +1 -1
- package/dist/visualization.cjs.map +1 -1
- package/dist/visualization.d.cts +331 -29
- package/dist/visualization.d.ts +331 -29
- package/dist/visualization.js +1 -1
- package/package.json +56 -35
- package/dist/chunk-CUQQ3ZBV.cjs +0 -4
- package/dist/chunk-CUQQ3ZBV.cjs.map +0 -1
- package/dist/chunk-GFY3L653.cjs +0 -62
- package/dist/chunk-GFY3L653.cjs.map +0 -1
- package/dist/chunk-MJOXUCDH.js +0 -62
- package/dist/chunk-MJOXUCDH.js.map +0 -1
- package/dist/chunk-WPB2LKCD.js +0 -4
- package/dist/chunk-WPB2LKCD.js.map +0 -1
- package/dist/chunk-WWD655BZ.cjs +0 -2
- package/dist/chunk-WWD655BZ.cjs.map +0 -1
- package/dist/chunk-YREXY7GT.js +0 -2
- package/dist/chunk-YREXY7GT.js.map +0 -1
- package/dist/visualization-4PVR5P7N.js +0 -2
- package/dist/visualization-LS3Z7Q3N.cjs +0 -2
- package/dist/visualization-LS3Z7Q3N.cjs.map +0 -1
- /package/dist/{visualization-4PVR5P7N.js.map → visualization-HDBKPJGQ.js.map} +0 -0
package/dist/visualization.d.cts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
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-
|
|
4
|
-
export { q as DisplayCurve, r as DisplayIdentity, s as DisplayItemBase, t as DisplayPoint, u as DisplayPosition, v as MeshBatch } from './types-
|
|
3
|
+
import { M as MaterialAppearanceOptions, f as GrasshopperComputeResponse, m as MeshExtractionOptions, n as MeshBatchParsingOptions, o as DisplayBatch, p as DisplayItem } from './types-BpOl6U02.cjs';
|
|
4
|
+
export { q as DisplayCurve, r as DisplayIdentity, s as DisplayItemBase, t as DisplayPoint, u as DisplayPosition, v as MeshBatch } from './types-BpOl6U02.cjs';
|
|
5
5
|
import { CSS2DObject } from 'three/addons/renderers/CSS2DRenderer.js';
|
|
6
6
|
import { LineSegments2 } from 'three/addons/lines/LineSegments2.js';
|
|
7
|
+
import { Pass } from 'three/addons/postprocessing/Pass.js';
|
|
7
8
|
import { RhinoModule } from 'rhino3dm';
|
|
8
9
|
import './types-BGhtYxZ-.cjs';
|
|
9
10
|
|
|
@@ -13,6 +14,13 @@ type CameraConfig = {
|
|
|
13
14
|
near?: number;
|
|
14
15
|
far?: number;
|
|
15
16
|
target?: THREE.Vector3;
|
|
17
|
+
/**
|
|
18
|
+
* Refit the perspective camera's near plane to the camera↔content gap every frame (default true).
|
|
19
|
+
* Recovers depth-buffer precision when zoomed out (precision ∝ near/z²), which is what stops
|
|
20
|
+
* distant surfaces z-fighting. `near` stays the lower bound — the plane is only raised, never
|
|
21
|
+
* lowered below it.
|
|
22
|
+
*/
|
|
23
|
+
dynamicNear?: boolean;
|
|
16
24
|
};
|
|
17
25
|
type LightingConfig = {
|
|
18
26
|
enableSunlight?: boolean;
|
|
@@ -40,6 +48,15 @@ type EnvironmentConfig = {
|
|
|
40
48
|
hdrPath?: string;
|
|
41
49
|
backgroundColor?: THREE.Color | string;
|
|
42
50
|
enableEnvironmentLighting?: boolean;
|
|
51
|
+
/**
|
|
52
|
+
* The scene's up axis. **Defaults to `(0, 0, 1)` — Rhino's Z-up**, not Three's native Y-up,
|
|
53
|
+
* because geometry arrives in Rhino's frame and is never rotated on ingress (see
|
|
54
|
+
* `coordinate-transform.ts`). Everything orientation-dependent derives from this: view presets,
|
|
55
|
+
* the default iso camera, sun position, grid plane, floor normal, and the hemisphere light.
|
|
56
|
+
*
|
|
57
|
+
* Overriding it reorients the viewer but does NOT rotate incoming geometry, so a Y-up value only
|
|
58
|
+
* makes sense if the host also feeds Y-up geometry.
|
|
59
|
+
*/
|
|
43
60
|
sceneUp?: THREE.Vector3;
|
|
44
61
|
showEnvironment?: boolean;
|
|
45
62
|
/**
|
|
@@ -81,6 +98,13 @@ type RenderConfig = {
|
|
|
81
98
|
* toward the display DPR for sharper AO at higher cost; only relevant when AO is enabled.
|
|
82
99
|
*/
|
|
83
100
|
aoPixelRatio?: number;
|
|
101
|
+
/**
|
|
102
|
+
* Render only when something changed (camera motion, invalidate(), pointer input, resize), with
|
|
103
|
+
* a ~500 ms safety repaint, instead of every animation frame. Default true — cuts idle GPU/battery
|
|
104
|
+
* to ~2 fps worth of work, which matters especially with ambient occlusion on. Set false to
|
|
105
|
+
* restore the legacy continuous loop.
|
|
106
|
+
*/
|
|
107
|
+
onDemand?: boolean;
|
|
84
108
|
};
|
|
85
109
|
/**
|
|
86
110
|
* A ready-to-go visual look. A `look` is a named bundle of LIGHTING/MATERIAL defaults only — it is
|
|
@@ -107,12 +131,31 @@ type Look = (typeof LOOKS)[number];
|
|
|
107
131
|
type EdgesConfig = {
|
|
108
132
|
/** Auto-attach edge overlays to meshes as they load. Default false (opt-in). */
|
|
109
133
|
enabled?: boolean;
|
|
110
|
-
/**
|
|
134
|
+
/**
|
|
135
|
+
* Force a single edge color for all meshes. Omit (the default) to derive each mesh's edge color
|
|
136
|
+
* from its own surface material, darkened by `darken` — so edges read as the object's own outline.
|
|
137
|
+
*/
|
|
111
138
|
color?: THREE.ColorRepresentation;
|
|
139
|
+
/**
|
|
140
|
+
* How far derived edge colors are darkened toward black, 0–1 (default 0.75). Ignored when `color`
|
|
141
|
+
* is set.
|
|
142
|
+
*/
|
|
143
|
+
darken?: number;
|
|
112
144
|
/** Edge thickness in CSS px. Default 1.5. */
|
|
113
145
|
width?: number;
|
|
114
|
-
/** Crease angle (degrees): keep edges where faces differ by more than this. Default
|
|
146
|
+
/** Crease angle (degrees): keep edges where faces differ by more than this. Default 44. */
|
|
115
147
|
thresholdAngle?: number;
|
|
148
|
+
/** Fade an overlay out as its mesh shrinks on screen, so far zoom-outs stay clean. Default true. */
|
|
149
|
+
distanceFade?: boolean;
|
|
150
|
+
/** Skip overlay extraction for meshes above this triangle count. Default 4M. See `EdgeOptions`. */
|
|
151
|
+
maxTriangles?: number;
|
|
152
|
+
/** Overlays above this segment count render opaque (no distance fade). Default 2M. */
|
|
153
|
+
maxSegments?: number;
|
|
154
|
+
/**
|
|
155
|
+
* When a mesh is skipped for exceeding `maxTriangles`, approximate its edges with the
|
|
156
|
+
* screen-space edge-detection pass (constant cost in triangle count). Default true.
|
|
157
|
+
*/
|
|
158
|
+
screenSpaceFallback?: boolean;
|
|
116
159
|
};
|
|
117
160
|
type ControlsConfig = {
|
|
118
161
|
enableDamping?: boolean;
|
|
@@ -138,7 +181,11 @@ type GridConfig = {
|
|
|
138
181
|
majorColor?: THREE.ColorRepresentation;
|
|
139
182
|
/** World radius at which the grid fully fades. Default 100. */
|
|
140
183
|
fadeDistance?: number;
|
|
141
|
-
/**
|
|
184
|
+
/**
|
|
185
|
+
* Axis the grid lies perpendicular to — the scene's up axis. Defaults to whichever axis
|
|
186
|
+
* `sceneUp` points along, so it is `'z'` (Rhino's horizontal ground) unless you override
|
|
187
|
+
* `sceneUp`. Set explicitly only to force a grid orientation that ignores the scene up.
|
|
188
|
+
*/
|
|
142
189
|
plane?: 'x' | 'y' | 'z';
|
|
143
190
|
};
|
|
144
191
|
/** Corner nav-cube/axis gizmo that snaps to preset views. See `createViewGizmo`. */
|
|
@@ -275,7 +322,8 @@ interface CameraControllerDeps {
|
|
|
275
322
|
/**
|
|
276
323
|
* The scene's up axis. Presets, the orthographic camera's up, and the iso direction are all derived
|
|
277
324
|
* from this so the controller is correct in any up convention (Three's native Y-up, Rhino's Z-up, …)
|
|
278
|
-
* without hardcoding an axis.
|
|
325
|
+
* without hardcoding an axis. Falls back to `perspective.up` when omitted; `initThree` always
|
|
326
|
+
* passes the configured `sceneUp`, which itself defaults to Rhino's Z-up.
|
|
279
327
|
*/
|
|
280
328
|
up?: THREE.Vector3;
|
|
281
329
|
}
|
|
@@ -303,7 +351,13 @@ interface GridOptions {
|
|
|
303
351
|
majorColor?: THREE.ColorRepresentation;
|
|
304
352
|
/** World-space radius at which the grid has fully faded out. Default 100. */
|
|
305
353
|
fadeDistance?: number;
|
|
306
|
-
/**
|
|
354
|
+
/**
|
|
355
|
+
* Axis the grid is laid perpendicular to — i.e. the scene's up axis. `'z'` is the horizontal
|
|
356
|
+
* ground in the Rhino Z-up frame the viewer uses; `'y'` is Three's native Y-up.
|
|
357
|
+
*
|
|
358
|
+
* This standalone default is `'y'`, but `initThree` always passes a plane derived from the
|
|
359
|
+
* configured `sceneUp`, so a viewer-created grid defaults to `'z'`.
|
|
360
|
+
*/
|
|
307
361
|
plane?: 'x' | 'y' | 'z';
|
|
308
362
|
}
|
|
309
363
|
interface Grid {
|
|
@@ -311,6 +365,13 @@ interface Grid {
|
|
|
311
365
|
readonly object: THREE.Mesh;
|
|
312
366
|
/** Keep the fade centered on the camera so the grid feels infinite as you move. Call per frame. */
|
|
313
367
|
update(cameraPosition: THREE.Vector3): void;
|
|
368
|
+
/**
|
|
369
|
+
* Rescale the grid's cell spacing and fade radius to the loaded content's extent. Call after a
|
|
370
|
+
* geometry change (e.g. right after `updateScene`) so a part that is 3 units or 3000 units wide
|
|
371
|
+
* both get sensibly-sized cells and a fade that reaches past the model. No-op for empty/degenerate
|
|
372
|
+
* bounds — the grid keeps its last (or default) scale. See {@link Grid.fitToContent}'s impl notes.
|
|
373
|
+
*/
|
|
374
|
+
fitToContent(bounds: THREE.Box3): void;
|
|
314
375
|
setVisible(visible: boolean): void;
|
|
315
376
|
dispose(): void;
|
|
316
377
|
}
|
|
@@ -491,9 +552,24 @@ declare const initThree: (canvas: HTMLCanvasElement, options?: ThreeInitializerO
|
|
|
491
552
|
measureTool: MeasureTool | null;
|
|
492
553
|
/**
|
|
493
554
|
* Attach edge overlays to the meshes under `root` (no-op unless `edges.enabled`). Call after
|
|
494
|
-
* loading meshes via `updateScene`, since meshes arrive after init.
|
|
555
|
+
* loading meshes via `updateScene`, since meshes arrive after init. Extraction for large meshes
|
|
556
|
+
* runs off-thread — their overlays attach a beat later; meshes over `edges.maxTriangles` are
|
|
557
|
+
* skipped and (by default) covered by the screen-space edge fallback instead.
|
|
495
558
|
*/
|
|
496
559
|
applyEdges: (root: THREE.Object3D) => void;
|
|
560
|
+
/**
|
|
561
|
+
* Remove edge overlays under `root` — the toggle-off counterpart of `applyEdges`. Prefer this
|
|
562
|
+
* over calling `removeEdges` directly: it also cancels in-flight async attaches' fallout and
|
|
563
|
+
* stands down the screen-space edge fallback if it was active.
|
|
564
|
+
*/
|
|
565
|
+
clearEdges: (root: THREE.Object3D) => void;
|
|
566
|
+
/**
|
|
567
|
+
* Request a repaint from the on-demand render loop. Camera motion, resizes, pointer input, and
|
|
568
|
+
* the built-in setters invalidate automatically; call this after mutating the scene externally
|
|
569
|
+
* (e.g. `updateScene`, adding user geometry) so the change shows immediately rather than on the
|
|
570
|
+
* next safety repaint. No-op (harmless) when `render.onDemand` is false.
|
|
571
|
+
*/
|
|
572
|
+
invalidate: () => void;
|
|
497
573
|
/** Toggle ambient occlusion at runtime — builds or tears down the postprocessing pipeline. */
|
|
498
574
|
setAmbientOcclusion: (enabled: boolean) => void;
|
|
499
575
|
/**
|
|
@@ -541,6 +617,12 @@ declare const initThree: (canvas: HTMLCanvasElement, options?: ThreeInitializerO
|
|
|
541
617
|
* loading or replacing geometry (e.g. after `updateScene`). No-op when sunlight/shadows are off.
|
|
542
618
|
*/
|
|
543
619
|
updateShadowBounds: () => void;
|
|
620
|
+
/**
|
|
621
|
+
* Rescale the grid's cell spacing and fade radius to the current scene content, so parts of any
|
|
622
|
+
* size get readable cells and a fade that reaches past the model. Call after loading or replacing
|
|
623
|
+
* geometry (e.g. after `updateScene`). No-op when the grid is off or there's no content.
|
|
624
|
+
*/
|
|
625
|
+
updateGridScale: () => void;
|
|
544
626
|
dispose: () => void;
|
|
545
627
|
fitToView: () => void;
|
|
546
628
|
clearSelection: () => void;
|
|
@@ -562,7 +644,8 @@ declare function updateScene(scene: THREE.Scene, meshes: THREE.Object3D[], camer
|
|
|
562
644
|
declare function parseColor(colorString: string): THREE.Color;
|
|
563
645
|
/**
|
|
564
646
|
* Shift objects along one world axis. Defaults to `z` — the up axis of the unified Z-up scene
|
|
565
|
-
* frame (see `../coordinate-transform.ts`), so grounding subtracts the content's lowest z.
|
|
647
|
+
* frame (see `../coordinate-transform.ts`), so grounding subtracts the content's lowest z. Pass an
|
|
648
|
+
* explicit axis when the scene is configured with a different `sceneUp`.
|
|
566
649
|
*/
|
|
567
650
|
declare function applyOffset(meshes: THREE.Object3D[], offset: number, axis?: 'x' | 'y' | 'z'): void;
|
|
568
651
|
/**
|
|
@@ -593,54 +676,262 @@ declare namespace threeMaterials {
|
|
|
593
676
|
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 };
|
|
594
677
|
}
|
|
595
678
|
|
|
679
|
+
/**
|
|
680
|
+
* The single source of truth for "which way is up, and what do front/right mean" in the viewer.
|
|
681
|
+
*
|
|
682
|
+
* Every up-dependent default (camera framing, sun position, ground offset, view presets) derives
|
|
683
|
+
* from {@link buildUpBasis} instead of hardcoding an axis. Before this module those defaults each
|
|
684
|
+
* spelled out a Z-up vector inline, so a scene configured Y-up got a below-horizon camera and a
|
|
685
|
+
* near-horizontal sun while the presets and floor correctly followed `sceneUp`.
|
|
686
|
+
*
|
|
687
|
+
* ## Why front is -forward
|
|
688
|
+
*
|
|
689
|
+
* The basis returns `forward` = the direction the camera LOOKS (from camera toward model), and the
|
|
690
|
+
* preset positions are the opposite (from target toward camera). Rhino's convention fixes the signs:
|
|
691
|
+
* its Front view looks along +Y, so the camera sits at -Y; its Right view looks along -X, so the
|
|
692
|
+
* camera sits at +X. Deriving `right` as `seed x up` (rather than `up x seed`) is what makes the
|
|
693
|
+
* handedness come out matching Rhino rather than mirrored.
|
|
694
|
+
*/
|
|
695
|
+
/** An orthonormal frame derived from a scene up axis. All vectors are unit length. */
|
|
696
|
+
interface UpBasis {
|
|
697
|
+
/** The scene up axis, normalized. */
|
|
698
|
+
up: THREE.Vector3;
|
|
699
|
+
/** The direction a "front" view looks along (from camera toward the model). */
|
|
700
|
+
forward: THREE.Vector3;
|
|
701
|
+
/** Completes a right-handed frame with `up` and `forward`. */
|
|
702
|
+
right: THREE.Vector3;
|
|
703
|
+
}
|
|
704
|
+
/**
|
|
705
|
+
* Derive the ground-plane axes for a given up vector.
|
|
706
|
+
*
|
|
707
|
+
* The seed picks whichever world axis is least parallel to `up`, so the cross products stay
|
|
708
|
+
* well-conditioned in any up convention. For Rhino's Z-up this yields forward = +Y and right = +X,
|
|
709
|
+
* matching Rhino's own Front/Right views; for Three's native Y-up it yields forward = -Z and
|
|
710
|
+
* right = +X, matching Three's convention that the default camera looks down -Z.
|
|
711
|
+
*/
|
|
712
|
+
declare function buildUpBasis(up: THREE.Vector3): UpBasis;
|
|
713
|
+
/**
|
|
714
|
+
* The default 3/4 iso camera OFFSET from the target, scaled to `distance`.
|
|
715
|
+
*
|
|
716
|
+
* Placed behind-left and above the model (the conventional architectural 3/4), expressed in the
|
|
717
|
+
* scene's own basis so it reads the same in any up convention. Callers add this to the framing
|
|
718
|
+
* target to get a camera position.
|
|
719
|
+
*/
|
|
720
|
+
declare function isoOffset(up: THREE.Vector3, distance: number): THREE.Vector3;
|
|
721
|
+
/**
|
|
722
|
+
* A default sun position: high above the model, offset to one side so surfaces get a directional
|
|
723
|
+
* gradient instead of flat top-down light. Expressed in the scene basis rather than a literal
|
|
724
|
+
* Z-up vector, so a Y-up scene still gets an overhead sun rather than a horizontal one.
|
|
725
|
+
*/
|
|
726
|
+
declare function sunOffset(up: THREE.Vector3, sideDistance: number, height: number): THREE.Vector3;
|
|
727
|
+
/**
|
|
728
|
+
* The rotation that puts an equirectangular environment map's horizon on the scene's ground plane.
|
|
729
|
+
*
|
|
730
|
+
* Three's equirect mapping is hardcoded to Y-up: it assumes the HDR's horizon lies in the XZ plane
|
|
731
|
+
* and its zenith points along +Y. In a Z-up scene that leaves the environment on its side — the
|
|
732
|
+
* horizon runs vertically and image-based lighting arrives from +Y rather than from overhead. The
|
|
733
|
+
* result is a subtly wrong key direction that a neutral studio HDR hides but any sky/ground HDR
|
|
734
|
+
* makes obvious.
|
|
735
|
+
*
|
|
736
|
+
* Returns the Euler that rotates the map's native +Y zenith onto `up`. Identity for a Y-up scene.
|
|
737
|
+
* Apply to BOTH `scene.environmentRotation` and `scene.backgroundRotation` — they are independent
|
|
738
|
+
* properties, and setting only one makes the visible background disagree with the lighting.
|
|
739
|
+
*/
|
|
740
|
+
declare function environmentRotationFor(up: THREE.Vector3): THREE.Euler;
|
|
741
|
+
/**
|
|
742
|
+
* Which world axis (`'x' | 'y' | 'z'`) the up vector most closely aligns with.
|
|
743
|
+
*
|
|
744
|
+
* Used for the grid plane and for the ground-offset axis — both need a single component index
|
|
745
|
+
* rather than a full vector. An off-axis up vector resolves to its dominant component.
|
|
746
|
+
*/
|
|
747
|
+
declare function upToAxis(up: THREE.Vector3): 'x' | 'y' | 'z';
|
|
748
|
+
|
|
596
749
|
/**
|
|
597
750
|
* Crisp boundary/crease edges overlaid on meshes — the defining "technical drawing" look that makes
|
|
598
751
|
* shaded geometry read as discrete objects rather than blobs.
|
|
599
752
|
*
|
|
600
|
-
*
|
|
601
|
-
*
|
|
602
|
-
* `LineMaterial` family as curves
|
|
603
|
-
* of `THREE.LineSegments`. The overlay is added as a
|
|
604
|
-
* transform and is disposed when the mesh subtree
|
|
753
|
+
* Edge segments are extracted by `extractEdgeSegments` (see edge-extract.ts — an
|
|
754
|
+
* `EdgesGeometry`-equivalent that is ~an order of magnitude faster and worker-portable) and
|
|
755
|
+
* rendered as fat `LineSegments2` using the same `LineMaterial` family as curves — so edges get
|
|
756
|
+
* controllable thickness, not the 1px cap of `THREE.LineSegments`. The overlay is added as a
|
|
757
|
+
* *child* of each mesh, so it inherits the mesh's transform and is disposed when the mesh subtree
|
|
758
|
+
* is cleared.
|
|
759
|
+
*
|
|
760
|
+
* Performance model (docs/plans/4.edge-overlay-performance.md):
|
|
761
|
+
* - Extraction results are cached at two levels: per source `BufferGeometry` (object identity,
|
|
762
|
+
* helps instanced parts within one solve) and by *content fingerprint* in an LRU — the viewer
|
|
763
|
+
* rebuilds all geometry objects every solve, so only a content key survives re-solves.
|
|
764
|
+
* - {@link addEdgesAsync} runs extraction for large meshes in a Worker built from a blob URL
|
|
765
|
+
* (bundler-agnostic; falls back to inline extraction when Workers are unavailable), keeping the
|
|
766
|
+
* main thread free of the multi-second stalls extraction causes at millions of triangles.
|
|
767
|
+
* - Caps bound the pathological cases: meshes above `maxTriangles` are skipped outright (tagged
|
|
768
|
+
* `userData.edgesSkipped = 'triangle-cap'`), overlays above `maxSegments` lose the distance
|
|
769
|
+
* fade so they render in the cheaper opaque pass.
|
|
770
|
+
*
|
|
771
|
+
* Depth strategy: surfaces render at TRUE depth, untouched; the LINES carry a small units-only
|
|
772
|
+
* polygonOffset toward the camera (see EDGE_OFFSET_FACTOR/UNITS).
|
|
773
|
+
*
|
|
774
|
+
* This reverses an earlier strategy that instead pushed each mesh's *surface* back with a
|
|
775
|
+
* slope-scaled offset (factor 1, units 2). That version bled badly: the slope term scales with
|
|
776
|
+
* dZ/dpixel, which is enormous on a surface viewed near edge-on, so grazing faces receded by much
|
|
777
|
+
* more than the millimetre gaps between stacked parts — geometry behind a wall then beat the wall's
|
|
778
|
+
* own receded surface and drew through it. It also clobbered the polygonOffset that look presets
|
|
779
|
+
* configure on their materials, and its "restore" path reset those to 0 rather than to the preset's
|
|
780
|
+
* values.
|
|
781
|
+
*
|
|
782
|
+
* A units-only bias on the lines is bounded by construction: a fixed number of depth quantization
|
|
783
|
+
* steps, independent of viewing angle, so it lifts an edge off its own coplanar surface without ever
|
|
784
|
+
* reaching across to a neighbouring part.
|
|
785
|
+
*
|
|
786
|
+
* The caveat the old strategy correctly identified: a depth ULP grows ~quadratically with viewing
|
|
787
|
+
* distance, so a constant bias is only safe while ULPs stay small. That is what the dynamic
|
|
788
|
+
* near-plane fitter (near-plane.ts) buys — it keeps `camera.near` proportional to the camera↔content
|
|
789
|
+
* gap, holding ULPs at micron scale even zoomed well out. The two mechanisms are load-bearing
|
|
790
|
+
* together; weakening the near fit will make this bias start to bleed.
|
|
605
791
|
*/
|
|
606
792
|
interface EdgeOptions {
|
|
607
|
-
/**
|
|
793
|
+
/**
|
|
794
|
+
* Force a single edge color for every overlay. When omitted (the default), each overlay derives
|
|
795
|
+
* its color from its own mesh's material — a darkened tint of the surface — so edges read as the
|
|
796
|
+
* object's own outline rather than a uniform black frame. Meshes with no readable material color
|
|
797
|
+
* fall back to {@link DEFAULT_EDGE_COLOR}.
|
|
798
|
+
*/
|
|
608
799
|
color?: THREE.ColorRepresentation;
|
|
800
|
+
/**
|
|
801
|
+
* How far to darken the derived edge color toward black, 0–1 (default 0.75). Only applies when
|
|
802
|
+
* `color` is omitted. Higher = darker edges; 0 leaves edges the surface color, 1 makes them black.
|
|
803
|
+
*/
|
|
804
|
+
darken?: number;
|
|
609
805
|
/** Edge thickness in CSS px. Default 1.5. */
|
|
610
806
|
width?: number;
|
|
611
807
|
/**
|
|
612
808
|
* Crease angle in degrees: an edge is kept only where its two faces differ by more than this.
|
|
613
|
-
* Default
|
|
809
|
+
* Default 44. Higher = fewer edges (only sharp creases); lower = more (catches gentle bends).
|
|
614
810
|
*/
|
|
615
811
|
thresholdAngle?: number;
|
|
812
|
+
/**
|
|
813
|
+
* Fade an overlay out as its own edges crowd together on screen (default true). Edges draw at a
|
|
814
|
+
* constant pixel width, so once neighbouring lines sit less than a pixel or two apart they stop
|
|
815
|
+
* resolving and merge into a dark smear — worst on layered sheet goods, whose millimetre-pitch
|
|
816
|
+
* laminations are sub-pixel at any normal zoom on a metre-scale part. Fading by edge density
|
|
817
|
+
* (not by how large the mesh is) returns those parts to a clean shaded read while leaving
|
|
818
|
+
* sparsely-edged geometry fully drawn at the same distance.
|
|
819
|
+
*/
|
|
820
|
+
distanceFade?: boolean;
|
|
821
|
+
/**
|
|
822
|
+
* Skip meshes above this triangle count entirely (default 4M) — extraction time is linear in
|
|
823
|
+
* triangles, and past this bound even the worker path burns seconds for a look the screen-space
|
|
824
|
+
* fallback approximates at constant cost. Skipped meshes are tagged
|
|
825
|
+
* `userData.edgesSkipped = 'triangle-cap'` so hosts can react (e.g. enable the render-pipeline
|
|
826
|
+
* edge pass).
|
|
827
|
+
*/
|
|
828
|
+
maxTriangles?: number;
|
|
829
|
+
/**
|
|
830
|
+
* Above this many extracted segments (default 2M), an overlay drops the distance fade so it
|
|
831
|
+
* renders opaque — millions of blended fat-line quads are a fill-rate cliff; opaque ones aren't.
|
|
832
|
+
*/
|
|
833
|
+
maxSegments?: number;
|
|
616
834
|
}
|
|
617
835
|
/** Tag on edge overlays so pick/fit/clear logic can recognize and skip or dispose them. */
|
|
618
836
|
declare const EDGE_USERDATA_KIND = "edge-overlay";
|
|
837
|
+
/** `userData.edgesSkipped` value on meshes whose triangle count exceeded {@link EdgeOptions.maxTriangles}. */
|
|
838
|
+
declare const EDGES_SKIPPED_TRIANGLE_CAP = "triangle-cap";
|
|
839
|
+
/** Whether an object is an edge overlay (for pick/fit filters elsewhere). */
|
|
840
|
+
declare function isEdgeOverlay(object: THREE.Object3D): boolean;
|
|
619
841
|
/**
|
|
620
842
|
* Walk an object subtree and attach an edge overlay to every `Mesh` found, returning the created
|
|
621
843
|
* overlays (so callers can dispose them explicitly if they don't clear the whole subtree). Meshes
|
|
622
844
|
* that already carry an overlay are skipped, so this is safe to call more than once.
|
|
623
845
|
*
|
|
624
846
|
* Skips the floor and the grid (they're aids, not content) and anything already tagged as an edge.
|
|
847
|
+
*
|
|
848
|
+
* Fully synchronous — extraction for every mesh runs on the calling thread. Interactive hosts with
|
|
849
|
+
* potentially-large meshes should prefer {@link addEdgesAsync}, which offloads big extractions to
|
|
850
|
+
* a worker.
|
|
625
851
|
*/
|
|
626
852
|
declare function addEdges(root: THREE.Object3D, options?: EdgeOptions): LineSegments2[];
|
|
627
|
-
/**
|
|
628
|
-
|
|
853
|
+
/**
|
|
854
|
+
* Like {@link addEdges}, but extraction for large meshes runs in a Worker so the main thread never
|
|
855
|
+
* stalls. Small meshes (< ~25k triangles) still attach synchronously before this returns — only
|
|
856
|
+
* heavy extractions arrive a beat later. Resolves with every overlay actually attached.
|
|
857
|
+
*
|
|
858
|
+
* Late results are dropped (never attached) when the mesh has left the root's subtree (scene was
|
|
859
|
+
* cleared by a newer solve), the root's edges were removed via {@link removeEdges}, or another
|
|
860
|
+
* apply already attached an overlay to that mesh.
|
|
861
|
+
*/
|
|
862
|
+
declare function addEdgesAsync(root: THREE.Object3D, options?: EdgeOptions): Promise<LineSegments2[]>;
|
|
629
863
|
/**
|
|
630
864
|
* Remove every edge overlay under `root`, disposing its geometry and material. The inverse of
|
|
631
|
-
* {@link addEdges}; together they make edges a live on/off toggle
|
|
865
|
+
* {@link addEdges}/{@link addEdgesAsync}; together they make edges a live on/off toggle — this
|
|
866
|
+
* also cancels any in-flight async attaches for `root`. Returns how many were removed.
|
|
632
867
|
*/
|
|
633
868
|
declare function removeEdges(root: THREE.Object3D): number;
|
|
634
869
|
|
|
635
870
|
/**
|
|
636
|
-
*
|
|
637
|
-
*
|
|
638
|
-
*
|
|
871
|
+
* Screen-space edge detection: draws crease/silhouette lines by finding depth and normal
|
|
872
|
+
* discontinuities, as a fullscreen pass — cost is O(pixels), independent of triangle count.
|
|
873
|
+
*
|
|
874
|
+
* This is the fallback look for scenes too heavy for geometry edge overlays (see
|
|
875
|
+
* docs/plans/4.edge-overlay-performance.md Phase 3): meshes over `EdgeOptions.maxTriangles` skip
|
|
876
|
+
* extraction, and this pass approximates the technical-drawing read at constant cost. Trade-offs
|
|
877
|
+
* vs geometry edges: uniform pixel width, one global color (no per-object tinting), view-dependent
|
|
878
|
+
* response, and gentle creases below the normal threshold don't register.
|
|
879
|
+
*
|
|
880
|
+
* Works like GTAOPass internally: the scene is re-rendered with a `MeshNormalMaterial` override
|
|
881
|
+
* into a normal target carrying a depth texture (a pattern this scene already tolerates for AO),
|
|
882
|
+
* then a fullscreen shader Roberts-crosses depth (relative view-Z difference, so far scenes don't
|
|
883
|
+
* dissolve into noise) and normals, and blends the edge color over the composed image.
|
|
884
|
+
*
|
|
885
|
+
* The render target is allocated lazily on first enabled render, so constructing the pass
|
|
886
|
+
* disabled costs nothing but the material.
|
|
887
|
+
*/
|
|
888
|
+
interface EdgeDetectionOptions {
|
|
889
|
+
/** Edge line color. Default 0x222222 — matches the geometry overlays' default. */
|
|
890
|
+
color?: THREE.ColorRepresentation;
|
|
891
|
+
/** Edge blend strength 0–1. Default 1. */
|
|
892
|
+
opacity?: number;
|
|
893
|
+
/**
|
|
894
|
+
* Normal discontinuity threshold, in summed `1 - dot(n₁, n₂)` across the two diagonal pairs.
|
|
895
|
+
* Lower catches gentler creases. Default 0.4 (≈ the 44° crease default of geometry edges).
|
|
896
|
+
*/
|
|
897
|
+
normalThreshold?: number;
|
|
898
|
+
/** Relative view-depth discontinuity threshold. Default 0.02 (2% of the center depth). */
|
|
899
|
+
depthThreshold?: number;
|
|
900
|
+
/** Sample offset in device px — line thickness. Default 1. */
|
|
901
|
+
thickness?: number;
|
|
902
|
+
}
|
|
903
|
+
declare class EdgeDetectionPass extends Pass {
|
|
904
|
+
camera: THREE.Camera;
|
|
905
|
+
private readonly scene;
|
|
906
|
+
private readonly normalMaterial;
|
|
907
|
+
private readonly edgeMaterial;
|
|
908
|
+
private readonly fsQuad;
|
|
909
|
+
private normalTarget;
|
|
910
|
+
private width;
|
|
911
|
+
private height;
|
|
912
|
+
constructor(scene: THREE.Scene, camera: THREE.Camera, width: number, height: number, options?: EdgeDetectionOptions);
|
|
913
|
+
private acquireNormalTarget;
|
|
914
|
+
setSize(width: number, height: number): void;
|
|
915
|
+
render(renderer: THREE.WebGLRenderer, writeBuffer: THREE.WebGLRenderTarget, readBuffer: THREE.WebGLRenderTarget): void;
|
|
916
|
+
dispose(): void;
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
/**
|
|
920
|
+
* Optional postprocessing pipeline. Default-OFF: the viewer only constructs this when a
|
|
921
|
+
* postprocessed feature (ambient occlusion, screen-space edges) is enabled, and otherwise renders
|
|
922
|
+
* with a plain `renderer.render` so the cheap path stays cheap (the chosen tradeoff — see
|
|
923
|
+
* cad-viewer-plan.md).
|
|
924
|
+
*
|
|
925
|
+
* Pipeline: RenderPass → GTAOPass? → EdgeDetectionPass? → SMAAPass → OutputPass. GTAO
|
|
926
|
+
* (ground-truth AO) is the modern replacement for SSAO/SAO — better contact shadows in crevices,
|
|
927
|
+
* the "engineered" depth cue. `screenSpaceRadius` is on so the AO radius is in screen space, which
|
|
928
|
+
* keeps it scale-robust across the viewer's mm→m scenes without per-scene tuning.
|
|
639
929
|
*
|
|
640
|
-
*
|
|
641
|
-
*
|
|
642
|
-
*
|
|
643
|
-
*
|
|
930
|
+
* EdgeDetectionPass draws crease/silhouette lines in screen space at O(pixels) — the fallback for
|
|
931
|
+
* scenes too triangle-heavy for geometry edge overlays (docs/plans/4.edge-overlay-performance.md).
|
|
932
|
+
* It sits before SMAA so its 1px lines get antialiased. Always constructed (its render target is
|
|
933
|
+
* lazy), so it can be toggled at runtime via {@link RenderPipeline.setEdgeDetection} without a
|
|
934
|
+
* pipeline rebuild.
|
|
644
935
|
*
|
|
645
936
|
* SMAA restores antialiasing on this path. The EffectComposer renders into an offscreen target, so
|
|
646
937
|
* the WebGLRenderer's own MSAA (`antialias: true`) does nothing here — without a dedicated AA pass,
|
|
@@ -658,12 +949,18 @@ interface RenderPipeline {
|
|
|
658
949
|
setSize(width: number, height: number, pixelRatio: number): void;
|
|
659
950
|
/** Point the passes at the currently active camera (call when projection changes). */
|
|
660
951
|
setCamera(camera: THREE.Camera): void;
|
|
952
|
+
/** Toggle the screen-space edge pass at runtime (no pipeline rebuild). */
|
|
953
|
+
setEdgeDetection(enabled: boolean): void;
|
|
954
|
+
/** Whether the screen-space edge pass currently runs. */
|
|
955
|
+
edgeDetectionEnabled(): boolean;
|
|
661
956
|
dispose(): void;
|
|
662
957
|
}
|
|
663
958
|
interface RenderPipelineOptions {
|
|
664
959
|
/** Tone mapping to apply in OutputPass (mirror the renderer's). */
|
|
665
960
|
toneMapping: THREE.ToneMapping;
|
|
666
961
|
toneMappingExposure: number;
|
|
962
|
+
/** Build the pipeline with the GTAO ambient-occlusion pass. Default true. */
|
|
963
|
+
ambientOcclusion?: boolean;
|
|
667
964
|
/** AO strength 0–1. Default 1. */
|
|
668
965
|
aoIntensity?: number;
|
|
669
966
|
/**
|
|
@@ -672,6 +969,11 @@ interface RenderPipelineOptions {
|
|
|
672
969
|
* pixelRatio is clamped to this. Default 1.
|
|
673
970
|
*/
|
|
674
971
|
aoPixelRatio?: number;
|
|
972
|
+
/**
|
|
973
|
+
* Start with the screen-space edge pass enabled; pass an object to tune it. The pass itself is
|
|
974
|
+
* always constructed (cheap while disabled) so it can be toggled later via `setEdgeDetection`.
|
|
975
|
+
*/
|
|
976
|
+
edgeDetection?: boolean | EdgeDetectionOptions;
|
|
675
977
|
}
|
|
676
978
|
declare function createRenderPipeline(renderer: THREE.WebGLRenderer, scene: THREE.Scene, camera: THREE.Camera, width: number, height: number, options: RenderPipelineOptions): RenderPipeline;
|
|
677
979
|
|
|
@@ -715,11 +1017,11 @@ declare const SCALE_FACTORS: Record<string, number>;
|
|
|
715
1017
|
* // With debugging enabled
|
|
716
1018
|
* const meshes = await getThreeMeshesFromComputeResponse(response, { debug: true });
|
|
717
1019
|
*
|
|
718
|
-
* //
|
|
1020
|
+
* // Opt in to seating the model on the grid instead of using its Rhino coordinates
|
|
719
1021
|
* const meshes = await getThreeMeshesFromComputeResponse(response, {
|
|
720
1022
|
* debug: true,
|
|
721
1023
|
* allowScaling: true,
|
|
722
|
-
* allowAutoPosition:
|
|
1024
|
+
* allowAutoPosition: true,
|
|
723
1025
|
* parsing: {
|
|
724
1026
|
* mergeByMaterial: false,
|
|
725
1027
|
* applyTransforms: true,
|
|
@@ -788,4 +1090,4 @@ interface DisplayItemParseOptions {
|
|
|
788
1090
|
*/
|
|
789
1091
|
declare function parseDisplayItems(items: DisplayItem[] | undefined, options?: DisplayItemParseOptions): THREE.Object3D[];
|
|
790
1092
|
|
|
791
|
-
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 };
|
|
1093
|
+
export { type CameraConfig, type CameraController, type CameraProjection, type ControlsConfig, DisplayBatch, DisplayItem, type DisplayItemParseOptions, EDGES_SKIPPED_TRIANGLE_CAP, EDGE_USERDATA_KIND, type EdgeDetectionOptions, EdgeDetectionPass, 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 UpBasis, type ViewGizmo, type ViewPreset, addEdges, addEdgesAsync, applyOffset, buildUpBasis, computeCombinedBoundingBox, createCameraController, createGrid, createLabelLayer, createMeasureTool, createRenderPipeline, createViewGizmo, environmentRotationFor, getThreeMeshesFromComputeResponse, initThree, isEdgeOverlay, isoOffset, parseColor, parseDisplayItems, parseMeshBatchBlob, parseMeshBatchObject, removeEdges, snapToVertex, sunOffset, upToAxis, updateScene };
|