three-cad-viewer 4.3.4 → 4.3.6

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 (59) hide show
  1. package/dist/scene/clipping.d.ts +6 -0
  2. package/dist/three-cad-viewer.esm.js +20 -5
  3. package/dist/three-cad-viewer.esm.js.map +1 -1
  4. package/dist/three-cad-viewer.esm.min.js +1 -1
  5. package/dist/three-cad-viewer.js +20 -5
  6. package/dist/three-cad-viewer.min.js +1 -1
  7. package/package.json +2 -3
  8. package/src/_version.ts +0 -1
  9. package/src/camera/camera.ts +0 -445
  10. package/src/camera/controls/CADOrbitControls.ts +0 -241
  11. package/src/camera/controls/CADTrackballControls.ts +0 -598
  12. package/src/camera/controls.ts +0 -380
  13. package/src/core/patches.ts +0 -16
  14. package/src/core/studio-manager.ts +0 -652
  15. package/src/core/types.ts +0 -892
  16. package/src/core/viewer-state.ts +0 -784
  17. package/src/core/viewer.ts +0 -4821
  18. package/src/index.ts +0 -151
  19. package/src/rendering/environment.ts +0 -840
  20. package/src/rendering/light-detection.ts +0 -327
  21. package/src/rendering/material-factory.ts +0 -735
  22. package/src/rendering/material-presets.ts +0 -289
  23. package/src/rendering/raycast.ts +0 -291
  24. package/src/rendering/room-environment.ts +0 -192
  25. package/src/rendering/studio-composer.ts +0 -577
  26. package/src/rendering/studio-floor.ts +0 -108
  27. package/src/rendering/texture-cache.ts +0 -324
  28. package/src/rendering/tree-model.ts +0 -542
  29. package/src/rendering/triplanar.ts +0 -329
  30. package/src/scene/animation.ts +0 -343
  31. package/src/scene/axes.ts +0 -108
  32. package/src/scene/bbox.ts +0 -223
  33. package/src/scene/clipping.ts +0 -640
  34. package/src/scene/grid.ts +0 -864
  35. package/src/scene/nestedgroup.ts +0 -1444
  36. package/src/scene/objectgroup.ts +0 -866
  37. package/src/scene/orientation.ts +0 -259
  38. package/src/scene/render-shape.ts +0 -634
  39. package/src/tools/cad_tools/measure.ts +0 -811
  40. package/src/tools/cad_tools/select.ts +0 -100
  41. package/src/tools/cad_tools/tools.ts +0 -231
  42. package/src/tools/cad_tools/ui.ts +0 -454
  43. package/src/tools/cad_tools/zebra.ts +0 -369
  44. package/src/types/html.d.ts +0 -5
  45. package/src/types/n8ao.d.ts +0 -28
  46. package/src/types/three-augmentation.d.ts +0 -60
  47. package/src/ui/display.ts +0 -3295
  48. package/src/ui/index.html +0 -505
  49. package/src/ui/info.ts +0 -177
  50. package/src/ui/slider.ts +0 -206
  51. package/src/ui/toolbar.ts +0 -347
  52. package/src/ui/treeview.ts +0 -945
  53. package/src/utils/decode-instances.ts +0 -233
  54. package/src/utils/font.ts +0 -60
  55. package/src/utils/gpu-tracker.ts +0 -265
  56. package/src/utils/logger.ts +0 -92
  57. package/src/utils/sizeof.ts +0 -116
  58. package/src/utils/timer.ts +0 -69
  59. package/src/utils/utils.ts +0 -446
@@ -1,289 +0,0 @@
1
- /**
2
- * Built-in material presets for Studio mode.
3
- *
4
- * 31 presets organized by category: metals (polished & matte/brushed),
5
- * plastics, glass & transparent, rubber & elastomers, painted surfaces,
6
- * and natural/other materials.
7
- *
8
- * These are pure data definitions — no textures, no runtime cost.
9
- * The `builtin` field is intentionally omitted; it is used by user-defined
10
- * materials to reference these presets, not by presets themselves.
11
- *
12
- * All color values are in sRGB color space (0-1 per channel).
13
- * The material factory converts sRGB to linear when creating Three.js materials.
14
- * Presets with neutral color (plastics, paints) rely on the leaf node's
15
- * color field for the actual tint via fallback in the material factory.
16
- *
17
- */
18
-
19
- import type { MaterialAppearance } from "../core/types.js";
20
-
21
- // =============================================================================
22
- // Preset Dictionary
23
- // =============================================================================
24
-
25
- /**
26
- * Built-in material presets keyed by preset name.
27
- *
28
- * Usage: look up a preset by the `material` tag on a leaf node, or via
29
- * `"builtin:<name>"` strings in the materials table.
30
- */
31
- export const MATERIAL_PRESETS: Record<string, MaterialAppearance> = {
32
- // ---------------------------------------------------------------------------
33
- // Metals -- Polished
34
- // ---------------------------------------------------------------------------
35
-
36
- "chrome": {
37
- name: "Chrome",
38
- color: [0.98, 0.98, 0.98, 1],
39
- metalness: 1.0,
40
- roughness: 0.05,
41
- },
42
-
43
- "polished-steel": {
44
- name: "Polished Steel",
45
- color: [0.91, 0.91, 0.92, 1],
46
- metalness: 1.0,
47
- roughness: 0.1,
48
- },
49
-
50
- "polished-aluminum": {
51
- name: "Polished Aluminum",
52
- color: [0.916, 0.923, 0.924, 1],
53
- metalness: 1.0,
54
- roughness: 0.1,
55
- },
56
-
57
- "gold": {
58
- name: "Gold",
59
- color: [1, 0.93, 0, 1],
60
- metalness: 1.0,
61
- roughness: 0.1,
62
- },
63
-
64
- "copper": {
65
- name: "Copper",
66
- color: [0.98, 0.82, 0.76, 1],
67
- metalness: 1.0,
68
- roughness: 0.15,
69
- },
70
-
71
- "brass": {
72
- name: "Brass",
73
- color: [0.95, 0.9, 0.7, 1],
74
- metalness: 1.0,
75
- roughness: 0.15,
76
- },
77
-
78
- // ---------------------------------------------------------------------------
79
- // Metals -- Matte / Brushed
80
- // ---------------------------------------------------------------------------
81
-
82
- "stainless-steel": {
83
- name: "Stainless Steel",
84
- color: [0.91, 0.91, 0.92, 1],
85
- metalness: 1.0,
86
- roughness: 0.4,
87
- },
88
-
89
- "brushed-aluminum": {
90
- name: "Brushed Aluminum",
91
- color: [0.916, 0.923, 0.924, 1],
92
- metalness: 1.0,
93
- roughness: 0.35,
94
- anisotropy: 0.5,
95
- },
96
-
97
- "cast-iron": {
98
- name: "Cast Iron",
99
- color: [0.68, 0.68, 0.69, 1],
100
- metalness: 0.9,
101
- roughness: 0.7,
102
- },
103
-
104
- "titanium": {
105
- name: "Titanium",
106
- color: [0.81, 0.79, 0.77, 1],
107
- metalness: 1.0,
108
- roughness: 0.45,
109
- },
110
-
111
- "galvanized": {
112
- name: "Galvanized",
113
- color: [0.88, 0.88, 0.9, 1],
114
- metalness: 0.8,
115
- roughness: 0.5,
116
- },
117
-
118
- // ---------------------------------------------------------------------------
119
- // Plastics
120
- // ---------------------------------------------------------------------------
121
-
122
- "plastic-glossy": {
123
- name: "Plastic (Glossy)",
124
- color: [0.91, 0.91, 0.91, 1],
125
- metalness: 0.0,
126
- roughness: 0.4,
127
- },
128
-
129
- "plastic-matte": {
130
- name: "Plastic (Matte)",
131
- color: [0.91, 0.91, 0.91, 1],
132
- metalness: 0.0,
133
- roughness: 0.6,
134
- },
135
-
136
- "abs-black": {
137
- name: "ABS Black",
138
- color: [0.25, 0.25, 0.25, 1],
139
- metalness: 0.0,
140
- roughness: 0.4,
141
- },
142
-
143
- "nylon": {
144
- name: "Nylon",
145
- color: [0.95, 0.94, 0.92, 1],
146
- metalness: 0.0,
147
- roughness: 0.55,
148
- },
149
-
150
- "acrylic-clear": {
151
- name: "Acrylic (Clear)",
152
- color: [1, 1, 1, 1],
153
- metalness: 0.0,
154
- roughness: 0.0,
155
- transmission: 0.95,
156
- ior: 1.49,
157
- },
158
-
159
- // ---------------------------------------------------------------------------
160
- // Glass & Transparent
161
- // ---------------------------------------------------------------------------
162
-
163
- "glass-clear": {
164
- name: "Glass (Clear)",
165
- color: [1, 1, 1, 1],
166
- metalness: 0.0,
167
- roughness: 0.0,
168
- transmission: 1.0,
169
- ior: 1.52,
170
- thickness: 2.0,
171
- },
172
-
173
- "glass-tinted": {
174
- name: "Glass (Tinted)",
175
- color: [0.8, 0.91, 0.95, 1],
176
- metalness: 0.0,
177
- roughness: 0.0,
178
- transmission: 0.9,
179
- ior: 1.52,
180
- thickness: 3.0,
181
- },
182
-
183
- "glass-frosted": {
184
- name: "Glass (Frosted)",
185
- color: [1, 1, 1, 1],
186
- metalness: 0.0,
187
- roughness: 0.3,
188
- transmission: 0.85,
189
- ior: 1.52,
190
- thickness: 2.0,
191
- },
192
-
193
- // ---------------------------------------------------------------------------
194
- // Rubber & Elastomers
195
- // ---------------------------------------------------------------------------
196
-
197
- "rubber-black": {
198
- name: "Rubber (Black)",
199
- color: [0.31, 0.31, 0.31, 1],
200
- metalness: 0.0,
201
- roughness: 0.9,
202
- },
203
-
204
- "rubber-gray": {
205
- name: "Rubber (Gray)",
206
- color: [0.63, 0.63, 0.63, 1],
207
- metalness: 0.0,
208
- roughness: 0.85,
209
- },
210
-
211
- "rubber-red": {
212
- name: "Rubber (Red)",
213
- color: [0.85, 0.35, 0.35, 1],
214
- metalness: 0.0,
215
- roughness: 0.8,
216
- },
217
-
218
- // ---------------------------------------------------------------------------
219
- // Painted Surfaces
220
- // ---------------------------------------------------------------------------
221
-
222
- "paint-matte": {
223
- name: "Paint (Matte)",
224
- color: [0.91, 0.91, 0.91, 1],
225
- metalness: 0.0,
226
- roughness: 0.7,
227
- },
228
-
229
- "paint-glossy": {
230
- name: "Paint (Glossy)",
231
- color: [0.91, 0.91, 0.91, 1],
232
- metalness: 0.0,
233
- roughness: 0.15,
234
- },
235
-
236
- "paint-metallic": {
237
- name: "Paint (Metallic)",
238
- color: [0.91, 0.91, 0.91, 1],
239
- metalness: 0.5,
240
- roughness: 0.25,
241
- },
242
-
243
- "car-paint": {
244
- name: "Car Paint",
245
- color: [0.91, 0, 0, 1],
246
- metalness: 0.5,
247
- roughness: 0.2,
248
- clearcoat: 1.0,
249
- clearcoatRoughness: 0.03,
250
- },
251
-
252
- // ---------------------------------------------------------------------------
253
- // Natural / Other
254
- // ---------------------------------------------------------------------------
255
-
256
- "ceramic-white": {
257
- name: "Ceramic (White)",
258
- color: [0.98, 0.98, 0.97, 1],
259
- metalness: 0.0,
260
- roughness: 0.1,
261
- },
262
-
263
- "carbon-fiber": {
264
- name: "Carbon Fiber",
265
- color: [0.25, 0.25, 0.25, 1],
266
- metalness: 0.3,
267
- roughness: 0.35,
268
- anisotropy: 0.3,
269
- },
270
-
271
- "concrete": {
272
- name: "Concrete",
273
- color: [0.83, 0.82, 0.8, 1],
274
- metalness: 0.0,
275
- roughness: 0.85,
276
- },
277
- };
278
-
279
- // =============================================================================
280
- // Sorted Name List
281
- // =============================================================================
282
-
283
- /**
284
- * Sorted list of all built-in material preset names.
285
- *
286
- * Useful for UI dropdowns, validation, and programmatic enumeration.
287
- * Derived from MATERIAL_PRESETS keys at module load time.
288
- */
289
- export const MATERIAL_PRESET_NAMES: string[] = Object.keys(MATERIAL_PRESETS).sort();
@@ -1,291 +0,0 @@
1
- import * as THREE from "three";
2
- import { KeyMapper, isMesh, isPoints, isLine } from "../utils/utils.js";
3
- import { isObjectGroup, type ObjectGroup } from "../scene/objectgroup.js";
4
- import type { Camera } from "../camera/camera.js";
5
-
6
- /**
7
- * Filter types for topology-based raycasting.
8
- */
9
- export const TopoFilter: {
10
- none: null;
11
- vertex: "vertex";
12
- edge: "edge";
13
- face: "face";
14
- solid: "solid";
15
- } = {
16
- none: null,
17
- vertex: "vertex",
18
- edge: "edge",
19
- face: "face",
20
- solid: "solid",
21
- };
22
-
23
- export type TopoFilterType = typeof TopoFilter[keyof typeof TopoFilter];
24
-
25
- interface RaycastFilters {
26
- topoFilter: TopoFilterType[];
27
- }
28
-
29
- interface RaycastCallback {
30
- (event: { mouse?: "left" | "right"; shift?: boolean; key?: string }): void;
31
- }
32
-
33
- /**
34
- * Represents a picked object from raycasting.
35
- * Can represent either a single shape or all faces of a solid.
36
- */
37
- export class PickedObject {
38
- obj: ObjectGroup;
39
- fromSolid: boolean;
40
-
41
- /**
42
- * Create a PickedObject.
43
- * @param objectGroup - The picked ObjectGroup.
44
- * @param fromSolid - Whether this pick is from a solid selection.
45
- */
46
- constructor(objectGroup: ObjectGroup, fromSolid: boolean) {
47
- this.obj = objectGroup;
48
- this.fromSolid = fromSolid;
49
- }
50
-
51
- /**
52
- * Returns all the faces ObjectGroups that define the solid from the picked object.
53
- */
54
- private _getSolidObjectGroups(solidSubObject: ObjectGroup): ObjectGroup[] {
55
- const solidGroup = solidSubObject.parent!.parent!;
56
- let facesGroup: THREE.Object3D | undefined;
57
- for (let i = 0; i < solidGroup.children.length; i++) {
58
- const child = solidGroup.children[i];
59
- if (child.name === solidGroup.name + "|faces") {
60
- facesGroup = child;
61
- break;
62
- }
63
- }
64
-
65
- return (facesGroup?.children || []).filter(isObjectGroup);
66
- }
67
-
68
- /**
69
- * If the picked object is part of a solid, returns all the faces ObjectGroups that define the solid.
70
- * Otherwise, returns the picked object.
71
- */
72
- objs(): ObjectGroup[] {
73
- if (this.fromSolid) {
74
- return this._getSolidObjectGroups(this.obj);
75
- } else {
76
- return [this.obj];
77
- }
78
- }
79
- }
80
-
81
- /**
82
- * Handles mouse-based raycasting for object selection in the 3D scene.
83
- * Supports topology filtering and provides click/keyboard callbacks.
84
- */
85
- class Raycaster {
86
- camera: Camera | null;
87
- group: THREE.Object3D | null;
88
- domElement: HTMLElement | null;
89
- width: number;
90
- height: number;
91
- threshold: number;
92
- callback: RaycastCallback;
93
- raycaster: THREE.Raycaster;
94
- raycastMode: boolean;
95
- lastPosition: THREE.Vector3 | null;
96
- mouse: THREE.Vector2;
97
- mouseMoved: boolean;
98
- filters: RaycastFilters;
99
-
100
- /**
101
- * Create a Raycaster for object picking.
102
- * @param camera - The camera used for ray projection.
103
- * @param domElement - The DOM element to listen for events.
104
- * @param width - Viewport width in pixels.
105
- * @param height - Viewport height in pixels.
106
- * @param threshold - Point picking threshold in world units.
107
- * @param group - The scene group to raycast against.
108
- * @param callback - Callback for pick events.
109
- */
110
- constructor(
111
- camera: Camera,
112
- domElement: HTMLElement,
113
- width: number,
114
- height: number,
115
- threshold: number,
116
- group: THREE.Object3D,
117
- callback: RaycastCallback
118
- ) {
119
- this.camera = camera;
120
- this.group = group;
121
- this.domElement = domElement;
122
- this.width = width;
123
- this.height = height;
124
- this.threshold = threshold;
125
- this.callback = callback;
126
-
127
- this.raycaster = new THREE.Raycaster();
128
- this.raycastMode = false;
129
-
130
- this.lastPosition = null;
131
-
132
- this.mouse = new THREE.Vector2();
133
- this.mouseMoved = false;
134
- this.filters = {
135
- topoFilter: [TopoFilter.none],
136
- };
137
- }
138
-
139
- /**
140
- * Dispose of event listeners and clean up resources.
141
- */
142
- dispose(): void {
143
- if (this.domElement) {
144
- this.domElement.removeEventListener("mousemove", this.onPointerMove);
145
- this.domElement.removeEventListener("mouseup", this.onMouseKeyUp);
146
- this.domElement.removeEventListener("mousedown", this.onMouseKeyDown);
147
- }
148
- // Keyboard listener is on document (canvas doesn't receive focus)
149
- document.removeEventListener("keydown", this.onKeyDown);
150
- this.raycastMode = false;
151
- this.group = null;
152
- this.domElement = null;
153
- this.camera = null;
154
- }
155
-
156
- /**
157
- * Initialize event listeners and enable raycast mode.
158
- */
159
- init(): void {
160
- if (!this.domElement) return;
161
- this.domElement.addEventListener("mousemove", this.onPointerMove);
162
- this.domElement.addEventListener("mouseup", this.onMouseKeyUp, false);
163
- this.domElement.addEventListener("mousedown", this.onMouseKeyDown, false);
164
- // Use document-level listener for keyboard (canvas doesn't receive focus)
165
- document.addEventListener("keydown", this.onKeyDown, false);
166
- this.raycastMode = true;
167
- }
168
-
169
- /**
170
- * Retrieve all the valid intersected objects by a ray caster from the mouse.
171
- */
172
- getIntersectedObjs(): THREE.Intersection[] {
173
- if (!this.camera || !this.group) return [];
174
- this.raycaster.setFromCamera(this.mouse, this.camera.getCamera());
175
- this.raycaster.params.Points!.threshold =
176
- this.threshold / this.camera.getZoom();
177
- this.raycaster.params.Line2 = { threshold: 4 };
178
- const objects = this.raycaster.intersectObjects([this.group], true);
179
- const validObjs: THREE.Intersection[] = [];
180
- for (const obj of objects) {
181
- const object = obj.object;
182
- // Accept Mesh (faces), Points (vertices), and Line (edges)
183
- const isValidType = isMesh(object) || isPoints(object) || isLine(object);
184
- if (isValidType && object.visible && !Array.isArray(object.material) && object.material.visible) {
185
- validObjs.push(obj);
186
- }
187
- }
188
- return validObjs;
189
- }
190
-
191
- /**
192
- * Retrieve all the valid intersected objects by a ray caster from the mouse.
193
- * The objects are sorted by their distance from the ray. (The closest first)
194
- */
195
- getValidIntersectedObjs(): THREE.Intersection[] {
196
- const validObjs: THREE.Intersection[] = [];
197
- if (this.mouseMoved) {
198
- const objects = this.getIntersectedObjs();
199
-
200
- for (const object of objects) {
201
- const obj = object.object;
202
- // Accept Mesh (faces), Points (vertices), and Line (edges)
203
- const isValidType = isMesh(obj) || isPoints(obj) || isLine(obj);
204
- if (!isValidType) continue;
205
- if (!obj.visible || Array.isArray(obj.material) || !obj.material.visible) continue;
206
-
207
- const objectGroup = object.object.parent;
208
- if (!isObjectGroup(objectGroup)) continue;
209
-
210
- if (!objectGroup.shapeInfo) continue; // clipping plane
211
-
212
- const topo = objectGroup.shapeInfo.topo;
213
-
214
- // Check if topology is acceptable given the topology filters
215
- const isSolid = objectGroup.subtype === "solid";
216
- const isSubShapeOfSolid =
217
- this.filters.topoFilter.includes(TopoFilter.solid) && isSolid;
218
-
219
- // topo is a string from shapeInfo, check if it matches any filter
220
- const topoMatchesFilter = this.filters.topoFilter.some(
221
- (filter) => filter === topo
222
- );
223
- const valid =
224
- isSubShapeOfSolid ||
225
- this.filters.topoFilter.includes(TopoFilter.none) ||
226
- topoMatchesFilter;
227
-
228
- if (valid) {
229
- validObjs.push(object);
230
- }
231
- }
232
- }
233
- return validObjs;
234
- }
235
-
236
- /**
237
- * Handle left mouse button down event
238
- */
239
- onMouseKeyDown = (e: MouseEvent): void => {
240
- if (this.raycastMode && this.camera) {
241
- if (e.button == THREE.MOUSE.LEFT || e.button == THREE.MOUSE.RIGHT) {
242
- this.lastPosition = this.camera.getPosition().clone();
243
- }
244
- }
245
- };
246
-
247
- /**
248
- * Handle left mouse button up event
249
- */
250
- onMouseKeyUp = (e: MouseEvent): void => {
251
- if (this.raycastMode && this.camera && this.lastPosition) {
252
- if (e.button == THREE.MOUSE.LEFT) {
253
- if (this.lastPosition.distanceTo(this.camera.getPosition()) < 1e-6) {
254
- this.callback({ mouse: "left", shift: KeyMapper.get(e, "shift") });
255
- }
256
- } else if (e.button == THREE.MOUSE.RIGHT) {
257
- if (this.lastPosition.distanceTo(this.camera.getPosition()) < 1e-6) {
258
- this.callback({ mouse: "right" });
259
- }
260
- }
261
- }
262
- };
263
-
264
- /**
265
- * Handle key down event
266
- */
267
- onKeyDown = (e: KeyboardEvent): void => {
268
- if (this.raycastMode) {
269
- if (e.key == "Backspace") {
270
- this.callback({ key: "Backspace" });
271
- } else if (e.key == "Escape") {
272
- this.callback({ key: "Escape" });
273
- }
274
- }
275
- };
276
-
277
- /**
278
- * Get the current mouse position
279
- */
280
- onPointerMove = (e: MouseEvent): void => {
281
- if (!this.domElement) return;
282
- const rect = this.domElement.getBoundingClientRect();
283
- const offsetX = rect.x + window.scrollX;
284
- const offsetY = rect.y + window.scrollY;
285
- this.mouse.x = ((e.pageX - offsetX) / this.width) * 2 - 1;
286
- this.mouse.y = -((e.pageY - offsetY) / this.height) * 2 + 1;
287
- this.mouseMoved = true;
288
- };
289
- }
290
-
291
- export { Raycaster };