First draft for FreeSpaceControl

This commit is contained in:
Michael Huebner 2025-03-11 13:33:01 +01:00
parent 3835354503
commit 75d98aad6b
3 changed files with 165 additions and 11 deletions

View file

@ -0,0 +1,158 @@
use context::prelude::cgmath::*;
use std::time::Duration;
pub struct FreeSpaceControlSettings {
/// m / s^2
pub max_forward_acceleration: f32,
/// m / s^2
pub max_forward_deceleration: f32,
/// m / s^2
/// up, down, left, right
pub max_strafe_acceleration: f32,
/// ° / s^2
pub max_yaw_acceleration: Deg<f32>,
/// ° / s^2
pub max_pitch_acceleration: Deg<f32>,
/// ° / s^2
pub max_roll_acceleration: Deg<f32>,
}
impl Default for FreeSpaceControlSettings {
fn default() -> Self {
Self {
max_forward_acceleration: 50.0,
max_forward_deceleration: 10.0,
max_strafe_acceleration: 5.0,
max_yaw_acceleration: Deg(5.0),
max_pitch_acceleration: Deg(5.0),
max_roll_acceleration: Deg(5.0),
}
}
}
pub struct FreeSpaceControl {
settings: FreeSpaceControlSettings,
/// (yaw, pitch, roll)
rotation: Vector3<Deg<f32>>,
position: Vector3<f32>,
/// (yaw, pitch, roll)
input_rotation: Vector3<f32>,
/// (forward, sideward, upward)
input_position: Vector3<f32>,
last_update: Option<Duration>,
}
impl FreeSpaceControl {
pub fn new(settings: FreeSpaceControlSettings) -> Self {
Self {
settings,
rotation: vec3(Deg(0.0), Deg(0.0), Deg(0.0)),
position: Vector3::zero(),
input_rotation: Vector3::zero(),
input_position: Vector3::zero(),
last_update: None,
}
}
pub fn replace_settings(&mut self, settings: FreeSpaceControlSettings) {
self.settings = settings;
}
pub fn set_throttle(&mut self, throttle: f32) {
debug_assert!(-1.0 <= throttle);
debug_assert!(throttle <= 1.0);
self.input_position.y = throttle;
}
pub fn set_left_right_strafe(&mut self, strafe: f32) {
debug_assert!(-1.0 <= strafe);
debug_assert!(strafe <= 1.0);
self.input_position.x = strafe;
}
pub fn set_up_down_strafe(&mut self, strafe: f32) {
debug_assert!(-1.0 <= strafe);
debug_assert!(strafe <= 1.0);
self.input_position.z = strafe;
}
pub fn set_yaw(&mut self, yaw: f32) {
debug_assert!(-1.0 <= yaw);
debug_assert!(yaw <= 1.0);
self.input_rotation.x = yaw;
}
pub fn set_pitch(&mut self, pitch: f32) {
debug_assert!(-1.0 <= pitch);
debug_assert!(pitch <= 1.0);
self.input_rotation.y = pitch;
}
pub fn set_roll(&mut self, roll: f32) {
debug_assert!(-1.0 <= roll);
debug_assert!(roll <= 1.0);
self.input_rotation.z = roll;
}
fn add_rotation(&mut self, rotation: Vector3<Deg<f32>>) {
self.rotation.x += rotation.x;
self.rotation.y += rotation.y;
self.rotation.z += rotation.z;
}
fn rotation_matrix(&self) -> Matrix3<f32> {
Matrix3::from_angle_z(self.rotation.x)
* Matrix3::from_angle_y(self.rotation.y)
* Matrix3::from_angle_x(self.rotation.z)
}
pub fn update(&mut self, now: Duration) -> Option<Matrix4<f32>> {
let diff = match self.last_update {
Some(last_update) => now - last_update,
None => {
self.last_update = Some(now);
return None;
}
};
let (rotation_changes, position_changes) = self.calculate_tick_changes(diff);
let rotated_position_changes = self.rotation_matrix() * position_changes;
self.add_rotation(rotation_changes);
self.position += rotated_position_changes;
Some(Matrix4::from(self.rotation_matrix()) * Matrix4::from_translation(self.position))
}
#[rustfmt::skip]
fn calculate_tick_changes(&self, diff: Duration) -> (Vector3<Deg<f32>>, Vector3<f32>) {
(
vec3(
Deg(diff.as_secs_f32() * self.input_rotation.x * self.settings.max_yaw_acceleration.0),
Deg(diff.as_secs_f32() * self.input_rotation.y * self.settings.max_pitch_acceleration.0),
Deg(diff.as_secs_f32() * self.input_rotation.z * self.settings.max_roll_acceleration.0),
),
vec3(
diff.as_secs_f32() * self.input_position.x * self.settings.max_strafe_acceleration,
diff.as_secs_f32() * self.input_position.y * if self.input_position.y > 0.0 { self.settings.max_forward_acceleration } else { self.settings.max_forward_deceleration },
diff.as_secs_f32() * self.input_position.z * self.settings.max_strafe_acceleration,
)
)
}
}

View file

@ -1,14 +1,9 @@
pub mod camera; pub mod camera;
pub mod light;
pub mod validcommandbuffer;
pub mod view;
pub mod top_down_camera_control;
pub mod view_frustum;
pub mod free_camera_control; pub mod free_camera_control;
pub mod free_space_control;
pub mod light;
pub mod prelude; pub mod prelude;
pub mod top_down_camera_control;
pub mod validcommandbuffer;
pub mod view;
pub mod view_frustum;

View file

@ -1,5 +1,6 @@
pub use super::camera::*; pub use super::camera::*;
pub use super::free_camera_control::*; pub use super::free_camera_control::*;
pub use super::free_space_control::*;
pub use super::light::*; pub use super::light::*;
pub use super::top_down_camera_control::*; pub use super::top_down_camera_control::*;
pub use super::validcommandbuffer::*; pub use super::validcommandbuffer::*;