@ifc-lite/renderer 1.14.3 → 1.14.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 (52) hide show
  1. package/dist/camera-animation.d.ts +10 -4
  2. package/dist/camera-animation.d.ts.map +1 -1
  3. package/dist/camera-animation.js +79 -39
  4. package/dist/camera-animation.js.map +1 -1
  5. package/dist/camera-controls.d.ts +63 -25
  6. package/dist/camera-controls.d.ts.map +1 -1
  7. package/dist/camera-controls.js +284 -186
  8. package/dist/camera-controls.js.map +1 -1
  9. package/dist/camera.d.ts +32 -14
  10. package/dist/camera.d.ts.map +1 -1
  11. package/dist/camera.js +74 -25
  12. package/dist/camera.js.map +1 -1
  13. package/dist/index.d.ts +68 -2
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +412 -51
  16. package/dist/index.js.map +1 -1
  17. package/dist/picker.d.ts +7 -0
  18. package/dist/picker.d.ts.map +1 -1
  19. package/dist/picker.js +15 -0
  20. package/dist/picker.js.map +1 -1
  21. package/dist/picking-manager.d.ts +3 -3
  22. package/dist/picking-manager.d.ts.map +1 -1
  23. package/dist/picking-manager.js +4 -4
  24. package/dist/picking-manager.js.map +1 -1
  25. package/dist/pipeline.d.ts +14 -0
  26. package/dist/pipeline.d.ts.map +1 -1
  27. package/dist/pipeline.js +32 -230
  28. package/dist/pipeline.js.map +1 -1
  29. package/dist/post-processor.d.ts +7 -0
  30. package/dist/post-processor.d.ts.map +1 -1
  31. package/dist/post-processor.js +15 -0
  32. package/dist/post-processor.js.map +1 -1
  33. package/dist/scene.d.ts +65 -9
  34. package/dist/scene.d.ts.map +1 -1
  35. package/dist/scene.js +482 -127
  36. package/dist/scene.js.map +1 -1
  37. package/dist/section-plane.d.ts +6 -0
  38. package/dist/section-plane.d.ts.map +1 -1
  39. package/dist/section-plane.js +12 -0
  40. package/dist/section-plane.js.map +1 -1
  41. package/dist/shaders/main.wgsl.d.ts +7 -0
  42. package/dist/shaders/main.wgsl.d.ts.map +1 -0
  43. package/dist/shaders/main.wgsl.js +239 -0
  44. package/dist/shaders/main.wgsl.js.map +1 -0
  45. package/dist/snap-detector.d.ts.map +1 -1
  46. package/dist/snap-detector.js +20 -6
  47. package/dist/snap-detector.js.map +1 -1
  48. package/package.json +4 -4
  49. package/dist/geometry-manager.d.ts +0 -99
  50. package/dist/geometry-manager.d.ts.map +0 -1
  51. package/dist/geometry-manager.js +0 -400
  52. package/dist/geometry-manager.js.map +0 -1
@@ -1,149 +1,239 @@
1
1
  /* This Source Code Form is subject to the terms of the Mozilla Public
2
2
  * License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
  * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
+ import { CAMERA_CONSTANTS as CC } from './constants.js';
5
+ // ---------------------------------------------------------------------------
6
+ // Tiny vec3 helpers (inline, no allocations beyond the return object)
7
+ // ---------------------------------------------------------------------------
8
+ /** Subtract a - b */
9
+ function sub(a, b) {
10
+ return { x: a.x - b.x, y: a.y - b.y, z: a.z - b.z };
11
+ }
12
+ function length(v) {
13
+ return Math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
14
+ }
15
+ function scale(v, s) {
16
+ return { x: v.x * s, y: v.y * s, z: v.z * s };
17
+ }
18
+ function normalize(v) {
19
+ const len = length(v);
20
+ return len > 1e-10 ? scale(v, 1 / len) : { x: 0, y: 0, z: 0 };
21
+ }
22
+ function cross(a, b) {
23
+ return {
24
+ x: a.y * b.z - a.z * b.y,
25
+ y: a.z * b.x - a.x * b.z,
26
+ z: a.x * b.y - a.y * b.x,
27
+ };
28
+ }
29
+ function dot(a, b) {
30
+ return a.x * b.x + a.y * b.y + a.z * b.z;
31
+ }
32
+ /** Rodrigues' rotation: rotate v around unit axis k by angle radians. */
33
+ function rodrigues(v, k, angle) {
34
+ const cosA = Math.cos(angle);
35
+ const sinA = Math.sin(angle);
36
+ const kDotV = dot(k, v);
37
+ const kxv = cross(k, v);
38
+ return {
39
+ x: v.x * cosA + kxv.x * sinA + k.x * kDotV * (1 - cosA),
40
+ y: v.y * cosA + kxv.y * sinA + k.y * kDotV * (1 - cosA),
41
+ z: v.z * cosA + kxv.z * sinA + k.z * kDotV * (1 - cosA),
42
+ };
43
+ }
44
+ /**
45
+ * Prevent the look direction from being too close to ±Y (vertical),
46
+ * which degenerates the view matrix (cross(forward, up) → 0 → model flips).
47
+ * Preserves the horizontal direction; only pulls the Y component back.
48
+ * Margin of ~0.6° from vertical — user can look 89.4° up/down.
49
+ */
50
+ const MAX_LOOK_Y = Math.cos(0.01); // cos(0.01 rad) ≈ 0.99995
51
+ function clampLookVertical(look) {
52
+ const len = length(look);
53
+ if (len < 1e-10)
54
+ return look;
55
+ const ny = look.y / len;
56
+ if (Math.abs(ny) <= MAX_LOOK_Y)
57
+ return look;
58
+ const clampedNy = Math.sign(ny) * MAX_LOOK_Y;
59
+ const horizSq = look.x * look.x + look.z * look.z;
60
+ if (horizSq < 1e-20)
61
+ return look; // purely vertical, can't recover direction
62
+ const targetHoriz = len * Math.sqrt(1 - clampedNy * clampedNy);
63
+ const hScale = targetHoriz / Math.sqrt(horizSq);
64
+ return { x: look.x * hScale, y: clampedNy * len, z: look.z * hScale };
65
+ }
66
+ /** Add offset to a Vec3 in place */
67
+ function addInPlace(v, offset) {
68
+ v.x += offset.x;
69
+ v.y += offset.y;
70
+ v.z += offset.z;
71
+ }
72
+ /** Copy xyz from src into dst */
73
+ function copyInto(dst, src) {
74
+ dst.x = src.x;
75
+ dst.y = src.y;
76
+ dst.z = src.z;
77
+ }
78
+ // ---------------------------------------------------------------------------
79
+ // Spherical coordinate helpers
80
+ // ---------------------------------------------------------------------------
81
+ /** Convert a direction vector (from pivot to point) into spherical angles,
82
+ * handling gimbal lock near the poles. */
83
+ function toSpherical(dir, dist) {
84
+ let phi = Math.acos(Math.max(-1, Math.min(1, dir.y / dist)));
85
+ let theta;
86
+ const sinPhi = Math.sin(phi);
87
+ if (sinPhi > CC.POLE_THRESHOLD) {
88
+ theta = Math.atan2(dir.x, dir.z);
89
+ }
90
+ else {
91
+ theta = 0;
92
+ phi = phi < Math.PI / 2 ? CC.MIN_PHI : CC.MAX_PHI;
93
+ }
94
+ return { theta, phi };
95
+ }
96
+ /** Convert spherical angles back to a Cartesian position relative to a pivot. */
97
+ function fromSpherical(pivot, dist, theta, phi) {
98
+ const sinPhi = Math.sin(phi);
99
+ return {
100
+ x: pivot.x + dist * sinPhi * Math.sin(theta),
101
+ y: pivot.y + dist * Math.cos(phi),
102
+ z: pivot.z + dist * sinPhi * Math.cos(theta),
103
+ };
104
+ }
105
+ function clampPhi(phi) {
106
+ return Math.max(CC.MIN_PHI, Math.min(CC.MAX_PHI, phi));
107
+ }
108
+ // ---------------------------------------------------------------------------
109
+ // CameraControls
110
+ // ---------------------------------------------------------------------------
4
111
  /**
5
112
  * Handles core camera movement: orbit, pan, and zoom.
6
- * Uses spherical coordinates for orbit with Y-up convention.
7
113
  */
8
114
  export class CameraControls {
9
115
  state;
10
116
  updateMatrices;
11
- /** Dynamic orbit pivot (for orbiting around selected element or cursor point) */
12
- orbitPivot = null;
117
+ /** Optional orbit pivot (set on object selection). null = orbit around camera.target. */
118
+ orbitCenter = null;
13
119
  constructor(state, updateMatrices) {
14
120
  this.state = state;
15
121
  this.updateMatrices = updateMatrices;
16
122
  }
17
123
  /**
18
- * Set temporary orbit pivot (for orbiting around selected element or cursor point)
19
- * When set, orbit() will rotate around this point instead of the camera target
124
+ * Set the orbit center without moving the camera.
125
+ * Future orbit() calls will rotate around this point.
126
+ * Pass null to revert to orbiting around camera.target.
20
127
  */
21
- setOrbitPivot(pivot) {
22
- this.orbitPivot = pivot ? { ...pivot } : null;
128
+ setOrbitCenter(center) {
129
+ this.orbitCenter = center ? { ...center } : null;
23
130
  }
131
+ // -------------------------------------------------------------------------
132
+ // Orbit
133
+ // -------------------------------------------------------------------------
24
134
  /**
25
- * Get current orbit pivot (returns temporary pivot if set, otherwise target)
26
- */
27
- getOrbitPivot() {
28
- return this.orbitPivot ? { ...this.orbitPivot } : { ...this.state.camera.target };
29
- }
30
- /**
31
- * Check if a temporary orbit pivot is set
135
+ * Orbit the camera around a pivot point (Y-up turntable style).
136
+ *
137
+ * When orbitCenter is set, position orbits around the external pivot and
138
+ * the look direction is rotated by the same axis-angle rotation (Rodrigues).
139
+ * Like Blender's turntable: horizontal = world Y, vertical = camera right.
140
+ * A vertical clamp on the look vector prevents view matrix degeneracy.
32
141
  */
33
- hasOrbitPivot() {
34
- return this.orbitPivot !== null;
142
+ orbit(deltaX, deltaY) {
143
+ this.state.camera.up = { x: 0, y: 1, z: 0 };
144
+ const dx = -deltaX * CC.ORBIT_SENSITIVITY;
145
+ const dy = -deltaY * CC.ORBIT_SENSITIVITY;
146
+ if (this.orbitCenter !== null) {
147
+ this.orbitAroundExternalPivot(this.orbitCenter, dx, dy);
148
+ }
149
+ else {
150
+ // Standard: rotate position around target, target stays fixed
151
+ const newPos = this.rotateAroundPivot(this.state.camera.position, this.state.camera.target, dx, dy);
152
+ copyInto(this.state.camera.position, newPos);
153
+ }
154
+ this.updateMatrices();
35
155
  }
36
156
  /**
37
- * Clear the orbit pivot
157
+ * Rotate a point around the pivot by the given theta/phi deltas.
38
158
  */
39
- clearOrbitPivot() {
40
- this.orbitPivot = null;
159
+ rotateAroundPivot(point, pivot, dx, dy) {
160
+ const dir = sub(point, pivot);
161
+ const dist = length(dir);
162
+ if (dist < 1e-6)
163
+ return { ...point };
164
+ const { theta, phi } = toSpherical(dir, dist);
165
+ return fromSpherical(pivot, dist, theta + dx, clampPhi(phi + dy));
41
166
  }
42
167
  /**
43
- * Orbit around target or pivot (Y-up coordinate system).
44
- * If an orbit pivot is set, orbits around that point.
168
+ * Orbit around an external pivot (Blender-style turntable with Rodrigues).
45
169
  *
46
- * Note: Does not handle velocity or preset view tracking;
47
- * the Camera class coordinates those concerns.
170
+ * 1. Horizontal: rotate offset + look around world Y (always stable).
171
+ * 2. Vertical: rotate offset + look around the orbit-sphere tangent
172
+ * (right axis derived from offset's horizontal component). Position
173
+ * phi is clamped to [MIN_PHI, MAX_PHI] so the right axis never
174
+ * degenerates (sin(MIN_PHI) ≈ 0.15 → always has XZ component).
175
+ * 3. Clamp the look vector's vertical angle to prevent the view matrix
176
+ * from degenerating when look ∥ Y. Margin is ~0.6° from vertical,
177
+ * so the user can look from 89.4° above or below.
48
178
  */
49
- orbit(deltaX, deltaY) {
50
- // Always ensure Y-up for consistent orbit behavior
51
- this.state.camera.up = { x: 0, y: 1, z: 0 };
52
- // Invert controls: mouse movement direction = model rotation direction
53
- const dx = -deltaX * 0.01;
54
- const dy = -deltaY * 0.01;
55
- // Use orbit pivot if set, otherwise use target
56
- const pivotPoint = this.orbitPivot || this.state.camera.target;
57
- const dir = {
58
- x: this.state.camera.position.x - pivotPoint.x,
59
- y: this.state.camera.position.y - pivotPoint.y,
60
- z: this.state.camera.position.z - pivotPoint.z,
61
- };
62
- const distance = Math.sqrt(dir.x * dir.x + dir.y * dir.y + dir.z * dir.z);
63
- if (distance < 1e-6)
179
+ orbitAroundExternalPivot(pivot, dx, dy) {
180
+ let offset = sub(this.state.camera.position, pivot);
181
+ const dist = length(offset);
182
+ if (dist < 1e-6)
64
183
  return;
65
- // Y-up coordinate system using standard spherical coordinates
66
- // theta: horizontal rotation around Y axis
67
- // phi: vertical angle from Y axis (0 = top, PI = bottom)
68
- let currentPhi = Math.acos(Math.max(-1, Math.min(1, dir.y / distance)));
69
- // When at poles (top/bottom view), use a stable theta based on current direction
70
- // to avoid gimbal lock issues
71
- let theta;
72
- const sinPhi = Math.sin(currentPhi);
73
- if (sinPhi > 0.05) {
74
- // Normal case - calculate theta from horizontal position
75
- theta = Math.atan2(dir.x, dir.z);
184
+ let look = sub(this.state.camera.target, this.state.camera.position);
185
+ const yAxis = { x: 0, y: 1, z: 0 };
186
+ // 1. Horizontal rotation around world Y (always stable)
187
+ offset = rodrigues(offset, yAxis, dx);
188
+ look = rodrigues(look, yAxis, dx);
189
+ // 2. Vertical rotation, clamped to prevent position from crossing poles
190
+ const offsetDir = scale(offset, 1 / dist);
191
+ const currentPhi = Math.acos(Math.max(-1, Math.min(1, offsetDir.y)));
192
+ const clampedDy = clampPhi(currentPhi + dy) - currentPhi;
193
+ if (Math.abs(clampedDy) > 1e-10) {
194
+ // Right axis = tangent to orbit sphere in the phi-increasing direction.
195
+ // {offset.z, 0, -offset.x} ensures positive angle → phi increases
196
+ // (camera moves down), matching the spherical-coord convention used
197
+ // by clampedDy. Always valid because phi is clamped away from the
198
+ // pole, so offset always has a horizontal component.
199
+ const rightN = normalize({ x: offset.z, y: 0, z: -offset.x });
200
+ offset = rodrigues(offset, rightN, clampedDy);
201
+ look = rodrigues(look, rightN, clampedDy);
76
202
  }
77
- else {
78
- // At a pole - determine which one and push away
79
- theta = 0; // Default theta when at pole
80
- if (currentPhi < Math.PI / 2) {
81
- // Top pole (phi ~ 0) - push down
82
- currentPhi = 0.15;
83
- }
84
- else {
85
- // Bottom pole (phi ~ PI) - push up
86
- currentPhi = Math.PI - 0.15;
87
- }
88
- }
89
- theta += dx;
90
- const phi = currentPhi + dy;
91
- // Clamp phi to prevent gimbal lock (stay away from exact poles)
92
- const phiClamped = Math.max(0.15, Math.min(Math.PI - 0.15, phi));
93
- // Calculate new camera position around pivot
94
- const newPosX = pivotPoint.x + distance * Math.sin(phiClamped) * Math.sin(theta);
95
- const newPosY = pivotPoint.y + distance * Math.cos(phiClamped);
96
- const newPosZ = pivotPoint.z + distance * Math.sin(phiClamped) * Math.cos(theta);
97
- // Update camera position
98
- this.state.camera.position.x = newPosX;
99
- this.state.camera.position.y = newPosY;
100
- this.state.camera.position.z = newPosZ;
101
- this.updateMatrices();
203
+ // 3. Prevent view flip: clamp look direction away from ±Y
204
+ look = clampLookVertical(look);
205
+ const newPos = { x: pivot.x + offset.x, y: pivot.y + offset.y, z: pivot.z + offset.z };
206
+ copyInto(this.state.camera.position, newPos);
207
+ copyInto(this.state.camera.target, {
208
+ x: newPos.x + look.x,
209
+ y: newPos.y + look.y,
210
+ z: newPos.z + look.z,
211
+ });
102
212
  }
213
+ // -------------------------------------------------------------------------
214
+ // Pan
215
+ // -------------------------------------------------------------------------
103
216
  /**
104
217
  * Pan camera (Y-up coordinate system).
105
- *
106
- * Note: Does not handle velocity; the Camera class coordinates that.
218
+ * Moves both position and target by the same offset (preserves orbit relationship).
107
219
  */
108
220
  pan(deltaX, deltaY) {
109
- const dir = {
110
- x: this.state.camera.position.x - this.state.camera.target.x,
111
- y: this.state.camera.position.y - this.state.camera.target.y,
112
- z: this.state.camera.position.z - this.state.camera.target.z,
113
- };
114
- const distance = Math.sqrt(dir.x * dir.x + dir.y * dir.y + dir.z * dir.z);
115
- // Right vector: cross product of direction and up (0,1,0)
116
- const right = {
117
- x: -dir.z,
118
- y: 0,
119
- z: dir.x,
120
- };
121
- const rightLen = Math.sqrt(right.x * right.x + right.z * right.z);
122
- if (rightLen > 1e-10) {
123
- right.x /= rightLen;
124
- right.z /= rightLen;
125
- }
126
- // Up vector: cross product of right and direction
127
- const up = {
128
- x: (right.z * dir.y - right.y * dir.z),
129
- y: (right.x * dir.z - right.z * dir.x),
130
- z: (right.y * dir.x - right.x * dir.y),
221
+ const dir = sub(this.state.camera.position, this.state.camera.target);
222
+ const dist = length(dir);
223
+ const right = normalize({ x: -dir.z, y: 0, z: dir.x });
224
+ const up = normalize(cross(right, dir));
225
+ const speed = dist * CC.PAN_SPEED_MULTIPLIER;
226
+ const offset = {
227
+ x: (right.x * deltaX + up.x * deltaY) * speed,
228
+ y: (right.y * deltaX + up.y * deltaY) * speed,
229
+ z: (right.z * deltaX + up.z * deltaY) * speed,
131
230
  };
132
- const upLen = Math.sqrt(up.x * up.x + up.y * up.y + up.z * up.z);
133
- if (upLen > 1e-10) {
134
- up.x /= upLen;
135
- up.y /= upLen;
136
- up.z /= upLen;
137
- }
138
- const panSpeed = distance * 0.001;
139
- this.state.camera.target.x += (right.x * deltaX + up.x * deltaY) * panSpeed;
140
- this.state.camera.target.y += (right.y * deltaX + up.y * deltaY) * panSpeed;
141
- this.state.camera.target.z += (right.z * deltaX + up.z * deltaY) * panSpeed;
142
- this.state.camera.position.x += (right.x * deltaX + up.x * deltaY) * panSpeed;
143
- this.state.camera.position.y += (right.y * deltaX + up.y * deltaY) * panSpeed;
144
- this.state.camera.position.z += (right.z * deltaX + up.z * deltaY) * panSpeed;
231
+ this.translateAll(offset);
145
232
  this.updateMatrices();
146
233
  }
234
+ // -------------------------------------------------------------------------
235
+ // Zoom
236
+ // -------------------------------------------------------------------------
147
237
  /**
148
238
  * Zoom camera towards mouse position.
149
239
  * @param delta - Zoom delta (positive = zoom out, negative = zoom in)
@@ -151,89 +241,97 @@ export class CameraControls {
151
241
  * @param mouseY - Mouse Y position in canvas coordinates
152
242
  * @param canvasWidth - Canvas width
153
243
  * @param canvasHeight - Canvas height
154
- *
155
- * Note: Does not handle velocity; the Camera class coordinates that.
156
244
  */
157
245
  zoom(delta, mouseX, mouseY, canvasWidth, canvasHeight) {
158
- const dir = {
159
- x: this.state.camera.position.x - this.state.camera.target.x,
160
- y: this.state.camera.position.y - this.state.camera.target.y,
161
- z: this.state.camera.position.z - this.state.camera.target.z,
162
- };
163
- const distance = Math.sqrt(dir.x * dir.x + dir.y * dir.y + dir.z * dir.z);
164
- // Normalize delta (wheel events can have large values)
165
- const normalizedDelta = Math.sign(delta) * Math.min(Math.abs(delta) * 0.001, 0.1);
246
+ const dir = sub(this.state.camera.position, this.state.camera.target);
247
+ const distance = length(dir);
248
+ if (distance < 1e-6)
249
+ return; // Degenerate: position target, nothing to zoom
250
+ const normalizedDelta = Math.sign(delta) * Math.min(Math.abs(delta) * CC.ZOOM_SENSITIVITY, CC.MAX_ZOOM_DELTA);
166
251
  const zoomFactor = 1 + normalizedDelta;
167
- // If mouse position provided, zoom towards that point
168
- if (mouseX !== undefined && mouseY !== undefined && canvasWidth && canvasHeight) {
169
- // Convert mouse to normalized device coordinates (-1 to 1)
170
- const ndcX = (mouseX / canvasWidth) * 2 - 1;
171
- const ndcY = 1 - (mouseY / canvasHeight) * 2; // Flip Y
172
- // Calculate offset from center in world space
173
- // Use the camera's right and up vectors
174
- const forward = {
175
- x: -dir.x / distance,
176
- y: -dir.y / distance,
177
- z: -dir.z / distance,
178
- };
179
- // Right = forward x up
180
- const up = this.state.camera.up;
181
- const right = {
182
- x: forward.y * up.z - forward.z * up.y,
183
- y: forward.z * up.x - forward.x * up.z,
184
- z: forward.x * up.y - forward.y * up.x,
185
- };
186
- const rightLen = Math.sqrt(right.x * right.x + right.y * right.y + right.z * right.z);
187
- if (rightLen > 1e-10) {
188
- right.x /= rightLen;
189
- right.y /= rightLen;
190
- right.z /= rightLen;
191
- }
192
- // Actual up = right x forward
193
- const actualUp = {
194
- x: right.y * forward.z - right.z * forward.y,
195
- y: right.z * forward.x - right.x * forward.z,
196
- z: right.x * forward.y - right.y * forward.x,
197
- };
198
- // Calculate view frustum size at target distance
199
- const halfHeight = this.state.projectionMode === 'orthographic'
200
- ? this.state.orthoSize
201
- : distance * Math.tan(this.state.camera.fov / 2);
202
- const halfWidth = halfHeight * this.state.camera.aspect;
203
- // World offset from center towards mouse position
204
- const worldOffsetX = ndcX * halfWidth;
205
- const worldOffsetY = ndcY * halfHeight;
206
- // Point in world space that mouse is pointing at (on the target plane)
207
- const mouseWorldPoint = {
208
- x: this.state.camera.target.x + right.x * worldOffsetX + actualUp.x * worldOffsetY,
209
- y: this.state.camera.target.y + right.y * worldOffsetX + actualUp.y * worldOffsetY,
210
- z: this.state.camera.target.z + right.z * worldOffsetX + actualUp.z * worldOffsetY,
211
- };
212
- // Move both camera and target towards mouse point while zooming
213
- const moveAmount = (1 - zoomFactor); // Negative when zooming in
214
- this.state.camera.target.x += (mouseWorldPoint.x - this.state.camera.target.x) * moveAmount;
215
- this.state.camera.target.y += (mouseWorldPoint.y - this.state.camera.target.y) * moveAmount;
216
- this.state.camera.target.z += (mouseWorldPoint.z - this.state.camera.target.z) * moveAmount;
217
- }
252
+ const forward = scale(dir, -1 / distance);
218
253
  if (this.state.projectionMode === 'orthographic') {
219
- // Orthographic: scale view volume instead of moving camera
220
- this.state.orthoSize = Math.max(0.01, this.state.orthoSize * zoomFactor);
221
- // Still move camera position to keep orbit distance consistent for when switching back
222
- const newDistance = Math.max(0.1, distance * zoomFactor);
223
- const scale = newDistance / distance;
224
- this.state.camera.position.x = this.state.camera.target.x + dir.x * scale;
225
- this.state.camera.position.y = this.state.camera.target.y + dir.y * scale;
226
- this.state.camera.position.z = this.state.camera.target.z + dir.z * scale;
254
+ // Compute the effective factor after clamping so mouse anchoring matches
255
+ // the actual zoom applied — prevents drift when orthoSize hits the floor.
256
+ const nextOrthoSize = Math.max(0.01, this.state.orthoSize * zoomFactor);
257
+ const effectiveFactor = nextOrthoSize / this.state.orthoSize;
258
+ if (mouseX !== undefined && mouseY !== undefined && canvasWidth && canvasHeight) {
259
+ this.shiftTargetTowardsMouse(dir, distance, forward, effectiveFactor, mouseX, mouseY, canvasWidth, canvasHeight);
260
+ }
261
+ this.zoomOrthographic(dir, nextOrthoSize);
227
262
  }
228
263
  else {
229
- // Perspective: scale distance
230
- const newDistance = Math.max(0.1, distance * zoomFactor);
231
- const scale = newDistance / distance;
232
- this.state.camera.position.x = this.state.camera.target.x + dir.x * scale;
233
- this.state.camera.position.y = this.state.camera.target.y + dir.y * scale;
234
- this.state.camera.position.z = this.state.camera.target.z + dir.z * scale;
264
+ if (mouseX !== undefined && mouseY !== undefined && canvasWidth && canvasHeight) {
265
+ this.shiftTargetTowardsMouse(dir, distance, forward, zoomFactor, mouseX, mouseY, canvasWidth, canvasHeight);
266
+ }
267
+ this.zoomPerspective(distance, forward, zoomFactor);
235
268
  }
236
269
  this.updateMatrices();
237
270
  }
271
+ /** Orthographic: set view volume size, keep camera distance unchanged. */
272
+ zoomOrthographic(dir, nextOrthoSize) {
273
+ this.state.orthoSize = nextOrthoSize;
274
+ this.state.camera.position.x = this.state.camera.target.x + dir.x;
275
+ this.state.camera.position.y = this.state.camera.target.y + dir.y;
276
+ this.state.camera.position.z = this.state.camera.target.z + dir.z;
277
+ }
278
+ /**
279
+ * Perspective: dolly-zoom — combines distance reduction with forward travel.
280
+ *
281
+ * Pure multiplicative zoom suffers from Zeno's paradox: each step covers a
282
+ * smaller absolute distance, so the user asymptotically approaches the target
283
+ * but can never pass it. By splitting each zoom step into distance reduction +
284
+ * forward dolly, the camera always makes real progress through the scene.
285
+ */
286
+ zoomPerspective(distance, forward, zoomFactor) {
287
+ const zoomStep = distance * (1 - zoomFactor); // positive when zooming in
288
+ const dolly = zoomStep * 0.5;
289
+ const newDistance = Math.max(0.001, distance - dolly);
290
+ // Move target (and orbit center) forward to traverse the scene
291
+ const dollyOffset = scale(forward, dolly);
292
+ addInPlace(this.state.camera.target, dollyOffset);
293
+ if (this.orbitCenter)
294
+ addInPlace(this.orbitCenter, dollyOffset);
295
+ // Position camera at new distance from updated target
296
+ const t = this.state.camera.target;
297
+ copyInto(this.state.camera.position, {
298
+ x: t.x - forward.x * newDistance,
299
+ y: t.y - forward.y * newDistance,
300
+ z: t.z - forward.z * newDistance,
301
+ });
302
+ }
303
+ /** Shift target toward the world point under the mouse cursor. */
304
+ shiftTargetTowardsMouse(dir, distance, forward, zoomFactor, mouseX, mouseY, canvasWidth, canvasHeight) {
305
+ const ndcX = (mouseX / canvasWidth) * 2 - 1;
306
+ const ndcY = 1 - (mouseY / canvasHeight) * 2;
307
+ const right = normalize(cross(forward, this.state.camera.up));
308
+ const actualUp = cross(right, forward);
309
+ const halfHeight = this.state.projectionMode === 'orthographic'
310
+ ? this.state.orthoSize
311
+ : distance * Math.tan(this.state.camera.fov / 2);
312
+ const halfWidth = halfHeight * this.state.camera.aspect;
313
+ // World point under mouse cursor (on the target plane)
314
+ const t = this.state.camera.target;
315
+ const mouseWorld = {
316
+ x: t.x + right.x * ndcX * halfWidth + actualUp.x * ndcY * halfHeight,
317
+ y: t.y + right.y * ndcX * halfWidth + actualUp.y * ndcY * halfHeight,
318
+ z: t.z + right.z * ndcX * halfWidth + actualUp.z * ndcY * halfHeight,
319
+ };
320
+ const moveAmount = 1 - zoomFactor;
321
+ t.x += (mouseWorld.x - t.x) * moveAmount;
322
+ t.y += (mouseWorld.y - t.y) * moveAmount;
323
+ t.z += (mouseWorld.z - t.z) * moveAmount;
324
+ }
325
+ // -------------------------------------------------------------------------
326
+ // Helpers
327
+ // -------------------------------------------------------------------------
328
+ /** Translate target, position, and orbit center by the same offset. */
329
+ translateAll(offset) {
330
+ addInPlace(this.state.camera.target, offset);
331
+ addInPlace(this.state.camera.position, offset);
332
+ if (this.orbitCenter) {
333
+ addInPlace(this.orbitCenter, offset);
334
+ }
335
+ }
238
336
  }
239
337
  //# sourceMappingURL=camera-controls.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"camera-controls.js","sourceRoot":"","sources":["../src/camera-controls.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AA2B/D;;;GAGG;AACH,MAAM,OAAO,cAAc;IAKN;IACA;IALnB,iFAAiF;IACzE,UAAU,GAAgB,IAAI,CAAC;IAEvC,YACmB,KAA0B,EAC1B,cAA0B;QAD1B,UAAK,GAAL,KAAK,CAAqB;QAC1B,mBAAc,GAAd,cAAc,CAAY;IAC1C,CAAC;IAEJ;;;OAGG;IACH,aAAa,CAAC,KAAkB;QAC9B,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IAChD,CAAC;IAED;;OAEG;IACH,aAAa;QACX,OAAO,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;IACpF,CAAC;IAED;;OAEG;IACH,aAAa;QACX,OAAO,IAAI,CAAC,UAAU,KAAK,IAAI,CAAC;IAClC,CAAC;IAED;;OAEG;IACH,eAAe;QACb,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;IACzB,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,MAAc,EAAE,MAAc;QAClC,mDAAmD;QACnD,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;QAE5C,uEAAuE;QACvE,MAAM,EAAE,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC;QAC1B,MAAM,EAAE,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC;QAE1B,+CAA+C;QAC/C,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC;QAE/D,MAAM,GAAG,GAAG;YACV,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC;YAC9C,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC;YAC9C,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC;SAC/C,CAAC;QAEF,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;QAC1E,IAAI,QAAQ,GAAG,IAAI;YAAE,OAAO;QAE5B,8DAA8D;QAC9D,2CAA2C;QAC3C,yDAAyD;QACzD,IAAI,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;QAExE,iFAAiF;QACjF,8BAA8B;QAC9B,IAAI,KAAa,CAAC;QAClB,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QACpC,IAAI,MAAM,GAAG,IAAI,EAAE,CAAC;YAClB,yDAAyD;YACzD,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;QACnC,CAAC;aAAM,CAAC;YACN,gDAAgD;YAChD,KAAK,GAAG,CAAC,CAAC,CAAC,6BAA6B;YACxC,IAAI,UAAU,GAAG,IAAI,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;gBAC7B,iCAAiC;gBACjC,UAAU,GAAG,IAAI,CAAC;YACpB,CAAC;iBAAM,CAAC;gBACN,mCAAmC;gBACnC,UAAU,GAAG,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC;YAC9B,CAAC;QACH,CAAC;QAED,KAAK,IAAI,EAAE,CAAC;QACZ,MAAM,GAAG,GAAG,UAAU,GAAG,EAAE,CAAC;QAE5B,gEAAgE;QAChE,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC;QAEjE,6CAA6C;QAC7C,MAAM,OAAO,GAAG,UAAU,CAAC,CAAC,GAAG,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACjF,MAAM,OAAO,GAAG,UAAU,CAAC,CAAC,GAAG,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QAC/D,MAAM,OAAO,GAAG,UAAU,CAAC,CAAC,GAAG,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAEjF,yBAAyB;QACzB,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,OAAO,CAAC;QACvC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,OAAO,CAAC;QACvC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,OAAO,CAAC;QAEvC,IAAI,CAAC,cAAc,EAAE,CAAC;IACxB,CAAC;IAED;;;;OAIG;IACH,GAAG,CAAC,MAAc,EAAE,MAAc;QAChC,MAAM,GAAG,GAAG;YACV,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YAC5D,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YAC5D,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;SAC7D,CAAC;QACF,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;QAE1E,0DAA0D;QAC1D,MAAM,KAAK,GAAG;YACZ,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;YACT,CAAC,EAAE,CAAC;YACJ,CAAC,EAAE,GAAG,CAAC,CAAC;SACT,CAAC;QACF,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QAClE,IAAI,QAAQ,GAAG,KAAK,EAAE,CAAC;YACrB,KAAK,CAAC,CAAC,IAAI,QAAQ,CAAC;YACpB,KAAK,CAAC,CAAC,IAAI,QAAQ,CAAC;QACtB,CAAC;QAED,kDAAkD;QAClD,MAAM,EAAE,GAAG;YACT,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;YACtC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;YACtC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;SACvC,CAAC;QACF,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;QACjE,IAAI,KAAK,GAAG,KAAK,EAAE,CAAC;YAClB,EAAE,CAAC,CAAC,IAAI,KAAK,CAAC;YACd,EAAE,CAAC,CAAC,IAAI,KAAK,CAAC;YACd,EAAE,CAAC,CAAC,IAAI,KAAK,CAAC;QAChB,CAAC;QAED,MAAM,QAAQ,GAAG,QAAQ,GAAG,KAAK,CAAC;QAClC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,MAAM,GAAG,EAAE,CAAC,CAAC,GAAG,MAAM,CAAC,GAAG,QAAQ,CAAC;QAC5E,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,MAAM,GAAG,EAAE,CAAC,CAAC,GAAG,MAAM,CAAC,GAAG,QAAQ,CAAC;QAC5E,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,MAAM,GAAG,EAAE,CAAC,CAAC,GAAG,MAAM,CAAC,GAAG,QAAQ,CAAC;QAC5E,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,MAAM,GAAG,EAAE,CAAC,CAAC,GAAG,MAAM,CAAC,GAAG,QAAQ,CAAC;QAC9E,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,MAAM,GAAG,EAAE,CAAC,CAAC,GAAG,MAAM,CAAC,GAAG,QAAQ,CAAC;QAC9E,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,MAAM,GAAG,EAAE,CAAC,CAAC,GAAG,MAAM,CAAC,GAAG,QAAQ,CAAC;QAE9E,IAAI,CAAC,cAAc,EAAE,CAAC;IACxB,CAAC;IAED;;;;;;;;;OASG;IACH,IAAI,CAAC,KAAa,EAAE,MAAe,EAAE,MAAe,EAAE,WAAoB,EAAE,YAAqB;QAC/F,MAAM,GAAG,GAAG;YACV,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YAC5D,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YAC5D,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;SAC7D,CAAC;QACF,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;QAC1E,uDAAuD;QACvD,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,KAAK,EAAE,GAAG,CAAC,CAAC;QAClF,MAAM,UAAU,GAAG,CAAC,GAAG,eAAe,CAAC;QAEvC,sDAAsD;QACtD,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,SAAS,IAAI,WAAW,IAAI,YAAY,EAAE,CAAC;YAChF,2DAA2D;YAC3D,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAC5C,MAAM,IAAI,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS;YAEvD,8CAA8C;YAC9C,wCAAwC;YACxC,MAAM,OAAO,GAAG;gBACd,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,QAAQ;gBACpB,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,QAAQ;gBACpB,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,QAAQ;aACrB,CAAC;YAEF,uBAAuB;YACvB,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;YAChC,MAAM,KAAK,GAAG;gBACZ,CAAC,EAAE,OAAO,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;gBACtC,CAAC,EAAE,OAAO,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;gBACtC,CAAC,EAAE,OAAO,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;aACvC,CAAC;YACF,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YACtF,IAAI,QAAQ,GAAG,KAAK,EAAE,CAAC;gBACrB,KAAK,CAAC,CAAC,IAAI,QAAQ,CAAC;gBACpB,KAAK,CAAC,CAAC,IAAI,QAAQ,CAAC;gBACpB,KAAK,CAAC,CAAC,IAAI,QAAQ,CAAC;YACtB,CAAC;YAED,8BAA8B;YAC9B,MAAM,QAAQ,GAAG;gBACf,CAAC,EAAE,KAAK,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC;gBAC5C,CAAC,EAAE,KAAK,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC;gBAC5C,CAAC,EAAE,KAAK,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC;aAC7C,CAAC;YAEF,iDAAiD;YACjD,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,KAAK,cAAc;gBAC7D,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS;gBACtB,CAAC,CAAC,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;YACnD,MAAM,SAAS,GAAG,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC;YAExD,kDAAkD;YAClD,MAAM,YAAY,GAAG,IAAI,GAAG,SAAS,CAAC;YACtC,MAAM,YAAY,GAAG,IAAI,GAAG,UAAU,CAAC;YAEvC,uEAAuE;YACvE,MAAM,eAAe,GAAG;gBACtB,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,YAAY,GAAG,QAAQ,CAAC,CAAC,GAAG,YAAY;gBAClF,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,YAAY,GAAG,QAAQ,CAAC,CAAC,GAAG,YAAY;gBAClF,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,YAAY,GAAG,QAAQ,CAAC,CAAC,GAAG,YAAY;aACnF,CAAC;YAEF,gEAAgE;YAChE,MAAM,UAAU,GAAG,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,2BAA2B;YAEhE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC;YAC5F,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC;YAC5F,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC;QAC9F,CAAC;QAED,IAAI,IAAI,CAAC,KAAK,CAAC,cAAc,KAAK,cAAc,EAAE,CAAC;YACjD,2DAA2D;YAC3D,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,UAAU,CAAC,CAAC;YACzE,uFAAuF;YACvF,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,QAAQ,GAAG,UAAU,CAAC,CAAC;YACzD,MAAM,KAAK,GAAG,WAAW,GAAG,QAAQ,CAAC;YACrC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC;YAC1E,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC;YAC1E,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC;QAC5E,CAAC;aAAM,CAAC;YACN,8BAA8B;YAC9B,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,QAAQ,GAAG,UAAU,CAAC,CAAC;YACzD,MAAM,KAAK,GAAG,WAAW,GAAG,QAAQ,CAAC;YACrC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC;YAC1E,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC;YAC1E,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC;QAC5E,CAAC;QAED,IAAI,CAAC,cAAc,EAAE,CAAC;IACxB,CAAC;CACF"}
1
+ {"version":3,"file":"camera-controls.js","sourceRoot":"","sources":["../src/camera-controls.ts"],"names":[],"mappings":"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"}
package/dist/camera.d.ts CHANGED
@@ -34,21 +34,15 @@ export declare class Camera {
34
34
  */
35
35
  setFOV(fov: number): void;
36
36
  /**
37
- * Set temporary orbit pivot (for orbiting around selected element or cursor point)
38
- * When set, orbit() will rotate around this point instead of the camera target
37
+ * Set the orbit center without moving the camera.
38
+ * Future orbit() calls will rotate around this point.
39
+ * Pass null to revert to orbiting around camera.target.
39
40
  */
40
- setOrbitPivot(pivot: Vec3 | null): void;
41
+ setOrbitCenter(center: Vec3 | null): void;
41
42
  /**
42
- * Get current orbit pivot (returns temporary pivot if set, otherwise target)
43
- */
44
- getOrbitPivot(): Vec3;
45
- /**
46
- * Check if a temporary orbit pivot is set
47
- */
48
- hasOrbitPivot(): boolean;
49
- /**
50
- * Orbit around target or pivot (Y-up coordinate system)
51
- * If an orbit pivot is set, orbits around that point and moves target along
43
+ * Orbit camera around the current pivot (Y-up coordinate system).
44
+ * If orbitCenter is set, both position and target rotate around it.
45
+ * Otherwise, position rotates around target (standard orbit).
52
46
  */
53
47
  orbit(deltaX: number, deltaY: number, addVelocity?: boolean): void;
54
48
  /**
@@ -122,7 +116,7 @@ export declare class Camera {
122
116
  */
123
117
  stopInertia(): void;
124
118
  /**
125
- * Reset camera state (clear orbit pivot, stop inertia, cancel animations)
119
+ * Reset camera state (clear orbit center, stop inertia, cancel animations)
126
120
  * Called when loading a new model to ensure clean state
127
121
  */
128
122
  reset(): void;
@@ -195,6 +189,30 @@ export declare class Camera {
195
189
  * Set orthographic view half-height
196
190
  */
197
191
  setOrthoSize(size: number): void;
192
+ /**
193
+ * Set scene bounds for tight orthographic near/far plane computation.
194
+ * Call this when geometry is loaded or changed.
195
+ */
196
+ setSceneBounds(bounds: {
197
+ min: {
198
+ x: number;
199
+ y: number;
200
+ z: number;
201
+ };
202
+ max: {
203
+ x: number;
204
+ y: number;
205
+ z: number;
206
+ };
207
+ } | null): void;
198
208
  private updateMatrices;
209
+ /**
210
+ * Compute tight near/far for orthographic mode by projecting the scene
211
+ * bounding sphere onto the camera view direction.
212
+ *
213
+ * This gives optimal depth precision (minimizing z-fighting) while ensuring
214
+ * no geometry is clipped regardless of camera position or view angle.
215
+ */
216
+ private computeOrthoNearFar;
199
217
  }
200
218
  //# sourceMappingURL=camera.d.ts.map