diff options
Diffstat (limited to 'src/gfx')
-rw-r--r-- | src/gfx/camera.rs | 119 | ||||
-rw-r--r-- | src/gfx/debug_menu.rs | 13 |
2 files changed, 102 insertions, 30 deletions
diff --git a/src/gfx/camera.rs b/src/gfx/camera.rs index 874c9fc..32d39ad 100644 --- a/src/gfx/camera.rs +++ b/src/gfx/camera.rs @@ -1,57 +1,134 @@ use super::{gpu::Gpu, util::MatrixUniform}; -use cgmath::{prelude::*, Deg, Matrix4, Rad}; +use cgmath::{prelude::*, Deg, Euler, Matrix3, Matrix4, Point3, Rad, Vector3}; use collision::Frustum; -use fps_camera::{FirstPerson, FirstPersonSettings}; use std::time::Duration; +#[derive(Default)] +pub struct CameraInput { + pub forward: bool, + pub left: bool, + pub backward: bool, + pub right: bool, + pub jump: bool, + pub sneak: bool, + pub mouse_x: f32, + pub mouse_y: f32, +} + pub struct Camera { + pub pos: Point3<f32>, + pub rot: Euler<Deg<f32>>, + pub speed: f32, pub fov: Rad<f32>, pub view: Matrix4<f32>, pub proj: Matrix4<f32>, pub frustum: Frustum<f32>, - pub first_person: FirstPerson, pub uniform: MatrixUniform, pub layout: wgpu::BindGroupLayout, + pub input: CameraInput, +} + +pub trait ToNative { + fn to_native(self) -> Self; +} + +impl<T> ToNative for Euler<T> +where + T: From<Deg<f32>> + std::ops::Add<T, Output = T> + std::ops::Neg<Output = T>, +{ + fn to_native(mut self) -> Self { + self.y = -self.y + Deg(270.0).into(); + self.z = -self.z; + self + } } impl Camera { pub fn new(gpu: &Gpu) -> Self { - let first_person = FirstPerson::new( - [0.0, 0.0, 0.0], - FirstPersonSettings { - speed_horizontal: 10.0, - speed_vertical: 10.0, - mouse_sensitivity_horizontal: 1.0, - mouse_sensitivity_vertical: 1.0, - }, - ); - let layout = MatrixUniform::layout(&gpu.device, "camera"); let uniform = MatrixUniform::new(&gpu.device, &layout, Matrix4::identity(), "camera", true); Self { + pos: Point3::new(0.0, 0.0, 0.0), + rot: Euler { + x: Deg(0.0), + y: Deg(0.0), + z: Deg(0.0), + }, + speed: 0.0, fov: Deg(90.0).into(), proj: Matrix4::identity(), view: Matrix4::identity(), frustum: Frustum::from_matrix4(Matrix4::identity()).unwrap(), - first_person, uniform, layout, + input: Default::default(), } } pub fn update(&mut self, gpu: &Gpu, dt: Duration) { - self.first_person.yaw += Rad::from(Deg(180.0)).0; - self.first_person.yaw *= -1.0; + let dt = dt.as_secs_f32(); + + let sensitivity = dt * 2.0; + + self.rot.y += Deg(sensitivity * self.input.mouse_x); + self.rot.z += Deg(sensitivity * self.input.mouse_y); + self.rot.z.0 = self.rot.z.0.min(89.9).max(-89.9); + + self.input.mouse_x = 0.0; + self.input.mouse_y = 0.0; + + let rot = Matrix3::from(self.rot.to_native()); - let cam = self.first_person.camera(dt.as_secs_f32()); + let forward = rot * Vector3::unit_x(); + let up = rot * Vector3::unit_y(); - self.first_person.yaw *= -1.0; - self.first_person.yaw -= Rad::from(Deg(180.0)).0; + { + let mut forward = forward; + let mut up = up; + let mut right = forward.cross(up); - self.first_person.position = cam.position; + let pitch_move = false; + + if !pitch_move { + forward.y = 0.0; + right.y = 0.0; + up = Vector3::unit_y(); + } + + let mut hdir = Vector3::zero(); + let mut vdir = Vector3::zero(); + + if self.input.forward { + hdir += forward; + } + if self.input.backward { + hdir -= forward; + } + if self.input.right { + hdir += right; + } + if self.input.left { + hdir -= right; + } + if self.input.jump { + vdir += up; + } + if self.input.sneak { + vdir -= up; + } + + self.pos += self.speed + * dt + * (vdir + + if hdir.is_zero() { + hdir + } else { + hdir.normalize() + }); + } - self.view = Matrix4::from(cam.orthogonal()); + self.view = Matrix4::look_at_dir(self.pos, forward, up); self.uniform.set(&gpu.queue, self.proj * self.view); } diff --git a/src/gfx/debug_menu.rs b/src/gfx/debug_menu.rs index daca08d..4baf0f1 100644 --- a/src/gfx/debug_menu.rs +++ b/src/gfx/debug_menu.rs @@ -1,5 +1,4 @@ use super::{camera::Camera, font::Font}; -use cgmath::{Deg, Rad}; use wgpu_glyph::{Section, Text}; pub struct DebugMenu { @@ -37,21 +36,17 @@ impl DebugMenu { offset += 20.0; }; - let angle = |x| Deg::from(Rad(x)).0; - - let pos = camera.first_person.position; - add_text(&format!( "{} {}", env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION") )); add_text(&format!("{} FPS", self.fps)); - add_text(&format!("({:.1}, {:.1}, {:.1})", pos[0], pos[1], pos[2])); add_text(&format!( - "yaw: {:.1}°", - (angle(camera.first_person.yaw) + 360.0) % 360.0 + "({:.1}, {:.1}, {:.1})", + camera.pos.x, camera.pos.y, camera.pos.z )); - add_text(&format!("pitch: {:.1}°", angle(camera.first_person.pitch))); + add_text(&format!("yaw: {:.1}°", (camera.rot.y.0 + 360.0) % 360.0)); + add_text(&format!("pitch: {:.1}°", camera.rot.z.0)); } } |