Skip to main content

slam_viewer/window/camera/
controller.rs

1//! Many of this code is from [kiss3d](https://github.com/sebcrozet/kiss3d)
2//! https://github.com/sebcrozet/kiss3d/blob/master/src/camera/first_person.rs
3
4use super::super::event::WindowEventState;
5use super::base::Camera;
6
7use nalgebra::Vector2;
8use slam_cv::Number;
9use winit::event::*;
10
11pub struct CameraControllerConfig<N>
12where
13    N: Number,
14{
15    pub mouse_left_speed: N,
16    pub mouse_right_speed: N,
17    pub scroll_speed: N,
18    pub keyboard_speed: N,
19}
20
21impl<N> Into<CameraController<N>> for CameraControllerConfig<N>
22where
23    N: Number,
24{
25    fn into(self) -> CameraController<N> {
26        CameraController {
27            config: self,
28
29            window_size: Vector2::zeros(),
30
31            cursor_d: Vector2::zeros(),
32            cursor_pos: None,
33            mouse_wheel_d: N::zero(),
34
35            is_left_mouse_pressed: false,
36            is_right_mouse_pressed: false,
37
38            is_left_key_pressed: false,
39            is_right_key_pressed: false,
40            is_up_key_pressed: false,
41            is_down_key_pressed: false,
42        }
43    }
44}
45
46pub struct CameraController<N>
47where
48    N: Number,
49{
50    config: CameraControllerConfig<N>,
51
52    cursor_d: Vector2<N>,
53    cursor_pos: Option<Vector2<N>>,
54    mouse_wheel_d: N,
55
56    pub(crate) window_size: Vector2<N>,
57
58    is_left_mouse_pressed: bool,
59    is_right_mouse_pressed: bool,
60
61    is_left_key_pressed: bool,
62    is_right_key_pressed: bool,
63    is_up_key_pressed: bool,
64    is_down_key_pressed: bool,
65}
66
67impl<N> CameraController<N>
68where
69    N: Number,
70{
71    pub fn process_events(&mut self, event: &WindowEvent) -> WindowEventState {
72        match event {
73            WindowEvent::Resized(size) => {
74                self.window_size.x = N::from(size.width).unwrap();
75                self.window_size.y = N::from(size.height).unwrap();
76                WindowEventState::Unused
77            }
78            WindowEvent::KeyboardInput {
79                input:
80                    KeyboardInput {
81                        state,
82                        virtual_keycode: Some(keycode),
83                        ..
84                    },
85                ..
86            } => {
87                let is_pressed = *state == ElementState::Pressed;
88                match keycode {
89                    VirtualKeyCode::A | VirtualKeyCode::Left => {
90                        self.is_left_key_pressed = is_pressed;
91                        WindowEventState::Consumed
92                    }
93                    VirtualKeyCode::D | VirtualKeyCode::Right => {
94                        self.is_right_key_pressed = is_pressed;
95                        WindowEventState::Consumed
96                    }
97                    VirtualKeyCode::W | VirtualKeyCode::Up => {
98                        self.is_up_key_pressed = is_pressed;
99                        WindowEventState::Consumed
100                    }
101                    VirtualKeyCode::S | VirtualKeyCode::Down => {
102                        self.is_down_key_pressed = is_pressed;
103                        WindowEventState::Consumed
104                    }
105                    _ => WindowEventState::Unused,
106                }
107            }
108            WindowEvent::MouseInput { state, button, .. } => {
109                self.cursor_pos = None;
110
111                let is_pressed = *state == ElementState::Pressed;
112                match button {
113                    MouseButton::Left => {
114                        self.is_left_mouse_pressed = is_pressed;
115                        WindowEventState::Consumed
116                    }
117                    MouseButton::Right => {
118                        self.is_right_mouse_pressed = is_pressed;
119                        WindowEventState::Consumed
120                    }
121                    _ => WindowEventState::Unused,
122                }
123            }
124            // TODO: calibrate
125            WindowEvent::CursorMoved { position, .. } => {
126                if self.is_left_mouse_pressed || self.is_right_mouse_pressed {
127                    let position =
128                        Vector2::new(N::from(position.x).unwrap(), N::from(position.y).unwrap());
129
130                    if let Some(cursor_pos) = self.cursor_pos {
131                        let delta = position - cursor_pos;
132                        self.cursor_d += delta;
133                    }
134
135                    self.cursor_pos = Some(position);
136                    WindowEventState::Consumed
137                } else {
138                    WindowEventState::Unused
139                }
140            }
141            WindowEvent::MouseWheel { delta, .. } => {
142                self.mouse_wheel_d += match delta {
143                    MouseScrollDelta::LineDelta(_, ny) => N::from(*ny).unwrap(),
144                    // TODO: calibrate
145                    MouseScrollDelta::PixelDelta(dp) => N::from(dp.x.max(dp.y)).unwrap(),
146                };
147                WindowEventState::Consumed
148            }
149            _ => WindowEventState::Unused,
150        }
151    }
152
153    pub fn update_camera(&mut self, camera: &mut Camera<N>) {
154        self.cursor_d.x /= self.window_size.x;
155        self.cursor_d.y /= self.window_size.y;
156
157        // mouse movement
158        if self.is_left_mouse_pressed {
159            camera.handle_left_button_displacement(self.cursor_d * self.config.mouse_left_speed);
160        }
161        if self.is_right_mouse_pressed {
162            camera.handle_right_button_displacement(self.cursor_d * self.config.mouse_right_speed);
163        }
164        self.cursor_d = Vector2::zeros();
165
166        // scroll movement
167        camera.handle_scroll(self.mouse_wheel_d * self.config.scroll_speed);
168        self.mouse_wheel_d = N::zero();
169
170        // keyboard input
171        let mut dkey = Vector2::<N>::zeros();
172        if self.is_left_key_pressed {
173            dkey.x -= N::one();
174        }
175        if self.is_right_key_pressed {
176            dkey.x += N::one();
177        }
178        if self.is_up_key_pressed {
179            dkey.y += N::one();
180        }
181        if self.is_down_key_pressed {
182            dkey.y -= N::one();
183        }
184        dkey *= self.config.keyboard_speed;
185
186        camera.handle_keyboard(dkey);
187    }
188}