@tonybfox/threejs-tools 1.0.4 → 1.0.5

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/index.d.mts CHANGED
@@ -3,11 +3,179 @@ export { CameraMode, DualCameraControls, DualCameraControlsOptions, ExternalCame
3
3
  export { CompassOverlay, CompassOverlayEvent, CompassOverlayOptions } from './compass/index.mjs';
4
4
  export { InfiniteGrid } from './grid/index.mjs';
5
5
  export { Measurement, MeasurementData, MeasurementPoint, MeasurementPointData, MeasurementTool, MeasurementToolEvents, MeasurementToolOptions, SnapMode, SnapResult } from './measurements/index.mjs';
6
+ import * as THREE from 'three';
6
7
  export { SunLightState, SunLightTool, SunLightToolEvents, SunLightToolOptions, SunLightWeather } from './sunlight/index.mjs';
7
8
  export { ElevationPoint, GeoCoordinates, TerrainData, TerrainDimensions, TerrainTool, TerrainToolEvents, TerrainToolOptions } from './terrain/index.mjs';
8
9
  export { TransformControls, TransformControlsGizmo, TransformControlsPlane, calculateBoundingBoxCenter } from './transform-controls/index.mjs';
9
10
  export { ViewHelper, ViewHelperCameraController, ViewHelperEvent, ViewHelperOptions } from './view-helper/index.mjs';
10
- import 'three';
11
11
  import 'camera-controls';
12
12
  import 'three/examples/jsm/renderers/CSS2DRenderer';
13
13
  import 'three/examples/jsm/renderers/CSS2DRenderer.js';
14
+
15
+ /**
16
+ * Configuration options for the OutlineTool
17
+ */
18
+ interface OutlineOptions {
19
+ /**
20
+ * Color of the outline (hex)
21
+ * @default 0xff0000
22
+ */
23
+ outlineColor?: number;
24
+ /**
25
+ * Thickness of edge lines in pixels (for both modes)
26
+ * @default 2
27
+ */
28
+ edgeLineWidth?: number;
29
+ /**
30
+ * Color of edge lines (hex) - only for 'mesh' mode
31
+ * @default 0xff0000
32
+ */
33
+ edgeLineColor?: number;
34
+ /**
35
+ * Angle threshold for edge detection (degrees) - only for 'mesh' mode
36
+ * Higher values = fewer edges detected
37
+ * @default 30
38
+ */
39
+ edgeThreshold?: number;
40
+ /**
41
+ * Scale multiplier for silhouette outline - only for 'mesh' mode
42
+ * @default 1.02
43
+ */
44
+ outlineScale?: number;
45
+ /**
46
+ * Enable silhouette outline (inverted hull) - only for 'mesh' mode
47
+ * @default true
48
+ */
49
+ enableSilhouette?: boolean;
50
+ /**
51
+ * Enable edge lines - only for 'mesh' mode
52
+ * @default true
53
+ */
54
+ enableEdgeLines?: boolean;
55
+ /**
56
+ * Edge strength for postprocess mode (0-1)
57
+ * @default 1.0
58
+ */
59
+ edgeStrength?: number;
60
+ /**
61
+ * Custom exclusion function to filter objects
62
+ * Return true to exclude an object from outlining
63
+ */
64
+ excludeFilter?: (object: THREE.Object3D) => boolean;
65
+ }
66
+ /**
67
+ * Internal data structure for tracking outlined objects
68
+ */
69
+ interface OutlineData {
70
+ originalObject: THREE.Object3D;
71
+ silhouetteMesh?: THREE.Mesh;
72
+ edgeLines?: any;
73
+ parent: THREE.Object3D;
74
+ idColor?: THREE.Color;
75
+ }
76
+
77
+ /**
78
+ * OutlineTool - Add outlines and edge lines to Three.js objects
79
+ *
80
+ * Features:
81
+ * - Two rendering modes: mesh-based and post-processing
82
+ * - Silhouette outlines using inverted hull technique
83
+ * - Edge lines for geometry visualization
84
+ * - Automatic updates when objects move/animate
85
+ * - Exclusion filters for specific object types
86
+ *
87
+ * @example
88
+ * ```typescript
89
+ * const outlineTool = new OutlineTool(renderer, {
90
+ * outlineColor: 0xff0000,
91
+ * edgeLineWidth: 2,
92
+ * })
93
+ *
94
+ * outlineTool.addObjects([mesh1, mesh2, mesh3])
95
+ * ```
96
+ */
97
+ declare class OutlineTool {
98
+ private options;
99
+ private outlineData;
100
+ private lineMaterial;
101
+ private renderer;
102
+ private composer;
103
+ private idRenderTarget;
104
+ private idMaterial;
105
+ /**
106
+ * Default exclusion filter
107
+ * Excludes Line2, LineSegments2, helpers, and gizmos
108
+ */
109
+ private static defaultExcludeFilter;
110
+ constructor(renderer: THREE.WebGLRenderer, options?: OutlineOptions);
111
+ private handleResize;
112
+ /**
113
+ * Add objects to be outlined
114
+ * @param objects - Array of Three.js objects to outline
115
+ */
116
+ addObjects(objects: THREE.Object3D[]): void;
117
+ /**
118
+ * Add a single object to be outlined
119
+ * @param object - Three.js object to outline
120
+ */
121
+ addObject(object: THREE.Object3D): void;
122
+ /**
123
+ * Remove objects from outlining
124
+ * @param objects - Array of objects to remove outlines from
125
+ */
126
+ removeObjects(objects: THREE.Object3D[]): void;
127
+ /**
128
+ * Remove a single object's outlines
129
+ * @param object - Object to remove outlines from
130
+ */
131
+ removeObject(object: THREE.Object3D): void;
132
+ /**
133
+ * Clear all outlines
134
+ */
135
+ clearAll(): void;
136
+ /**
137
+ * Update outlines to match current object transforms
138
+ * Call this in your animation loop (for mesh mode only)
139
+ */
140
+ update(): void;
141
+ /**
142
+ * Render with outlines (for postprocess mode)
143
+ * Call this instead of renderer.render() when using postprocess mode
144
+ */
145
+ render(scene: THREE.Scene, camera: THREE.Camera): void;
146
+ /**
147
+ * Render the ID buffer for edge detection
148
+ */
149
+ private renderIdBuffer;
150
+ /**
151
+ * Update outline options
152
+ * @param options - Partial options to update
153
+ */
154
+ setOptions(options: Partial<OutlineOptions>): void;
155
+ /**
156
+ * Create silhouette outline mesh
157
+ */
158
+ private createSilhouette;
159
+ /**
160
+ * Create edge lines
161
+ */
162
+ private createEdgeLines;
163
+ /**
164
+ * Type guard for THREE.Mesh
165
+ */
166
+ private isMesh;
167
+ /**
168
+ * Dispose mesh and its resources
169
+ */
170
+ private disposeMesh;
171
+ /**
172
+ * Dispose LineSegments2 and its resources
173
+ */
174
+ private disposeLineSegments;
175
+ /**
176
+ * Cleanup and dispose resources
177
+ */
178
+ dispose(): void;
179
+ }
180
+
181
+ export { type OutlineData, type OutlineOptions, OutlineTool };
package/dist/index.d.ts CHANGED
@@ -3,11 +3,179 @@ export { CameraMode, DualCameraControls, DualCameraControlsOptions, ExternalCame
3
3
  export { CompassOverlay, CompassOverlayEvent, CompassOverlayOptions } from './compass/index.js';
4
4
  export { InfiniteGrid } from './grid/index.js';
5
5
  export { Measurement, MeasurementData, MeasurementPoint, MeasurementPointData, MeasurementTool, MeasurementToolEvents, MeasurementToolOptions, SnapMode, SnapResult } from './measurements/index.js';
6
+ import * as THREE from 'three';
6
7
  export { SunLightState, SunLightTool, SunLightToolEvents, SunLightToolOptions, SunLightWeather } from './sunlight/index.js';
7
8
  export { ElevationPoint, GeoCoordinates, TerrainData, TerrainDimensions, TerrainTool, TerrainToolEvents, TerrainToolOptions } from './terrain/index.js';
8
9
  export { TransformControls, TransformControlsGizmo, TransformControlsPlane, calculateBoundingBoxCenter } from './transform-controls/index.js';
9
10
  export { ViewHelper, ViewHelperCameraController, ViewHelperEvent, ViewHelperOptions } from './view-helper/index.js';
10
- import 'three';
11
11
  import 'camera-controls';
12
12
  import 'three/examples/jsm/renderers/CSS2DRenderer';
13
13
  import 'three/examples/jsm/renderers/CSS2DRenderer.js';
14
+
15
+ /**
16
+ * Configuration options for the OutlineTool
17
+ */
18
+ interface OutlineOptions {
19
+ /**
20
+ * Color of the outline (hex)
21
+ * @default 0xff0000
22
+ */
23
+ outlineColor?: number;
24
+ /**
25
+ * Thickness of edge lines in pixels (for both modes)
26
+ * @default 2
27
+ */
28
+ edgeLineWidth?: number;
29
+ /**
30
+ * Color of edge lines (hex) - only for 'mesh' mode
31
+ * @default 0xff0000
32
+ */
33
+ edgeLineColor?: number;
34
+ /**
35
+ * Angle threshold for edge detection (degrees) - only for 'mesh' mode
36
+ * Higher values = fewer edges detected
37
+ * @default 30
38
+ */
39
+ edgeThreshold?: number;
40
+ /**
41
+ * Scale multiplier for silhouette outline - only for 'mesh' mode
42
+ * @default 1.02
43
+ */
44
+ outlineScale?: number;
45
+ /**
46
+ * Enable silhouette outline (inverted hull) - only for 'mesh' mode
47
+ * @default true
48
+ */
49
+ enableSilhouette?: boolean;
50
+ /**
51
+ * Enable edge lines - only for 'mesh' mode
52
+ * @default true
53
+ */
54
+ enableEdgeLines?: boolean;
55
+ /**
56
+ * Edge strength for postprocess mode (0-1)
57
+ * @default 1.0
58
+ */
59
+ edgeStrength?: number;
60
+ /**
61
+ * Custom exclusion function to filter objects
62
+ * Return true to exclude an object from outlining
63
+ */
64
+ excludeFilter?: (object: THREE.Object3D) => boolean;
65
+ }
66
+ /**
67
+ * Internal data structure for tracking outlined objects
68
+ */
69
+ interface OutlineData {
70
+ originalObject: THREE.Object3D;
71
+ silhouetteMesh?: THREE.Mesh;
72
+ edgeLines?: any;
73
+ parent: THREE.Object3D;
74
+ idColor?: THREE.Color;
75
+ }
76
+
77
+ /**
78
+ * OutlineTool - Add outlines and edge lines to Three.js objects
79
+ *
80
+ * Features:
81
+ * - Two rendering modes: mesh-based and post-processing
82
+ * - Silhouette outlines using inverted hull technique
83
+ * - Edge lines for geometry visualization
84
+ * - Automatic updates when objects move/animate
85
+ * - Exclusion filters for specific object types
86
+ *
87
+ * @example
88
+ * ```typescript
89
+ * const outlineTool = new OutlineTool(renderer, {
90
+ * outlineColor: 0xff0000,
91
+ * edgeLineWidth: 2,
92
+ * })
93
+ *
94
+ * outlineTool.addObjects([mesh1, mesh2, mesh3])
95
+ * ```
96
+ */
97
+ declare class OutlineTool {
98
+ private options;
99
+ private outlineData;
100
+ private lineMaterial;
101
+ private renderer;
102
+ private composer;
103
+ private idRenderTarget;
104
+ private idMaterial;
105
+ /**
106
+ * Default exclusion filter
107
+ * Excludes Line2, LineSegments2, helpers, and gizmos
108
+ */
109
+ private static defaultExcludeFilter;
110
+ constructor(renderer: THREE.WebGLRenderer, options?: OutlineOptions);
111
+ private handleResize;
112
+ /**
113
+ * Add objects to be outlined
114
+ * @param objects - Array of Three.js objects to outline
115
+ */
116
+ addObjects(objects: THREE.Object3D[]): void;
117
+ /**
118
+ * Add a single object to be outlined
119
+ * @param object - Three.js object to outline
120
+ */
121
+ addObject(object: THREE.Object3D): void;
122
+ /**
123
+ * Remove objects from outlining
124
+ * @param objects - Array of objects to remove outlines from
125
+ */
126
+ removeObjects(objects: THREE.Object3D[]): void;
127
+ /**
128
+ * Remove a single object's outlines
129
+ * @param object - Object to remove outlines from
130
+ */
131
+ removeObject(object: THREE.Object3D): void;
132
+ /**
133
+ * Clear all outlines
134
+ */
135
+ clearAll(): void;
136
+ /**
137
+ * Update outlines to match current object transforms
138
+ * Call this in your animation loop (for mesh mode only)
139
+ */
140
+ update(): void;
141
+ /**
142
+ * Render with outlines (for postprocess mode)
143
+ * Call this instead of renderer.render() when using postprocess mode
144
+ */
145
+ render(scene: THREE.Scene, camera: THREE.Camera): void;
146
+ /**
147
+ * Render the ID buffer for edge detection
148
+ */
149
+ private renderIdBuffer;
150
+ /**
151
+ * Update outline options
152
+ * @param options - Partial options to update
153
+ */
154
+ setOptions(options: Partial<OutlineOptions>): void;
155
+ /**
156
+ * Create silhouette outline mesh
157
+ */
158
+ private createSilhouette;
159
+ /**
160
+ * Create edge lines
161
+ */
162
+ private createEdgeLines;
163
+ /**
164
+ * Type guard for THREE.Mesh
165
+ */
166
+ private isMesh;
167
+ /**
168
+ * Dispose mesh and its resources
169
+ */
170
+ private disposeMesh;
171
+ /**
172
+ * Dispose LineSegments2 and its resources
173
+ */
174
+ private disposeLineSegments;
175
+ /**
176
+ * Cleanup and dispose resources
177
+ */
178
+ dispose(): void;
179
+ }
180
+
181
+ export { type OutlineData, type OutlineOptions, OutlineTool };
package/dist/index.mjs CHANGED
@@ -9,7 +9,7 @@ import {
9
9
  } from "./chunk-IAZH4OHC.mjs";
10
10
  import {
11
11
  AssetLoader
12
- } from "./chunk-27WUVRGX.mjs";
12
+ } from "./chunk-LUE7VHLK.mjs";
13
13
  import {
14
14
  DualCameraControls
15
15
  } from "./chunk-XA7OKYSM.mjs";
@@ -29,12 +29,350 @@ import {
29
29
  import {
30
30
  TerrainTool
31
31
  } from "./chunk-FBTT6MU6.mjs";
32
+
33
+ // packages/outline/src/OutlineTool.ts
34
+ import * as THREE from "three";
35
+ import { LineSegments2 } from "three/examples/jsm/lines/LineSegments2.js";
36
+ import { LineSegmentsGeometry } from "three/examples/jsm/lines/LineSegmentsGeometry.js";
37
+ import { LineMaterial } from "three/examples/jsm/lines/LineMaterial.js";
38
+ var _OutlineTool = class _OutlineTool {
39
+ constructor(renderer, options = {}) {
40
+ this.outlineData = /* @__PURE__ */ new Map();
41
+ this.lineMaterial = null;
42
+ this.composer = null;
43
+ this.idRenderTarget = null;
44
+ this.idMaterial = null;
45
+ this.handleResize = () => {
46
+ const size = this.renderer.getSize(new THREE.Vector2());
47
+ if (this.lineMaterial) {
48
+ this.lineMaterial.resolution.set(size.width, size.height);
49
+ }
50
+ if (this.idRenderTarget) {
51
+ this.idRenderTarget.setSize(size.width, size.height);
52
+ }
53
+ if (this.composer) {
54
+ this.composer.setSize(size.width, size.height);
55
+ }
56
+ };
57
+ this.renderer = renderer;
58
+ this.options = {
59
+ outlineColor: options.outlineColor ?? 16711680,
60
+ edgeLineWidth: options.edgeLineWidth ?? 2,
61
+ edgeLineColor: options.edgeLineColor ?? 16711680,
62
+ edgeThreshold: options.edgeThreshold ?? 30,
63
+ outlineScale: options.outlineScale ?? 1.02,
64
+ enableSilhouette: options.enableSilhouette ?? true,
65
+ enableEdgeLines: options.enableEdgeLines ?? true,
66
+ edgeStrength: options.edgeStrength ?? 1,
67
+ excludeFilter: options.excludeFilter ?? _OutlineTool.defaultExcludeFilter
68
+ };
69
+ const size = renderer.getSize(new THREE.Vector2());
70
+ this.lineMaterial = new LineMaterial({
71
+ color: this.options.edgeLineColor,
72
+ linewidth: this.options.edgeLineWidth,
73
+ resolution: new THREE.Vector2(size.width, size.height)
74
+ });
75
+ window.addEventListener("resize", this.handleResize);
76
+ }
77
+ /**
78
+ * Add objects to be outlined
79
+ * @param objects - Array of Three.js objects to outline
80
+ */
81
+ addObjects(objects) {
82
+ objects.forEach((obj) => this.addObject(obj));
83
+ }
84
+ /**
85
+ * Add a single object to be outlined
86
+ * @param object - Three.js object to outline
87
+ */
88
+ addObject(object) {
89
+ const uuid = object.uuid;
90
+ if (this.outlineData.has(uuid)) {
91
+ console.warn(`Object ${object.name || uuid} is already outlined`);
92
+ return;
93
+ }
94
+ const outlines = [];
95
+ object.traverse((child) => {
96
+ if (!this.isMesh(child) || this.options.excludeFilter(child)) {
97
+ return;
98
+ }
99
+ const mesh = child;
100
+ const data = {
101
+ originalObject: mesh,
102
+ parent: mesh.parent
103
+ };
104
+ if (this.options.enableSilhouette) {
105
+ data.silhouetteMesh = this.createSilhouette(mesh);
106
+ mesh.parent.add(data.silhouetteMesh);
107
+ }
108
+ if (this.options.enableEdgeLines) {
109
+ data.edgeLines = this.createEdgeLines(mesh);
110
+ mesh.parent.add(data.edgeLines);
111
+ }
112
+ outlines.push(data);
113
+ });
114
+ if (outlines.length > 0) {
115
+ this.outlineData.set(uuid, outlines);
116
+ }
117
+ }
118
+ /**
119
+ * Remove objects from outlining
120
+ * @param objects - Array of objects to remove outlines from
121
+ */
122
+ removeObjects(objects) {
123
+ objects.forEach((obj) => this.removeObject(obj));
124
+ }
125
+ /**
126
+ * Remove a single object's outlines
127
+ * @param object - Object to remove outlines from
128
+ */
129
+ removeObject(object) {
130
+ const uuid = object.uuid;
131
+ const outlines = this.outlineData.get(uuid);
132
+ if (!outlines) {
133
+ return;
134
+ }
135
+ outlines.forEach((data) => {
136
+ if (data.silhouetteMesh) {
137
+ data.parent.remove(data.silhouetteMesh);
138
+ this.disposeMesh(data.silhouetteMesh);
139
+ }
140
+ if (data.edgeLines) {
141
+ data.parent.remove(data.edgeLines);
142
+ this.disposeLineSegments(data.edgeLines);
143
+ }
144
+ if (data.originalObject.userData.outlineIdColor) {
145
+ delete data.originalObject.userData.outlineIdColor;
146
+ }
147
+ });
148
+ this.outlineData.delete(uuid);
149
+ }
150
+ /**
151
+ * Clear all outlines
152
+ */
153
+ clearAll() {
154
+ const objects = Array.from(this.outlineData.keys());
155
+ objects.forEach((uuid) => {
156
+ const outlines = this.outlineData.get(uuid);
157
+ if (outlines && outlines.length > 0) {
158
+ this.removeObject(outlines[0].originalObject.parent);
159
+ }
160
+ });
161
+ }
162
+ /**
163
+ * Update outlines to match current object transforms
164
+ * Call this in your animation loop (for mesh mode only)
165
+ */
166
+ update() {
167
+ this.outlineData.forEach((outlines) => {
168
+ outlines.forEach((data) => {
169
+ const mesh = data.originalObject;
170
+ if (data.silhouetteMesh) {
171
+ data.silhouetteMesh.position.copy(mesh.position);
172
+ data.silhouetteMesh.rotation.copy(mesh.rotation);
173
+ data.silhouetteMesh.quaternion.copy(mesh.quaternion);
174
+ data.silhouetteMesh.scale.copy(mesh.scale);
175
+ data.silhouetteMesh.scale.multiplyScalar(this.options.outlineScale);
176
+ }
177
+ if (data.edgeLines) {
178
+ data.edgeLines.position.copy(mesh.position);
179
+ data.edgeLines.rotation.copy(mesh.rotation);
180
+ data.edgeLines.quaternion.copy(mesh.quaternion);
181
+ data.edgeLines.scale.copy(mesh.scale);
182
+ }
183
+ });
184
+ });
185
+ }
186
+ /**
187
+ * Render with outlines (for postprocess mode)
188
+ * Call this instead of renderer.render() when using postprocess mode
189
+ */
190
+ render(scene, camera) {
191
+ this.renderIdBuffer(scene, camera);
192
+ this.composer.render();
193
+ }
194
+ /**
195
+ * Render the ID buffer for edge detection
196
+ */
197
+ renderIdBuffer(scene, camera) {
198
+ if (!this.idRenderTarget || !this.idMaterial) {
199
+ return;
200
+ }
201
+ const oldRT = this.renderer.getRenderTarget();
202
+ const oldOverride = scene.overrideMaterial;
203
+ const visibilityMap = /* @__PURE__ */ new Map();
204
+ scene.traverse((obj) => {
205
+ visibilityMap.set(obj, obj.visible);
206
+ if (this.isMesh(obj) && !obj.userData.outlineIdColor) {
207
+ obj.visible = false;
208
+ }
209
+ });
210
+ scene.overrideMaterial = this.idMaterial;
211
+ scene.traverse((obj) => {
212
+ if (!this.isMesh(obj)) return;
213
+ const mesh = obj;
214
+ mesh.onBeforeRender = () => {
215
+ const idColor = mesh.userData.outlineIdColor;
216
+ if (idColor) {
217
+ this.idMaterial.color.copy(idColor);
218
+ }
219
+ };
220
+ });
221
+ this.renderer.setRenderTarget(this.idRenderTarget);
222
+ this.renderer.clear();
223
+ this.renderer.render(scene, camera);
224
+ scene.traverse((obj) => {
225
+ if (!this.isMesh(obj)) return;
226
+ obj.onBeforeRender = () => {
227
+ };
228
+ const originalVisibility = visibilityMap.get(obj);
229
+ if (originalVisibility !== void 0) {
230
+ obj.visible = originalVisibility;
231
+ }
232
+ });
233
+ scene.overrideMaterial = oldOverride;
234
+ this.renderer.setRenderTarget(oldRT);
235
+ }
236
+ /**
237
+ * Update outline options
238
+ * @param options - Partial options to update
239
+ */
240
+ setOptions(options) {
241
+ const needsRecreate = options.outlineColor !== void 0 || options.edgeLineColor !== void 0 || options.edgeThreshold !== void 0 || options.enableSilhouette !== void 0 || options.enableEdgeLines !== void 0;
242
+ Object.assign(this.options, options);
243
+ if (options.edgeLineWidth !== void 0 && this.lineMaterial) {
244
+ this.lineMaterial.linewidth = options.edgeLineWidth;
245
+ }
246
+ if (options.edgeLineColor !== void 0 && this.lineMaterial) {
247
+ this.lineMaterial.color.setHex(options.edgeLineColor);
248
+ }
249
+ if (needsRecreate) {
250
+ const objects = [];
251
+ this.outlineData.forEach((outlines) => {
252
+ if (outlines.length > 0) {
253
+ let root = outlines[0].originalObject;
254
+ while (root.parent && !this.outlineData.has(root.parent.uuid)) {
255
+ root = root.parent;
256
+ }
257
+ objects.push(root);
258
+ }
259
+ });
260
+ this.clearAll();
261
+ this.addObjects(objects);
262
+ }
263
+ }
264
+ /**
265
+ * Create silhouette outline mesh
266
+ */
267
+ createSilhouette(mesh) {
268
+ const outlineMesh = mesh.clone();
269
+ outlineMesh.material = new THREE.MeshBasicMaterial({
270
+ color: this.options.outlineColor,
271
+ side: THREE.BackSide
272
+ });
273
+ outlineMesh.renderOrder = -1;
274
+ outlineMesh.scale.multiplyScalar(this.options.outlineScale);
275
+ outlineMesh.userData.excludeOutline = true;
276
+ return outlineMesh;
277
+ }
278
+ /**
279
+ * Create edge lines
280
+ */
281
+ createEdgeLines(mesh) {
282
+ if (!this.lineMaterial) {
283
+ throw new Error("Line material not initialized");
284
+ }
285
+ const edges = new THREE.EdgesGeometry(
286
+ mesh.geometry,
287
+ this.options.edgeThreshold
288
+ );
289
+ const lineGeometry = new LineSegmentsGeometry();
290
+ const positions = edges.attributes.position.array;
291
+ lineGeometry.setPositions(positions);
292
+ const edgeLines = new LineSegments2(lineGeometry, this.lineMaterial);
293
+ edgeLines.computeLineDistances();
294
+ edgeLines.scale.copy(mesh.scale);
295
+ edgeLines.rotation.copy(mesh.rotation);
296
+ edgeLines.position.copy(mesh.position);
297
+ edgeLines.userData.excludeOutline = true;
298
+ edges.dispose();
299
+ return edgeLines;
300
+ }
301
+ /**
302
+ * Type guard for THREE.Mesh
303
+ */
304
+ isMesh(object) {
305
+ return object.isMesh === true;
306
+ }
307
+ /**
308
+ * Dispose mesh and its resources
309
+ */
310
+ disposeMesh(mesh) {
311
+ if (mesh.geometry) {
312
+ mesh.geometry.dispose();
313
+ }
314
+ if (Array.isArray(mesh.material)) {
315
+ mesh.material.forEach((mat) => mat.dispose());
316
+ } else if (mesh.material) {
317
+ mesh.material.dispose();
318
+ }
319
+ }
320
+ /**
321
+ * Dispose LineSegments2 and its resources
322
+ */
323
+ disposeLineSegments(line) {
324
+ if (line.geometry) {
325
+ line.geometry.dispose();
326
+ }
327
+ }
328
+ /**
329
+ * Cleanup and dispose resources
330
+ */
331
+ dispose() {
332
+ this.clearAll();
333
+ if (this.lineMaterial) {
334
+ this.lineMaterial.dispose();
335
+ }
336
+ if (this.idRenderTarget) {
337
+ this.idRenderTarget.dispose();
338
+ }
339
+ if (this.idMaterial) {
340
+ this.idMaterial.dispose();
341
+ }
342
+ if (this.composer) {
343
+ this.composer = null;
344
+ }
345
+ window.removeEventListener("resize", this.handleResize);
346
+ }
347
+ };
348
+ /**
349
+ * Default exclusion filter
350
+ * Excludes Line2, LineSegments2, helpers, and gizmos
351
+ */
352
+ _OutlineTool.defaultExcludeFilter = (object) => {
353
+ if (object.type === "Line2" || object.type === "LineSegments2") {
354
+ return true;
355
+ }
356
+ if (object.type.includes("Helper")) {
357
+ return true;
358
+ }
359
+ if (object.userData.excludeOutline) {
360
+ return true;
361
+ }
362
+ const name = object.name.toLowerCase();
363
+ if (name.includes("arrow") || name.includes("gizmo") || name.includes("control")) {
364
+ return true;
365
+ }
366
+ return false;
367
+ };
368
+ var OutlineTool = _OutlineTool;
32
369
  export {
33
370
  AssetLoader,
34
371
  CompassOverlay,
35
372
  DualCameraControls,
36
373
  InfiniteGrid,
37
374
  MeasurementTool,
375
+ OutlineTool,
38
376
  SnapMode,
39
377
  SunLightTool,
40
378
  TerrainTool,