diff options
-rw-r--r-- | Cargo.lock | 60 | ||||
-rw-r--r-- | Cargo.toml | 4 | ||||
-rw-r--r-- | src/gfx.rs | 73 | ||||
-rw-r--r-- | src/gfx/camera.rs | 119 | ||||
-rw-r--r-- | src/gfx/debug_menu.rs | 13 | ||||
-rw-r--r-- | src/main.rs | 1 | ||||
-rw-r--r-- | src/net.rs | 5 |
7 files changed, 157 insertions, 118 deletions
@@ -628,17 +628,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] -name = "fps-camera" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60c7ada020a020615930e1faeb0a4106b1d327bad75498ae06a1ea9063b1e9b3" -dependencies = [ - "bitflags", - "piston3d-cam", - "vecmath", -] - -[[package]] name = "fps_counter" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1180,7 +1169,6 @@ dependencies = [ "cgmath", "collision", "crossbeam-channel", - "fps-camera", "fps_counter", "futures", "guillotiere", @@ -1193,7 +1181,6 @@ dependencies = [ "serde_yaml", "sha2", "srp", - "threadpool", "tokio", "wgpu", "wgpu_glyph", @@ -1620,22 +1607,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] -name = "piston-float" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b058c3a640efd4bcf63266512e4bb03187192c1b29edd38b16d5a014613e3199" - -[[package]] -name = "piston3d-cam" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6153024c02c4d09e3193ce0eb63abc585fda3389de375bbd41f059b91f2c520a" -dependencies = [ - "quaternion", - "vecmath", -] - -[[package]] name = "pkg-config" version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1685,15 +1656,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74605f360ce573babfe43964cbe520294dcb081afbf8c108fc6e23036b4da2df" [[package]] -name = "quaternion" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5598168e2776e6000e53955f69d238183160199a2c43375e3aa0f74bd34e675" -dependencies = [ - "vecmath", -] - -[[package]] name = "quote" version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2213,15 +2175,6 @@ dependencies = [ ] [[package]] -name = "threadpool" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" -dependencies = [ - "num_cpus", -] - -[[package]] name = "tiny-skia" version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2357,15 +2310,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" [[package]] -name = "vecmath" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bdd6034ee9c1e5e12485f3e4120e12777f6c81cf43bf9a73bff98ed2b479afe" -dependencies = [ - "piston-float", -] - -[[package]] name = "version_check" version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2778,9 +2722,9 @@ checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" [[package]] name = "winit" -version = "0.28.1" +version = "0.28.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4755d4ba0e3d30fc7beef2095e246b1e6a6fad0717608bcb87a2df4b003bcf" +checksum = "866db3f712fffba75d31bf0cdecf357c8aeafd158c5b7ab51dba2a2b2d47f196" dependencies = [ "android-activity", "bitflags", @@ -14,7 +14,6 @@ bytemuck = { version = "1.13.0", features = ["derive"] } cgmath = "0.17.0" collision = "0.20.1" crossbeam-channel = "0.5.8" -fps-camera = "0.1.2" fps_counter = "2.0.0" futures = { version = "0.3.26" } guillotiere = "0.6.2" @@ -27,8 +26,7 @@ serde = { version = "1.0.159", features = ["derive"] } serde_yaml = "0.9.21" sha2 = "0.10.6" srp = { git = "https://github.com/minetest-rust/PAKEs.git" } -threadpool = "1.8.1" tokio = { version = "1.25.0", features = ["rt", "rt-multi-thread", "signal"] } wgpu = "0.15.1" wgpu_glyph = "0.19.0" -winit = "0.28.1" +winit = "0.28.6" @@ -1,11 +1,11 @@ use crate::{GfxEvent::*, NetEvent}; -use cgmath::Rad; use std::time::Instant; use tokio::sync::mpsc; use winit::{ event::{DeviceEvent::*, Event::*, WindowEvent::*}, event_loop::ControlFlow::ExitWithCode, platform::run_return::EventLoopExtRunReturn, + window::CursorGrabMode, }; mod camera; @@ -38,6 +38,22 @@ pub async fn run( let mut fps_counter = fps_counter::FPSCounter::new(); let mut game_paused = false; + let update_cursor_mode = |game_paused| { + let modes: &[CursorGrabMode] = if game_paused { + &[CursorGrabMode::None] + } else { + &[CursorGrabMode::Confined, CursorGrabMode::Locked] + }; + + for mode in modes { + if window.set_cursor_grab(*mode).is_ok() { + return; + } + } + }; + + update_cursor_mode(game_paused); + event_loop.run_return(|event, _, flow| match event { MainEventsCleared => window.request_redraw(), RedrawRequested(id) if id == window.id() => { @@ -52,11 +68,7 @@ pub async fn run( } net_events - .send(NetEvent::PlayerPos( - camera.first_person.position.into(), - Rad(camera.first_person.yaw).into(), - Rad(camera.first_person.pitch).into(), - )) + .send(NetEvent::PlayerPos(camera.pos, camera.rot.y, camera.rot.z)) .ok(); let mut render = || { @@ -91,6 +103,7 @@ pub async fn run( event, window_id: id, } if id == window.id() => match event { + Focused(false) => camera.input = Default::default(), CloseRequested => *flow = ExitWithCode(0), Resized(size) | ScaleFactorChanged { @@ -109,12 +122,20 @@ pub async fn run( }, .. } => { - use fps_camera::Actions; use winit::event::{ElementState, VirtualKeyCode as Key}; if key == Key::Escape && key_state == ElementState::Pressed { game_paused = !game_paused; window.set_cursor_visible(game_paused); + update_cursor_mode(game_paused); + + if game_paused { + camera.input = Default::default(); + } + } + + if game_paused { + return; } if key == Key::F3 && key_state == ElementState::Pressed { @@ -122,20 +143,15 @@ pub async fn run( } if !game_paused { - let actions = match key { - Key::W => Actions::MOVE_FORWARD, - Key::A => Actions::STRAFE_LEFT, - Key::S => Actions::MOVE_BACKWARD, - Key::D => Actions::STRAFE_RIGHT, - Key::Space => Actions::FLY_UP, - Key::LShift => Actions::FLY_DOWN, - _ => Actions::empty(), - }; - - match key_state { - ElementState::Pressed => camera.first_person.enable_actions(actions), - ElementState::Released => camera.first_person.disable_action(actions), - } + *(match key { + Key::W => &mut camera.input.forward, + Key::A => &mut camera.input.left, + Key::S => &mut camera.input.backward, + Key::D => &mut camera.input.right, + Key::Space => &mut camera.input.jump, + Key::LShift => &mut camera.input.sneak, + _ => return, + }) = key_state == ElementState::Pressed; } } _ => {} @@ -145,9 +161,9 @@ pub async fn run( .. } => { if !game_paused { - camera - .first_person - .update_mouse(-delta.0 as f32, delta.1 as f32); + camera.input.mouse_x += delta.0 as f32; + camera.input.mouse_y += delta.1 as f32; + window .set_cursor_position(winit::dpi::PhysicalPosition::new( gpu.config.width / 2, @@ -179,9 +195,12 @@ pub async fn run( } } PlayerPos(pos, pitch, yaw) => { - camera.first_person.position = pos.into(); - camera.first_person.pitch = Rad::<f32>::from(pitch).0; - camera.first_person.yaw = Rad::<f32>::from(yaw).0; + camera.pos = pos; + camera.rot.y = yaw; + camera.rot.z = pitch; + } + MovementSpeed(speed) => { + camera.speed = speed; } }, _ => {} 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)); } } diff --git a/src/main.rs b/src/main.rs index 759a5bf..037cacb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -14,6 +14,7 @@ pub enum GfxEvent { NodeDefs(HashMap<u16, mt_net::NodeDef>), MapBlock(Point3<i16>, Box<mt_net::MapBlock>), PlayerPos(Point3<f32>, Deg<f32>, Deg<f32>), + MovementSpeed(f32), } #[derive(Debug, Clone)] @@ -245,6 +245,11 @@ impl Conn { ChatMsg { text, .. } => { println!("{text}"); } + Movement { walk_speed, .. } => { + self.events + .send_event(GfxEvent::MovementSpeed(walk_speed)) + .ok(); + } _ => {} } } |