From b812541eb8ce20289ffcdaaba7900415a9ff339b Mon Sep 17 00:00:00 2001 From: Garrett Johnson Date: Sat, 7 Dec 2024 15:43:25 +0900 Subject: [PATCH] Fix ortho zoom (#855) --- src/three/controls/EnvironmentControls.js | 48 ++++++++++++++++------- 1 file changed, 33 insertions(+), 15 deletions(-) diff --git a/src/three/controls/EnvironmentControls.js b/src/three/controls/EnvironmentControls.js index e9e3ac924..ff543f5bd 100644 --- a/src/three/controls/EnvironmentControls.js +++ b/src/three/controls/EnvironmentControls.js @@ -809,17 +809,39 @@ export class EnvironmentControls extends EventDispatcher { this._updateZoomDirection(); // zoom straight into the globe if we haven't hit anything - if ( this.zoomPointSet || this._updateZoomPoint() ) { + const zoomIntoPoint = this.zoomPointSet || this._updateZoomPoint(); + + // get the mouse position before zoom + _mouseBefore.unproject( camera ); + + // zoom the camera + const normalizedDelta = Math.pow( 0.95, Math.abs( scale * 0.05 ) ); + let scaleFactor = scale > 0 ? 1 / Math.abs( normalizedDelta ) : normalizedDelta; + scaleFactor *= zoomSpeed; + + if ( scaleFactor > 1 ) { + + if ( maxZoom < camera.zoom * scaleFactor ) { - // get the mouse position before zoom - _mouseBefore.unproject( camera ); + scaleFactor = 1; - // zoom the camera - const normalizedDelta = Math.pow( 0.95, Math.abs( scale * 0.05 ) ); - const scaleFactor = scale > 0 ? 1 / Math.abs( normalizedDelta ) : normalizedDelta; + } + + } else { - camera.zoom = Math.max( minZoom, Math.min( maxZoom, camera.zoom * scaleFactor * zoomSpeed ) ); - camera.updateProjectionMatrix(); + if ( minZoom > camera.zoom * scaleFactor ) { + + scaleFactor = 1; + + } + + } + + camera.zoom *= scaleFactor; + camera.updateProjectionMatrix(); + + // adjust the surface point to be in the same position if the globe is hovered over + if ( zoomIntoPoint ) { // get the mouse position after zoom mouseToCoords( _pointer.x, _pointer.y, domElement, _mouseAfter ); @@ -829,15 +851,11 @@ export class EnvironmentControls extends EventDispatcher { camera.position.sub( _mouseAfter ).add( _mouseBefore ); camera.updateMatrixWorld(); - } else { - - const normalizedDelta = Math.pow( 0.95, Math.abs( scale * 0.05 ) ); - const scaleFactor = scale > 0 ? 1 / Math.abs( normalizedDelta ) : normalizedDelta; - camera.zoom = Math.max( minZoom, Math.min( maxZoom, camera.zoom * scaleFactor * zoomSpeed ) ); - camera.updateProjectionMatrix(); - } + // TODO: the user can currently zoom into the sky and hide the globe. + // Consider forcing the camera to zoom into the closest horizon point + } else { // initialize the zoom direction