rendering, physics, player and camera WIP

This commit is contained in:
Jonas H
2026-01-01 19:54:00 +01:00
commit 5d2eca0393
51 changed files with 8734 additions and 0 deletions

188
src/utility/input.rs Executable file
View File

@@ -0,0 +1,188 @@
use glam::Vec2;
use sdl3::{event::Event, keyboard::Keycode};
pub struct InputState
{
pub w: bool,
pub a: bool,
pub s: bool,
pub d: bool,
pub space: bool,
pub shift: bool,
pub space_just_pressed: bool,
pub noclip_just_pressed: bool,
pub mouse_delta: (f32, f32),
pub mouse_captured: bool,
pub noclip_mode: bool,
pub quit_requested: bool,
}
impl InputState
{
pub fn new() -> Self
{
Self {
w: false,
a: false,
s: false,
d: false,
space: false,
shift: false,
space_just_pressed: false,
noclip_just_pressed: false,
mouse_delta: (0.0, 0.0),
mouse_captured: true,
noclip_mode: false,
quit_requested: false,
}
}
pub fn handle_event(&mut self, event: &Event) -> bool
{
match event
{
Event::Quit { .. } =>
{
self.quit_requested = true;
return true;
}
Event::KeyDown {
keycode: Some(key),
repeat,
..
} =>
{
if !repeat
{
self.handle_keydown(*key);
if *key == Keycode::Escape
{
self.quit_requested = true;
return true;
}
if *key == Keycode::I
{
self.mouse_captured = !self.mouse_captured;
return true;
}
}
}
Event::KeyUp {
keycode: Some(key), ..
} =>
{
self.handle_keyup(*key);
}
Event::MouseMotion { xrel, yrel, .. } =>
{
self.handle_mouse_motion(*xrel as f32, *yrel as f32);
}
_ =>
{}
}
false
}
pub fn handle_keydown(&mut self, key: Keycode)
{
match key
{
Keycode::W => self.w = true,
Keycode::A => self.a = true,
Keycode::S => self.s = true,
Keycode::D => self.d = true,
Keycode::Space =>
{
if !self.space
{
self.space_just_pressed = true;
}
self.space = true;
}
Keycode::LShift | Keycode::RShift => self.shift = true,
Keycode::N => self.noclip_just_pressed = true,
_ =>
{}
}
}
pub fn handle_keyup(&mut self, key: Keycode)
{
match key
{
Keycode::W => self.w = false,
Keycode::A => self.a = false,
Keycode::S => self.s = false,
Keycode::D => self.d = false,
Keycode::Space => self.space = false,
Keycode::LShift | Keycode::RShift => self.shift = false,
_ =>
{}
}
}
pub fn handle_mouse_motion(&mut self, xrel: f32, yrel: f32)
{
if self.mouse_captured
{
self.mouse_delta = (xrel, yrel);
}
}
pub fn process_post_events(&mut self)
{
if self.noclip_just_pressed
{
self.noclip_mode = !self.noclip_mode;
println!(
"Noclip mode: {}",
if self.noclip_mode { "ON" } else { "OFF" }
);
}
}
pub fn clear_just_pressed(&mut self)
{
self.space_just_pressed = false;
self.noclip_just_pressed = false;
self.mouse_delta = (0.0, 0.0);
}
pub fn get_movement_input(&self) -> Vec2
{
let mut input = Vec2::ZERO;
if self.w
{
input.y += 1.0;
}
if self.s
{
input.y -= 1.0;
}
if self.a
{
input.x -= 1.0;
}
if self.d
{
input.x += 1.0;
}
if input.length_squared() > 1.0
{
input = input.normalize();
}
input
}
}

3
src/utility/mod.rs Normal file
View File

@@ -0,0 +1,3 @@
pub(crate) mod input;
pub(crate) mod time;
pub(crate) mod transform;

22
src/utility/time.rs Normal file
View File

@@ -0,0 +1,22 @@
use std::sync::OnceLock;
use std::time::Instant;
static GAME_START: OnceLock<Instant> = OnceLock::new();
pub struct Time;
impl Time
{
pub fn init()
{
GAME_START.get_or_init(Instant::now);
}
pub fn get_time_elapsed() -> f32
{
GAME_START
.get()
.map(|start| start.elapsed().as_secs_f32())
.unwrap_or(0.0)
}
}

143
src/utility/transform.rs Normal file
View File

@@ -0,0 +1,143 @@
use glam::{Mat4, Quat, Vec3};
use nalgebra::{self as na, Isometry3};
#[derive(Copy, Clone, Debug)]
pub struct Transform
{
pub position: Vec3,
pub rotation: Quat,
pub scale: Vec3,
}
impl Transform
{
pub const IDENTITY: Self = Self {
position: Vec3::ZERO,
rotation: Quat::IDENTITY,
scale: Vec3::ONE,
};
pub fn from_position(position: Vec3) -> Self
{
Self::IDENTITY.translated(position)
}
pub fn to_matrix(&self) -> Mat4
{
Mat4::from_scale_rotation_translation(self.scale, self.rotation, self.position)
}
pub fn get_matrix(&self) -> Mat4
{
self.to_matrix()
}
pub fn translated(mut self, new_position: Vec3) -> Self
{
self.set_position(new_position);
self
}
pub fn get_position(&self) -> Vec3
{
self.position
}
pub fn set_position(&mut self, position: Vec3)
{
self.position = position;
}
pub fn set_rotation(&mut self, rotation: Quat)
{
self.rotation = rotation;
}
pub fn set_scale(&mut self, scale: Vec3)
{
self.scale = scale;
}
pub fn set_uniform_scale(&mut self, scale: f32)
{
self.scale = Vec3::splat(scale);
}
pub fn set_matrix(&mut self, matrix: Mat4)
{
let (scale, rotation, translation) = matrix.to_scale_rotation_translation();
self.position = translation;
self.rotation = rotation;
self.scale = scale;
}
}
impl Default for Transform
{
fn default() -> Self
{
Self::IDENTITY
}
}
impl From<Transform> for Mat4
{
fn from(t: Transform) -> Self
{
t.to_matrix()
}
}
impl From<&Transform> for Mat4
{
fn from(t: &Transform) -> Self
{
t.to_matrix()
}
}
impl From<Transform> for Isometry3<f32>
{
fn from(t: Transform) -> Self
{
let translation = na::Vector3::new(t.position.x, t.position.y, t.position.z);
let rotation = na::UnitQuaternion::from_quaternion(na::Quaternion::new(
t.rotation.w,
t.rotation.x,
t.rotation.y,
t.rotation.z,
));
Isometry3::from_parts(translation.into(), rotation)
}
}
impl From<&Transform> for Isometry3<f32>
{
fn from(t: &Transform) -> Self
{
(*t).into()
}
}
impl From<Isometry3<f32>> for Transform
{
fn from(iso: Isometry3<f32>) -> Self
{
let pos = iso.translation.vector;
let rot = iso.rotation;
Self {
position: Vec3::new(pos.x, pos.y, pos.z),
rotation: Quat::from_xyzw(rot.i, rot.j, rot.k, rot.w),
scale: Vec3::ONE,
}
}
}
impl From<&Isometry3<f32>> for Transform
{
fn from(iso: &Isometry3<f32>) -> Self
{
(*iso).into()
}
}