three-cad-viewer 4.1.2 → 4.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Readme.md +12 -5
- package/dist/camera/camera.d.ts +14 -2
- package/dist/core/studio-manager.d.ts +91 -0
- package/dist/core/types.d.ts +260 -9
- package/dist/core/viewer-state.d.ts +28 -2
- package/dist/core/viewer.d.ts +200 -6
- package/dist/index.d.ts +7 -2
- package/dist/rendering/environment.d.ts +239 -0
- package/dist/rendering/light-detection.d.ts +44 -0
- package/dist/rendering/material-factory.d.ts +77 -2
- package/dist/rendering/material-presets.d.ts +32 -0
- package/dist/rendering/room-environment.d.ts +13 -0
- package/dist/rendering/studio-composer.d.ts +130 -0
- package/dist/rendering/studio-floor.d.ts +53 -0
- package/dist/rendering/texture-cache.d.ts +142 -0
- package/dist/rendering/triplanar.d.ts +37 -0
- package/dist/scene/animation.d.ts +1 -1
- package/dist/scene/clipping.d.ts +31 -0
- package/dist/scene/nestedgroup.d.ts +64 -27
- package/dist/scene/objectgroup.d.ts +47 -0
- package/dist/three-cad-viewer.css +339 -29
- package/dist/three-cad-viewer.esm.js +27567 -11874
- package/dist/three-cad-viewer.esm.js.map +1 -1
- package/dist/three-cad-viewer.esm.min.js +10 -4
- package/dist/three-cad-viewer.js +27486 -11787
- package/dist/three-cad-viewer.min.js +10 -4
- package/dist/ui/display.d.ts +147 -0
- package/dist/utils/decode-instances.d.ts +60 -0
- package/dist/utils/utils.d.ts +10 -0
- package/package.json +4 -2
- package/src/_version.ts +1 -1
- package/src/camera/camera.ts +27 -10
- package/src/core/studio-manager.ts +682 -0
- package/src/core/types.ts +328 -9
- package/src/core/viewer-state.ts +84 -4
- package/src/core/viewer.ts +453 -22
- package/src/index.ts +25 -1
- package/src/rendering/environment.ts +840 -0
- package/src/rendering/light-detection.ts +327 -0
- package/src/rendering/material-factory.ts +456 -2
- package/src/rendering/material-presets.ts +303 -0
- package/src/rendering/raycast.ts +2 -2
- package/src/rendering/room-environment.ts +192 -0
- package/src/rendering/studio-composer.ts +577 -0
- package/src/rendering/studio-floor.ts +108 -0
- package/src/rendering/texture-cache.ts +1020 -0
- package/src/rendering/triplanar.ts +329 -0
- package/src/scene/animation.ts +3 -2
- package/src/scene/clipping.ts +59 -0
- package/src/scene/nestedgroup.ts +399 -0
- package/src/scene/objectgroup.ts +186 -11
- package/src/scene/orientation.ts +12 -0
- package/src/scene/render-shape.ts +55 -21
- package/src/types/n8ao.d.ts +28 -0
- package/src/ui/display.ts +1032 -27
- package/src/ui/index.html +181 -44
- package/src/utils/decode-instances.ts +233 -0
- package/src/utils/utils.ts +33 -20
package/Readme.md
CHANGED
|
@@ -257,7 +257,7 @@ After the initial `viewer.render()`, parts can be added, removed, or updated wit
|
|
|
257
257
|
`addPart(parentPath, partData)` creates new Three.js objects (meshes, edges, clipping stencils) from the part data and inserts them into the scene graph and navigation tree. `removePart(path)` disposes the Three.js objects and removes the part from the scene.
|
|
258
258
|
|
|
259
259
|
```js
|
|
260
|
-
viewer.addPart("/Group", partData);
|
|
260
|
+
viewer.addPart("/Group", partData); // creates "/Group/PartName"
|
|
261
261
|
viewer.removePart("/Group/PartName");
|
|
262
262
|
```
|
|
263
263
|
|
|
@@ -296,9 +296,12 @@ Add, remove, and update calls can be freely mixed within a single batch.
|
|
|
296
296
|
viewer.render(shapes, renderOptions, viewerOptions);
|
|
297
297
|
|
|
298
298
|
viewer.ensureStencilSize({
|
|
299
|
-
xmin: -200,
|
|
300
|
-
|
|
301
|
-
|
|
299
|
+
xmin: -200,
|
|
300
|
+
xmax: 200,
|
|
301
|
+
ymin: -200,
|
|
302
|
+
ymax: 200,
|
|
303
|
+
zmin: 0,
|
|
304
|
+
zmax: 300,
|
|
302
305
|
});
|
|
303
306
|
|
|
304
307
|
// All updates within these bounds are now stencil-rebuild-free
|
|
@@ -340,7 +343,7 @@ Pass a partial keymap to override individual bindings — unspecified keys keep
|
|
|
340
343
|
|
|
341
344
|
```javascript
|
|
342
345
|
const displayOptions = {
|
|
343
|
-
keymap: { axes: "q", reset: "!" },
|
|
346
|
+
keymap: { axes: "q", reset: "!" }, // only these two change
|
|
344
347
|
};
|
|
345
348
|
```
|
|
346
349
|
|
|
@@ -427,3 +430,7 @@ For the deployment, see [Release.md](./Release.md)
|
|
|
427
430
|
# Changes
|
|
428
431
|
|
|
429
432
|
see [Changes.md](./Changes.md)
|
|
433
|
+
|
|
434
|
+
## Credit
|
|
435
|
+
|
|
436
|
+
- The toycar example is downloaded from https://grabcad.com/library/toy-rider-car-1 and tessellated
|
package/dist/camera/camera.d.ts
CHANGED
|
@@ -22,6 +22,13 @@ type UpMode = "y_up" | "z_up" | "legacy";
|
|
|
22
22
|
*/
|
|
23
23
|
declare class Camera {
|
|
24
24
|
private static readonly DISTANCE_FACTOR;
|
|
25
|
+
/**
|
|
26
|
+
* Near plane factor: near = max(0.1, NEAR_FACTOR * distance).
|
|
27
|
+
* With far = 100 * distance, this gives a far/near ratio of 10,000:1,
|
|
28
|
+
* which is comfortable for 24-bit depth buffers and avoids z-fighting
|
|
29
|
+
* on large models (e.g. toycar at ~1100 unit bounding radius).
|
|
30
|
+
*/
|
|
31
|
+
private static readonly NEAR_FACTOR;
|
|
25
32
|
target: THREE.Vector3;
|
|
26
33
|
ortho: boolean;
|
|
27
34
|
up: UpMode;
|
|
@@ -31,6 +38,11 @@ declare class Camera {
|
|
|
31
38
|
pCamera: THREE.PerspectiveCamera;
|
|
32
39
|
oCamera: THREE.OrthographicCamera;
|
|
33
40
|
camera: THREE.PerspectiveCamera | THREE.OrthographicCamera;
|
|
41
|
+
/**
|
|
42
|
+
* Compute the near clipping plane from the bounding radius.
|
|
43
|
+
* Keeps the far/near ratio bounded for depth buffer precision.
|
|
44
|
+
*/
|
|
45
|
+
private static _computeNear;
|
|
34
46
|
/**
|
|
35
47
|
* Create a combined camera (orthographic and perspective).
|
|
36
48
|
* @param width - canvas width.
|
|
@@ -42,8 +54,8 @@ declare class Camera {
|
|
|
42
54
|
*/
|
|
43
55
|
constructor(width: number, height: number, distance: number, target: Vector3Tuple, ortho: boolean, up: UpDirection);
|
|
44
56
|
/**
|
|
45
|
-
* Update the far clipping
|
|
46
|
-
* @param distance - The new bounding radius to base the
|
|
57
|
+
* Update the near/far clipping planes for both cameras.
|
|
58
|
+
* @param distance - The new bounding radius to base the clipping planes on.
|
|
47
59
|
*/
|
|
48
60
|
updateFarPlane(distance: number): void;
|
|
49
61
|
/**
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* StudioManager — orchestrates Studio mode rendering.
|
|
3
|
+
*
|
|
4
|
+
* Extracted from viewer.ts to reduce its complexity. Owns the Studio-specific
|
|
5
|
+
* resources (composer, floor, shadow lights, environment manager) and handles
|
|
6
|
+
* all Studio subscriptions and mode enter/leave logic.
|
|
7
|
+
*
|
|
8
|
+
* Communicates with the Viewer via the StudioManagerContext interface to avoid
|
|
9
|
+
* a circular dependency.
|
|
10
|
+
*/
|
|
11
|
+
import * as THREE from "three";
|
|
12
|
+
import { EnvironmentManager } from "../rendering/environment.js";
|
|
13
|
+
import { StudioFloor } from "../rendering/studio-floor.js";
|
|
14
|
+
import { ViewerState } from "./viewer-state.js";
|
|
15
|
+
import type { NestedGroup, ObjectGroup } from "../scene/nestedgroup.js";
|
|
16
|
+
import type { Camera } from "../camera/camera.js";
|
|
17
|
+
import type { Clipping } from "../scene/clipping.js";
|
|
18
|
+
import type { BoundingBox } from "../scene/bbox.js";
|
|
19
|
+
/**
|
|
20
|
+
* Abstraction over Viewer that StudioManager uses. Keeps the dependency
|
|
21
|
+
* one-directional (StudioManager → context, never StudioManager → Viewer).
|
|
22
|
+
*/
|
|
23
|
+
export interface StudioManagerContext {
|
|
24
|
+
renderer: THREE.WebGLRenderer;
|
|
25
|
+
state: ViewerState;
|
|
26
|
+
/** Whether viewer has rendered content. */
|
|
27
|
+
isRendered(): boolean;
|
|
28
|
+
getScene(): THREE.Scene;
|
|
29
|
+
getCamera(): Camera;
|
|
30
|
+
getAmbientLight(): THREE.AmbientLight;
|
|
31
|
+
getDirectLight(): THREE.DirectionalLight;
|
|
32
|
+
getNestedGroup(): NestedGroup;
|
|
33
|
+
getClipping(): Clipping;
|
|
34
|
+
getBbox(): BoundingBox | null;
|
|
35
|
+
getLastBboxId(): string | null;
|
|
36
|
+
setAxes(flag: boolean, notify?: boolean): void;
|
|
37
|
+
setGrids(grids: [boolean, boolean, boolean], notify?: boolean): void;
|
|
38
|
+
setOrtho(flag: boolean, notify?: boolean): void;
|
|
39
|
+
update(updateMarker: boolean, notify?: boolean): void;
|
|
40
|
+
dispatchEvent(event: Event): void;
|
|
41
|
+
onSelectionChanged(id: string | null): void;
|
|
42
|
+
}
|
|
43
|
+
declare class StudioManager {
|
|
44
|
+
readonly envManager: EnvironmentManager;
|
|
45
|
+
readonly floor: StudioFloor;
|
|
46
|
+
private _composer;
|
|
47
|
+
private _active;
|
|
48
|
+
private _savedClippingState;
|
|
49
|
+
private _savedViewState;
|
|
50
|
+
private _shadowLights;
|
|
51
|
+
private _ctx;
|
|
52
|
+
constructor(ctx: StudioManagerContext);
|
|
53
|
+
get isActive(): boolean;
|
|
54
|
+
get hasComposer(): boolean;
|
|
55
|
+
/** Render via composer (call from Viewer.update / _animate). */
|
|
56
|
+
render(): void;
|
|
57
|
+
/** Update composer camera (call from Viewer.switchCamera). */
|
|
58
|
+
setCamera(camera: THREE.Camera): void;
|
|
59
|
+
/** Resize composer (call from Viewer.resize). */
|
|
60
|
+
setSize(width: number, height: number): void;
|
|
61
|
+
/** Whether env background needs per-frame update. */
|
|
62
|
+
get isEnvBackgroundActive(): boolean;
|
|
63
|
+
/** Update env background (ortho workaround, call per frame). */
|
|
64
|
+
updateEnvBackground(renderer: THREE.WebGLRenderer, camera: THREE.Camera): void;
|
|
65
|
+
/** Check if an environment name is a Poly Haven preset. */
|
|
66
|
+
isEnvPreset(name: string): boolean;
|
|
67
|
+
/**
|
|
68
|
+
* Get the ObjectGroup and path for the currently selected object.
|
|
69
|
+
* Returns null if nothing selected or Studio mode inactive.
|
|
70
|
+
*/
|
|
71
|
+
getSelectedObjectGroup(): {
|
|
72
|
+
object: ObjectGroup;
|
|
73
|
+
path: string;
|
|
74
|
+
} | null;
|
|
75
|
+
enterStudioMode: () => Promise<void>;
|
|
76
|
+
leaveStudioMode: () => void;
|
|
77
|
+
resetStudio: () => void;
|
|
78
|
+
/**
|
|
79
|
+
* Dispose all Studio resources. Called from Viewer.dispose().
|
|
80
|
+
* Must be called BEFORE renderer.dispose().
|
|
81
|
+
*/
|
|
82
|
+
dispose(): void;
|
|
83
|
+
private _setupSubscriptions;
|
|
84
|
+
private _configureFloor;
|
|
85
|
+
private _configureShadowLights;
|
|
86
|
+
private _removeShadowLights;
|
|
87
|
+
private _setShadowsEnabled;
|
|
88
|
+
private _applyToneMapping;
|
|
89
|
+
private _rebuildMaterials;
|
|
90
|
+
}
|
|
91
|
+
export { StudioManager };
|
package/dist/core/types.d.ts
CHANGED
|
@@ -15,11 +15,24 @@ export type UpDirection = "Z" | "Y" | "legacy";
|
|
|
15
15
|
/** Animation mode */
|
|
16
16
|
export type AnimationMode = "none" | "animation" | "explode";
|
|
17
17
|
/** Active sidebar tab */
|
|
18
|
-
export type ActiveTab = "tree" | "clip" | "material" | "zebra";
|
|
18
|
+
export type ActiveTab = "tree" | "clip" | "material" | "zebra" | "studio";
|
|
19
19
|
/** Zebra color scheme */
|
|
20
20
|
export type ZebraColorScheme = "blackwhite" | "colorful" | "grayscale";
|
|
21
21
|
/** Zebra mapping mode */
|
|
22
22
|
export type ZebraMappingMode = "reflection" | "normal";
|
|
23
|
+
/**
|
|
24
|
+
* Studio environment preset name.
|
|
25
|
+
* - "studio": Built-in procedural RoomEnvironment (zero network)
|
|
26
|
+
* - "none": No environment map
|
|
27
|
+
* - Any other string: Poly Haven HDR preset slug or custom HDR URL
|
|
28
|
+
*/
|
|
29
|
+
export type StudioEnvironment = string;
|
|
30
|
+
/** Studio tone mapping algorithm */
|
|
31
|
+
export type StudioToneMapping = "neutral" | "ACES" | "none";
|
|
32
|
+
/** Studio background mode */
|
|
33
|
+
export type StudioBackground = "grey" | "darkgrey" | "white" | "gradient" | "gradient-dark" | "environment" | "transparent";
|
|
34
|
+
/** Studio texture mapping mode */
|
|
35
|
+
export type StudioTextureMapping = "triplanar" | "parametric";
|
|
23
36
|
/** Shape type */
|
|
24
37
|
export type ShapeType = "shapes" | "edges" | "vertices";
|
|
25
38
|
/** Shape subtype */
|
|
@@ -43,6 +56,8 @@ export declare enum CollapseState {
|
|
|
43
56
|
export type ColorValue = number | string;
|
|
44
57
|
/** RGB color as tuple [r, g, b] with values 0-1 */
|
|
45
58
|
export type RGBColor = [number, number, number];
|
|
59
|
+
/** RGBA color as tuple [r, g, b, a] with values 0-1 */
|
|
60
|
+
export type RGBAColor = [number, number, number, number];
|
|
46
61
|
/** Axis colors per theme - array of RGB colors for X, Y, Z axes */
|
|
47
62
|
export type AxisColors = Record<Theme, RGBColor[]>;
|
|
48
63
|
/** Flat axis colors per theme - all RGB values concatenated for line geometry */
|
|
@@ -126,7 +141,7 @@ export interface ChangeNotification {
|
|
|
126
141
|
/** Callback for notifications */
|
|
127
142
|
export type NotificationCallback = (change: ChangeNotification) => void;
|
|
128
143
|
/** Action shortcut names for toolbar buttons and tabs */
|
|
129
|
-
export type ActionShortcutName = "axes" | "axes0" | "grid" | "gridxy" | "perspective" | "transparent" | "blackedges" | "zscale" | "reset" | "resize" | "iso" | "front" | "rear" | "top" | "bottom" | "left" | "right" | "explode" | "distance" | "properties" | "select" | "help" | "play" | "stop" | "tree" | "clip" | "material" | "zebra";
|
|
144
|
+
export type ActionShortcutName = "axes" | "axes0" | "grid" | "gridxy" | "perspective" | "transparent" | "blackedges" | "zscale" | "reset" | "resize" | "iso" | "front" | "rear" | "top" | "bottom" | "left" | "right" | "explode" | "distance" | "properties" | "select" | "help" | "play" | "stop" | "tree" | "clip" | "material" | "zebra" | "studio";
|
|
130
145
|
/** Action keymap: action name → key character */
|
|
131
146
|
export type ActionKeymap = Partial<Record<ActionShortcutName, string>>;
|
|
132
147
|
/** Combined keymap: modifier keys + action shortcuts */
|
|
@@ -168,28 +183,34 @@ export interface DisplayOptions {
|
|
|
168
183
|
zscaleTool?: boolean;
|
|
169
184
|
/** Show zebra tool (default: true) */
|
|
170
185
|
zebraTool?: boolean;
|
|
186
|
+
/** Show studio tool (default: true) */
|
|
187
|
+
studioTool?: boolean;
|
|
171
188
|
/** Enable measurement debug mode (default: false) */
|
|
172
189
|
measurementDebug?: boolean;
|
|
190
|
+
/** External canvas element to use for the WebGL renderer, enabling shared WebGL context scenarios (default: undefined — renderer creates its own canvas) */
|
|
191
|
+
canvas?: HTMLCanvasElement;
|
|
192
|
+
/** External WebGL context to use for the renderer. When provided together with `canvas`, the renderer will use this context instead of creating a new one. Useful for sharing a context with other renderers like PixiJS. (default: undefined) */
|
|
193
|
+
gl?: WebGLRenderingContext | WebGL2RenderingContext;
|
|
173
194
|
}
|
|
174
195
|
/** Render options */
|
|
175
196
|
export interface RenderOptions {
|
|
176
197
|
/** Default edge color (default: 0x707070) */
|
|
177
198
|
edgeColor?: number;
|
|
178
|
-
/** Ambient light intensity (default:
|
|
199
|
+
/** Ambient light intensity (default: 1) */
|
|
179
200
|
ambientIntensity?: number;
|
|
180
|
-
/** Direct light intensity (default:
|
|
201
|
+
/** Direct light intensity (default: 1.1) */
|
|
181
202
|
directIntensity?: number;
|
|
182
|
-
/** Metalness (default: 0.
|
|
203
|
+
/** Metalness (default: 0.3) */
|
|
183
204
|
metalness?: number;
|
|
184
|
-
/** Roughness (default: 0.
|
|
205
|
+
/** Roughness (default: 0.65) */
|
|
185
206
|
roughness?: number;
|
|
186
207
|
/** Default opacity level for transparency (default: 0.5) */
|
|
187
208
|
defaultOpacity?: number;
|
|
188
209
|
/** Show triangle normals when normalLen > 0 (default: 0) */
|
|
189
210
|
normalLen?: number;
|
|
190
211
|
}
|
|
191
|
-
/** Viewer options */
|
|
192
|
-
export interface ViewerOptions {
|
|
212
|
+
/** Viewer options (includes studio mode configuration) */
|
|
213
|
+
export interface ViewerOptions extends StudioModeOptions {
|
|
193
214
|
/** Use OrbitControls or TrackballControls (default: "orbit") */
|
|
194
215
|
control?: ControlType;
|
|
195
216
|
/** Show X-, Y-, Z-axes (default: false) */
|
|
@@ -264,8 +285,33 @@ export interface ZebraOptions {
|
|
|
264
285
|
/** Zebra mapping mode (default: "reflection") */
|
|
265
286
|
zebraMappingMode?: ZebraMappingMode;
|
|
266
287
|
}
|
|
288
|
+
/** Studio mode options (environment, tone mapping, edges) */
|
|
289
|
+
export interface StudioModeOptions {
|
|
290
|
+
/** Environment preset or custom HDR URL (default: "studio") */
|
|
291
|
+
studioEnvironment?: string;
|
|
292
|
+
/** Environment map intensity, 0-1 (default: 0.5) */
|
|
293
|
+
studioEnvIntensity?: number;
|
|
294
|
+
/** Background mode (default: "environment") */
|
|
295
|
+
studioBackground?: StudioBackground;
|
|
296
|
+
/** Tone mapping algorithm (default: "neutral") */
|
|
297
|
+
studioToneMapping?: StudioToneMapping;
|
|
298
|
+
/** Tone mapping exposure, 0-2 (default: 1.0) */
|
|
299
|
+
studioExposure?: number;
|
|
300
|
+
/** Use 4K environment maps instead of 2K (default: false) */
|
|
301
|
+
studio4kEnvMaps?: boolean;
|
|
302
|
+
/** Texture mapping mode: triplanar projection or parametric UVs (default: "triplanar") */
|
|
303
|
+
studioTextureMapping?: StudioTextureMapping;
|
|
304
|
+
/** Environment map rotation in degrees, 0-360 (default: 0) */
|
|
305
|
+
studioEnvRotation?: number;
|
|
306
|
+
/** Shadow intensity, 0-1 (default: 0 = off) */
|
|
307
|
+
studioShadowIntensity?: number;
|
|
308
|
+
/** Shadow softness, 0-1 (default: 0.3) */
|
|
309
|
+
studioShadowSoftness?: number;
|
|
310
|
+
/** Ambient occlusion intensity, 0-3.0 (default: 0 = off) */
|
|
311
|
+
studioAOIntensity?: number;
|
|
312
|
+
}
|
|
267
313
|
/** Combined options for initialization */
|
|
268
|
-
export type CombinedOptions = DisplayOptions & RenderOptions & ViewerOptions & ZebraOptions;
|
|
314
|
+
export type CombinedOptions = DisplayOptions & RenderOptions & ViewerOptions & ZebraOptions & StudioModeOptions;
|
|
269
315
|
/** Complete state shape with all properties */
|
|
270
316
|
export interface ViewerStateShape {
|
|
271
317
|
theme: Theme;
|
|
@@ -283,6 +329,7 @@ export interface ViewerStateShape {
|
|
|
283
329
|
explodeTool: boolean;
|
|
284
330
|
zscaleTool: boolean;
|
|
285
331
|
zebraTool: boolean;
|
|
332
|
+
studioTool: boolean;
|
|
286
333
|
measurementDebug: boolean;
|
|
287
334
|
ambientIntensity: number;
|
|
288
335
|
directIntensity: number;
|
|
@@ -326,6 +373,17 @@ export interface ViewerStateShape {
|
|
|
326
373
|
zebraDirection: number;
|
|
327
374
|
zebraColorScheme: ZebraColorScheme;
|
|
328
375
|
zebraMappingMode: ZebraMappingMode;
|
|
376
|
+
studioEnvironment: string;
|
|
377
|
+
studioEnvIntensity: number;
|
|
378
|
+
studioBackground: StudioBackground;
|
|
379
|
+
studioToneMapping: StudioToneMapping;
|
|
380
|
+
studioExposure: number;
|
|
381
|
+
studio4kEnvMaps: boolean;
|
|
382
|
+
studioTextureMapping: StudioTextureMapping;
|
|
383
|
+
studioEnvRotation: number;
|
|
384
|
+
studioShadowIntensity: number;
|
|
385
|
+
studioShadowSoftness: number;
|
|
386
|
+
studioAOIntensity: number;
|
|
329
387
|
activeTool: string | null;
|
|
330
388
|
animationMode: AnimationMode;
|
|
331
389
|
animationSliderValue: number;
|
|
@@ -335,6 +393,176 @@ export interface ViewerStateShape {
|
|
|
335
393
|
}
|
|
336
394
|
/** Keys of ViewerStateShape */
|
|
337
395
|
export type StateKey = keyof ViewerStateShape;
|
|
396
|
+
/**
|
|
397
|
+
* Material appearance definition for Studio mode.
|
|
398
|
+
*
|
|
399
|
+
* All fields are optional. Only provided fields override defaults.
|
|
400
|
+
* In Studio mode the viewer uses MeshPhysicalMaterial; properties left
|
|
401
|
+
* unset default to their "off" values (transmission=0, clearcoat=0, etc.)
|
|
402
|
+
* which the shader skips at near-zero cost.
|
|
403
|
+
*
|
|
404
|
+
* This is a data-format interface (describes JSON input), not a Three.js material.
|
|
405
|
+
* Texture string fields reference either a key in the root-level `textures` table,
|
|
406
|
+
* a data URI, or a URL resolved against the HTML page.
|
|
407
|
+
*/
|
|
408
|
+
export interface MaterialAppearance {
|
|
409
|
+
/** Display name */
|
|
410
|
+
name?: string;
|
|
411
|
+
/** Reference to a built-in preset (e.g., "stainless-steel", "car-paint") */
|
|
412
|
+
builtin?: string;
|
|
413
|
+
/** sRGB base color. Accepts RGBA tuple [r,g,b,a] (0-1) or CSS hex string "#rrggbb". */
|
|
414
|
+
color?: RGBAColor | string;
|
|
415
|
+
/** Texture reference for base color */
|
|
416
|
+
map?: string;
|
|
417
|
+
/** Metalness factor, 0-1 (default: 0.0) */
|
|
418
|
+
metalness?: number;
|
|
419
|
+
/** Roughness factor, 0-1 (default: 0.5) */
|
|
420
|
+
roughness?: number;
|
|
421
|
+
/** Normal map texture reference */
|
|
422
|
+
normalMap?: string;
|
|
423
|
+
/** Ambient occlusion texture reference */
|
|
424
|
+
aoMap?: string;
|
|
425
|
+
/** Metalness map texture reference */
|
|
426
|
+
metalnessMap?: string;
|
|
427
|
+
/** Roughness map texture reference */
|
|
428
|
+
roughnessMap?: string;
|
|
429
|
+
/** Emissive color, linear RGB */
|
|
430
|
+
emissive?: RGBColor;
|
|
431
|
+
/** Emissive map texture reference */
|
|
432
|
+
emissiveMap?: string;
|
|
433
|
+
/** Emissive intensity multiplier (default: 1.0) */
|
|
434
|
+
emissiveIntensity?: number;
|
|
435
|
+
/** Alpha blending mode */
|
|
436
|
+
alphaMode?: "OPAQUE" | "MASK" | "BLEND";
|
|
437
|
+
/** Alpha cutoff threshold for MASK mode (default: 0.5) */
|
|
438
|
+
alphaCutoff?: number;
|
|
439
|
+
/** Transmission factor, 0-1 */
|
|
440
|
+
transmission?: number;
|
|
441
|
+
/** Transmission map texture reference */
|
|
442
|
+
transmissionMap?: string;
|
|
443
|
+
/** Clearcoat intensity, 0-1 */
|
|
444
|
+
clearcoat?: number;
|
|
445
|
+
/** Clearcoat roughness */
|
|
446
|
+
clearcoatRoughness?: number;
|
|
447
|
+
/** Clearcoat intensity texture reference */
|
|
448
|
+
clearcoatMap?: string;
|
|
449
|
+
/** Clearcoat roughness texture reference */
|
|
450
|
+
clearcoatRoughnessMap?: string;
|
|
451
|
+
/** Clearcoat normal map texture reference */
|
|
452
|
+
clearcoatNormalMap?: string;
|
|
453
|
+
/** Thickness for volume effects */
|
|
454
|
+
thickness?: number;
|
|
455
|
+
/** Thickness map texture reference */
|
|
456
|
+
thicknessMap?: string;
|
|
457
|
+
/** Attenuation distance for volume absorption */
|
|
458
|
+
attenuationDistance?: number;
|
|
459
|
+
/** Attenuation color, linear RGB */
|
|
460
|
+
attenuationColor?: RGBColor;
|
|
461
|
+
/** Index of refraction (default: 1.5) */
|
|
462
|
+
ior?: number;
|
|
463
|
+
/** Specular intensity, 0-1 */
|
|
464
|
+
specularIntensity?: number;
|
|
465
|
+
/** Specular tint color, linear RGB */
|
|
466
|
+
specularColor?: RGBColor;
|
|
467
|
+
/** Specular intensity texture reference */
|
|
468
|
+
specularIntensityMap?: string;
|
|
469
|
+
/** Specular color texture reference */
|
|
470
|
+
specularColorMap?: string;
|
|
471
|
+
/** Sheen intensity, 0-1 (required to enable sheen layer) */
|
|
472
|
+
sheen?: number;
|
|
473
|
+
/** Sheen tint color, linear RGB */
|
|
474
|
+
sheenColor?: RGBColor;
|
|
475
|
+
/** Sheen roughness */
|
|
476
|
+
sheenRoughness?: number;
|
|
477
|
+
/** Sheen color texture reference */
|
|
478
|
+
sheenColorMap?: string;
|
|
479
|
+
/** Sheen roughness texture reference */
|
|
480
|
+
sheenRoughnessMap?: string;
|
|
481
|
+
/** Anisotropy strength, 0-1 */
|
|
482
|
+
anisotropy?: number;
|
|
483
|
+
/** Anisotropy rotation in radians */
|
|
484
|
+
anisotropyRotation?: number;
|
|
485
|
+
/** Anisotropy direction texture reference */
|
|
486
|
+
anisotropyMap?: string;
|
|
487
|
+
/** Use MeshBasicMaterial (unlit, no shading) */
|
|
488
|
+
unlit?: boolean;
|
|
489
|
+
/** Render both sides of faces (THREE.DoubleSide) */
|
|
490
|
+
doubleSided?: boolean;
|
|
491
|
+
}
|
|
492
|
+
/**
|
|
493
|
+
* Material definition from threejs-materials (Three.js MeshPhysicalMaterial-compatible).
|
|
494
|
+
*
|
|
495
|
+
* This format is produced by the threejs-materials Python library, which catalogs
|
|
496
|
+
* PBR materials from ambientCG, GPUOpen, PolyHaven, and PhysicallyBased.
|
|
497
|
+
* The `properties` dict uses simplified property names (e.g., "color", "roughness",
|
|
498
|
+
* "normal") where each entry has an optional `value` (scalar or color array in
|
|
499
|
+
* linear RGB) and/or `texture` (inline data URI).
|
|
500
|
+
*
|
|
501
|
+
* Detected by the presence of the `properties` key.
|
|
502
|
+
* Extra keys from threejs-materials (id, name, source, url, license) pass through
|
|
503
|
+
* harmlessly and are not part of this interface.
|
|
504
|
+
*/
|
|
505
|
+
export interface MaterialXMaterial {
|
|
506
|
+
/** Material properties from threejs-materials. Each key maps to { value?, texture? } */
|
|
507
|
+
properties: Record<string, {
|
|
508
|
+
value?: unknown;
|
|
509
|
+
texture?: string;
|
|
510
|
+
}>;
|
|
511
|
+
/** Optional texture tiling [u, v], default [1, 1]. Applied to all textures. */
|
|
512
|
+
textureRepeat?: [number, number];
|
|
513
|
+
}
|
|
514
|
+
/**
|
|
515
|
+
* Type guard to check if a material entry is a threejs-materials format dict.
|
|
516
|
+
* Detected by the presence of the `properties` key.
|
|
517
|
+
*/
|
|
518
|
+
export declare function isMaterialXMaterial(m: unknown): m is MaterialXMaterial;
|
|
519
|
+
/**
|
|
520
|
+
* Entry in the root-level `textures` table.
|
|
521
|
+
*
|
|
522
|
+
* Each entry is either embedded (base64-encoded image data) or a URL reference
|
|
523
|
+
* loaded on demand. At least one of `data`+`format` or `url` must be provided.
|
|
524
|
+
* An empty TextureEntry is invalid and will be ignored at runtime.
|
|
525
|
+
* Multiple builtin preset texture fields can reference the same key for
|
|
526
|
+
* deduplication. threejs-materials carry their own textures as inline data URIs.
|
|
527
|
+
*/
|
|
528
|
+
export interface TextureEntry {
|
|
529
|
+
/** Base64-encoded image data (for embedded textures) */
|
|
530
|
+
data?: string;
|
|
531
|
+
/** Image format, e.g., "png", "jpg", "webp" (required when data is provided) */
|
|
532
|
+
format?: string;
|
|
533
|
+
/** URL to load the texture from (for URL-referenced textures) */
|
|
534
|
+
url?: string;
|
|
535
|
+
}
|
|
536
|
+
/**
|
|
537
|
+
* Root-level Studio mode configuration.
|
|
538
|
+
*
|
|
539
|
+
* Optional configuration for the rendering environment, only used when
|
|
540
|
+
* the Studio tab is active. Fields map directly to ViewerState keys on load.
|
|
541
|
+
*/
|
|
542
|
+
export interface StudioOptions {
|
|
543
|
+
/** Environment preset slug, custom HDR URL, or "none" (default: "studio") */
|
|
544
|
+
environment?: StudioEnvironment;
|
|
545
|
+
/** Environment map intensity, 0-1 (default: 0.5) */
|
|
546
|
+
envIntensity?: number;
|
|
547
|
+
/** Background mode (default: "environment") */
|
|
548
|
+
background?: StudioBackground;
|
|
549
|
+
/** Tone mapping algorithm (default: "neutral") */
|
|
550
|
+
toneMapping?: StudioToneMapping;
|
|
551
|
+
/** Tone mapping exposure (default: 1.0) */
|
|
552
|
+
toneMappingExposure?: number;
|
|
553
|
+
/** Use 4K environment maps instead of 2K (default: false) */
|
|
554
|
+
use4kEnvMaps?: boolean;
|
|
555
|
+
/** Texture mapping mode (default: "triplanar") */
|
|
556
|
+
textureMapping?: StudioTextureMapping;
|
|
557
|
+
/** Environment map rotation in degrees (default: 0) */
|
|
558
|
+
envRotation?: number;
|
|
559
|
+
/** Shadow intensity, 0-1 (default: 0 = off) */
|
|
560
|
+
shadowIntensity?: number;
|
|
561
|
+
/** Shadow softness, 0-1 (default: 0.3) */
|
|
562
|
+
shadowSoftness?: number;
|
|
563
|
+
/** Ambient occlusion intensity, 0-3.0 (default: 0 = off) */
|
|
564
|
+
aoIntensity?: number;
|
|
565
|
+
}
|
|
338
566
|
/** Encoded texture */
|
|
339
567
|
export interface Texture {
|
|
340
568
|
height: number;
|
|
@@ -370,6 +598,8 @@ export interface Shape {
|
|
|
370
598
|
triangles_per_face?: number[] | Uint32Array;
|
|
371
599
|
/** Number of segments per edge (when edges is flat) */
|
|
372
600
|
segments_per_edge?: number[] | Uint32Array;
|
|
601
|
+
/** UV coordinates (2 floats per vertex, same indexing as vertices) */
|
|
602
|
+
uvs?: number[] | Float32Array;
|
|
373
603
|
}
|
|
374
604
|
/**
|
|
375
605
|
* Shape with flat binary format (TypedArrays with per-face/per-edge counts).
|
|
@@ -397,6 +627,15 @@ export interface ShapeNested {
|
|
|
397
627
|
edge_types: number[];
|
|
398
628
|
face_types: number[];
|
|
399
629
|
}
|
|
630
|
+
/**
|
|
631
|
+
* Shape reference for the instanced/compressed format.
|
|
632
|
+
* Before decoding, a part's shape field may be `{ ref: N }` referencing
|
|
633
|
+
* the Nth entry in the instances array. After decoding, all ShapeRefs
|
|
634
|
+
* are replaced with full Shape objects.
|
|
635
|
+
*/
|
|
636
|
+
export interface ShapeRef {
|
|
637
|
+
ref: number;
|
|
638
|
+
}
|
|
400
639
|
/**
|
|
401
640
|
* Check if shape uses binary format (has triangles_per_face).
|
|
402
641
|
*/
|
|
@@ -471,6 +710,18 @@ export interface Shapes {
|
|
|
471
710
|
width?: number | undefined;
|
|
472
711
|
/** Vertex size in pixels (added during decomposition for vertex shapes) */
|
|
473
712
|
size?: number | undefined;
|
|
713
|
+
/** Material tag referencing materials table or built-in preset (leaf nodes) */
|
|
714
|
+
material?: string | undefined;
|
|
715
|
+
/** User-defined material library (root node).
|
|
716
|
+
* Values can be:
|
|
717
|
+
* - string: builtin preset reference (e.g., "builtin:car-paint")
|
|
718
|
+
* - MaterialXMaterial: threejs-materials format (detected by `properties` key)
|
|
719
|
+
* - MaterialAppearance: preset with overrides (e.g., { builtin: "acrylic-clear", color: "#55a0e3" })
|
|
720
|
+
*/
|
|
721
|
+
materials?: Record<string, string | MaterialXMaterial | MaterialAppearance> | undefined;
|
|
722
|
+
/** Shared texture table for builtin preset materials (root node).
|
|
723
|
+
* threejs-materials carry their own textures inline. */
|
|
724
|
+
textures?: Record<string, TextureEntry> | undefined;
|
|
474
725
|
}
|
|
475
726
|
/** Callback for DOM events */
|
|
476
727
|
export type DomEventCallback = (event: Event) => void;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as THREE from "three";
|
|
2
|
-
import { CollapseState, type Theme, type ThemeInput, type ControlType, type UpDirection, type AnimationMode, type ActiveTab, type ZebraColorScheme, type ZebraMappingMode, type Keymap, type StateChange, type StateSubscriber, type GlobalStateSubscriber, type SubscribeOptions, type RenderOptions, type ViewerOptions } from "./types";
|
|
2
|
+
import { CollapseState, type Theme, type ThemeInput, type ControlType, type UpDirection, type AnimationMode, type ActiveTab, type ZebraColorScheme, type ZebraMappingMode, type StudioBackground, type StudioToneMapping, type StudioTextureMapping, type Keymap, type StateChange, type StateSubscriber, type GlobalStateSubscriber, type SubscribeOptions, type RenderOptions, type ViewerOptions, type StudioOptions } from "./types";
|
|
3
3
|
/**
|
|
4
4
|
* Display configuration defaults
|
|
5
5
|
*/
|
|
@@ -19,6 +19,7 @@ interface DisplayDefaults {
|
|
|
19
19
|
explodeTool: boolean;
|
|
20
20
|
zscaleTool: boolean;
|
|
21
21
|
zebraTool: boolean;
|
|
22
|
+
studioTool: boolean;
|
|
22
23
|
measurementDebug: boolean;
|
|
23
24
|
}
|
|
24
25
|
/**
|
|
@@ -78,6 +79,22 @@ interface ZebraDefaults {
|
|
|
78
79
|
zebraColorScheme: ZebraColorScheme;
|
|
79
80
|
zebraMappingMode: ZebraMappingMode;
|
|
80
81
|
}
|
|
82
|
+
/**
|
|
83
|
+
* Studio mode defaults
|
|
84
|
+
*/
|
|
85
|
+
interface StudioModeDefaults {
|
|
86
|
+
studioEnvironment: string;
|
|
87
|
+
studioEnvIntensity: number;
|
|
88
|
+
studioBackground: StudioBackground;
|
|
89
|
+
studioToneMapping: StudioToneMapping;
|
|
90
|
+
studioExposure: number;
|
|
91
|
+
studio4kEnvMaps: boolean;
|
|
92
|
+
studioTextureMapping: StudioTextureMapping;
|
|
93
|
+
studioEnvRotation: number;
|
|
94
|
+
studioShadowIntensity: number;
|
|
95
|
+
studioShadowSoftness: number;
|
|
96
|
+
studioAOIntensity: number;
|
|
97
|
+
}
|
|
81
98
|
/**
|
|
82
99
|
* Runtime state defaults
|
|
83
100
|
*/
|
|
@@ -92,7 +109,7 @@ interface RuntimeDefaults {
|
|
|
92
109
|
/**
|
|
93
110
|
* Complete state shape
|
|
94
111
|
*/
|
|
95
|
-
type StateShape = DisplayDefaults & RenderDefaults & ViewerDefaults & ZebraDefaults & RuntimeDefaults;
|
|
112
|
+
type StateShape = DisplayDefaults & RenderDefaults & ViewerDefaults & ZebraDefaults & StudioModeDefaults & RuntimeDefaults;
|
|
96
113
|
/**
|
|
97
114
|
* Keys of the state shape
|
|
98
115
|
*/
|
|
@@ -160,6 +177,10 @@ declare class ViewerState {
|
|
|
160
177
|
* Zebra tool settings
|
|
161
178
|
*/
|
|
162
179
|
static ZEBRA_DEFAULTS: ZebraDefaults;
|
|
180
|
+
/**
|
|
181
|
+
* Studio mode settings
|
|
182
|
+
*/
|
|
183
|
+
static STUDIO_MODE_DEFAULTS: StudioModeDefaults;
|
|
163
184
|
/**
|
|
164
185
|
* Runtime state (not from options, changes during execution)
|
|
165
186
|
*/
|
|
@@ -198,6 +219,11 @@ declare class ViewerState {
|
|
|
198
219
|
* Converts Vector3Tuple/QuaternionTuple to THREE objects.
|
|
199
220
|
*/
|
|
200
221
|
updateViewerState(options: ViewerOptions, notify?: boolean): void;
|
|
222
|
+
/**
|
|
223
|
+
* Update studio state from StudioOptions (shapes.studioOptions).
|
|
224
|
+
* Maps short field names to prefixed state keys.
|
|
225
|
+
*/
|
|
226
|
+
updateStudioState(options: StudioOptions): void;
|
|
201
227
|
/**
|
|
202
228
|
* Get all state as a plain object (for serialization)
|
|
203
229
|
*/
|