Merge pull request #127 from sotrh/device-events

modified camera tutorial to use `DeviceEvent`
pull/128/head
sotrh 4 years ago committed by GitHub
commit 12569be5de
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -142,8 +142,8 @@ impl CameraController {
pub fn process_scroll(&mut self, delta: &MouseScrollDelta) {
self.scroll = match delta {
// I'm assuming a line is about 100 pixels
MouseScrollDelta::LineDelta(_, scroll) => scroll * 100.0,
MouseScrollDelta::PixelDelta(PhysicalPosition { y: scroll, .. }) => *scroll as f32,
MouseScrollDelta::LineDelta(_, scroll) => -scroll * 0.5,
MouseScrollDelta::PixelDelta(PhysicalPosition { y: scroll, .. }) => -*scroll as f32,
};
}

@ -135,7 +135,6 @@ struct State {
#[allow(dead_code)]
debug_material: model::Material,
// NEW!
last_mouse_pos: PhysicalPosition<f64>,
mouse_pressed: bool,
}
@ -484,7 +483,6 @@ impl State {
#[allow(dead_code)]
debug_material,
// NEW!
last_mouse_pos: (0.0, 0.0).into(),
mouse_pressed: false,
}
}
@ -501,35 +499,29 @@ impl State {
}
// UPDATED!
fn input(&mut self, event: &WindowEvent) -> bool {
fn input(&mut self, event: &DeviceEvent) -> bool {
match event {
WindowEvent::KeyboardInput {
input:
KeyboardInput {
virtual_keycode: Some(key),
state,
..
},
..
} => self.camera_controller.process_keyboard(*key, *state),
WindowEvent::MouseWheel { delta, .. } => {
DeviceEvent::Key(
KeyboardInput {
virtual_keycode: Some(key),
state,
..
}
) => self.camera_controller.process_keyboard(*key, *state),
DeviceEvent::MouseWheel { delta, .. } => {
self.camera_controller.process_scroll(delta);
true
}
WindowEvent::MouseInput {
button: MouseButton::Left,
DeviceEvent::Button {
button: 1, // Left Mouse Button
state,
..
} => {
self.mouse_pressed = *state == ElementState::Pressed;
true
}
WindowEvent::CursorMoved { position, .. } => {
let mouse_dx = position.x - self.last_mouse_pos.x;
let mouse_dy = position.y - self.last_mouse_pos.y;
self.last_mouse_pos = *position;
DeviceEvent::MouseMotion { delta } => {
if self.mouse_pressed {
self.camera_controller.process_mouse(mouse_dx, mouse_dy);
self.camera_controller.process_mouse(delta.0, delta.1);
}
true
}
@ -629,31 +621,36 @@ fn main() {
*control_flow = ControlFlow::Poll;
match event {
Event::MainEventsCleared => window.request_redraw(),
Event::DeviceEvent {
ref event,
.. // We're not using device_id currently
} => {
state.input(event);
}
// UPDATED!
Event::WindowEvent {
ref event,
window_id,
} if window_id == window.id() => {
if !state.input(event) {
match event {
WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit,
WindowEvent::KeyboardInput { input, .. } => match input {
KeyboardInput {
state: ElementState::Pressed,
virtual_keycode: Some(VirtualKeyCode::Escape),
..
} => {
*control_flow = ControlFlow::Exit;
}
_ => {}
},
WindowEvent::Resized(physical_size) => {
state.resize(*physical_size);
}
WindowEvent::ScaleFactorChanged { new_inner_size, .. } => {
state.resize(**new_inner_size);
match event {
WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit,
WindowEvent::KeyboardInput { input, .. } => match input {
KeyboardInput {
state: ElementState::Pressed,
virtual_keycode: Some(VirtualKeyCode::Escape),
..
} => {
*control_flow = ControlFlow::Exit;
}
_ => {}
},
WindowEvent::Resized(physical_size) => {
state.resize(*physical_size);
}
WindowEvent::ScaleFactorChanged { new_inner_size, .. } => {
state.resize(**new_inner_size);
}
_ => {}
}
}
// UPDATED!

@ -140,10 +140,10 @@ impl CameraController {
}
pub fn process_scroll(&mut self, delta: &MouseScrollDelta) {
self.scroll = -match delta {
self.scroll = match delta {
// I'm assuming a line is about 100 pixels
MouseScrollDelta::LineDelta(_, scroll) => scroll * 100.0,
MouseScrollDelta::PixelDelta(PhysicalPosition { y: scroll, .. }) => *scroll as f32,
MouseScrollDelta::LineDelta(_, scroll) => -scroll * 0.5,
MouseScrollDelta::PixelDelta(PhysicalPosition { y: scroll, .. }) => -*scroll as f32,
};
}

@ -497,35 +497,29 @@ impl State {
texture::Texture::create_depth_texture(&self.device, &self.sc_desc, "depth_texture");
}
fn input(&mut self, event: &WindowEvent) -> bool {
fn input(&mut self, event: &DeviceEvent) -> bool {
match event {
WindowEvent::KeyboardInput {
input:
KeyboardInput {
virtual_keycode: Some(key),
state,
..
},
..
} => self.camera_controller.process_keyboard(*key, *state),
WindowEvent::MouseWheel { delta, .. } => {
DeviceEvent::Key(
KeyboardInput {
virtual_keycode: Some(key),
state,
..
}
) => self.camera_controller.process_keyboard(*key, *state),
DeviceEvent::MouseWheel { delta, .. } => {
self.camera_controller.process_scroll(delta);
true
}
WindowEvent::MouseInput {
button: MouseButton::Left,
DeviceEvent::Button {
button: 1, // Left Mouse Button
state,
..
} => {
self.mouse_pressed = *state == ElementState::Pressed;
true
}
WindowEvent::CursorMoved { position, .. } => {
let mouse_dx = position.x - self.last_mouse_pos.x;
let mouse_dy = position.y - self.last_mouse_pos.y;
self.last_mouse_pos = *position;
DeviceEvent::MouseMotion { delta } => {
if self.mouse_pressed {
self.camera_controller.process_mouse(mouse_dx, mouse_dy);
self.camera_controller.process_mouse(delta.0, delta.1);
}
true
}
@ -624,31 +618,35 @@ fn main() {
*control_flow = ControlFlow::Poll;
match event {
Event::MainEventsCleared => window.request_redraw(),
Event::DeviceEvent {
ref event,
.. // We're not using device_id currently
} => {
state.input(event);
}
Event::WindowEvent {
ref event,
window_id,
} if window_id == window.id() => {
if !state.input(event) {
match event {
WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit,
WindowEvent::KeyboardInput { input, .. } => match input {
KeyboardInput {
state: ElementState::Pressed,
virtual_keycode: Some(VirtualKeyCode::Escape),
..
} => {
*control_flow = ControlFlow::Exit;
}
_ => {}
},
WindowEvent::Resized(physical_size) => {
state.resize(*physical_size);
}
WindowEvent::ScaleFactorChanged { new_inner_size, .. } => {
state.resize(**new_inner_size);
match event {
WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit,
WindowEvent::KeyboardInput { input, .. } => match input {
KeyboardInput {
state: ElementState::Pressed,
virtual_keycode: Some(VirtualKeyCode::Escape),
..
} => {
*control_flow = ControlFlow::Exit;
}
_ => {}
},
WindowEvent::Resized(physical_size) => {
state.resize(*physical_size);
}
WindowEvent::ScaleFactorChanged { new_inner_size, .. } => {
state.resize(**new_inner_size);
}
_ => {}
}
}
Event::RedrawRequested(_) => {

@ -4,7 +4,7 @@ use std::time::Duration;
use winit::dpi::PhysicalPosition;
use winit::event::*;
#[cfg_attr(rustfmt, rustfmt_skip)]
#[rustfmt::skip]
pub const OPENGL_TO_WGPU_MATRIX: cgmath::Matrix4<f32> = cgmath::Matrix4::new(
1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
@ -12,20 +12,6 @@ pub const OPENGL_TO_WGPU_MATRIX: cgmath::Matrix4<f32> = cgmath::Matrix4::new(
0.0, 0.0, 0.5, 1.0,
);
pub fn camera_setup<V: Into<Point3<f32>>, Y: Into<Rad<f32>>, P: Into<Rad<f32>>>(
position: V,
yaw: Y,
pitch: P,
width: u32,
height: u32,
) -> (Camera, Projection, CameraController) {
(
Camera::new(position, yaw, pitch),
Projection::new(width, height, Deg(45.0), 0.1, 100.0),
CameraController::new(4.0, 0.4),
)
}
#[derive(Debug)]
pub struct Camera {
pub position: Point3<f32>,
@ -154,10 +140,10 @@ impl CameraController {
}
pub fn process_scroll(&mut self, delta: &MouseScrollDelta) {
self.scroll = -match delta {
self.scroll = match delta {
// I'm assuming a line is about 100 pixels
MouseScrollDelta::LineDelta(_, scroll) => scroll * 100.0,
MouseScrollDelta::PixelDelta(PhysicalPosition { y: scroll, .. }) => *scroll as f32,
MouseScrollDelta::LineDelta(_, scroll) => -scroll * 0.5,
MouseScrollDelta::PixelDelta(PhysicalPosition { y: scroll, .. }) => -*scroll as f32,
};
}
@ -179,6 +165,7 @@ impl CameraController {
let scrollward =
Vector3::new(pitch_cos * yaw_cos, pitch_sin, pitch_cos * yaw_sin).normalize();
camera.position += scrollward * self.scroll * self.speed * self.sensitivity * dt;
self.scroll = 0.0;
// Move up/down. Since we don't use roll, we can just
// modify the y coordinate directly.

@ -192,7 +192,7 @@ pub trait Demo: 'static + Sized {
pub async fn run<D: Demo>() -> Result<(), Error> {
wgpu_subscriber::initialize_default_subscriber(None);
let event_loop = EventLoop::new();
let window = WindowBuilder::new()
.with_title(env!("CARGO_PKG_NAME"))

@ -259,7 +259,7 @@ impl Uniforms {
}
```
We need to change our `State` to use our `Camera`, `CameraProjection` and `Projection` as well. We'll also add two fields for later: `last_mouse_pos`, and `mouse_pressed`.
We need to change our `State` to use our `Camera`, `CameraProjection` and `Projection` as well. We'll also add a `mouse_pressed` field to store whether the mouse was pressed.
```rust
struct State {
@ -269,7 +269,6 @@ struct State {
camera_controller: camera::CameraController, // UPDATED!
// ...
// NEW!
last_mouse_pos: PhysicalPosition<f64>,
mouse_pressed: bool,
}
```
@ -297,7 +296,6 @@ impl State {
camera_controller,
// ...
// NEW!
last_mouse_pos: (0.0, 0.0).into(),
mouse_pressed: false,
}
}
@ -314,44 +312,33 @@ fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
}
```
`input` will need to be updated as well.
`input()` will need to be updated as well. Up to this point we have been using `WindowEvent`s for our camera controls. While this works, it's not the best solution. The [winit docs](https://docs.rs/winit/0.23.0/winit/event/enum.WindowEvent.html?search=#variant.CursorMoved) inform us that OS will often transform the data for the `CursorMoved` event to allow effects such as cursor acceleration. Because of this, we're going to change our `input()` function to use `DeviceEvent` instead of `WindowEvent`.
```rust
// UPDATED!
fn input(&mut self, event: &WindowEvent) -> bool {
fn input(&mut self, event: &DeviceEvent) -> bool {
match event {
WindowEvent::KeyboardInput {
input: KeyboardInput {
DeviceEvent::Key(
KeyboardInput {
virtual_keycode: Some(key),
state,
..
},
..
} => self.camera_controller.process_keyboard(*key, *state),
WindowEvent::MouseWheel {
delta,
..
} => {
}
) => self.camera_controller.process_keyboard(*key, *state),
DeviceEvent::MouseWheel { delta, .. } => {
self.camera_controller.process_scroll(delta);
true
}
WindowEvent::MouseInput {
button: MouseButton::Left,
DeviceEvent::Button {
button: 1, // Left Mouse Button
state,
..
} => {
self.mouse_pressed = *state == ElementState::Pressed;
true
}
WindowEvent::CursorMoved {
position,
..
} => {
let mouse_dx = position.x - self.last_mouse_pos.x;
let mouse_dy = position.y - self.last_mouse_pos.y;
self.last_mouse_pos = *position;
DeviceEvent::MouseMotion { delta } => {
if self.mouse_pressed {
self.camera_controller.process_mouse(mouse_dx, mouse_dy);
self.camera_controller.process_mouse(delta.0, delta.1);
}
true
}
@ -360,6 +347,54 @@ fn input(&mut self, event: &WindowEvent) -> bool {
}
```
This change means will have to modify the event loop in `main()` as well.
```rust
fn main() {
// ...
event_loop.run(move |event, _, control_flow| {
*control_flow = ControlFlow::Poll;
match event {
// ...
// NEW!
Event::DeviceEvent {
ref event,
.. // We're not using device_id currently
} => {
state.input(event);
}
// UPDATED!
Event::WindowEvent {
ref event,
window_id,
} if window_id == window.id() => {
match event {
WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit,
WindowEvent::KeyboardInput { input, .. } => match input {
KeyboardInput {
state: ElementState::Pressed,
virtual_keycode: Some(VirtualKeyCode::Escape),
..
} => {
*control_flow = ControlFlow::Exit;
}
_ => {}
},
WindowEvent::Resized(physical_size) => {
state.resize(*physical_size);
}
WindowEvent::ScaleFactorChanged { new_inner_size, .. } => {
state.resize(**new_inner_size);
}
_ => {}
}
}
// ...
}
});
}
```
The `update` function requires a bit more explanation. The `update_camera` function on the `CameraController` has a parameter `dt: Duration` which is the delta time or time between frames. This is to help smooth out the camera movement so that it's not locked be the framerate. Currently we aren't calculating `dt`, so I decided to pass it into `update` as a parameter.
```rust

Loading…
Cancel
Save