diff --git a/src/kiri/core/init.js b/src/kiri/core/init.js index 4fc8df0a..1ae29582 100644 --- a/src/kiri/core/init.js +++ b/src/kiri/core/init.js @@ -135,7 +135,6 @@ api.event.on("set.threaded", bool => setThreaded(bool)); function booleanSave() { let control = settings().controller; - let setProjection = ui.ortho.checked !== control.ortho; if (control.assembly != ui.assembly.checked) { client.wasm(ui.assembly.checked); } @@ -171,9 +170,7 @@ function booleanSave() { updateStats(); updateDrawer(); api.event.emit('boolean.update'); - if (setProjection) { - space.view.setProjection(control.ortho ? 'orthographic' : 'perspective'); - } + space.view.setProjection(control.ortho ? 'orthographic' : 'perspective'); } function updateDrawer() { @@ -1605,6 +1602,7 @@ function init_two() { space.view.setZoom(control.reverseZoom, control.zoomSpeed); space.platform.setGridZOff(undefined); space.platform.setZOff(0.05); + space.view.setProjection(control.ortho ? 'orthographic' : 'perspective'); // restore UI state from settings ui.antiAlias.checked = control.antiAlias; diff --git a/src/moto/orbit.js b/src/moto/orbit.js index bcb65686..097e7f0b 100644 --- a/src/moto/orbit.js +++ b/src/moto/orbit.js @@ -299,12 +299,24 @@ class Orbit extends EventDispatcher { phiSet = null; pan.set(0, 0, 0); - scaleSave *= scale; - if (mode === MODE.ORTHOGRAPHIC) { - scope.object.zoom = 1/scale; + // For orthographic, constrain zoom based on maxDistance/minDistance + // Effective distance is base distance times inverse of zoom + let baseDistance = offset.length(); + let newScaleSave = scaleSave * scale; + + // Clamp scaleSave to maintain reasonable zoom levels + // Larger scaleSave = smaller zoom = more zoomed out (like larger distance) + // Smaller scaleSave = larger zoom = more zoomed in (like smaller distance) + let maxScaleSave = scope.maxDistance / baseDistance; + let minScaleSave = scope.minDistance / baseDistance; + newScaleSave = Math.max(minScaleSave, Math.min(maxScaleSave, newScaleSave)); + + scaleSave = newScaleSave; + scope.object.zoom = 1 / scaleSave; scope.object.updateProjectionMatrix(); } else { + scaleSave *= scale; scale = 1; } @@ -340,7 +352,9 @@ class Orbit extends EventDispatcher { }; function getZoomScale(factor = 1) { - return Math.pow(0.95, factor); + // Use slower zoom for orthographic mode + let base = mode === MODE.ORTHOGRAPHIC ? 0.98 : 0.95; + return Math.pow(base, factor); } function onMouseDown(event) { diff --git a/src/moto/space.js b/src/moto/space.js index 808cf02a..da94a180 100644 --- a/src/moto/space.js +++ b/src/moto/space.js @@ -1466,7 +1466,7 @@ let Space = { } // Save current view state - const position = viewControl.getPosition(); + const position = viewControl.getPosition(true); const target = viewControl.getTarget().clone(); const distance = camera.position.distanceTo(target); @@ -1477,7 +1477,7 @@ let Space = { // Calculate ortho size based on perspective distance and FOV const size = distance * Math.tan(perspective * Math.PI / 180 / 2); newCamera = new THREE.OrthographicCamera( - -size * asp, size * asp, size, -size, 0.1, 100000 + -size * asp, size * asp, size, -size, -10000, 100000 ); } else { newCamera = new THREE.PerspectiveCamera( @@ -1577,7 +1577,7 @@ let Space = { renderer.localClippingEnabled = true; cameraType = ortho ? 'orthographic' : 'perspective'; camera = ortho ? - new THREE.OrthographicCamera(-100 * aspect(), 100 * aspect(), 100, -100, 0.1, 100000) : + new THREE.OrthographicCamera(-100 * aspect(), 100 * aspect(), 100, -100, -10000, 100000) : new THREE.PerspectiveCamera(perspective, aspect(), 0.1, 100000); camera.position.set(0, 200, 340);