From 0649240e7be2c6d594226dd4e8031c5011420363 Mon Sep 17 00:00:00 2001 From: Truman Kilen Date: Wed, 28 Jan 2026 23:13:48 -0600 Subject: [PATCH 1/2] Make zoom in and out deltas symmetric --- src/renderer/control/control2d.rs | 7 ++++--- src/renderer/control/free_orbit_control.rs | 5 +++-- src/renderer/control/orbit_control.rs | 5 +++-- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/renderer/control/control2d.rs b/src/renderer/control/control2d.rs index 7cdfdd02..824c2ddf 100644 --- a/src/renderer/control/control2d.rs +++ b/src/renderer/control/control2d.rs @@ -81,14 +81,15 @@ impl Control2D { camera: &mut three_d_asset::Camera, delta: f32, position: PhysicalPoint, - speed: f32, + sensitivity: f32, ) { - let speed = speed / camera.zoom_factor(); let mut target = camera.position_at_pixel(position); target.z = 0.0; + let distance = 1.0 / camera.zoom_factor(); + let zoom_amount = distance * (1.0 - (-delta * sensitivity).exp()); camera.zoom_towards( target, - speed * delta, + zoom_amount, 1.0 / self.max_zoom_factor, 1.0 / self.min_zoom_factor, ); diff --git a/src/renderer/control/free_orbit_control.rs b/src/renderer/control/free_orbit_control.rs index 0c154258..fd0db20a 100644 --- a/src/renderer/control/free_orbit_control.rs +++ b/src/renderer/control/free_orbit_control.rs @@ -47,10 +47,11 @@ impl FreeOrbitControl { } Event::MouseWheel { delta, handled, .. } => { if !*handled { - let speed = 0.01 * self.target.distance(camera.position()) + 0.001; + let distance = self.target.distance(camera.position()); + let zoom_amount = distance * (1.0 - (-delta.1 * 0.01).exp()); camera.zoom_towards( self.target, - speed * delta.1, + zoom_amount, self.min_distance, self.max_distance, ); diff --git a/src/renderer/control/orbit_control.rs b/src/renderer/control/orbit_control.rs index 5efc84ea..cf230a1b 100644 --- a/src/renderer/control/orbit_control.rs +++ b/src/renderer/control/orbit_control.rs @@ -51,10 +51,11 @@ impl OrbitControl { } Event::MouseWheel { delta, handled, .. } => { if !*handled { - let speed = 0.01 * self.target.distance(camera.position()) + 0.001; + let distance = self.target.distance(camera.position()); + let zoom_amount = distance * (1.0 - (-delta.1 * 0.01).exp()); camera.zoom_towards( self.target, - speed * delta.1, + zoom_amount, self.min_distance, self.max_distance, ); From ade6589f6d2fe95e41b146dca9ef9078f79bfafd Mon Sep 17 00:00:00 2001 From: Truman Kilen Date: Wed, 28 Jan 2026 23:14:31 -0600 Subject: [PATCH 2/2] Attempt to normalize mouse wheel zoom across web/desktop platforms --- .../winit_window/frame_input_generator.rs | 34 ++++++++++--------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/src/window/winit_window/frame_input_generator.rs b/src/window/winit_window/frame_input_generator.rs index b4019d08..45f69f0d 100644 --- a/src/window/winit_window/frame_input_generator.rs +++ b/src/window/winit_window/frame_input_generator.rs @@ -189,26 +189,28 @@ impl FrameInputGenerator { } WindowEvent::MouseWheel { delta, .. } => { if let Some(position) = self.cursor_pos { - match delta { + // Normalize scroll deltas so one "tick" produces similar values across platforms. + // Values determined experimentally + const LINE_HEIGHT: f64 = 24.0; + const BROWSER_LINE_HEIGHT: f64 = 100.0; + let (x, y) = match delta { winit::event::MouseScrollDelta::LineDelta(x, y) => { - let line_height = 24.0; // TODO - self.events.push(crate::Event::MouseWheel { - delta: (*x * line_height, *y * line_height), - position: position.into(), - modifiers: self.modifiers, - handled: false, - }); + ((*x as f64) * LINE_HEIGHT, (*y as f64) * LINE_HEIGHT) } winit::event::MouseScrollDelta::PixelDelta(delta) => { - let d = delta.to_logical(self.device_pixel_ratio); - self.events.push(crate::Event::MouseWheel { - delta: (d.x, d.y), - position: position.into(), - modifiers: self.modifiers, - handled: false, - }); + let d = delta.to_logical::(self.device_pixel_ratio); + ( + d.x * LINE_HEIGHT / BROWSER_LINE_HEIGHT, + d.y * LINE_HEIGHT / BROWSER_LINE_HEIGHT, + ) } - } + }; + self.events.push(crate::Event::MouseWheel { + delta: (x as f32, y as f32), + position: position.into(), + modifiers: self.modifiers, + handled: false, + }); } } WindowEvent::TouchpadMagnify { delta, .. } => {