From 9476eca47cffdd1f60b62a9f1a60847e7d501dc2 Mon Sep 17 00:00:00 2001 From: Marco Thomas Date: Sat, 28 Aug 2021 15:08:58 +0200 Subject: [PATCH] Somewhat working camera controller --- src/camera_controller.rs | 146 +++++++++++++++++++++++++-------------- src/main.rs | 46 ++++-------- src/state.rs | 38 +++++++--- 3 files changed, 139 insertions(+), 91 deletions(-) diff --git a/src/camera_controller.rs b/src/camera_controller.rs index 3cead26..5ca1140 100644 --- a/src/camera_controller.rs +++ b/src/camera_controller.rs @@ -1,27 +1,23 @@ -use winit::event::*; - -#[derive(Debug)] -struct IsPressed(bool); - -impl From for IsPressed { - fn from(item: bool) -> Self { - IsPressed(item) - } -} +use cgmath::Vector2; +use cgmath::Point3; +use winit::{dpi::PhysicalPosition, event::*}; #[derive(Debug)] enum ButtonPress { - Up(IsPressed), - Down(IsPressed), - Left(IsPressed), - Right(IsPressed), - Forward(IsPressed), - Backward(IsPressed), + Up(ElementState), + Down(ElementState), + Left(ElementState), + Right(ElementState), + Forward(ElementState), + Backward(ElementState), + Reset(ElementState), } pub struct CameraController { speed: f32, button_press: Option, + old_mouse: PhysicalPosition, + mouse_movement: Vector2, } impl CameraController { @@ -29,10 +25,12 @@ impl CameraController { Self { speed, button_press: None, + old_mouse: PhysicalPosition::new(0.0, 0.0), + mouse_movement: Vector2::new(0.0, 0.0), } } - pub fn process_events(&mut self, event: &WindowEvent) -> bool { + pub fn input(&mut self, event: &WindowEvent) { match event { WindowEvent::KeyboardInput { input: @@ -42,55 +40,103 @@ impl CameraController { .. }, .. - } => { - let pressed = (*state == ElementState::Pressed).into(); - match key { - VirtualKeyCode::W => { - self.button_press = Some(ButtonPress::Forward(pressed)); - true - } - VirtualKeyCode::A => { - self.button_press = Some(ButtonPress::Left(pressed)); - true - } - VirtualKeyCode::S => { - self.button_press = Some(ButtonPress::Backward(pressed)); - true - } - VirtualKeyCode::D => { - self.button_press = Some(ButtonPress::Right(pressed)); - true - } - VirtualKeyCode::Space => { - self.button_press = Some(ButtonPress::Up(pressed)); - true - } - VirtualKeyCode::LShift => { - self.button_press = Some(ButtonPress::Down(pressed)); - true - } - _ => false, + } => match key { + VirtualKeyCode::W => { + self.button_press = Some(ButtonPress::Forward(*state)); } + VirtualKeyCode::A => { + self.button_press = Some(ButtonPress::Left(*state)); + } + VirtualKeyCode::S => { + self.button_press = Some(ButtonPress::Backward(*state)); + } + VirtualKeyCode::D => { + self.button_press = Some(ButtonPress::Right(*state)); + } + VirtualKeyCode::Space => { + self.button_press = Some(ButtonPress::Up(*state)); + } + VirtualKeyCode::LShift => { + self.button_press = Some(ButtonPress::Down(*state)); + } + VirtualKeyCode::Return => { + self.button_press = Some(ButtonPress::Reset(*state)); + } + _ => {}, + }, + WindowEvent::CursorMoved { position, .. } => { + self.mouse_movement = Vector2 { + x: (*position).x - self.old_mouse.x, + y: (*position).y - self.old_mouse.y, + }; + + self.old_mouse = *position; } - _ => false, + _ => {}, } } - pub fn update_camera(&self, camera: &mut crate::camera::Camera) { + /// Update the camera vectors + /// Vectors are casted from (0, 0, 0) to both the target and the eye + pub fn update_camera(&mut self, camera: &mut crate::camera::Camera) { + // TODO what about delta time? use cgmath::InnerSpace; + // Casted eye -> target let forward = camera.target - camera.eye; let forward_norm = forward.normalize(); let forward_mag = forward.magnitude(); + // cross product of forwards and up => perpendicular right + let right = forward_norm.cross(camera.up); + let right_norm = right.normalize(); + match self.button_press { - Some(ButtonPress::Forward(IsPressed(true))) if forward_mag > self.speed => { + // keyboard buttons: + // target stays in place + // eye moves + // check movement vector, if too close + Some(ButtonPress::Forward(ElementState::Pressed)) if forward_mag > self.speed => { camera.eye += forward_norm * self.speed; } - Some(ButtonPress::Backward(IsPressed(true))) => { + Some(ButtonPress::Backward(ElementState::Pressed)) => { camera.eye -= forward_norm * self.speed; } + Some(ButtonPress::Right(ElementState::Pressed)) => { + let vector = right_norm * self.speed; + camera.eye += vector; + camera.target += vector; + } + Some(ButtonPress::Left(ElementState::Pressed)) => { + let vector = right_norm * self.speed; + camera.eye -= vector; + camera.target -= vector; + } + Some(ButtonPress::Up(ElementState::Pressed)) => { + let vector = camera.up.normalize() * self.speed; + camera.eye += vector; + camera.target += vector; + } + Some(ButtonPress::Down(ElementState::Pressed)) => { + let vector = camera.up.normalize() * self.speed; + camera.eye -= vector; + camera.target -= vector; + } + Some(ButtonPress::Reset(ElementState::Pressed)) => { + camera.target = Point3::new(0.0, 0.0, 0.0); + } _ => {} } - // TODO add rest of the movement + + // mouse movement: + // target moves + // eye stays in place + let decr = 200.0; + camera.target.x += (self.mouse_movement.x as f32) / decr; + camera.target.y -= (self.mouse_movement.y as f32) / decr; + self.mouse_movement = Vector2 { x: 0.0, y: 0.0 }; + + dbg!(&camera.eye); + dbg!(&camera.target); + dbg!(self.mouse_movement); } } diff --git a/src/main.rs b/src/main.rs index 9622cf3..f2d6ee2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,4 @@ -use winit::{ - event::*, - event_loop::{ControlFlow, EventLoop}, - window::WindowBuilder, -}; +use winit::{dpi::PhysicalPosition, event::*, event_loop::{ControlFlow, EventLoop}, window::WindowBuilder}; mod state; mod vertex; @@ -16,7 +12,12 @@ use crate::state::State; fn main() { env_logger::init(); let event_loop = EventLoop::new(); - let window = WindowBuilder::new().build(&event_loop).unwrap(); + let mut window = WindowBuilder::new() + .build(&event_loop) + .unwrap(); + //window.set_cursor_visible(false); + //window.set_cursor_grab(true).unwrap(); + // wait until Future is ready let mut state = pollster::block_on(State::new(&window)); @@ -24,33 +25,14 @@ fn main() { Event::WindowEvent { ref event, // forward event window_id - } if window_id == window.id() // be sure to only use the current one - => if !state.input(event) { // don't continue if input hasn't been processed yet - match event { - // TODO can't this be moved to state.input() - WindowEvent::CloseRequested | - WindowEvent::KeyboardInput { - input: KeyboardInput { - state: ElementState::Pressed, - virtual_keycode: Some(VirtualKeyCode::Escape), - // ignore the other entries - .. - }, - // ignore the other entries - .. - } => *control_flow = ControlFlow::Exit, - WindowEvent::Resized(physical_size) => { - state.resize(*physical_size) - }, - WindowEvent::ScaleFactorChanged {new_inner_size, ..} => { - state.resize(**new_inner_size); - }, - // Discard all other WindowEvents - _ => {} - } - }, + } if window_id == window.id() => { + state.input(event, control_flow); + } Event::RedrawRequested(_) => { - state.update(); + // update the entire scene + state.update(&mut window); + + // render the update match state.render() { Ok(_) => {}, // recreate swap_chain diff --git a/src/state.rs b/src/state.rs index 58ecb3c..ca9ce6a 100644 --- a/src/state.rs +++ b/src/state.rs @@ -2,10 +2,7 @@ use wgpu::{ PrimitiveTopology, util::DeviceExt, }; -use winit::{ - event::*, - window::Window, -}; +use winit::{dpi::PhysicalPosition, event::*, window::Window, event_loop::{ControlFlow}}; /// Hold state with important information pub struct State { @@ -135,7 +132,7 @@ impl State { // x, y, z // 1 up, 2 back // +z is out of the screen - eye: (0.0, 1.0, 2.0).into(), + eye: (0.0, 0.0, 2.0).into(), // look at the center target: (0.0, 0.0, 0.0).into(), // which way is up @@ -307,9 +304,26 @@ impl State { } } - /// Idicate, whether an event has been fully processed - pub fn input(&mut self, event: &WindowEvent) -> bool { + /// Process input of the WindowEvent + pub fn input(&mut self, event: &WindowEvent, control_flow: &mut ControlFlow) { match event { + WindowEvent::CloseRequested | + WindowEvent::KeyboardInput { + input: KeyboardInput { + state: ElementState::Pressed, + virtual_keycode: Some(VirtualKeyCode::Escape), + // ignore the other entries + .. + }, + // ignore the other entries + .. + } => *control_flow = ControlFlow::Exit, + WindowEvent::Resized(physical_size) => { + self.resize(*physical_size) + }, + WindowEvent::ScaleFactorChanged {new_inner_size, ..} => { + self.resize(**new_inner_size); + }, // WindowEvent::CursorMoved { position, .. } => { // let x = (position.x as f64) / self.size.width as f64; // let y = (position.y as f64) / self.size.height as f64; @@ -327,14 +341,20 @@ impl State { // self.use_pentagon = !self.use_pentagon; // true // } - _ => self.camera_controller.process_events(event) + _ => self.camera_controller.input(event) } } /// Update State before render() - pub fn update(&mut self) { + pub fn update(&mut self, window: &mut winit::window::Window) { // reposition camera self.camera_controller.update_camera(&mut self.camera); + // always move cursor back to center after controller update, + // so we don't loose it + window.set_cursor_position(PhysicalPosition::new( + self.size.width / 2, + self.size.height / 2, + )).unwrap(); // update projection for uniform buffer self.uniform.update_view_proj(&self.camera); // write uniform buffer to queue