First draft for FreeSpaceControl
This commit is contained in:
parent
3835354503
commit
75d98aad6b
3 changed files with 165 additions and 11 deletions
158
engine/src/scene/general/free_space_control.rs
Normal file
158
engine/src/scene/general/free_space_control.rs
Normal 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,
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
|
@ -1,14 +1,9 @@
|
|||
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_space_control;
|
||||
pub mod light;
|
||||
pub mod prelude;
|
||||
pub mod top_down_camera_control;
|
||||
pub mod validcommandbuffer;
|
||||
pub mod view;
|
||||
pub mod view_frustum;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
pub use super::camera::*;
|
||||
pub use super::free_camera_control::*;
|
||||
pub use super::free_space_control::*;
|
||||
pub use super::light::*;
|
||||
pub use super::top_down_camera_control::*;
|
||||
pub use super::validcommandbuffer::*;
|
||||
|
|
Loading…
Reference in a new issue