From a50b95de09a4de3ffc182741e5e412d3fa0f10de Mon Sep 17 00:00:00 2001 From: Avery Date: Tue, 1 Apr 2025 10:42:28 +0200 Subject: [PATCH 1/2] Fixed movement controller, nix flake --- flake.lock | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++ flake.nix | 33 +++++++++++++++++++++++++++++ src/main.rs | 22 ++++++++++++++----- 3 files changed, 111 insertions(+), 5 deletions(-) create mode 100644 flake.lock create mode 100644 flake.nix diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..f49fde0 --- /dev/null +++ b/flake.lock @@ -0,0 +1,61 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1743315132, + "narHash": "sha256-6hl6L/tRnwubHcA4pfUUtk542wn2Om+D4UnDhlDW9BE=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "52faf482a3889b7619003c0daec593a1912fddc1", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..24242cb --- /dev/null +++ b/flake.nix @@ -0,0 +1,33 @@ +{ + inputs = { + nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable"; + + flake-utils.url = "github:numtide/flake-utils"; + }; + + outputs = { + self, + nixpkgs, + flake-utils, + } @ inputs: + flake-utils.lib.eachDefaultSystem (system: let + pkgs = import nixpkgs { + inherit system; + }; + lib = nixpkgs.lib; + in { + devShells.default = pkgs.mkShell { + VULKAN_SDK = "${pkgs.vulkan-validation-layers}/share/vulkan/explicit_layer.d"; + # LD_LIBRARY_PATH = "$LD_LIBRARY_PATH:${pkgs.SDL2}/lib/"; + LD_LIBRARY_PATH = lib.makeLibraryPath (with pkgs; [SDL2 vulkan-loader]); + buildInputs = with pkgs; [ + SDL2 + SDL2.dev + vulkan-headers + vulkan-loader + vulkan-validation-layers # maybe? + # glm and whatnot … + ]; + }; + }); +} diff --git a/src/main.rs b/src/main.rs index ee497da..1d7bcf5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,6 +9,9 @@ use ash::vk; use std::ffi::CStr; use std::ffi::CString; +use std::thread; +use std::time::Duration; +use std::time::Instant; use raw_window_handle::HasDisplayHandle; use raw_window_handle::HasWindowHandle; @@ -1146,6 +1149,7 @@ fn main() { let mut running = true; while running { + let now = Instant::now(); for event in event_pump.poll_iter() { match event { Event::Quit { .. } => running = false, @@ -1156,7 +1160,8 @@ fn main() { width = w as u32; height = h as u32; unsafe { - dev.device_wait_idle().expect("Failed to wait for device idle"); + dev.device_wait_idle() + .expect("Failed to wait for device idle"); swapchain_loader.destroy_swapchain(swapchain, None); } (swapchain, extents) = setup_swapchain( @@ -1183,13 +1188,16 @@ fn main() { framebufs = make_framebufs(&dev, &swap_views, &depth_view, &pass, width, height); } - Event::KeyDown { - keycode: Some(keycode), - .. - } => handle_key(keycode, &mut camera), _ => {} } } + + event_pump + .keyboard_state() + .pressed_scancodes() + .filter_map(Keycode::from_scancode) + .for_each(|k| handle_key(k, &mut camera)); + wait_for_fence(&dev, &fence_flight); reset_fence(&dev, &fence_flight); @@ -1227,5 +1235,9 @@ fn main() { ); queue_present(&swapchain_loader, &queue, &swapchain, img_inx, &sem_finish); + + let elapsed = now.elapsed(); + let delay = (1000_0000u128 / 240).saturating_sub(elapsed.as_micros()); + thread::sleep(Duration::from_micros(delay as u64)); } } -- 2.39.1 From d7615e56580361e7da41084ed9dd68e861705a1d Mon Sep 17 00:00:00 2001 From: Avery Date: Sun, 13 Apr 2025 13:47:19 +0200 Subject: [PATCH 2/2] New movement controller --- src/main.rs | 88 +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 55 insertions(+), 33 deletions(-) diff --git a/src/main.rs b/src/main.rs index 1d7bcf5..f22341d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,7 +6,9 @@ use ash::Entry; use ash::Instance; use ash::khr::{surface, swapchain}; use ash::vk; +use sdl2::mouse::MouseUtil; +use std::cmp; use std::ffi::CStr; use std::ffi::CString; use std::thread; @@ -23,6 +25,13 @@ use sdl2::video::Window; const APP_NAME: &str = "MineClone"; +const MOV_STEP: f32 = 0.05; +const ROT_STEP: f32 = 0.05; +const ROT_MOUSE_SCALE: f32 = 0.001; + +const MAX_WIDTH: u32 = 3440; +const MAX_HEIGHT: u32 = 1440; + const MESH_SIZE: u64 = 36 * 2 * 4 * 4; const POSITIONS: [f32; 36 * 2 * 4] = [ @@ -571,8 +580,8 @@ fn setup_swapchain( .image_format(format.format) .image_color_space(format.color_space) .image_extent(vk::Extent2D { - width: std::cmp::max(caps.current_extent.width, width), - height: std::cmp::max(caps.current_extent.height, height), + width: cmp::min(cmp::max(caps.current_extent.width, width), MAX_WIDTH), + height: cmp::min(cmp::max(caps.current_extent.height, height), MAX_HEIGHT), }) .image_array_layers(1) .image_usage(vk::ImageUsageFlags::COLOR_ATTACHMENT) @@ -956,43 +965,29 @@ struct Camera { rotation: Vector3, } -fn handle_key(keycode: Keycode, camera: &mut Camera) { - let mov_scale = 0.05; - let rot_scale = 0.05; +fn handle_cont_key(keycode: Keycode, camera: &mut Camera, mouse: &MouseUtil) { match keycode { Keycode::W => { - camera.origin.x -= -camera.rotation.y.sin() * mov_scale; - camera.origin.z -= camera.rotation.y.cos() * mov_scale; + camera.origin.x -= -camera.rotation.y.sin() * MOV_STEP; + camera.origin.z -= camera.rotation.y.cos() * MOV_STEP; } Keycode::S => { - camera.origin.x += -camera.rotation.y.sin() * mov_scale; - camera.origin.z += camera.rotation.y.cos() * mov_scale; + camera.origin.x += -camera.rotation.y.sin() * MOV_STEP; + camera.origin.z += camera.rotation.y.cos() * MOV_STEP; } Keycode::A => { - camera.origin.x += camera.rotation.y.cos() * mov_scale; - camera.origin.z += camera.rotation.y.sin() * mov_scale; + camera.origin.x += camera.rotation.y.cos() * MOV_STEP; + camera.origin.z += camera.rotation.y.sin() * MOV_STEP; } Keycode::D => { - camera.origin.z -= camera.rotation.y.sin() * mov_scale; - camera.origin.x -= camera.rotation.y.cos() * mov_scale; - } - Keycode::R => { - camera.rotation.x += rot_scale; - } - Keycode::F => { - camera.rotation.x -= rot_scale; - } - Keycode::Q => { - camera.rotation.y += rot_scale; - } - Keycode::E => { - camera.rotation.y -= rot_scale; + camera.origin.z -= camera.rotation.y.sin() * MOV_STEP; + camera.origin.x -= camera.rotation.y.cos() * MOV_STEP; } Keycode::Space => { - camera.origin.y += mov_scale; + camera.origin.y += MOV_STEP; } Keycode::LShift => { - camera.origin.y -= mov_scale; + camera.origin.y -= MOV_STEP; } _ => {} } @@ -1001,20 +996,21 @@ fn handle_key(keycode: Keycode, camera: &mut Camera) { fn main() { let sdl_context = sdl2::init().unwrap(); let video_subsystem = sdl_context.video().unwrap(); + let mouse = sdl_context.mouse(); let mut width = 1024; let mut height = 768; - let max_width = 3440; - let max_height = 1440; - - let window = video_subsystem + let mut window = video_subsystem .window(APP_NAME, width, height) .vulkan() .resizable() .build() .unwrap(); + // We start in relative move + mouse.set_relative_mouse_mode(true); + let entry = Entry::linked(); let instance = create_instance(&window, &entry); @@ -1046,7 +1042,11 @@ fn main() { let mesh_mem = mem_alloc(&dev, host_visible_inx, MESH_SIZE); // Max viewport size is 3440x1440 - let depth_mem = mem_alloc(&dev, host_invisible_inx, max_width * max_height * 8); + let depth_mem = mem_alloc( + &dev, + host_invisible_inx, + (MAX_WIDTH * MAX_HEIGHT * 8) as u64, + ); let mut depth_img = make_depth_img( &dev, @@ -1188,6 +1188,28 @@ fn main() { framebufs = make_framebufs(&dev, &swap_views, &depth_view, &pass, width, height); } + // We do this key here and not in `handle_cont_key()` because we don't want key + // repeat, just a single press + Event::KeyDown { + keycode: Some(Keycode::ESCAPE), + repeat: false, + .. + } => { + mouse.set_relative_mouse_mode(!mouse.relative_mouse_mode()); + } + Event::MouseMotion { + window_id, + xrel, + yrel, + .. + } + // We only wanna do movement if the mouse is in relative mode (ie. its pinned to + // the center of the window and hidden) + if mouse.relative_mouse_mode() => { + camera.rotation.y -= xrel as f32 * ROT_MOUSE_SCALE; + camera.rotation.x += yrel as f32 * ROT_MOUSE_SCALE; + mouse.warp_mouse_in_window(&window, width as i32 / 2, height as i32 / 2); + } _ => {} } } @@ -1196,7 +1218,7 @@ fn main() { .keyboard_state() .pressed_scancodes() .filter_map(Keycode::from_scancode) - .for_each(|k| handle_key(k, &mut camera)); + .for_each(|k| handle_cont_key(k, &mut camera, &mouse)); wait_for_fence(&dev, &fence_flight); reset_fence(&dev, &fence_flight); -- 2.39.1