Skip to content

Commit

Permalink
Keep focus point under cursor when moving model
Browse files Browse the repository at this point in the history
This doesn't work perfectly yet, probably due to #18.
  • Loading branch information
hannobraun committed Dec 4, 2021
1 parent b6673cc commit 8985bb9
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 35 deletions.
7 changes: 4 additions & 3 deletions src/input/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use winit::{
},
};

use crate::{camera::Camera, math::Point};
use crate::{camera::Camera, math::Point, window::Window};

use super::{movement::Movement, rotation::Rotation, zoom::Zoom};

Expand Down Expand Up @@ -61,12 +61,13 @@ impl Handler {
&mut self,
cursor: PhysicalPosition<f64>,
camera: &mut Camera,
window: &Window,
) {
if let Some(previous) = self.cursor {
let diff_x = cursor.x - previous.x;
let diff_y = cursor.y - previous.y;

self.movement.apply(diff_x, diff_y, camera);
self.movement.apply(self.cursor, camera, window);
self.rotation.apply(diff_x, diff_y, camera);
}

Expand All @@ -87,7 +88,7 @@ impl Handler {
self.rotation.stop();
}
(MouseButton::Right, ElementState::Pressed) => {
self.movement.start(focus_point);
self.movement.start(focus_point, self.cursor);
}
(MouseButton::Right, ElementState::Released) => {
self.movement.stop();
Expand Down
68 changes: 37 additions & 31 deletions src/input/movement.rs
Original file line number Diff line number Diff line change
@@ -1,51 +1,57 @@
use nalgebra::Translation2;
use nalgebra::{distance, Translation2};
use winit::dpi::PhysicalPosition;

use crate::{camera::Camera, math::Point};
use crate::{camera::Camera, math::Point, window::Window};

pub struct Movement {
focus_point: Option<Point>,
cursor: Option<PhysicalPosition<f64>>,
}

impl Movement {
pub fn new() -> Self {
Self { focus_point: None }
Self {
focus_point: None,
cursor: None,
}
}

pub fn start(&mut self, focus_point: Option<Point>) {
pub fn start(
&mut self,
focus_point: Option<Point>,
cursor: Option<PhysicalPosition<f64>>,
) {
self.focus_point = focus_point;
self.cursor = cursor;
}

pub fn stop(&mut self) {
self.focus_point = None;
}

pub fn apply(&mut self, diff_x: f64, diff_y: f64, camera: &mut Camera) {
if let Some(_) = self.focus_point {
// TASK: Moving feels good, if you're dragging the model exactly
// where your mouse goes. It feels weird, if the mouse cursor
// moves faster or slower than the model you're moving.
//
// The following factor achieves this good-feeling move for
// relatively small models at the default distance between
// camera and model origin. It breaks down when moving the
// camera closer or away from the model, which is the far more
// common case.
//
// It would be nicer to have a zoom factor that depends on the
// distance between camera and model origin, or even the
// distance between the camera and the part of the model the
// mouse is currently pointing at (or more precisely, the
// distance between the camera and a plane that touches the
// surface of the model where the mouse is pointing, and whose
// normal is parallel to the camera's viewing direction).
let f = 0.2;

let trans_x = diff_x * f;
let trans_y = -diff_y * f;

let translation = Translation2::new(trans_x, trans_y);

camera.translation = translation * camera.translation;
pub fn apply(
&mut self,
cursor: Option<PhysicalPosition<f64>>,
camera: &mut Camera,
window: &Window,
) {
if let (Some(previous), Some(cursor)) = (self.cursor, cursor) {
let previous = camera.cursor_to_model_space(previous, window);
let cursor = camera.cursor_to_model_space(cursor, window);

if let Some(focus_point) = self.focus_point {
let d1 = distance(&camera.position(), &cursor);
let d2 = distance(&camera.position(), &focus_point);

let f = d2 / d1;

let diff = (cursor - previous) * f;
let translation = Translation2::new(diff.x, diff.y);

camera.translation = translation * camera.translation;
}
}

self.cursor = cursor;
}
}
6 changes: 5 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,11 @@ fn main() -> anyhow::Result<()> {
event: WindowEvent::CursorMoved { position, .. },
..
} => {
input_handler.handle_cursor_moved(position, &mut camera);
input_handler.handle_cursor_moved(
position,
&mut camera,
&window,
);
}
Event::WindowEvent {
event: WindowEvent::MouseInput { state, button, .. },
Expand Down

0 comments on commit 8985bb9

Please sign in to comment.