Files
first-voxels/src/app/camera_controller.rs
T
2021-04-16 10:54:00 +02:00

125 lines
4.8 KiB
Rust

use winit::event::Event;
use winit::event::{WindowEvent, DeviceEvent, KeyboardInput, ElementState, VirtualKeyCode};
use cgmath::{InnerSpace, Matrix4, Rad, Deg, Transform, Vector3};
use crate::renderer::camera::Camera;
#[derive(Default)]
struct CameraMovement {
pub up: bool,
pub down: bool,
pub fwd: bool,
pub back: bool,
pub left: bool,
pub right: bool,
pub shift: bool,
pub speed: f32,
}
#[derive(Default)]
struct CameraRotation {
pub yaw: f32, // vertical axis
pub pitch: f32, // horizontal axis
pub sensitivity: f32,
}
impl CameraRotation {
fn yaw_rad(&mut self) -> Rad<f32> { Rad::from(Deg(self.yaw)) }
fn pitch_rad(&mut self) -> Rad<f32> { Rad::from(Deg(self.pitch)) }
fn yaw_rot(&mut self) -> Matrix4<f32> { Matrix4::from_angle_y(-self.yaw_rad()) }
fn pitch_rot(&mut self)-> Matrix4<f32> { Matrix4::from_angle_x(-self.pitch_rad()) }
}
pub struct CameraController {
enabled: bool,
movement: CameraMovement,
rotation: CameraRotation,
}
impl CameraController {
pub fn new() -> Self {
let mut movement = CameraMovement::default();
movement.speed = 2.0;
let mut rotation = CameraRotation::default();
rotation.sensitivity = 0.2;
Self { enabled: false, movement, rotation }
}
pub fn set_enabled(&mut self, enabled: bool) {
self.enabled = enabled;
}
pub fn handle_input(&mut self, event: &Event<()>) -> bool {
// Abort if not enabled
if !self.enabled { return false; }
match event {
Event::WindowEvent { ref event, .. } => {
match event {
WindowEvent::KeyboardInput { input: KeyboardInput { state, virtual_keycode: Some(keycode), .. }, .. } => {
let is_pressed = *state == ElementState::Pressed;
match keycode {
VirtualKeyCode::Q => { self.movement.down = is_pressed; true }
VirtualKeyCode::E | VirtualKeyCode::Space => { self.movement.up = is_pressed; true }
VirtualKeyCode::W | VirtualKeyCode::Up => { self.movement.fwd = is_pressed; true }
VirtualKeyCode::A | VirtualKeyCode::Left => { self.movement.left = is_pressed; true }
VirtualKeyCode::S | VirtualKeyCode::Down => { self.movement.back = is_pressed; true }
VirtualKeyCode::D | VirtualKeyCode::Right => { self.movement.right = is_pressed; true }
VirtualKeyCode::LShift => { self.movement.shift = is_pressed; true }
_ => false,
}
}
_ => false
}
},
Event::DeviceEvent { device_id: _, event } => {
match event {
DeviceEvent::MouseMotion { delta } => {
// Increment
self.rotation.yaw += delta.0 as f32 * self.rotation.sensitivity;
self.rotation.pitch -= delta.1 as f32 * self.rotation.sensitivity;
// Clamp
if self.rotation.yaw > 360.0 { self.rotation.yaw -= 360.0; }
if self.rotation.yaw < 0.0 { self.rotation.yaw += 360.0; }
self.rotation.pitch = self.rotation.pitch.clamp(-70.0, 70.0);
true
}
_ => false
}
}
_ => false
}
}
pub fn update_camera(&mut self, camera: &mut Camera, delta_time: f32) {
// Abort if not enabled
if !self.enabled { return; }
// Rotation
let yaw_rot = self.rotation.yaw_rot();
let pitch_rot = self.rotation.pitch_rot();
camera.forward = yaw_rot.transform_vector(pitch_rot.transform_vector(Vector3::unit_z()));
camera.up = yaw_rot.transform_vector(pitch_rot.transform_vector(Vector3::unit_y()));
// Movement amount
let mut amount = delta_time * self.movement.speed;
if self.movement.shift { amount *= 2.0; }
// Forward and backwards
if self.movement.fwd && camera.forward.magnitude() > amount { camera.position += camera.forward.normalize() * amount; }
if self.movement.back { camera.position -= camera.forward.normalize() * amount; }
// Up and down
if self.movement.up { camera.position += camera.up.normalize() * amount; }
if self.movement.down { camera.position -= camera.up.normalize() * amount; }
// Left and right
let right = camera.forward.cross(camera.up);
if self.movement.right { camera.position += right * amount; }
if self.movement.left { camera.position -= right * amount; }
}
}