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.
- package/dist/scene/clipping.d.ts +6 -0
- package/dist/three-cad-viewer.esm.js +20 -5
- package/dist/three-cad-viewer.esm.js.map +1 -1
- package/dist/three-cad-viewer.esm.min.js +1 -1
- package/dist/three-cad-viewer.js +20 -5
- package/dist/three-cad-viewer.min.js +1 -1
- package/package.json +2 -3
- package/src/_version.ts +0 -1
- package/src/camera/camera.ts +0 -445
- package/src/camera/controls/CADOrbitControls.ts +0 -241
- package/src/camera/controls/CADTrackballControls.ts +0 -598
- package/src/camera/controls.ts +0 -380
- package/src/core/patches.ts +0 -16
- package/src/core/studio-manager.ts +0 -652
- package/src/core/types.ts +0 -892
- package/src/core/viewer-state.ts +0 -784
- package/src/core/viewer.ts +0 -4821
- package/src/index.ts +0 -151
- package/src/rendering/environment.ts +0 -840
- package/src/rendering/light-detection.ts +0 -327
- package/src/rendering/material-factory.ts +0 -735
- package/src/rendering/material-presets.ts +0 -289
- package/src/rendering/raycast.ts +0 -291
- package/src/rendering/room-environment.ts +0 -192
- package/src/rendering/studio-composer.ts +0 -577
- package/src/rendering/studio-floor.ts +0 -108
- package/src/rendering/texture-cache.ts +0 -324
- package/src/rendering/tree-model.ts +0 -542
- package/src/rendering/triplanar.ts +0 -329
- package/src/scene/animation.ts +0 -343
- package/src/scene/axes.ts +0 -108
- package/src/scene/bbox.ts +0 -223
- package/src/scene/clipping.ts +0 -640
- package/src/scene/grid.ts +0 -864
- package/src/scene/nestedgroup.ts +0 -1444
- package/src/scene/objectgroup.ts +0 -866
- package/src/scene/orientation.ts +0 -259
- package/src/scene/render-shape.ts +0 -634
- package/src/tools/cad_tools/measure.ts +0 -811
- package/src/tools/cad_tools/select.ts +0 -100
- package/src/tools/cad_tools/tools.ts +0 -231
- package/src/tools/cad_tools/ui.ts +0 -454
- package/src/tools/cad_tools/zebra.ts +0 -369
- package/src/types/html.d.ts +0 -5
- package/src/types/n8ao.d.ts +0 -28
- package/src/types/three-augmentation.d.ts +0 -60
- package/src/ui/display.ts +0 -3295
- package/src/ui/index.html +0 -505
- package/src/ui/info.ts +0 -177
- package/src/ui/slider.ts +0 -206
- package/src/ui/toolbar.ts +0 -347
- package/src/ui/treeview.ts +0 -945
- package/src/utils/decode-instances.ts +0 -233
- package/src/utils/font.ts +0 -60
- package/src/utils/gpu-tracker.ts +0 -265
- package/src/utils/logger.ts +0 -92
- package/src/utils/sizeof.ts +0 -116
- package/src/utils/timer.ts +0 -69
- package/src/utils/utils.ts +0 -446
package/src/scene/clipping.ts
DELETED
|
@@ -1,640 +0,0 @@
|
|
|
1
|
-
import * as THREE from "three";
|
|
2
|
-
import type { Vector3Tuple } from "three";
|
|
3
|
-
import { ObjectGroup } from "./nestedgroup.js";
|
|
4
|
-
import { CLIP_INDICES } from "../core/types";
|
|
5
|
-
import type { Theme, ClipIndex } from "../core/types";
|
|
6
|
-
import { toVector3Tuple, deepDispose } from "../utils/utils.js";
|
|
7
|
-
|
|
8
|
-
// ============================================================================
|
|
9
|
-
// Constants
|
|
10
|
-
// ============================================================================
|
|
11
|
-
|
|
12
|
-
/** Default normals for the three clipping planes (X, Y, Z) */
|
|
13
|
-
const DEFAULT_NORMALS = [
|
|
14
|
-
new THREE.Vector3(-1, 0, 0),
|
|
15
|
-
new THREE.Vector3(0, -1, 0),
|
|
16
|
-
new THREE.Vector3(0, 0, -1),
|
|
17
|
-
];
|
|
18
|
-
|
|
19
|
-
/** Plane colors by theme */
|
|
20
|
-
const PLANE_COLORS: Record<Theme, number[]> = {
|
|
21
|
-
light: [0xff0000, 0x00ff00, 0x0000ff],
|
|
22
|
-
dark: [0xff4500, 0x32cd32, 0x3b9eff],
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
/** Plane helper opacity by theme */
|
|
26
|
-
const PLANE_HELPER_OPACITY: Record<Theme, number> = {
|
|
27
|
-
light: 0.1,
|
|
28
|
-
dark: 0.2,
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
// ============================================================================
|
|
32
|
-
// ClippingMaterials - Factory for clipping-related materials
|
|
33
|
-
// ============================================================================
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Factory for creating clipping-related materials.
|
|
37
|
-
* Centralizes material creation and avoids global state.
|
|
38
|
-
*/
|
|
39
|
-
class ClippingMaterials {
|
|
40
|
-
/**
|
|
41
|
-
* Create a plane helper material.
|
|
42
|
-
* @param theme - The UI theme ('light' or 'dark').
|
|
43
|
-
* @returns The plane helper material.
|
|
44
|
-
*/
|
|
45
|
-
static createPlaneHelperMaterial(theme: Theme): THREE.MeshBasicMaterial {
|
|
46
|
-
return new THREE.MeshBasicMaterial({
|
|
47
|
-
opacity: PLANE_HELPER_OPACITY[theme] || 0.1,
|
|
48
|
-
transparent: true,
|
|
49
|
-
depthWrite: false,
|
|
50
|
-
toneMapped: false,
|
|
51
|
-
side: THREE.DoubleSide,
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Create a back stencil material.
|
|
57
|
-
* Increments stencil buffer where back faces are visible (clipped region).
|
|
58
|
-
* @returns The back stencil material.
|
|
59
|
-
*/
|
|
60
|
-
static createBackStencilMaterial(): THREE.MeshBasicMaterial {
|
|
61
|
-
return new THREE.MeshBasicMaterial({
|
|
62
|
-
depthWrite: false,
|
|
63
|
-
depthTest: false,
|
|
64
|
-
colorWrite: false,
|
|
65
|
-
side: THREE.BackSide,
|
|
66
|
-
stencilWrite: true,
|
|
67
|
-
stencilFunc: THREE.AlwaysStencilFunc,
|
|
68
|
-
stencilFail: THREE.IncrementWrapStencilOp,
|
|
69
|
-
stencilZFail: THREE.IncrementWrapStencilOp,
|
|
70
|
-
stencilZPass: THREE.IncrementWrapStencilOp,
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Create a front stencil material.
|
|
76
|
-
* Decrements stencil buffer where front faces are visible.
|
|
77
|
-
* @returns The front stencil material.
|
|
78
|
-
*/
|
|
79
|
-
static createFrontStencilMaterial(): THREE.MeshBasicMaterial {
|
|
80
|
-
return new THREE.MeshBasicMaterial({
|
|
81
|
-
depthWrite: false,
|
|
82
|
-
depthTest: false,
|
|
83
|
-
colorWrite: false,
|
|
84
|
-
side: THREE.FrontSide,
|
|
85
|
-
stencilWrite: true,
|
|
86
|
-
stencilFunc: THREE.AlwaysStencilFunc,
|
|
87
|
-
stencilFail: THREE.DecrementWrapStencilOp,
|
|
88
|
-
stencilZFail: THREE.DecrementWrapStencilOp,
|
|
89
|
-
stencilZPass: THREE.DecrementWrapStencilOp,
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* Create a stencil plane material.
|
|
95
|
-
* Draws plane where stencil buffer != 0 (clipped region).
|
|
96
|
-
* @param color - The plane color as hex.
|
|
97
|
-
* @param clippingPlanes - Other clipping planes to apply.
|
|
98
|
-
* @returns The stencil plane material.
|
|
99
|
-
*/
|
|
100
|
-
static createStencilPlaneMaterial(color: number, clippingPlanes: THREE.Plane[]): THREE.MeshStandardMaterial {
|
|
101
|
-
const material = new THREE.MeshStandardMaterial({
|
|
102
|
-
color: new THREE.Color(color),
|
|
103
|
-
metalness: 0.3,
|
|
104
|
-
roughness: 0.65,
|
|
105
|
-
opacity: 1.0,
|
|
106
|
-
transparent: false,
|
|
107
|
-
side: THREE.DoubleSide,
|
|
108
|
-
polygonOffset: true,
|
|
109
|
-
polygonOffsetFactor: 1.0,
|
|
110
|
-
polygonOffsetUnits: 1.0,
|
|
111
|
-
stencilWrite: true,
|
|
112
|
-
stencilRef: 0,
|
|
113
|
-
stencilFunc: THREE.NotEqualStencilFunc,
|
|
114
|
-
stencilFail: THREE.ReplaceStencilOp,
|
|
115
|
-
stencilZFail: THREE.ReplaceStencilOp,
|
|
116
|
-
stencilZPass: THREE.ReplaceStencilOp,
|
|
117
|
-
clippingPlanes: clippingPlanes,
|
|
118
|
-
});
|
|
119
|
-
return material;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// ============================================================================
|
|
124
|
-
// CenteredPlane - Plane with center-relative constant
|
|
125
|
-
// ============================================================================
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* A THREE.Plane that maintains a constant relative to a center point.
|
|
129
|
-
*/
|
|
130
|
-
class CenteredPlane extends THREE.Plane {
|
|
131
|
-
center: number[];
|
|
132
|
-
centeredConstant: number;
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* Create a CenteredPlane.
|
|
136
|
-
* @param normal - The plane normal vector.
|
|
137
|
-
* @param constant - The centered constant value.
|
|
138
|
-
* @param center - The center point [x, y, z].
|
|
139
|
-
*/
|
|
140
|
-
constructor(normal: THREE.Vector3, constant: number, center: number[]) {
|
|
141
|
-
super(normal, constant);
|
|
142
|
-
this.center = center;
|
|
143
|
-
this.centeredConstant = constant;
|
|
144
|
-
this.setConstant(constant);
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
/**
|
|
148
|
-
* Set the constant relative to the center point.
|
|
149
|
-
* @param value - The centered constant value.
|
|
150
|
-
*/
|
|
151
|
-
setConstant(value: number): void {
|
|
152
|
-
this.centeredConstant = value;
|
|
153
|
-
const c = this.distanceToPoint(new THREE.Vector3(...this.center));
|
|
154
|
-
const z = this.distanceToPoint(new THREE.Vector3(0, 0, 0));
|
|
155
|
-
this.constant = z - c + value;
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
// ============================================================================
|
|
160
|
-
// PlaneMesh - Visual representation of a clipping plane
|
|
161
|
-
// ============================================================================
|
|
162
|
-
|
|
163
|
-
/**
|
|
164
|
-
* A THREE.Group that only contains PlaneMesh children.
|
|
165
|
-
*/
|
|
166
|
-
class PlaneMeshGroup extends THREE.Group {
|
|
167
|
-
declare children: PlaneMesh[];
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
/**
|
|
171
|
-
* A mesh that visually represents a clipping plane.
|
|
172
|
-
*/
|
|
173
|
-
class PlaneMesh extends THREE.Mesh {
|
|
174
|
-
declare type: string;
|
|
175
|
-
declare material: THREE.MeshBasicMaterial | THREE.MeshStandardMaterial;
|
|
176
|
-
|
|
177
|
-
/** Shared matrix for lookAt calculations */
|
|
178
|
-
static matrix = new THREE.Matrix4();
|
|
179
|
-
|
|
180
|
-
index: number;
|
|
181
|
-
plane: CenteredPlane;
|
|
182
|
-
size: number;
|
|
183
|
-
center: number[];
|
|
184
|
-
|
|
185
|
-
/**
|
|
186
|
-
* Create a PlaneMesh.
|
|
187
|
-
* @param index - The plane index (0, 1, or 2).
|
|
188
|
-
* @param plane - The clipping plane.
|
|
189
|
-
* @param center - The center point [x, y, z].
|
|
190
|
-
* @param size - The size of the plane mesh.
|
|
191
|
-
* @param material - The material for the mesh.
|
|
192
|
-
* @param color - The color as hex value.
|
|
193
|
-
* @param type - The mesh type identifier.
|
|
194
|
-
*/
|
|
195
|
-
constructor(
|
|
196
|
-
index: number,
|
|
197
|
-
plane: CenteredPlane,
|
|
198
|
-
center: number[],
|
|
199
|
-
size: number,
|
|
200
|
-
material: THREE.MeshBasicMaterial | THREE.MeshStandardMaterial,
|
|
201
|
-
color: number,
|
|
202
|
-
type: string
|
|
203
|
-
) {
|
|
204
|
-
const meshGeometry = new THREE.PlaneGeometry(2, 2);
|
|
205
|
-
meshGeometry.computeBoundingSphere();
|
|
206
|
-
material.color.set(new THREE.Color(color));
|
|
207
|
-
super(meshGeometry, material);
|
|
208
|
-
|
|
209
|
-
this.type = type;
|
|
210
|
-
this.index = index;
|
|
211
|
-
this.plane = plane;
|
|
212
|
-
this.size = size;
|
|
213
|
-
this.center = center;
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
/**
|
|
217
|
-
* Clear stencil buffer after rendering stencil planes.
|
|
218
|
-
* @param renderer - The renderer.
|
|
219
|
-
*/
|
|
220
|
-
onAfterRender = (renderer: THREE.WebGLRenderer): void => {
|
|
221
|
-
if (this.type.startsWith("StencilPlane")) {
|
|
222
|
-
renderer.clearStencil();
|
|
223
|
-
}
|
|
224
|
-
};
|
|
225
|
-
|
|
226
|
-
/**
|
|
227
|
-
* Update the mesh's world matrix to align with the clipping plane.
|
|
228
|
-
* @param force - Force update even if not needed.
|
|
229
|
-
*/
|
|
230
|
-
updateMatrixWorld(force?: boolean): void {
|
|
231
|
-
this.position.set(0, 0, 0);
|
|
232
|
-
this.scale.set(0.5 * this.size, 0.5 * this.size, 1);
|
|
233
|
-
|
|
234
|
-
PlaneMesh.matrix.lookAt(this.position, this.plane.normal, this.up);
|
|
235
|
-
this.quaternion.setFromRotationMatrix(PlaneMesh.matrix);
|
|
236
|
-
|
|
237
|
-
this.translateZ(this.plane.constant);
|
|
238
|
-
super.updateMatrixWorld(force);
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
/**
|
|
243
|
-
* Create a stencil mesh for clipping visualization.
|
|
244
|
-
* @param name - The mesh name.
|
|
245
|
-
* @param material - The stencil material.
|
|
246
|
-
* @param geometry - The shape geometry.
|
|
247
|
-
* @param plane - The clipping plane.
|
|
248
|
-
* @returns The stencil mesh.
|
|
249
|
-
*/
|
|
250
|
-
function createStencil(
|
|
251
|
-
name: string,
|
|
252
|
-
material: THREE.MeshBasicMaterial,
|
|
253
|
-
geometry: THREE.BufferGeometry,
|
|
254
|
-
plane: THREE.Plane
|
|
255
|
-
): THREE.Mesh {
|
|
256
|
-
material.clippingPlanes = [plane];
|
|
257
|
-
const mesh = new THREE.Mesh(geometry, material);
|
|
258
|
-
mesh.name = name;
|
|
259
|
-
return mesh;
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
// ============================================================================
|
|
263
|
-
// Clipping - Main clipping management class
|
|
264
|
-
// ============================================================================
|
|
265
|
-
|
|
266
|
-
interface NestedGroupLike {
|
|
267
|
-
groups: Record<string, ObjectGroup | unknown>;
|
|
268
|
-
rootGroup: THREE.Group | null;
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
interface ClippingOptions {
|
|
272
|
-
onNormalChange?: (index: ClipIndex, normalArray: Vector3Tuple) => void;
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
/**
|
|
276
|
-
* Saved clipping state for mode transitions (e.g., entering/leaving Studio mode).
|
|
277
|
-
* Captures only Clipping-internal state; renderer flags and ViewerState keys
|
|
278
|
-
* are managed by the caller.
|
|
279
|
-
*/
|
|
280
|
-
interface ClippingState {
|
|
281
|
-
/** Centered constant (position) for each of the 3 clip planes */
|
|
282
|
-
planeConstants: [number, number, number];
|
|
283
|
-
/** Whether the plane helper meshes (translucent colored rectangles) are visible */
|
|
284
|
-
helperVisible: boolean;
|
|
285
|
-
/** Whether the stencil plane meshes (solid colored caps) are visible */
|
|
286
|
-
planesVisible: boolean;
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
/**
|
|
290
|
-
* Manages clipping planes, stencil rendering, and plane visualization.
|
|
291
|
-
*/
|
|
292
|
-
class Clipping extends THREE.Group {
|
|
293
|
-
center: number[] | null;
|
|
294
|
-
distance: number;
|
|
295
|
-
onNormalChange: ((index: ClipIndex, normalArray: Vector3Tuple) => void) | null;
|
|
296
|
-
theme: Theme;
|
|
297
|
-
nestedGroup!: NestedGroupLike;
|
|
298
|
-
size: number;
|
|
299
|
-
clipPlanes!: CenteredPlane[];
|
|
300
|
-
reverseClipPlanes!: CenteredPlane[];
|
|
301
|
-
objectColors!: number[];
|
|
302
|
-
objectColorCaps: boolean;
|
|
303
|
-
planeHelpers!: PlaneMeshGroup | null;
|
|
304
|
-
private _planeMeshGroup: PlaneMeshGroup | null;
|
|
305
|
-
|
|
306
|
-
/**
|
|
307
|
-
* Create a Clipping instance.
|
|
308
|
-
* @param center - The center point [x, y, z].
|
|
309
|
-
* @param size - The size of the clipping region.
|
|
310
|
-
* @param nestedGroup - The nested group containing objects to clip.
|
|
311
|
-
* @param options - Configuration options.
|
|
312
|
-
* @param theme - The UI theme ('light' or 'dark').
|
|
313
|
-
*/
|
|
314
|
-
constructor(
|
|
315
|
-
center: number[],
|
|
316
|
-
size: number,
|
|
317
|
-
nestedGroup: NestedGroupLike,
|
|
318
|
-
options: ClippingOptions,
|
|
319
|
-
theme: Theme
|
|
320
|
-
) {
|
|
321
|
-
super();
|
|
322
|
-
this.center = center;
|
|
323
|
-
this.distance = size / 2;
|
|
324
|
-
this.onNormalChange = options.onNormalChange || null;
|
|
325
|
-
this.theme = theme;
|
|
326
|
-
this.nestedGroup = nestedGroup;
|
|
327
|
-
this.size = size;
|
|
328
|
-
|
|
329
|
-
this.clipPlanes = [];
|
|
330
|
-
this.reverseClipPlanes = [];
|
|
331
|
-
this.objectColors = [];
|
|
332
|
-
this.objectColorCaps = false;
|
|
333
|
-
|
|
334
|
-
// Cached reference to avoid O(n) lookups
|
|
335
|
-
this._planeMeshGroup = null;
|
|
336
|
-
|
|
337
|
-
this.name = "PlaneHelpers";
|
|
338
|
-
|
|
339
|
-
this._createClipPlanes(center);
|
|
340
|
-
this._createPlaneHelpers(center, size, theme);
|
|
341
|
-
this._createStencils(center, size, theme);
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
/**
|
|
345
|
-
* Create the three clipping planes and their reverse counterparts.
|
|
346
|
-
* @param center - The center point.
|
|
347
|
-
*/
|
|
348
|
-
private _createClipPlanes(center: number[]): void {
|
|
349
|
-
for (const i of CLIP_INDICES) {
|
|
350
|
-
const plane = new CenteredPlane(DEFAULT_NORMALS[i], this.distance, center);
|
|
351
|
-
this.clipPlanes.push(plane);
|
|
352
|
-
|
|
353
|
-
const reversePlane = new CenteredPlane(
|
|
354
|
-
DEFAULT_NORMALS[i].clone().negate(),
|
|
355
|
-
-this.distance,
|
|
356
|
-
center,
|
|
357
|
-
);
|
|
358
|
-
this.reverseClipPlanes.push(reversePlane);
|
|
359
|
-
|
|
360
|
-
if (this.onNormalChange) {
|
|
361
|
-
this.onNormalChange(i, toVector3Tuple(DEFAULT_NORMALS[i].toArray()));
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
/**
|
|
367
|
-
* Create the visual plane helpers.
|
|
368
|
-
* @param center - The center point.
|
|
369
|
-
* @param size - The size of the plane helpers.
|
|
370
|
-
* @param theme - The UI theme.
|
|
371
|
-
*/
|
|
372
|
-
private _createPlaneHelpers(center: number[], size: number, theme: Theme): void {
|
|
373
|
-
this.planeHelpers = new PlaneMeshGroup();
|
|
374
|
-
this.planeHelpers.name = "PlaneHelpers";
|
|
375
|
-
|
|
376
|
-
for (let i = 0; i < 3; i++) {
|
|
377
|
-
const material = ClippingMaterials.createPlaneHelperMaterial(theme);
|
|
378
|
-
|
|
379
|
-
this.planeHelpers.add(
|
|
380
|
-
new PlaneMesh(
|
|
381
|
-
i,
|
|
382
|
-
this.clipPlanes[i],
|
|
383
|
-
center,
|
|
384
|
-
size,
|
|
385
|
-
material,
|
|
386
|
-
PLANE_COLORS[theme][i],
|
|
387
|
-
"PlaneHelper",
|
|
388
|
-
),
|
|
389
|
-
);
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
// Each plane helper is clipped by the other two planes
|
|
393
|
-
for (let i = 0; i < 3; i++) {
|
|
394
|
-
const otherPlanes = this.clipPlanes.filter((_, j) => j !== i);
|
|
395
|
-
this.planeHelpers.children[i].material.clippingPlanes = otherPlanes;
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
this.planeHelpers.visible = false;
|
|
399
|
-
this.add(this.planeHelpers);
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
/**
|
|
403
|
-
* Create stencil meshes for solid objects.
|
|
404
|
-
* @param center - The center point.
|
|
405
|
-
* @param size - The size of the stencil planes.
|
|
406
|
-
* @param theme - The UI theme.
|
|
407
|
-
*/
|
|
408
|
-
private _createStencils(center: number[], size: number, theme: Theme): void {
|
|
409
|
-
this._planeMeshGroup = new PlaneMeshGroup();
|
|
410
|
-
this._planeMeshGroup.name = "PlaneMeshes";
|
|
411
|
-
|
|
412
|
-
for (let i = 0; i < 3; i++) {
|
|
413
|
-
const plane = this.clipPlanes[i];
|
|
414
|
-
const otherPlanes = this.clipPlanes.filter((_, j) => j !== i);
|
|
415
|
-
let j = 0;
|
|
416
|
-
|
|
417
|
-
for (const path in this.nestedGroup.groups) {
|
|
418
|
-
const group = this.nestedGroup.groups[path];
|
|
419
|
-
|
|
420
|
-
if (group instanceof ObjectGroup && group.subtype === "solid" && group.front) {
|
|
421
|
-
// Store color for each plane-solid combination (mirrors _planeMeshGroup order)
|
|
422
|
-
const frontMesh = group.front;
|
|
423
|
-
const material = frontMesh.material;
|
|
424
|
-
this.objectColors.push(material.color.getHex());
|
|
425
|
-
|
|
426
|
-
// Create clipping group with front and back stencils
|
|
427
|
-
const clippingGroup = new THREE.Group();
|
|
428
|
-
clippingGroup.name = `clipping-${i}`;
|
|
429
|
-
|
|
430
|
-
clippingGroup.add(
|
|
431
|
-
createStencil(
|
|
432
|
-
`frontStencil-${i}-${j}`,
|
|
433
|
-
ClippingMaterials.createFrontStencilMaterial(),
|
|
434
|
-
group.shapeGeometry!,
|
|
435
|
-
plane,
|
|
436
|
-
),
|
|
437
|
-
);
|
|
438
|
-
|
|
439
|
-
clippingGroup.add(
|
|
440
|
-
createStencil(
|
|
441
|
-
`backStencil-${i}-${j}`,
|
|
442
|
-
ClippingMaterials.createBackStencilMaterial(),
|
|
443
|
-
group.shapeGeometry!,
|
|
444
|
-
plane,
|
|
445
|
-
),
|
|
446
|
-
);
|
|
447
|
-
|
|
448
|
-
group.addClipping(clippingGroup, i);
|
|
449
|
-
|
|
450
|
-
// Create stencil plane mesh
|
|
451
|
-
const planeMaterial = ClippingMaterials.createStencilPlaneMaterial(
|
|
452
|
-
PLANE_COLORS[theme][i],
|
|
453
|
-
otherPlanes,
|
|
454
|
-
);
|
|
455
|
-
|
|
456
|
-
this._planeMeshGroup.add(
|
|
457
|
-
new PlaneMesh(
|
|
458
|
-
i,
|
|
459
|
-
plane,
|
|
460
|
-
center,
|
|
461
|
-
size,
|
|
462
|
-
planeMaterial,
|
|
463
|
-
PLANE_COLORS[theme][i],
|
|
464
|
-
`StencilPlane-${i}-${j}`,
|
|
465
|
-
),
|
|
466
|
-
);
|
|
467
|
-
j++;
|
|
468
|
-
}
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
this.nestedGroup.rootGroup!.add(this._planeMeshGroup);
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
/**
|
|
476
|
-
* Rebuild stencil meshes after scene changes (part add/remove).
|
|
477
|
-
* Clears existing stencils from all ObjectGroups and rebuilds from scratch.
|
|
478
|
-
* Also updates clipping region size if center/size changed.
|
|
479
|
-
* @param center - The new center point [x, y, z].
|
|
480
|
-
* @param size - The new size of the clipping region.
|
|
481
|
-
*/
|
|
482
|
-
rebuildStencils(center: number[], size: number): void {
|
|
483
|
-
// Clear existing clipping stencils from all ObjectGroups
|
|
484
|
-
for (const path in this.nestedGroup.groups) {
|
|
485
|
-
const group = this.nestedGroup.groups[path];
|
|
486
|
-
if (group instanceof ObjectGroup) {
|
|
487
|
-
group.clearClipping();
|
|
488
|
-
}
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
// Remove old plane mesh group from scene
|
|
492
|
-
if (this._planeMeshGroup && this.nestedGroup.rootGroup) {
|
|
493
|
-
this.nestedGroup.rootGroup.remove(this._planeMeshGroup);
|
|
494
|
-
deepDispose(this._planeMeshGroup);
|
|
495
|
-
this._planeMeshGroup = null;
|
|
496
|
-
}
|
|
497
|
-
|
|
498
|
-
// Clear object colors
|
|
499
|
-
this.objectColors = [];
|
|
500
|
-
|
|
501
|
-
// Update size/distance
|
|
502
|
-
this.center = center;
|
|
503
|
-
this.size = size;
|
|
504
|
-
this.distance = size / 2;
|
|
505
|
-
|
|
506
|
-
// Rebuild stencils with current state
|
|
507
|
-
this._createStencils(center, size, this.theme);
|
|
508
|
-
|
|
509
|
-
// Reapply object color caps if enabled
|
|
510
|
-
if (this.objectColorCaps) {
|
|
511
|
-
this.setObjectColorCaps(true);
|
|
512
|
-
}
|
|
513
|
-
}
|
|
514
|
-
|
|
515
|
-
/**
|
|
516
|
-
* Set the constant (distance from center) for a clipping plane.
|
|
517
|
-
* @param index - The plane index (0, 1, or 2).
|
|
518
|
-
* @param value - The constant value relative to center.
|
|
519
|
-
*/
|
|
520
|
-
setConstant(index: ClipIndex, value: number): void {
|
|
521
|
-
this.clipPlanes[index].setConstant(value);
|
|
522
|
-
this.reverseClipPlanes[index].setConstant(-value);
|
|
523
|
-
}
|
|
524
|
-
|
|
525
|
-
/**
|
|
526
|
-
* Set the normal vector for a clipping plane.
|
|
527
|
-
* @param index - The plane index (0, 1, or 2).
|
|
528
|
-
* @param normal - The new normal vector.
|
|
529
|
-
*/
|
|
530
|
-
setNormal = (index: ClipIndex, normal: THREE.Vector3): void => {
|
|
531
|
-
const n = normal.clone();
|
|
532
|
-
this.clipPlanes[index].normal = n;
|
|
533
|
-
this.reverseClipPlanes[index].normal = n.clone().negate();
|
|
534
|
-
this.setConstant(index, this.distance);
|
|
535
|
-
if (this.onNormalChange) {
|
|
536
|
-
this.onNormalChange(index, toVector3Tuple(n.toArray()));
|
|
537
|
-
}
|
|
538
|
-
};
|
|
539
|
-
|
|
540
|
-
/**
|
|
541
|
-
* Get whether object color caps mode is enabled.
|
|
542
|
-
* @returns True if object color caps mode is enabled.
|
|
543
|
-
*/
|
|
544
|
-
getObjectColorCaps = (): boolean => {
|
|
545
|
-
return this.objectColorCaps;
|
|
546
|
-
};
|
|
547
|
-
|
|
548
|
-
/**
|
|
549
|
-
* Toggle object color caps mode.
|
|
550
|
-
* When enabled, stencil planes use the original object colors.
|
|
551
|
-
* When disabled, stencil planes use theme-based plane colors.
|
|
552
|
-
* @param flag - True to enable object color caps.
|
|
553
|
-
*/
|
|
554
|
-
setObjectColorCaps = (flag: boolean): void => {
|
|
555
|
-
if (!this._planeMeshGroup) return;
|
|
556
|
-
|
|
557
|
-
let i = 0;
|
|
558
|
-
let j = -1;
|
|
559
|
-
const len = this._planeMeshGroup.children.length / 3;
|
|
560
|
-
for (const mesh of this._planeMeshGroup.children) {
|
|
561
|
-
if (i % len === 0) {
|
|
562
|
-
j++;
|
|
563
|
-
}
|
|
564
|
-
const color = flag ? this.objectColors[i] : PLANE_COLORS[this.theme][j];
|
|
565
|
-
mesh.material.color.set(new THREE.Color(color));
|
|
566
|
-
i++;
|
|
567
|
-
}
|
|
568
|
-
this.objectColorCaps = flag;
|
|
569
|
-
};
|
|
570
|
-
|
|
571
|
-
/**
|
|
572
|
-
* Set visibility of stencil plane meshes.
|
|
573
|
-
* @param flag - True to show, false to hide.
|
|
574
|
-
*/
|
|
575
|
-
setVisible = (flag: boolean): void => {
|
|
576
|
-
if (!this._planeMeshGroup) return;
|
|
577
|
-
|
|
578
|
-
for (const mesh of this._planeMeshGroup.children) {
|
|
579
|
-
mesh.material.visible = flag;
|
|
580
|
-
}
|
|
581
|
-
};
|
|
582
|
-
|
|
583
|
-
/**
|
|
584
|
-
* Save the current clipping state for later restoration.
|
|
585
|
-
* Captures plane positions, helper visibility, and stencil plane visibility.
|
|
586
|
-
* Used by Studio mode to snapshot clipping state before disabling clipping.
|
|
587
|
-
*
|
|
588
|
-
* Note: `renderer.localClippingEnabled` and `clipPlaneHelpers` ViewerState
|
|
589
|
-
* are managed by the caller (Display/Viewer layer), not captured here.
|
|
590
|
-
*/
|
|
591
|
-
saveState(): ClippingState {
|
|
592
|
-
return {
|
|
593
|
-
planeConstants: [
|
|
594
|
-
this.clipPlanes[0].centeredConstant,
|
|
595
|
-
this.clipPlanes[1].centeredConstant,
|
|
596
|
-
this.clipPlanes[2].centeredConstant,
|
|
597
|
-
],
|
|
598
|
-
helperVisible: this.planeHelpers?.visible ?? false,
|
|
599
|
-
planesVisible: this._planeMeshGroup?.children.length
|
|
600
|
-
? this._planeMeshGroup.children[0].material.visible
|
|
601
|
-
: false,
|
|
602
|
-
};
|
|
603
|
-
}
|
|
604
|
-
|
|
605
|
-
/**
|
|
606
|
-
* Restore a previously saved clipping state.
|
|
607
|
-
* Re-applies plane positions, helper visibility, and stencil plane visibility.
|
|
608
|
-
* Used by Studio mode when leaving to restore the clipping configuration.
|
|
609
|
-
*
|
|
610
|
-
* @param state - The state previously captured by `saveState()`.
|
|
611
|
-
*/
|
|
612
|
-
restoreState(state: ClippingState): void {
|
|
613
|
-
// Restore plane positions
|
|
614
|
-
for (const i of CLIP_INDICES) {
|
|
615
|
-
this.setConstant(i, state.planeConstants[i]);
|
|
616
|
-
}
|
|
617
|
-
|
|
618
|
-
// Restore plane helper visibility
|
|
619
|
-
if (this.planeHelpers) {
|
|
620
|
-
this.planeHelpers.visible = state.helperVisible;
|
|
621
|
-
}
|
|
622
|
-
|
|
623
|
-
// Restore stencil plane mesh visibility
|
|
624
|
-
this.setVisible(state.planesVisible);
|
|
625
|
-
}
|
|
626
|
-
|
|
627
|
-
/**
|
|
628
|
-
* Clean up resources.
|
|
629
|
-
* Note: We don't null out arrays/references as GC handles cleanup when the Clipping object is collected.
|
|
630
|
-
*/
|
|
631
|
-
dispose(): void {
|
|
632
|
-
this.onNormalChange = null;
|
|
633
|
-
this.center = null;
|
|
634
|
-
this.planeHelpers = null;
|
|
635
|
-
this._planeMeshGroup = null;
|
|
636
|
-
}
|
|
637
|
-
}
|
|
638
|
-
|
|
639
|
-
export { Clipping };
|
|
640
|
-
export type { ClippingState };
|