125 lines
4.8 KiB
Rust
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; }
|
|
|
|
|
|
}
|
|
}
|