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,116 +0,0 @@
1
- /**
2
- * Options for memory size calculation.
3
- */
4
- interface MemorySizeOptions {
5
- excludeAttributes?: string[];
6
- visited?: WeakSet<object>;
7
- }
8
-
9
- function calculateObjectSize(obj: unknown, options: MemorySizeOptions = {}): number {
10
- const {
11
- excludeAttributes = ["parent", "context", "_parent", "__parent"],
12
- visited = new WeakSet(),
13
- } = options;
14
-
15
- // Prevent circular reference
16
- if (obj === null || obj === undefined) return 0;
17
-
18
- // Check for primitive types
19
- if (
20
- ["number", "string", "boolean", "symbol", "bigint"].includes(typeof obj)
21
- ) {
22
- return estimatePrimitiveSize(obj as string | number | boolean | symbol | bigint);
23
- }
24
-
25
- // Prevent circular references
26
- if (typeof obj === "object" && visited.has(obj)) return 0;
27
- if (typeof obj === "object") visited.add(obj);
28
-
29
- // Handle Arrays
30
- if (Array.isArray(obj)) {
31
- return obj.reduce(
32
- (total, item) =>
33
- total +
34
- calculateObjectSize(item, {
35
- excludeAttributes,
36
- visited,
37
- }),
38
- estimateArrayOverhead(obj),
39
- );
40
- }
41
-
42
- // Handle TypedArrays
43
- if (ArrayBuffer.isView(obj)) {
44
- return obj.byteLength + estimateTypedArrayOverhead();
45
- }
46
-
47
- // Handle Maps
48
- if (obj instanceof Map) {
49
- let mapSize = estimateMapOverhead(obj);
50
- for (const [key, value] of obj) {
51
- mapSize += calculateObjectSize(key, { excludeAttributes, visited });
52
- mapSize += calculateObjectSize(value, { excludeAttributes, visited });
53
- }
54
- return mapSize;
55
- }
56
-
57
- // Handle regular objects
58
- if (typeof obj === "object") {
59
- let objectSize = estimateObjectOverhead();
60
- for (const key in obj) {
61
- // Skip excluded attributes
62
- if (
63
- Object.prototype.hasOwnProperty.call(obj, key) &&
64
- !excludeAttributes.includes(key)
65
- ) {
66
- objectSize += calculateObjectSize(key, { excludeAttributes, visited });
67
- objectSize += calculateObjectSize((obj as Record<string, unknown>)[key], {
68
- excludeAttributes,
69
- visited,
70
- });
71
- }
72
- }
73
- return objectSize;
74
- }
75
-
76
- // For functions or unknown types
77
- return 0;
78
- }
79
-
80
- function estimatePrimitiveSize(primitive: string | number | boolean | symbol | bigint | null | undefined): number {
81
- if (primitive === null || primitive === undefined) return 0;
82
- switch (typeof primitive) {
83
- case "number":
84
- return 8; // 64-bit float
85
- case "string":
86
- return primitive.length * 2; // Assume UTF-16 encoding
87
- case "boolean":
88
- return 4;
89
- case "symbol":
90
- return 8;
91
- case "bigint":
92
- return 8;
93
- default:
94
- return 0;
95
- }
96
- }
97
-
98
- function estimateArrayOverhead(arr: unknown[]): number {
99
- return 24 + arr.length * 8; // Array header + pointer overhead
100
- }
101
-
102
- function estimateTypedArrayOverhead(): number {
103
- return 24; // Typical overhead for TypedArrays
104
- }
105
-
106
- function estimateMapOverhead(map: Map<unknown, unknown>): number {
107
- return 40 + map.size * 16; // Map header + entry overhead
108
- }
109
-
110
- function estimateObjectOverhead(): number {
111
- return 32; // Basic object overhead
112
- }
113
-
114
- export function sizeof(obj: unknown): number {
115
- return calculateObjectSize(obj);
116
- }
@@ -1,69 +0,0 @@
1
- /**
2
- * Performance timing utility for measuring execution time.
3
- *
4
- * @example
5
- * ```typescript
6
- * const timer = new Timer("render", true);
7
- * // ... do some work ...
8
- * timer.split("tessellation complete");
9
- * // ... do more work ...
10
- * timer.stop();
11
- * ```
12
- *
13
- * @public
14
- */
15
- class Timer {
16
- private prefix: string;
17
- private timeit: boolean;
18
- private start: number;
19
- private last: number;
20
-
21
- /**
22
- * Create a new Timer instance.
23
- *
24
- * @param prefix - Label prefix for log messages
25
- * @param timeit - If false, all timing operations are no-ops
26
- */
27
- constructor(prefix: string, timeit: boolean) {
28
- this.prefix = prefix;
29
- this.timeit = timeit;
30
- this.start = performance.now();
31
- this.last = this.start;
32
- if (timeit) {
33
- console.info(`three-cad-viewer: ${prefix}:timer start`);
34
- }
35
- }
36
-
37
- /**
38
- * Log a split time (time since last split or start).
39
- *
40
- * @param msg - Message to include in the log output
41
- */
42
- split(msg: string): void {
43
- if (this.timeit) {
44
- const t = performance.now();
45
- console.info(
46
- `three-cad-viewer: ${this.prefix}:${msg}:timer split ${(
47
- t - this.last
48
- ).toFixed(1)} ms`,
49
- );
50
- this.last = t;
51
- }
52
- }
53
-
54
- /**
55
- * Log total elapsed time and stop the timer.
56
- */
57
- stop(): void {
58
- if (this.timeit) {
59
- const t = performance.now();
60
- console.info(
61
- `three-cad-viewer: ${this.prefix}:timer stop ${(t - this.start).toFixed(
62
- 1,
63
- )} ms:`,
64
- );
65
- }
66
- }
67
- }
68
-
69
- export { Timer };
@@ -1,446 +0,0 @@
1
- import * as THREE from "three";
2
- import type { Vector3Tuple, QuaternionTuple } from "three";
3
- import type { LineSegments2 } from "three/examples/jsm/lines/LineSegments2.js";
4
- import type { Axis } from "../core/types.js";
5
- import { gpuTracker } from "./gpu-tracker.js";
6
-
7
- // =============================================================================
8
- // Constants
9
- // =============================================================================
10
-
11
- /** Unit vectors for each axis */
12
- export const AXIS_VECTORS: Readonly<Record<Axis, THREE.Vector3>> = {
13
- x: new THREE.Vector3(1, 0, 0),
14
- y: new THREE.Vector3(0, 1, 0),
15
- z: new THREE.Vector3(0, 0, 1),
16
- };
17
-
18
- // =============================================================================
19
- // Utility Functions
20
- // =============================================================================
21
-
22
- /**
23
- * Flatten a nested array of numbers to a 1D array.
24
- * The cast is necessary because TypeScript's flat() return type
25
- * is a complex union that doesn't simplify to number[].
26
- */
27
- function flatten(arr: number[][] | number[][][] | number[][][][], depth: number = 1): number[] {
28
- return arr.flat(depth) as number[];
29
- }
30
-
31
- /**
32
- * Convert an array to Vector3Tuple with validation.
33
- * Throws if the input is not a 3-element array.
34
- */
35
- function toVector3Tuple(arr: number[]): Vector3Tuple {
36
- if (!Array.isArray(arr) || arr.length !== 3) {
37
- throw new Error(`Expected array of length 3, got ${Array.isArray(arr) ? arr.length : typeof arr}`);
38
- }
39
- return arr as Vector3Tuple;
40
- }
41
-
42
- /**
43
- * Convert an array to QuaternionTuple with validation.
44
- * Throws if the input is not a 4-element array.
45
- */
46
- function toQuaternionTuple(arr: number[]): QuaternionTuple {
47
- if (!Array.isArray(arr) || arr.length !== 4) {
48
- throw new Error(`Expected array of length 4, got ${Array.isArray(arr) ? arr.length : typeof arr}`);
49
- }
50
- return arr as QuaternionTuple;
51
- }
52
-
53
- function isEqual(obj1: unknown, obj2: unknown, tol: number = 1e-9): boolean {
54
- if (Array.isArray(obj1) && Array.isArray(obj2)) {
55
- return (
56
- obj1.length === obj2.length && obj1.every((v, i) => isEqual(v, obj2[i], tol))
57
- );
58
- } else if (obj1 !== null && obj2 !== null && typeof obj1 === "object" && typeof obj2 === "object") {
59
- const rec1 = obj1 as Record<string, unknown>;
60
- const rec2 = obj2 as Record<string, unknown>;
61
- const keys1 = Object.keys(rec1);
62
- const keys2 = Object.keys(rec2);
63
-
64
- if (
65
- keys1.length === keys2.length &&
66
- keys1.every((key) => Object.prototype.hasOwnProperty.call(rec2, key))
67
- ) {
68
- return keys1.every((key) => isEqual(rec1[key], rec2[key], tol));
69
- } else {
70
- return false;
71
- }
72
- } else {
73
- if (typeof obj1 === "number" && typeof obj2 === "number") {
74
- return Math.abs(obj1 - obj2) < tol;
75
- }
76
- return obj1 === obj2;
77
- }
78
- }
79
-
80
- function sceneTraverse(obj: THREE.Object3D | null | undefined, fn: (obj: THREE.Object3D) => void): void {
81
- if (!obj) return;
82
-
83
- fn(obj);
84
-
85
- if (obj.children && obj.children.length > 0) {
86
- obj.children.forEach((o) => {
87
- sceneTraverse(o, fn);
88
- });
89
- }
90
- }
91
-
92
- interface GeometryLike {
93
- dispose: () => void;
94
- attributes: Record<string, unknown>;
95
- }
96
-
97
- function disposeGeometry(geometry: GeometryLike | null | undefined): void {
98
- if (geometry) {
99
- gpuTracker.untrack("geometry", geometry);
100
- geometry.dispose();
101
- for (const attr of Object.values(geometry.attributes)) {
102
- if (attr && typeof attr === "object" && "dispose" in attr && typeof attr.dispose === "function") {
103
- attr.dispose();
104
- }
105
- }
106
- }
107
- }
108
-
109
- interface Disposable {
110
- dispose: () => void;
111
- }
112
-
113
- interface MaterialLike {
114
- dispose: () => void;
115
- // MeshStandardMaterial texture maps
116
- map?: Disposable | null;
117
- normalMap?: Disposable | null;
118
- roughnessMap?: Disposable | null;
119
- metalnessMap?: Disposable | null;
120
- aoMap?: Disposable | null;
121
- emissiveMap?: Disposable | null;
122
- alphaMap?: Disposable | null;
123
- bumpMap?: Disposable | null;
124
- // MeshPhysicalMaterial additional texture maps
125
- transmissionMap?: Disposable | null;
126
- clearcoatMap?: Disposable | null;
127
- clearcoatRoughnessMap?: Disposable | null;
128
- clearcoatNormalMap?: Disposable | null;
129
- thicknessMap?: Disposable | null;
130
- specularIntensityMap?: Disposable | null;
131
- specularColorMap?: Disposable | null;
132
- sheenColorMap?: Disposable | null;
133
- sheenRoughnessMap?: Disposable | null;
134
- anisotropyMap?: Disposable | null;
135
- }
136
-
137
- /** All texture map property names on MaterialLike (for iteration) */
138
- const MATERIAL_TEXTURE_KEYS: readonly (keyof Omit<MaterialLike, "dispose">)[] = [
139
- // MeshStandardMaterial
140
- "map", "normalMap", "roughnessMap", "metalnessMap",
141
- "aoMap", "emissiveMap", "alphaMap", "bumpMap",
142
- // MeshPhysicalMaterial
143
- "transmissionMap", "clearcoatMap", "clearcoatRoughnessMap", "clearcoatNormalMap",
144
- "thicknessMap", "specularIntensityMap", "specularColorMap",
145
- "sheenColorMap", "sheenRoughnessMap", "anisotropyMap",
146
- ];
147
-
148
- /**
149
- * Dispose a material and detach its texture references.
150
- *
151
- * Texture GPU resources are NOT freed here -- TextureCache is the sole owner
152
- * of loaded textures and is responsible for calling texture.dispose().
153
- * This function only nulls out the material's texture map references to
154
- * break the association, then disposes the material itself.
155
- */
156
- function disposeMaterial(material: MaterialLike | null | undefined): void {
157
- if (!material) return;
158
-
159
- // Detach all texture references (do NOT dispose -- TextureCache owns them)
160
- for (const key of MATERIAL_TEXTURE_KEYS) {
161
- if (material[key]) {
162
- (material as unknown as Record<string, unknown>)[key] = null;
163
- }
164
- }
165
-
166
- gpuTracker.untrack("material", material);
167
- material.dispose();
168
- }
169
-
170
- interface MeshLike {
171
- geometry?: GeometryLike | null;
172
- material?: MaterialLike | MaterialLike[] | null;
173
- isMesh?: boolean;
174
- isLine?: boolean;
175
- isPoints?: boolean;
176
- }
177
-
178
- function disposeMesh(mesh: MeshLike): void {
179
- if (mesh.geometry) {
180
- disposeGeometry(mesh.geometry);
181
- }
182
-
183
- if (mesh.material) {
184
- if (Array.isArray(mesh.material)) {
185
- mesh.material.forEach(disposeMaterial);
186
- } else {
187
- disposeMaterial(mesh.material);
188
- }
189
- }
190
- }
191
-
192
- interface DisposableTree extends MeshLike {
193
- children?: DisposableTree[];
194
- dispose?: () => void;
195
- }
196
-
197
- function deepDispose(tree: DisposableTree | DisposableTree[] | null | undefined): void {
198
- if (!tree) {
199
- return;
200
- }
201
- if (Array.isArray(tree)) {
202
- tree.forEach(deepDispose);
203
- return;
204
- }
205
- if (Array.isArray(tree.children)) {
206
- tree.children.forEach(deepDispose);
207
- }
208
- if (tree.dispose) {
209
- tree.dispose();
210
- } else if (tree.isMesh || tree.isLine || tree.isPoints) {
211
- disposeMesh(tree);
212
- }
213
- }
214
-
215
- function format(v: number, b: number = 2, a: number = 2): string {
216
- const s = Math.abs(v).toFixed(a);
217
- let padding = "";
218
- const int = s.split(".")[0];
219
- for (let i = int.length; i < b; i++) padding += " ";
220
- padding += v < 0 ? "-" : " ";
221
- return padding + s;
222
- }
223
-
224
- function prettyPrintVector(v: number[], a: number, b: number): string {
225
- return `${format(v[0], a, b)}, ${format(v[1], a, b)}, ${format(v[2], a, b)}`;
226
- }
227
-
228
- // KeyEventLike matches MouseEvent, PointerEvent, KeyboardEvent etc.
229
- type KeyEventLike = {
230
- ctrlKey: boolean;
231
- shiftKey: boolean;
232
- altKey: boolean;
233
- metaKey: boolean;
234
- };
235
-
236
- type KeyEventKey = keyof KeyEventLike;
237
- type MappedKey = "shift" | "ctrl" | "meta" | "alt";
238
-
239
- interface KeyMappingConfig {
240
- shift: KeyEventKey;
241
- ctrl: KeyEventKey;
242
- meta: KeyEventKey;
243
- alt: KeyEventKey;
244
- }
245
-
246
- class _KeyMapper {
247
- private keyMapping: Record<MappedKey, KeyEventKey>;
248
- private actionShortcuts: Record<string, string>;
249
- private reverseActionShortcuts: Record<string, string>;
250
-
251
- constructor() {
252
- this.keyMapping = {
253
- shift: "ctrlKey",
254
- ctrl: "shiftKey",
255
- meta: "altKey",
256
- alt: "metaKey",
257
- };
258
- this.actionShortcuts = {};
259
- this.reverseActionShortcuts = {};
260
- }
261
-
262
- getshortcuts = (key: MappedKey): string => {
263
- return this.keyMapping[key].replace("Key", "");
264
- };
265
-
266
- get_config(): Record<MappedKey, KeyEventKey> {
267
- return Object.assign({}, this.keyMapping);
268
- }
269
-
270
- get = (event: KeyEventLike, key: MappedKey): boolean => {
271
- const prop = this.keyMapping[key];
272
- return event[prop];
273
- };
274
-
275
- set = (config: Partial<KeyMappingConfig>): void => {
276
- for (const key of Object.keys(config) as MappedKey[]) {
277
- const value = config[key];
278
- if (value !== undefined) {
279
- this.keyMapping[key] = value;
280
- }
281
- }
282
- };
283
-
284
- setActionShortcuts = (shortcuts: Record<string, string>): void => {
285
- this.actionShortcuts = { ...shortcuts };
286
- this.reverseActionShortcuts = {};
287
- for (const [action, key] of Object.entries(shortcuts)) {
288
- this.reverseActionShortcuts[key] = action;
289
- }
290
- };
291
-
292
- getActionForKey = (key: string): string | undefined => {
293
- return this.reverseActionShortcuts[key];
294
- };
295
-
296
- getShortcutForAction = (action: string): string | undefined => {
297
- return this.actionShortcuts[action];
298
- };
299
-
300
- getActionShortcuts = (): Record<string, string> => {
301
- return { ...this.actionShortcuts };
302
- };
303
- }
304
-
305
- // see https://discourse.threejs.org/t/updates-to-lighting-in-three-js-r155/53733
306
- function scaleLight(intensity: number): number {
307
- return Math.round(Math.PI * intensity);
308
- }
309
-
310
- // =============================================================================
311
- // THREE.js Type Guards
312
- // =============================================================================
313
-
314
- /**
315
- * Type guard to check if an Object3D is a Mesh.
316
- */
317
- function isMesh(obj: THREE.Object3D): obj is THREE.Mesh {
318
- return "isMesh" in obj && obj.isMesh === true;
319
- }
320
-
321
- /**
322
- * Type guard to check if an Object3D is a Line.
323
- */
324
- function isLine(obj: THREE.Object3D): obj is THREE.Line {
325
- return "isLine" in obj && obj.isLine === true;
326
- }
327
-
328
- /**
329
- * Type guard to check if an Object3D is a Points.
330
- */
331
- function isPoints(obj: THREE.Object3D): obj is THREE.Points {
332
- return "isPoints" in obj && obj.isPoints === true;
333
- }
334
-
335
- /**
336
- * Type guard to check if an object is an OrthographicCamera.
337
- * Accepts Object3D to allow use in controls where camera type is broader.
338
- */
339
- function isOrthographicCamera(obj: THREE.Object3D): obj is THREE.OrthographicCamera {
340
- return "isOrthographicCamera" in obj && (obj as THREE.OrthographicCamera).isOrthographicCamera === true;
341
- }
342
-
343
- /**
344
- * Type guard to check if an object is a PerspectiveCamera.
345
- * Accepts Object3D to allow use in controls where camera type is broader.
346
- */
347
- function isPerspectiveCamera(obj: THREE.Object3D): obj is THREE.PerspectiveCamera {
348
- return "isPerspectiveCamera" in obj && (obj as THREE.PerspectiveCamera).isPerspectiveCamera === true;
349
- }
350
-
351
- /**
352
- * Type guard to check if an Object3D is a LineSegments2 (fat line).
353
- */
354
- function isLineSegments2(obj: THREE.Object3D): obj is LineSegments2 {
355
- return obj.type === "LineSegments2";
356
- }
357
-
358
- /**
359
- * Type guard to check if a material has a color property.
360
- */
361
- function hasColor(material: THREE.Material): material is THREE.Material & { color: THREE.Color } {
362
- return "color" in material;
363
- }
364
-
365
- /**
366
- * Type guard to check if a material has emissive property.
367
- */
368
- function hasEmissive(material: THREE.Material): material is THREE.Material & { emissive: THREE.Color } {
369
- return "emissive" in material;
370
- }
371
-
372
- /**
373
- * Type guard to check if a material is a MeshStandardMaterial.
374
- */
375
- function isMeshStandardMaterial(material: THREE.Material): material is THREE.MeshStandardMaterial {
376
- return "isMeshStandardMaterial" in material && material.isMeshStandardMaterial === true;
377
- }
378
-
379
- const KeyMapper = new _KeyMapper();
380
-
381
- interface EventListenerEntry {
382
- target: EventTarget;
383
- event: string;
384
- handler: EventListenerOrEventListenerObject;
385
- options: boolean | AddEventListenerOptions;
386
- }
387
-
388
- class EventListenerManager {
389
- private listeners: EventListenerEntry[];
390
-
391
- constructor() {
392
- this.listeners = [];
393
- }
394
-
395
- add = (
396
- target: EventTarget,
397
- event: string,
398
- handler: EventListenerOrEventListenerObject,
399
- options: boolean | AddEventListenerOptions = false
400
- ): void => {
401
- target.addEventListener(event, handler, options);
402
- this.listeners.push({
403
- target: target,
404
- event: event,
405
- handler: handler,
406
- options: options,
407
- });
408
- };
409
-
410
- dispose(): void {
411
- this.listeners.forEach(({ target, event, handler, options }) => {
412
- target.removeEventListener(event, handler, options);
413
- });
414
- this.listeners = [];
415
- }
416
- }
417
-
418
- export {
419
- flatten,
420
- isEqual,
421
- sceneTraverse,
422
- prettyPrintVector,
423
- KeyMapper,
424
- scaleLight,
425
- deepDispose,
426
- disposeGeometry,
427
- EventListenerManager,
428
- // Type guards
429
- isMesh,
430
- isLine,
431
- isPoints,
432
- isOrthographicCamera,
433
- isPerspectiveCamera,
434
- isLineSegments2,
435
- hasColor,
436
- hasEmissive,
437
- isMeshStandardMaterial,
438
- toVector3Tuple,
439
- toQuaternionTuple,
440
- };
441
-
442
- export type {
443
- KeyEventKey,
444
- KeyMappingConfig,
445
- DisposableTree,
446
- };