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.
Files changed (58) hide show
  1. package/dist/three-cad-viewer.esm.js +8 -5
  2. package/dist/three-cad-viewer.esm.js.map +1 -1
  3. package/dist/three-cad-viewer.esm.min.js +1 -1
  4. package/dist/three-cad-viewer.js +8 -5
  5. package/dist/three-cad-viewer.min.js +1 -1
  6. package/package.json +2 -3
  7. package/src/_version.ts +0 -1
  8. package/src/camera/camera.ts +0 -445
  9. package/src/camera/controls/CADOrbitControls.ts +0 -241
  10. package/src/camera/controls/CADTrackballControls.ts +0 -598
  11. package/src/camera/controls.ts +0 -380
  12. package/src/core/patches.ts +0 -16
  13. package/src/core/studio-manager.ts +0 -652
  14. package/src/core/types.ts +0 -892
  15. package/src/core/viewer-state.ts +0 -784
  16. package/src/core/viewer.ts +0 -4821
  17. package/src/index.ts +0 -151
  18. package/src/rendering/environment.ts +0 -840
  19. package/src/rendering/light-detection.ts +0 -327
  20. package/src/rendering/material-factory.ts +0 -735
  21. package/src/rendering/material-presets.ts +0 -289
  22. package/src/rendering/raycast.ts +0 -291
  23. package/src/rendering/room-environment.ts +0 -192
  24. package/src/rendering/studio-composer.ts +0 -577
  25. package/src/rendering/studio-floor.ts +0 -108
  26. package/src/rendering/texture-cache.ts +0 -324
  27. package/src/rendering/tree-model.ts +0 -542
  28. package/src/rendering/triplanar.ts +0 -329
  29. package/src/scene/animation.ts +0 -343
  30. package/src/scene/axes.ts +0 -108
  31. package/src/scene/bbox.ts +0 -223
  32. package/src/scene/clipping.ts +0 -650
  33. package/src/scene/grid.ts +0 -864
  34. package/src/scene/nestedgroup.ts +0 -1448
  35. package/src/scene/objectgroup.ts +0 -866
  36. package/src/scene/orientation.ts +0 -259
  37. package/src/scene/render-shape.ts +0 -634
  38. package/src/tools/cad_tools/measure.ts +0 -811
  39. package/src/tools/cad_tools/select.ts +0 -100
  40. package/src/tools/cad_tools/tools.ts +0 -231
  41. package/src/tools/cad_tools/ui.ts +0 -454
  42. package/src/tools/cad_tools/zebra.ts +0 -369
  43. package/src/types/html.d.ts +0 -5
  44. package/src/types/n8ao.d.ts +0 -28
  45. package/src/types/three-augmentation.d.ts +0 -60
  46. package/src/ui/display.ts +0 -3295
  47. package/src/ui/index.html +0 -505
  48. package/src/ui/info.ts +0 -177
  49. package/src/ui/slider.ts +0 -206
  50. package/src/ui/toolbar.ts +0 -347
  51. package/src/ui/treeview.ts +0 -945
  52. package/src/utils/decode-instances.ts +0 -233
  53. package/src/utils/font.ts +0 -60
  54. package/src/utils/gpu-tracker.ts +0 -265
  55. package/src/utils/logger.ts +0 -92
  56. package/src/utils/sizeof.ts +0 -116
  57. package/src/utils/timer.ts +0 -69
  58. package/src/utils/utils.ts +0 -446
@@ -1,598 +0,0 @@
1
- /**
2
- * CADTrackballControls - Extended TrackballControls for CAD applications
3
- *
4
- * Adds:
5
- * - Holroyd (non-tumbling) trackball rotation mode
6
- * - rotateX/Y/Z methods for programmatic world-axis rotation
7
- * - Quaternion-based saveState/reset
8
- *
9
- * Internal TrackballControls methods/properties used (see three-augmentation.d.ts):
10
- * - _onMouseDown: Replaced to customize modifier key behavior (shift=pan)
11
- * - _getMouseOnCircle: Called to convert page coordinates for rotation
12
- * - _getMouseOnScreen: Called to convert page coordinates for pan/zoom
13
- * - _rotateCamera: Overridden to implement holroyd sphere projection
14
- * - _panCamera: Overridden to use quaternion-based camera orientation in holroyd mode
15
- * - _zoomCamera: Called for zoom handling
16
- * - _moveCurr/_movePrev: Rotation tracking vectors
17
- * - _zoomStart/_zoomEnd: Zoom tracking vectors
18
- * - _panStart/_panEnd: Pan tracking vectors
19
- * - _eye: Camera-to-target vector
20
- * - _lastPosition: Change detection
21
- * - _target0/_position0/_up0/_zoom0: Saved state for reset
22
- * - state/keyState: Current interaction mode tracking
23
- * - noRotate/noZoom/noPan: Feature disable flags
24
- */
25
-
26
- import { TrackballControls } from "three/examples/jsm/controls/TrackballControls.js";
27
- import { MOUSE, Quaternion, Vector2, Vector3, Camera } from "three";
28
- import {
29
- KeyMapper,
30
- AXIS_VECTORS,
31
- isOrthographicCamera,
32
- isPerspectiveCamera,
33
- } from "../../utils/utils.js";
34
- import type { Axis } from "../../core/types.js";
35
-
36
- // State constants matching TrackballControls internal state
37
- const STATE = {
38
- NONE: -1,
39
- ROTATE: 0,
40
- ZOOM: 1,
41
- PAN: 2,
42
- };
43
-
44
- // Used for change detection in holroyd mode
45
- const _lastQuaternion = new Quaternion();
46
- let _lastZoom = 1;
47
-
48
- // Reusable objects for rotation calculations
49
- const _quaternion = new Quaternion();
50
- const _axis = new Vector3();
51
- const _rotateStart3 = new Vector3();
52
- const _rotateEnd3 = new Vector3();
53
-
54
- // Reusable objects for pan calculations
55
- const _panDirection = new Vector3();
56
- const _cameraUp = new Vector3();
57
- const _cameraRight = new Vector3();
58
-
59
- class CADTrackballControls extends TrackballControls {
60
- holroyd: boolean;
61
- radius: number;
62
- quaternion0: Quaternion;
63
- private _holroydStart: Vector2;
64
- private _holroydEnd: Vector2;
65
- private _holroydActive: boolean;
66
- private _horizontalRotate: boolean;
67
- private _verticalRotate: boolean;
68
- private _holroydPointerDown?: (event: PointerEvent) => void;
69
- private _holroydPointerMove?: (event: PointerEvent) => void;
70
- private _holroydPointerUp?: () => void;
71
- private _holroydWheel?: (event: WheelEvent) => void;
72
- private _parentOnMouseDown!: (event: MouseEvent) => void;
73
-
74
- // Expose internal properties for type safety
75
- declare state: number;
76
- declare keyState: number;
77
- declare _moveCurr: Vector2;
78
- declare _movePrev: Vector2;
79
- declare _zoomStart: Vector2;
80
- declare _zoomEnd: Vector2;
81
- declare _panStart: Vector2;
82
- declare _panEnd: Vector2;
83
- declare _eye: Vector3;
84
- declare _lastPosition: Vector3;
85
- declare _target0: Vector3;
86
- declare _position0: Vector3;
87
- declare _up0: Vector3;
88
- declare _zoom0: number;
89
- declare noRotate: boolean;
90
- declare noZoom: boolean;
91
- declare noPan: boolean;
92
- declare _onMouseDown: (event: MouseEvent) => void;
93
- declare _getMouseOnCircle: (pageX: number, pageY: number) => Vector2;
94
- declare _getMouseOnScreen: (pageX: number, pageY: number) => Vector2;
95
- declare _zoomCamera: () => void;
96
-
97
- /**
98
- * Constructs CAD-enhanced trackball controls.
99
- *
100
- * @param object - The camera to control.
101
- * @param domElement - The HTML element for event listeners.
102
- */
103
- constructor(object: Camera, domElement: HTMLElement | null = null) {
104
- super(object, domElement!);
105
-
106
- /**
107
- * Enable holroyd (non-tumbling) trackball mode.
108
- * When true, uses a projection that prevents disorientation.
109
- */
110
- this.holroyd = true;
111
-
112
- /**
113
- * NDC trackball radius for holroyd projection.
114
- */
115
- this.radius = 0.9;
116
-
117
- /**
118
- * Saved quaternion for reset (in addition to position/up/zoom).
119
- */
120
- this.quaternion0 = this.object.quaternion.clone();
121
-
122
- // Holroyd-specific: track absolute page coordinates for sphere projection
123
- // These store the raw page coordinates, not processed values
124
- this._holroydStart = new Vector2();
125
- this._holroydEnd = new Vector2();
126
- this._holroydActive = false;
127
-
128
- // Rotation axis restriction flags (set via modifier keys)
129
- // When false, that axis is locked (coordinate set to 0 in sphere projection)
130
- this._horizontalRotate = true; // meta key restricts to horizontal only
131
- this._verticalRotate = true; // ctrl key restricts to vertical only
132
-
133
- // Add our own pointer event listeners to capture raw coordinates
134
- // This runs alongside the parent's handlers
135
- if (domElement) {
136
- this._holroydPointerDown = this._onHolroydPointerDown.bind(this);
137
- this._holroydPointerMove = this._onHolroydPointerMove.bind(this);
138
- this._holroydPointerUp = this._onHolroydPointerUp.bind(this);
139
- this._holroydWheel = this._onHolroydWheel.bind(this);
140
- domElement.addEventListener("pointerdown", this._holroydPointerDown);
141
- domElement.addEventListener("pointermove", this._holroydPointerMove);
142
- domElement.addEventListener("pointerup", this._holroydPointerUp);
143
- domElement.addEventListener("pointercancel", this._holroydPointerUp);
144
- domElement.addEventListener("wheel", this._holroydWheel, {
145
- passive: false,
146
- });
147
- }
148
-
149
- // Save parent's _onMouseDown before overriding (for holroyd=false fallback)
150
- this._parentOnMouseDown = this._onMouseDown;
151
- this._onMouseDown = this._handleMouseDown.bind(this);
152
- }
153
-
154
- /**
155
- * Custom mouse down handler to support shift+drag for pan.
156
- * When holroyd=false, delegates to parent for pure Three.js behavior.
157
- */
158
- private _handleMouseDown(event: MouseEvent): void {
159
- // When holroyd is disabled, use pure Three.js TrackballControls behavior
160
- if (!this.holroyd) {
161
- this._parentOnMouseDown(event);
162
- return;
163
- }
164
-
165
- let mouseAction: number;
166
-
167
- switch (event.button) {
168
- case 0:
169
- mouseAction = this.mouseButtons.LEFT!;
170
- break;
171
- case 1:
172
- mouseAction = this.mouseButtons.MIDDLE!;
173
- break;
174
- case 2:
175
- mouseAction = this.mouseButtons.RIGHT!;
176
- break;
177
- default:
178
- mouseAction = -1;
179
- }
180
-
181
- // Shift + left click = pan (via KeyMapper)
182
- if (mouseAction === MOUSE.ROTATE && KeyMapper.get(event, "shift")) {
183
- mouseAction = MOUSE.PAN;
184
- }
185
-
186
- switch (mouseAction) {
187
- case MOUSE.DOLLY:
188
- this.state = STATE.ZOOM;
189
- break;
190
- case MOUSE.ROTATE:
191
- this.state = STATE.ROTATE;
192
- break;
193
- case MOUSE.PAN:
194
- this.state = STATE.PAN;
195
- break;
196
- default:
197
- this.state = STATE.NONE;
198
- }
199
-
200
- const state = this.keyState !== STATE.NONE ? this.keyState : this.state;
201
-
202
- if (state === STATE.ROTATE && !this.noRotate) {
203
- this._moveCurr.copy(this._getMouseOnCircle(event.pageX, event.pageY));
204
- this._movePrev.copy(this._moveCurr);
205
- } else if (state === STATE.ZOOM && !this.noZoom) {
206
- this._zoomStart.copy(this._getMouseOnScreen(event.pageX, event.pageY));
207
- this._zoomEnd.copy(this._zoomStart);
208
- } else if (state === STATE.PAN && !this.noPan) {
209
- this._panStart.copy(this._getMouseOnScreen(event.pageX, event.pageY));
210
- this._panEnd.copy(this._panStart);
211
- }
212
-
213
- this.dispatchEvent({ type: "start" });
214
- }
215
-
216
- /**
217
- * Capture raw pointer coordinates on pointer down for holroyd.
218
- * Works for all pointer types (mouse, touch, pen, trackpad).
219
- * Also checks modifier keys for rotation axis restriction.
220
- */
221
- private _onHolroydPointerDown(event: PointerEvent): void {
222
- if (!this.holroyd) return;
223
-
224
- // Only activate holroyd for rotation (left mouse button or touch)
225
- // Right mouse (button 2) is for pan, middle (button 1) for zoom
226
- // For touch, button is 0
227
- if (event.button !== 0) return;
228
-
229
- // Shift key triggers pan instead of rotation (via KeyMapper)
230
- if (KeyMapper.get(event, "shift")) return;
231
-
232
- this._holroydStart.set(event.pageX, event.pageY);
233
- this._holroydEnd.set(event.pageX, event.pageY);
234
- this._holroydActive = true;
235
-
236
- // Check modifier keys for rotation restriction
237
- // Works for all pointer types (e.g., touchscreen + keyboard on laptops)
238
- // ctrl: restrict to vertical rotation only (horizontalRotate = false)
239
- // meta: restrict to horizontal rotation only (verticalRotate = false)
240
- this._horizontalRotate = !KeyMapper.get(event, "ctrl");
241
- this._verticalRotate = !KeyMapper.get(event, "meta");
242
- }
243
-
244
- /**
245
- * Capture raw pointer coordinates on pointer move for holroyd.
246
- * Only captures when actively dragging.
247
- * Works for all pointer types (mouse, touch, pen, trackpad).
248
- */
249
- private _onHolroydPointerMove(event: PointerEvent): void {
250
- if (this.holroyd && this._holroydActive) {
251
- this._holroydEnd.set(event.pageX, event.pageY);
252
- }
253
- // Call update to process the pointer movement and dispatch "change" event
254
- // This enables change-listener mode (non-animation loop) to work
255
- // Note: this runs for all pointer moves while dragging (rotate, pan, zoom)
256
- if (this.state !== -1) {
257
- // STATE.NONE = -1
258
- this.update();
259
- }
260
- }
261
-
262
- /**
263
- * Reset holroyd active state and rotation restrictions on pointer up.
264
- */
265
- private _onHolroydPointerUp(): void {
266
- this._holroydActive = false;
267
- this._horizontalRotate = true;
268
- this._verticalRotate = true;
269
- }
270
-
271
- /**
272
- * Handle wheel events for zoom - call update after parent processes wheel.
273
- * This enables change-listener mode (non-animation loop) to work for zoom.
274
- */
275
- private _onHolroydWheel(): void {
276
- // Parent's wheel handler already processed the event, just call update
277
- this.update();
278
-
279
- // TrackballControls uses dynamic damping (staticMoving=false) which only
280
- // consumes ~20% of the zoom delta per update() call. In animation-loop mode
281
- // this creates smooth deceleration, but in change-listener mode (no continuous
282
- // updates) the residual delta persists and gets applied on the next interaction
283
- // (e.g., clicking to rotate), causing a phantom zoom. Clear it.
284
- this._zoomStart.copy(this._zoomEnd);
285
- }
286
-
287
- /**
288
- * Override dispose to clean up our event listeners.
289
- */
290
- dispose(): void {
291
- if (
292
- this.domElement &&
293
- this._holroydPointerDown &&
294
- this._holroydPointerMove &&
295
- this._holroydPointerUp &&
296
- this._holroydWheel
297
- ) {
298
- this.domElement.removeEventListener(
299
- "pointerdown",
300
- this._holroydPointerDown,
301
- );
302
- this.domElement.removeEventListener(
303
- "pointermove",
304
- this._holroydPointerMove,
305
- );
306
- this.domElement.removeEventListener("pointerup", this._holroydPointerUp);
307
- this.domElement.removeEventListener(
308
- "pointercancel",
309
- this._holroydPointerUp,
310
- );
311
- this.domElement.removeEventListener("wheel", this._holroydWheel);
312
- }
313
- super.dispose();
314
- }
315
-
316
- /**
317
- * Save the current state including quaternion.
318
- */
319
- saveState(): void {
320
- this._target0.copy(this.target);
321
- this._position0.copy(this.object.position);
322
- this._up0.copy(this.object.up);
323
- if (isPerspectiveCamera(this.object) || isOrthographicCamera(this.object)) {
324
- this._zoom0 = this.object.zoom;
325
- }
326
- this.quaternion0.copy(this.object.quaternion);
327
- }
328
-
329
- /**
330
- * Reset to saved state including quaternion.
331
- */
332
- reset(): void {
333
- super.reset();
334
- this.object.quaternion.copy(this.quaternion0);
335
- }
336
-
337
- // Expose saved state properties for compatibility with controls.js
338
- get target0(): Vector3 {
339
- return this._target0;
340
- }
341
- get position0(): Vector3 {
342
- return this._position0;
343
- }
344
- get zoom0(): number {
345
- return this._zoom0;
346
- }
347
- set zoom0(value: number) {
348
- this._zoom0 = value;
349
- }
350
-
351
- /**
352
- * Project page coordinates onto the holroyd trackball sphere.
353
- * Uses the original CameraControls coordinate system:
354
- * - NDC x: -1 (left) to +1 (right)
355
- * - NDC y: -1 (bottom) to +1 (top)
356
- */
357
- private _getMouseOnSphere(
358
- pageX: number,
359
- pageY: number,
360
- target: Vector3,
361
- ): Vector3 {
362
- const rect = this.domElement!.getBoundingClientRect();
363
-
364
- // Convert to NDC space (-1 to 1)
365
- // Note: Do NOT apply rotateSpeed here - it would break the sphere geometry
366
- // rotateSpeed is applied to the final angle instead
367
- // Apply rotation axis restrictions: set coordinate to 0 if that axis is locked
368
- const x = this._horizontalRotate
369
- ? (pageX - rect.left) / (rect.width / 2) - 1.0
370
- : 0;
371
- const y = this._verticalRotate
372
- ? 1.0 - (pageY - rect.top) / (rect.height / 2)
373
- : 0;
374
-
375
- // Holroyd sphere projection
376
- const r2 = this.radius * this.radius;
377
- const d2 = x * x + y * y;
378
-
379
- if (d2 <= r2 / 2) {
380
- // Inside sphere - project onto sphere surface
381
- target.set(x, y, Math.sqrt(r2 - d2));
382
- } else {
383
- // Outside sphere - use hyperbolic sheet for smooth falloff
384
- target.set(x, y, r2 / (2 * Math.sqrt(d2)));
385
- }
386
-
387
- return target;
388
- }
389
-
390
- /**
391
- * Override update to skip lookAt in holroyd mode.
392
- *
393
- * Standard TrackballControls calls lookAt() which recomputes the quaternion
394
- * from position and up. In holroyd mode, we set the quaternion directly,
395
- * so lookAt() would destroy the tilted rotation axis effect.
396
- *
397
- * When holroyd=false, delegates to parent for pure Three.js behavior.
398
- */
399
- update(): void {
400
- // When holroyd is disabled, use pure Three.js TrackballControls behavior
401
- if (!this.holroyd) {
402
- super.update();
403
- return;
404
- }
405
-
406
- this._eye.subVectors(this.object.position, this.target);
407
-
408
- if (!this.noRotate) {
409
- this._rotateCamera();
410
- }
411
-
412
- if (!this.noZoom) {
413
- this._zoomCamera();
414
- }
415
-
416
- if (!this.noPan) {
417
- this._panCamera();
418
- }
419
-
420
- this.object.position.addVectors(this.target, this._eye);
421
-
422
- // In holroyd mode, we set quaternion directly - skip lookAt
423
- // Just check for changes and dispatch event
424
- const currentZoom =
425
- isPerspectiveCamera(this.object) || isOrthographicCamera(this.object)
426
- ? this.object.zoom
427
- : 1;
428
- const zoomChanged = Math.abs(currentZoom - _lastZoom) > 0.000001;
429
- if (
430
- this._lastPosition.distanceToSquared(this.object.position) > 0.000001 ||
431
- _lastQuaternion.dot(this.object.quaternion) < 0.999999 ||
432
- zoomChanged
433
- ) {
434
- this.dispatchEvent({ type: "change" });
435
- this._lastPosition.copy(this.object.position);
436
- _lastQuaternion.copy(this.object.quaternion);
437
- _lastZoom = currentZoom;
438
- }
439
- }
440
-
441
- /**
442
- * Override rotation to support holroyd mode.
443
- *
444
- * The key difference from standard TrackballControls:
445
- * - Standard: uses delta-based rotation from _moveCurr - _movePrev
446
- * - Holroyd: projects absolute positions onto a virtual sphere
447
- *
448
- * This gives the "grab and rotate" feel where the rotation axis
449
- * depends on WHERE you grab, not just HOW you move.
450
- */
451
- _rotateCamera(): void {
452
- if (!this.holroyd) {
453
- // Use default TrackballControls rotation
454
- super._rotateCamera();
455
- return;
456
- }
457
-
458
- // Only process if start and end are different (actual movement)
459
- if (
460
- this._holroydStart.x === this._holroydEnd.x &&
461
- this._holroydStart.y === this._holroydEnd.y
462
- ) {
463
- this._movePrev.copy(this._moveCurr);
464
- return;
465
- }
466
-
467
- // Project both start and end positions onto the holroyd sphere
468
- this._getMouseOnSphere(
469
- this._holroydStart.x,
470
- this._holroydStart.y,
471
- _rotateStart3,
472
- );
473
- this._getMouseOnSphere(this._holroydEnd.x, this._holroydEnd.y, _rotateEnd3);
474
-
475
- // Calculate rotation axis as cross product of the two sphere points
476
- _axis.crossVectors(_rotateStart3, _rotateEnd3);
477
- const angle = Math.atan(_axis.length() / _rotateStart3.dot(_rotateEnd3));
478
-
479
- if (angle) {
480
- _axis.normalize();
481
-
482
- // Transform axis from screen space to world space via camera orientation
483
- _axis.applyQuaternion(this.object.quaternion);
484
-
485
- // Apply rotation - use full rotation (no damping) to preserve non-tumbling property
486
- // The original CameraControls had enableDamping=false by default
487
- // Damping would break the geodesic rotation property that prevents tumbling
488
- const finalAngle = -2 * angle * this.rotateSpeed;
489
-
490
- _quaternion.setFromAxisAngle(_axis, finalAngle);
491
-
492
- // Apply rotation via premultiplication (world-space rotation)
493
- this.object.quaternion.premultiply(_quaternion);
494
- this._eye.applyQuaternion(_quaternion);
495
- }
496
-
497
- // Update start to end for next frame
498
- this._holroydStart.copy(this._holroydEnd);
499
-
500
- // Keep parent state consistent
501
- this._movePrev.copy(this._moveCurr);
502
- }
503
-
504
- /**
505
- * Override pan to use quaternion-based camera orientation in holroyd mode.
506
- *
507
- * The parent TrackballControls uses this.object.up for pan direction,
508
- * but in holroyd mode we rotate via quaternion without updating up.
509
- * This calculates pan direction from the camera's actual orientation.
510
- */
511
- _panCamera(): void {
512
- if (!this.holroyd) {
513
- super._panCamera();
514
- return;
515
- }
516
-
517
- const mouseChange = _panDirection.set(
518
- this._panEnd.x - this._panStart.x,
519
- this._panEnd.y - this._panStart.y,
520
- 0,
521
- );
522
-
523
- if (mouseChange.lengthSq() === 0) {
524
- return;
525
- }
526
-
527
- // Apply pan scaling based on camera type
528
- if (isOrthographicCamera(this.object)) {
529
- // For orthographic: pan distance = frustum size at zoom level
530
- // mouseChange is already normalized, so just scale by world units visible
531
- const scaleX = (this.object.right - this.object.left) / this.object.zoom;
532
- const scaleY = (this.object.top - this.object.bottom) / this.object.zoom;
533
- mouseChange.x *= scaleX * this.panSpeed * 4;
534
- mouseChange.y *= scaleY * this.panSpeed * 4;
535
- } else if (isPerspectiveCamera(this.object) && this.domElement) {
536
- // For perspective: correct for aspect ratio since _getMouseOnScreen normalizes by width
537
- const aspect = this.domElement.clientWidth / this.domElement.clientHeight;
538
- mouseChange.x *= aspect;
539
- mouseChange.multiplyScalar(this._eye.length() * this.panSpeed * 1.6);
540
- } else {
541
- // Fallback for other camera types
542
- mouseChange.multiplyScalar(this._eye.length() * this.panSpeed * 2.0);
543
- }
544
-
545
- // Get camera's actual right and up vectors from quaternion
546
- // Camera looks down -Z in its local space, so:
547
- // - local +X is right
548
- // - local +Y is up
549
- _cameraRight.set(1, 0, 0).applyQuaternion(this.object.quaternion);
550
- _cameraUp.set(0, 1, 0).applyQuaternion(this.object.quaternion);
551
-
552
- // Pan = right * mouseX + up * mouseY (negate X for correct direction)
553
- _cameraRight.multiplyScalar(-mouseChange.x);
554
- _cameraUp.multiplyScalar(mouseChange.y);
555
-
556
- this.object.position.add(_cameraRight).add(_cameraUp);
557
- this.target.add(_cameraRight).add(_cameraUp);
558
-
559
- this._panStart.copy(this._panEnd);
560
- }
561
-
562
- /**
563
- * Rotate camera around world X-axis.
564
- */
565
- rotateX(angle: number): void {
566
- this._rotateAroundAxis("x", angle);
567
- }
568
-
569
- /**
570
- * Rotate camera around world Y-axis.
571
- */
572
- rotateY(angle: number): void {
573
- this._rotateAroundAxis("y", angle);
574
- }
575
-
576
- /**
577
- * Rotate camera around world Z-axis.
578
- */
579
- rotateZ(angle: number): void {
580
- this._rotateAroundAxis("z", angle);
581
- }
582
-
583
- /**
584
- * Internal method to rotate around a world axis.
585
- */
586
- private _rotateAroundAxis(axisName: Axis, angle: number): void {
587
- const axis = AXIS_VECTORS[axisName];
588
- _quaternion.setFromAxisAngle(axis, angle);
589
-
590
- this.object.quaternion.premultiply(_quaternion);
591
- this.object.position
592
- .sub(this.target)
593
- .applyQuaternion(_quaternion)
594
- .add(this.target);
595
- }
596
- }
597
-
598
- export { CADTrackballControls };