three-cad-viewer 4.3.5 → 4.3.7
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/three-cad-viewer.esm.js +8 -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 +8 -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 -650
- package/src/scene/grid.ts +0 -864
- package/src/scene/nestedgroup.ts +0 -1448
- 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
|
@@ -1,233 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Decode the compressed/instanced shape format.
|
|
3
|
-
*
|
|
4
|
-
* The instanced format wraps a standard Shapes object:
|
|
5
|
-
* ```
|
|
6
|
-
* { instances: [ { vertices: {shape,dtype,buffer,codec}, ... }, ... ],
|
|
7
|
-
* shapes: { version, parts, loc, name, id, bb, ... } }
|
|
8
|
-
* ```
|
|
9
|
-
*
|
|
10
|
-
* Each instance contains base64-encoded geometry buffers. Parts reference
|
|
11
|
-
* instances via `"shape": { "ref": N }`. After decoding, the result is a
|
|
12
|
-
* standard Shapes tree with TypedArrays — identical to the existing format.
|
|
13
|
-
*/
|
|
14
|
-
import type { Shape, Shapes } from "../core/types.js";
|
|
15
|
-
|
|
16
|
-
// =============================================================================
|
|
17
|
-
// Types for the encoded format
|
|
18
|
-
// =============================================================================
|
|
19
|
-
|
|
20
|
-
/** A single base64-encoded buffer entry. */
|
|
21
|
-
interface EncodedBuffer {
|
|
22
|
-
shape: number[];
|
|
23
|
-
dtype: "float32" | "int32" | "uint32";
|
|
24
|
-
buffer: string;
|
|
25
|
-
codec: "b64";
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/** An encoded geometry instance (all 9 buffer fields + optional uvs). */
|
|
29
|
-
interface EncodedInstance {
|
|
30
|
-
vertices: EncodedBuffer;
|
|
31
|
-
triangles: EncodedBuffer;
|
|
32
|
-
normals: EncodedBuffer;
|
|
33
|
-
edges: EncodedBuffer;
|
|
34
|
-
obj_vertices: EncodedBuffer;
|
|
35
|
-
face_types: EncodedBuffer;
|
|
36
|
-
edge_types: EncodedBuffer;
|
|
37
|
-
triangles_per_face: EncodedBuffer;
|
|
38
|
-
segments_per_edge: EncodedBuffer;
|
|
39
|
-
uvs?: EncodedBuffer;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/** Top-level structure of the instanced format. */
|
|
43
|
-
interface InstancedData {
|
|
44
|
-
instances: EncodedInstance[];
|
|
45
|
-
shapes: Shapes;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/** Shape reference (before resolution). */
|
|
49
|
-
interface ShapeRef {
|
|
50
|
-
ref: number;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// =============================================================================
|
|
54
|
-
// Decoding
|
|
55
|
-
// =============================================================================
|
|
56
|
-
|
|
57
|
-
/** Maximum decoded buffer size (512 MB). */
|
|
58
|
-
const MAX_BUFFER_BYTES = 512 * 1024 * 1024;
|
|
59
|
-
|
|
60
|
-
/** Decode a base64 string to a Uint8Array. */
|
|
61
|
-
function fromBase64(b64: string): Uint8Array {
|
|
62
|
-
const binary = atob(b64);
|
|
63
|
-
if (binary.length > MAX_BUFFER_BYTES) {
|
|
64
|
-
throw new Error(
|
|
65
|
-
`Decoded buffer size ${binary.length} bytes exceeds maximum of ${MAX_BUFFER_BYTES} bytes`,
|
|
66
|
-
);
|
|
67
|
-
}
|
|
68
|
-
const bytes = new Uint8Array(binary.length);
|
|
69
|
-
for (let i = 0; i < binary.length; i++) {
|
|
70
|
-
bytes[i] = binary.charCodeAt(i);
|
|
71
|
-
}
|
|
72
|
-
return bytes;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/** Decode a single encoded buffer entry to a typed array. */
|
|
76
|
-
function decodeBuffer(buf: EncodedBuffer): Float32Array | Uint32Array {
|
|
77
|
-
const bytes = fromBase64(buf.buffer);
|
|
78
|
-
const arrayBuffer = bytes.buffer.slice(
|
|
79
|
-
bytes.byteOffset,
|
|
80
|
-
bytes.byteOffset + bytes.byteLength,
|
|
81
|
-
);
|
|
82
|
-
switch (buf.dtype) {
|
|
83
|
-
case "float32":
|
|
84
|
-
return new Float32Array(arrayBuffer);
|
|
85
|
-
case "int32":
|
|
86
|
-
case "uint32":
|
|
87
|
-
return new Uint32Array(arrayBuffer);
|
|
88
|
-
default:
|
|
89
|
-
throw new Error(`Unknown dtype: ${buf.dtype}`);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
/** Decode all buffer fields of an instance into a Shape object. */
|
|
94
|
-
function decodeInstance(inst: EncodedInstance): Shape {
|
|
95
|
-
const shape: Shape = {
|
|
96
|
-
vertices: decodeBuffer(inst.vertices) as Float32Array,
|
|
97
|
-
triangles: decodeBuffer(inst.triangles) as Uint32Array,
|
|
98
|
-
normals: decodeBuffer(inst.normals) as Float32Array,
|
|
99
|
-
edges: decodeBuffer(inst.edges) as Float32Array,
|
|
100
|
-
obj_vertices: decodeBuffer(inst.obj_vertices) as Float32Array,
|
|
101
|
-
face_types: decodeBuffer(inst.face_types) as Uint32Array,
|
|
102
|
-
edge_types: decodeBuffer(inst.edge_types) as Uint32Array,
|
|
103
|
-
triangles_per_face: decodeBuffer(inst.triangles_per_face) as Uint32Array,
|
|
104
|
-
segments_per_edge: decodeBuffer(inst.segments_per_edge) as Uint32Array,
|
|
105
|
-
};
|
|
106
|
-
if (inst.uvs) {
|
|
107
|
-
shape.uvs = decodeBuffer(inst.uvs) as Float32Array;
|
|
108
|
-
}
|
|
109
|
-
return shape;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
/** Check if a value is an encoded buffer (inline base64 field). */
|
|
113
|
-
function isEncodedBuffer(val: unknown): val is EncodedBuffer {
|
|
114
|
-
return (
|
|
115
|
-
typeof val === "object" &&
|
|
116
|
-
val !== null &&
|
|
117
|
-
"buffer" in val &&
|
|
118
|
-
"dtype" in val &&
|
|
119
|
-
"codec" in val &&
|
|
120
|
-
(val as EncodedBuffer).codec === "b64"
|
|
121
|
-
);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
/**
|
|
125
|
-
* Decode any inline encoded buffers on a shape object.
|
|
126
|
-
* Mutates the shape in place, replacing EncodedBuffer fields with TypedArrays.
|
|
127
|
-
*/
|
|
128
|
-
function decodeInlineShapeBuffers(shape: Record<string, unknown>): void {
|
|
129
|
-
for (const key of Object.keys(shape)) {
|
|
130
|
-
if (isEncodedBuffer(shape[key])) {
|
|
131
|
-
shape[key] = decodeBuffer(shape[key] as EncodedBuffer);
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* Walk the shapes tree and decode any inline encoded buffers found in
|
|
138
|
-
* part.shape objects. This handles edge/vertex-only objects that embed
|
|
139
|
-
* encoded buffers directly (not via instance refs).
|
|
140
|
-
*/
|
|
141
|
-
function decodeInlineBuffers(shapes: Shapes): void {
|
|
142
|
-
if (shapes.parts) {
|
|
143
|
-
for (const part of shapes.parts) {
|
|
144
|
-
if (
|
|
145
|
-
part.shape != null &&
|
|
146
|
-
typeof part.shape === "object" &&
|
|
147
|
-
!isShapeRef(part.shape as unknown)
|
|
148
|
-
) {
|
|
149
|
-
decodeInlineShapeBuffers(part.shape as unknown as Record<string, unknown>);
|
|
150
|
-
}
|
|
151
|
-
if (part.parts) {
|
|
152
|
-
decodeInlineBuffers(part);
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
/** Check if a shape field is an unresolved reference. */
|
|
159
|
-
function isShapeRef(shape: unknown): shape is ShapeRef {
|
|
160
|
-
return (
|
|
161
|
-
typeof shape === "object" &&
|
|
162
|
-
shape !== null &&
|
|
163
|
-
"ref" in shape &&
|
|
164
|
-
typeof (shape as ShapeRef).ref === "number"
|
|
165
|
-
);
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
/**
|
|
169
|
-
* Recursively walk the shapes tree and replace { ref: N } entries
|
|
170
|
-
* with the corresponding decoded instance.
|
|
171
|
-
*
|
|
172
|
-
* Before decoding, `part.shape` may be `{ ref: N }` which doesn't match
|
|
173
|
-
* the `Shape` type. We use `unknown` casts since this operates on raw
|
|
174
|
-
* (pre-typed) data that is being transformed into the proper type.
|
|
175
|
-
*/
|
|
176
|
-
function resolveRefs(shapes: Shapes, decoded: Shape[]): void {
|
|
177
|
-
if (shapes.parts) {
|
|
178
|
-
for (const part of shapes.parts) {
|
|
179
|
-
if (isShapeRef(part.shape as unknown)) {
|
|
180
|
-
const ref = (part.shape as unknown as ShapeRef).ref;
|
|
181
|
-
if (ref < 0 || ref >= decoded.length) {
|
|
182
|
-
throw new Error(
|
|
183
|
-
`Shape ref ${ref} is out of bounds (${decoded.length} instances decoded)`,
|
|
184
|
-
);
|
|
185
|
-
}
|
|
186
|
-
part.shape = decoded[ref];
|
|
187
|
-
}
|
|
188
|
-
if (part.parts) {
|
|
189
|
-
resolveRefs(part, decoded);
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
// =============================================================================
|
|
196
|
-
// Public API
|
|
197
|
-
// =============================================================================
|
|
198
|
-
|
|
199
|
-
/**
|
|
200
|
-
* Type guard: check if data is in the instanced format.
|
|
201
|
-
* Detected by the presence of an `instances` array and a `shapes` object.
|
|
202
|
-
*/
|
|
203
|
-
function isInstancedFormat(data: unknown): data is InstancedData {
|
|
204
|
-
return (
|
|
205
|
-
typeof data === "object" &&
|
|
206
|
-
data !== null &&
|
|
207
|
-
"instances" in data &&
|
|
208
|
-
Array.isArray((data as InstancedData).instances) &&
|
|
209
|
-
"shapes" in data &&
|
|
210
|
-
typeof (data as InstancedData).shapes === "object"
|
|
211
|
-
);
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
/**
|
|
215
|
-
* Decode the instanced format into a standard Shapes object.
|
|
216
|
-
*
|
|
217
|
-
* 1. Decode all instance buffers from base64 → TypedArrays
|
|
218
|
-
* 2. Walk the shapes tree and replace { ref: N } with decoded instances
|
|
219
|
-
* 3. Return the unwrapped Shapes object
|
|
220
|
-
*/
|
|
221
|
-
function decodeInstancedFormat(data: InstancedData): Shapes {
|
|
222
|
-
// Decode all instances
|
|
223
|
-
const decoded = data.instances.map(decodeInstance);
|
|
224
|
-
|
|
225
|
-
// Resolve all shape references
|
|
226
|
-
const shapes = data.shapes;
|
|
227
|
-
resolveRefs(shapes, decoded);
|
|
228
|
-
|
|
229
|
-
return shapes;
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
export { isInstancedFormat, decodeInstancedFormat, decodeInlineBuffers };
|
|
233
|
-
export type { InstancedData, EncodedBuffer, EncodedInstance };
|
package/src/utils/font.ts
DELETED
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Helvetiker font subset - only X, Y, Z glyphs for axis labels.
|
|
3
|
-
* Full font: https://github.com/mrdoob/three.js/blob/dev/examples/fonts/helvetiker_regular.typeface.json
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
interface Glyph {
|
|
7
|
-
x_min: number;
|
|
8
|
-
x_max: number;
|
|
9
|
-
ha: number;
|
|
10
|
-
o: string;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export interface FontData {
|
|
14
|
-
glyphs: Record<string, Glyph>;
|
|
15
|
-
cssFontWeight?: string;
|
|
16
|
-
ascender: number;
|
|
17
|
-
underlinePosition: number;
|
|
18
|
-
cssFontStyle?: string;
|
|
19
|
-
boundingBox: { yMin: number; xMin: number; yMax: number; xMax: number };
|
|
20
|
-
resolution: number;
|
|
21
|
-
descender: number;
|
|
22
|
-
familyName: string;
|
|
23
|
-
lineHeight?: number;
|
|
24
|
-
underlineThickness: number;
|
|
25
|
-
original_font_information: Record<string, string>;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export const helvetiker: FontData = {
|
|
29
|
-
glyphs: {
|
|
30
|
-
X: {
|
|
31
|
-
x_min: -0.015625,
|
|
32
|
-
x_max: 854.15625,
|
|
33
|
-
ha: 940,
|
|
34
|
-
o: "m 854 0 l 683 0 l 423 409 l 166 0 l 0 0 l 347 519 l 18 1013 l 186 1013 l 428 637 l 675 1013 l 836 1013 l 504 520 l 854 0 ",
|
|
35
|
-
},
|
|
36
|
-
Y: {
|
|
37
|
-
x_min: 0,
|
|
38
|
-
x_max: 820,
|
|
39
|
-
ha: 886,
|
|
40
|
-
o: "m 820 1013 l 482 416 l 482 0 l 342 0 l 342 416 l 0 1013 l 140 1013 l 411 534 l 679 1012 l 820 1013 ",
|
|
41
|
-
},
|
|
42
|
-
Z: {
|
|
43
|
-
x_min: 0,
|
|
44
|
-
x_max: 779,
|
|
45
|
-
ha: 849,
|
|
46
|
-
o: "m 779 0 l 0 0 l 0 113 l 621 896 l 40 896 l 40 1013 l 779 1013 l 778 887 l 171 124 l 779 124 l 779 0 ",
|
|
47
|
-
},
|
|
48
|
-
},
|
|
49
|
-
cssFontWeight: "normal",
|
|
50
|
-
ascender: 1189,
|
|
51
|
-
underlinePosition: -100,
|
|
52
|
-
cssFontStyle: "normal",
|
|
53
|
-
boundingBox: { yMin: -334, xMin: -111, yMax: 1189, xMax: 1672 },
|
|
54
|
-
resolution: 1000,
|
|
55
|
-
descender: -334,
|
|
56
|
-
familyName: "Helvetiker",
|
|
57
|
-
lineHeight: 1522,
|
|
58
|
-
underlineThickness: 50,
|
|
59
|
-
original_font_information: {},
|
|
60
|
-
};
|
package/src/utils/gpu-tracker.ts
DELETED
|
@@ -1,265 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* GPU Resource Tracker for three-cad-viewer.
|
|
3
|
-
*
|
|
4
|
-
* Tracks Three.js GPU resources (geometries, materials, textures) to detect memory leaks
|
|
5
|
-
* or inspect current allocations. By default, only maintains counts. Enable debug mode
|
|
6
|
-
* for detailed creation info.
|
|
7
|
-
*
|
|
8
|
-
* @example
|
|
9
|
-
* // Check resource counts
|
|
10
|
-
* import { gpuTracker } from "three-cad-viewer";
|
|
11
|
-
* console.log(gpuTracker.summary);
|
|
12
|
-
* // { geometry: 5, material: 10, texture: 1, total: 16 }
|
|
13
|
-
*
|
|
14
|
-
* @example
|
|
15
|
-
* // Debug mode - see detailed allocation info
|
|
16
|
-
* gpuTracker.enableDebug();
|
|
17
|
-
* // ... create viewer and render objects ...
|
|
18
|
-
* gpuTracker.details(); // Shows what's currently allocated
|
|
19
|
-
* // ... dispose viewer ...
|
|
20
|
-
* gpuTracker.details(); // After dispose, shows any leaks
|
|
21
|
-
*/
|
|
22
|
-
|
|
23
|
-
import { logger } from "./logger.js";
|
|
24
|
-
|
|
25
|
-
/** Resource types tracked by the GPU tracker */
|
|
26
|
-
export type ResourceType = "geometry" | "material" | "texture";
|
|
27
|
-
|
|
28
|
-
/** Information about a tracked resource (debug mode only) */
|
|
29
|
-
export interface TrackedResource {
|
|
30
|
-
/** Type of GPU resource */
|
|
31
|
-
type: ResourceType;
|
|
32
|
-
/** Human-readable label for identification */
|
|
33
|
-
label: string;
|
|
34
|
-
/** Stack trace at creation time (truncated) */
|
|
35
|
-
stack: string;
|
|
36
|
-
/** Timestamp of creation (performance.now()) */
|
|
37
|
-
timestamp: number;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/** Summary of current resource counts */
|
|
41
|
-
export interface ResourceSummary {
|
|
42
|
-
geometry: number;
|
|
43
|
-
material: number;
|
|
44
|
-
texture: number;
|
|
45
|
-
total: number;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// Internal state
|
|
49
|
-
const counts: Record<ResourceType, number> = {
|
|
50
|
-
geometry: 0,
|
|
51
|
-
material: 0,
|
|
52
|
-
texture: 0,
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
let debugMode = false;
|
|
56
|
-
const tracked = new Map<object, TrackedResource>();
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* GPU Resource Tracker.
|
|
60
|
-
*
|
|
61
|
-
* Tracks creation and disposal of Three.js GPU resources to help detect memory leaks.
|
|
62
|
-
* Access via `window.tcv_gpu` in browser console for debugging.
|
|
63
|
-
*/
|
|
64
|
-
export const gpuTracker = {
|
|
65
|
-
/**
|
|
66
|
-
* Enable debug mode to capture creation info (stack traces, labels).
|
|
67
|
-
* Call before creating any viewer resources for full tracking.
|
|
68
|
-
*
|
|
69
|
-
* Performance impact: Captures stack trace on every resource creation.
|
|
70
|
-
* Only enable when debugging leaks.
|
|
71
|
-
*/
|
|
72
|
-
enableDebug(): void {
|
|
73
|
-
debugMode = true;
|
|
74
|
-
logger.info("GPU tracker debug mode enabled");
|
|
75
|
-
},
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* Disable debug mode and clear tracked objects.
|
|
79
|
-
*/
|
|
80
|
-
disableDebug(): void {
|
|
81
|
-
debugMode = false;
|
|
82
|
-
tracked.clear();
|
|
83
|
-
logger.info("GPU tracker debug mode disabled");
|
|
84
|
-
},
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Check if debug mode is enabled.
|
|
88
|
-
*/
|
|
89
|
-
get isDebugEnabled(): boolean {
|
|
90
|
-
return debugMode;
|
|
91
|
-
},
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* Track a GPU resource creation.
|
|
95
|
-
*
|
|
96
|
-
* @param type - Resource type (geometry, material, texture)
|
|
97
|
-
* @param obj - The Three.js object being tracked
|
|
98
|
-
* @param label - Optional descriptive label (e.g., "front face material for /Assembly/Part1")
|
|
99
|
-
*/
|
|
100
|
-
track(type: ResourceType, obj: object, label?: string): void {
|
|
101
|
-
counts[type]++;
|
|
102
|
-
|
|
103
|
-
if (debugMode) {
|
|
104
|
-
// Capture stack trace, skip first 2 lines (Error + this function)
|
|
105
|
-
const stack = new Error().stack?.split("\n").slice(2, 6).join("\n") ?? "";
|
|
106
|
-
|
|
107
|
-
tracked.set(obj, {
|
|
108
|
-
type,
|
|
109
|
-
label: label ?? "unlabeled",
|
|
110
|
-
stack,
|
|
111
|
-
timestamp: performance.now(),
|
|
112
|
-
});
|
|
113
|
-
}
|
|
114
|
-
},
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* Untrack a GPU resource after disposal.
|
|
118
|
-
*
|
|
119
|
-
* @param type - Resource type (required in non-debug mode)
|
|
120
|
-
* @param obj - The Three.js object being untracked (optional in non-debug mode)
|
|
121
|
-
*/
|
|
122
|
-
untrack(type: ResourceType, obj?: object): void {
|
|
123
|
-
if (debugMode && obj) {
|
|
124
|
-
const info = tracked.get(obj);
|
|
125
|
-
if (info) {
|
|
126
|
-
counts[info.type]--;
|
|
127
|
-
tracked.delete(obj);
|
|
128
|
-
return;
|
|
129
|
-
}
|
|
130
|
-
// Object not found - was created before debug mode enabled or before tracking was added
|
|
131
|
-
// Don't warn, just fall through to decrement (or skip if count is 0)
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
// Non-debug mode or object not found: decrement counter if positive
|
|
135
|
-
// Silently ignore if count is already 0 (resource wasn't tracked)
|
|
136
|
-
if (counts[type] > 0) {
|
|
137
|
-
counts[type]--;
|
|
138
|
-
}
|
|
139
|
-
},
|
|
140
|
-
|
|
141
|
-
/**
|
|
142
|
-
* Get current resource counts.
|
|
143
|
-
*/
|
|
144
|
-
get summary(): ResourceSummary {
|
|
145
|
-
return {
|
|
146
|
-
geometry: counts.geometry,
|
|
147
|
-
material: counts.material,
|
|
148
|
-
texture: counts.texture,
|
|
149
|
-
total: counts.geometry + counts.material + counts.texture,
|
|
150
|
-
};
|
|
151
|
-
},
|
|
152
|
-
|
|
153
|
-
/**
|
|
154
|
-
* Get all tracked resources (debug mode only).
|
|
155
|
-
*
|
|
156
|
-
* @returns Array of currently tracked resources
|
|
157
|
-
*/
|
|
158
|
-
getResources(): TrackedResource[] {
|
|
159
|
-
if (!debugMode) {
|
|
160
|
-
logger.warn("GPU tracker: getResources() requires debug mode - call enableDebug() first");
|
|
161
|
-
return [];
|
|
162
|
-
}
|
|
163
|
-
return Array.from(tracked.values());
|
|
164
|
-
},
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
* Get tracked resources grouped by type.
|
|
168
|
-
*/
|
|
169
|
-
getResourcesByType(): Record<ResourceType, TrackedResource[]> {
|
|
170
|
-
const resources = this.getResources();
|
|
171
|
-
return {
|
|
172
|
-
geometry: resources.filter((r) => r.type === "geometry"),
|
|
173
|
-
material: resources.filter((r) => r.type === "material"),
|
|
174
|
-
texture: resources.filter((r) => r.type === "texture"),
|
|
175
|
-
};
|
|
176
|
-
},
|
|
177
|
-
|
|
178
|
-
/**
|
|
179
|
-
* Log details of currently tracked resources.
|
|
180
|
-
* Useful for inspecting allocations or detecting leaks after disposal.
|
|
181
|
-
* Always outputs to console regardless of logger level.
|
|
182
|
-
*/
|
|
183
|
-
details(): void {
|
|
184
|
-
const { total, geometry, material, texture } = this.summary;
|
|
185
|
-
|
|
186
|
-
if (total === 0) {
|
|
187
|
-
console.log("GPU tracker: No resources currently allocated");
|
|
188
|
-
return;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
console.log(`GPU tracker: ${total} resources allocated:`);
|
|
192
|
-
console.log(` - Geometries: ${geometry}`);
|
|
193
|
-
console.log(` - Materials: ${material}`);
|
|
194
|
-
console.log(` - Textures: ${texture}`);
|
|
195
|
-
|
|
196
|
-
if (debugMode) {
|
|
197
|
-
const resources = this.getResources();
|
|
198
|
-
console.log("\nResource details:");
|
|
199
|
-
resources.forEach((resource, i) => {
|
|
200
|
-
console.log(`\n[${i + 1}] ${resource.type}: ${resource.label}`);
|
|
201
|
-
console.log(` Created at: ${resource.timestamp.toFixed(2)}ms`);
|
|
202
|
-
console.log(` Stack:\n${resource.stack}`);
|
|
203
|
-
});
|
|
204
|
-
} else {
|
|
205
|
-
console.log("\nFor detailed resource info, enable debug mode before creating resources:");
|
|
206
|
-
console.log(" gpuTracker.enableDebug()");
|
|
207
|
-
}
|
|
208
|
-
},
|
|
209
|
-
|
|
210
|
-
/**
|
|
211
|
-
* Reset all counters and tracked objects.
|
|
212
|
-
* Useful for testing or starting fresh.
|
|
213
|
-
*/
|
|
214
|
-
reset(): void {
|
|
215
|
-
counts.geometry = 0;
|
|
216
|
-
counts.material = 0;
|
|
217
|
-
counts.texture = 0;
|
|
218
|
-
tracked.clear();
|
|
219
|
-
},
|
|
220
|
-
|
|
221
|
-
/**
|
|
222
|
-
* Assert that all resources have been disposed.
|
|
223
|
-
* Useful in tests.
|
|
224
|
-
*
|
|
225
|
-
* @throws Error if any resources remain
|
|
226
|
-
*/
|
|
227
|
-
assertEmpty(): void {
|
|
228
|
-
const { total } = this.summary;
|
|
229
|
-
if (total !== 0) {
|
|
230
|
-
this.details();
|
|
231
|
-
throw new Error(`GPU tracker: ${total} resources not disposed`);
|
|
232
|
-
}
|
|
233
|
-
},
|
|
234
|
-
|
|
235
|
-
// Convenience methods for common Three.js types
|
|
236
|
-
|
|
237
|
-
/**
|
|
238
|
-
* Track a geometry and return it (for chaining).
|
|
239
|
-
*/
|
|
240
|
-
trackGeometry<T extends object>(geometry: T, label?: string): T {
|
|
241
|
-
this.track("geometry", geometry, label);
|
|
242
|
-
return geometry;
|
|
243
|
-
},
|
|
244
|
-
|
|
245
|
-
/**
|
|
246
|
-
* Track a material and return it (for chaining).
|
|
247
|
-
*/
|
|
248
|
-
trackMaterial<T extends object>(material: T, label?: string): T {
|
|
249
|
-
this.track("material", material, label);
|
|
250
|
-
return material;
|
|
251
|
-
},
|
|
252
|
-
|
|
253
|
-
/**
|
|
254
|
-
* Track a texture and return it (for chaining).
|
|
255
|
-
*/
|
|
256
|
-
trackTexture<T extends object>(texture: T, label?: string): T {
|
|
257
|
-
this.track("texture", texture, label);
|
|
258
|
-
return texture;
|
|
259
|
-
},
|
|
260
|
-
};
|
|
261
|
-
|
|
262
|
-
// Expose globally for browser debugging
|
|
263
|
-
if (typeof window !== "undefined") {
|
|
264
|
-
(window as unknown as { tcv_gpu: typeof gpuTracker }).tcv_gpu = gpuTracker;
|
|
265
|
-
}
|
package/src/utils/logger.ts
DELETED
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Minimal logging utility for three-cad-viewer.
|
|
3
|
-
*
|
|
4
|
-
* Provides leveled logging that can be controlled by library consumers.
|
|
5
|
-
* Default level is "warn" (only warnings and errors shown).
|
|
6
|
-
*
|
|
7
|
-
* @example
|
|
8
|
-
* // Library consumer can enable debug output:
|
|
9
|
-
* import { logger } from "three-cad-viewer";
|
|
10
|
-
* logger.setLevel("debug");
|
|
11
|
-
*
|
|
12
|
-
* @example
|
|
13
|
-
* // Silence all logging:
|
|
14
|
-
* logger.setLevel("silent");
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
/** Available log levels in order of verbosity */
|
|
18
|
-
export type LogLevel = "debug" | "info" | "warn" | "error" | "silent";
|
|
19
|
-
|
|
20
|
-
const levels: Record<LogLevel, number> = {
|
|
21
|
-
debug: 0,
|
|
22
|
-
info: 1,
|
|
23
|
-
warn: 2,
|
|
24
|
-
error: 3,
|
|
25
|
-
silent: 4,
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
let currentLevel: LogLevel = "warn";
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Logger instance for three-cad-viewer.
|
|
32
|
-
*
|
|
33
|
-
* Methods: debug, info, warn, error
|
|
34
|
-
* Control: setLevel(), getLevel()
|
|
35
|
-
*/
|
|
36
|
-
export const logger = {
|
|
37
|
-
/**
|
|
38
|
-
* Set the minimum log level. Messages below this level are suppressed.
|
|
39
|
-
* @param level - The minimum level to display
|
|
40
|
-
*/
|
|
41
|
-
setLevel(level: LogLevel): void {
|
|
42
|
-
currentLevel = level;
|
|
43
|
-
},
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Get the current log level.
|
|
47
|
-
* @returns The current minimum log level
|
|
48
|
-
*/
|
|
49
|
-
getLevel(): LogLevel {
|
|
50
|
-
return currentLevel;
|
|
51
|
-
},
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Log debug message (verbose, for development).
|
|
55
|
-
* Only shown when level is "debug".
|
|
56
|
-
*/
|
|
57
|
-
debug(...args: unknown[]): void {
|
|
58
|
-
if (levels[currentLevel] <= levels.debug) {
|
|
59
|
-
console.log("[three-cad-viewer]", ...args);
|
|
60
|
-
}
|
|
61
|
-
},
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Log info message (general information).
|
|
65
|
-
* Shown when level is "debug" or "info".
|
|
66
|
-
*/
|
|
67
|
-
info(...args: unknown[]): void {
|
|
68
|
-
if (levels[currentLevel] <= levels.info) {
|
|
69
|
-
console.log("[three-cad-viewer]", ...args);
|
|
70
|
-
}
|
|
71
|
-
},
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Log warning message (potential issues).
|
|
75
|
-
* Shown when level is "debug", "info", or "warn".
|
|
76
|
-
*/
|
|
77
|
-
warn(...args: unknown[]): void {
|
|
78
|
-
if (levels[currentLevel] <= levels.warn) {
|
|
79
|
-
console.warn("[three-cad-viewer]", ...args);
|
|
80
|
-
}
|
|
81
|
-
},
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Log error message (failures).
|
|
85
|
-
* Shown unless level is "silent".
|
|
86
|
-
*/
|
|
87
|
-
error(...args: unknown[]): void {
|
|
88
|
-
if (levels[currentLevel] <= levels.error) {
|
|
89
|
-
console.error("[three-cad-viewer]", ...args);
|
|
90
|
-
}
|
|
91
|
-
},
|
|
92
|
-
};
|