summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock60
-rw-r--r--Cargo.toml4
-rw-r--r--src/gfx.rs73
-rw-r--r--src/gfx/camera.rs119
-rw-r--r--src/gfx/debug_menu.rs13
-rw-r--r--src/main.rs1
-rw-r--r--src/net.rs5
7 files changed, 157 insertions, 118 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 132816f..53b0862 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -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",
diff --git a/Cargo.toml b/Cargo.toml
index e4d5af9..941d3eb 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -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"
diff --git a/src/gfx.rs b/src/gfx.rs
index c465baa..2c4a219 100644
--- a/src/gfx.rs
+++ b/src/gfx.rs
@@ -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)]
diff --git a/src/net.rs b/src/net.rs
index 78597c1..2598651 100644
--- a/src/net.rs
+++ b/src/net.rs
@@ -245,6 +245,11 @@ impl Conn {
ChatMsg { text, .. } => {
println!("{text}");
}
+ Movement { walk_speed, .. } => {
+ self.events
+ .send_event(GfxEvent::MovementSpeed(walk_speed))
+ .ok();
+ }
_ => {}
}
}