diff options
| author | HampusM <hampus@hampusmat.com> | 2024-04-16 23:01:40 +0200 | 
|---|---|---|
| committer | HampusM <hampus@hampusmat.com> | 2024-04-16 23:01:40 +0200 | 
| commit | 188c413d6693b3e649820e3f6d9f0842ebba0ce3 (patch) | |
| tree | 456d10124fa2aff37c1040b29d6edae099637dab | |
| parent | 67d6f1914af5aace3084bb943b00b454a55451ab (diff) | |
feat(engine): add fly camera extension
| -rw-r--r-- | engine/src/camera.rs | 2 | ||||
| -rw-r--r-- | engine/src/camera/fly.rs | 140 | 
2 files changed, 142 insertions, 0 deletions
diff --git a/engine/src/camera.rs b/engine/src/camera.rs index 640c1f4..5b71e2f 100644 --- a/engine/src/camera.rs +++ b/engine/src/camera.rs @@ -3,6 +3,8 @@ use ecs::Component;  use crate::projection::{Perspective, Projection};  use crate::vector::Vec3; +pub mod fly; +  #[derive(Debug, Component)]  pub struct Camera  { diff --git a/engine/src/camera/fly.rs b/engine/src/camera/fly.rs new file mode 100644 index 0000000..7fa435b --- /dev/null +++ b/engine/src/camera/fly.rs @@ -0,0 +1,140 @@ +use ecs::component::local::Local; +use ecs::sole::Single; +use ecs::system::{Into, System}; +use ecs::{Component, Query}; +use glfw::window::{Key, KeyState}; + +use crate::camera::Camera; +use crate::delta_time::DeltaTime; +use crate::event::Update as UpdateEvent; +use crate::input::{Cursor, Keys}; +use crate::vector::{Vec2, Vec3}; + +/// Fly camera extension. +pub struct Extension(pub Options); + +impl ecs::extension::Extension for Extension +{ +    fn collect(self, mut collector: ecs::extension::Collector<'_>) +    { +        collector.add_system( +            UpdateEvent, +            update.into_system().initialize(( +                CursorState { +                    current_yaw: -90.0, +                    ..Default::default() +                }, +                self.0, +            )), +        ); +    } +} + +#[derive(Debug, Component)] +pub struct Options +{ +    pub camera_speed: f32, +    pub mouse_sensitivity: f32, +} + +fn update( +    camera_query: Query<(Camera,)>, +    keys: Single<Keys>, +    cursor: Single<Cursor>, +    delta_time: Single<DeltaTime>, +    mut cursor_state: Local<CursorState>, +    options: Local<Options>, +) +{ +    let Some((mut camera,)) = camera_query.iter().next() else { +        #[cfg(feature = "debug")] +        tracing::warn!("No camera"); + +        return; +    }; + +    if cursor.has_moved && cursor_state.first_mouse { +        println!("First cursor move"); + +        cursor_state.last_pos = cursor.position; +        cursor_state.first_mouse = false; +    } + +    let delta_time = delta_time.duration; + +    let mut x_offset = cursor.position.x - cursor_state.last_pos.x; +    let mut y_offset = cursor_state.last_pos.y - cursor.position.y; + +    cursor_state.last_pos = cursor.position; + +    x_offset *= f64::from(options.mouse_sensitivity); +    y_offset *= f64::from(options.mouse_sensitivity); + +    cursor_state.current_yaw += x_offset; +    cursor_state.current_pitch += y_offset; + +    if cursor_state.current_pitch > 89.0 { +        cursor_state.current_pitch = 89.0; +    } else if cursor_state.current_pitch < -89.0 { +        cursor_state.current_pitch = -89.0; +    } + +    // TODO: This casting to a f32 from a f64 is horrible. fix it +    #[allow(clippy::cast_possible_truncation)] +    let direction = Vec3 { +        x: (cursor_state.current_yaw.to_radians().cos() +            * cursor_state.current_pitch.to_radians().cos()) as f32, +        y: cursor_state.current_pitch.to_radians().sin() as f32, +        z: (cursor_state.current_yaw.to_radians().sin() +            * cursor_state.current_pitch.to_radians().cos()) as f32, +    } +    .normalize(); + +    let cam_right = direction.cross(&Vec3::UP).normalize(); + +    camera.global_up = cam_right.cross(&direction).normalize(); + +    if matches!(keys.get_key_state(Key::W), KeyState::Pressed) { +        camera.position += direction * options.camera_speed * delta_time.as_secs_f32(); +    } + +    if matches!(keys.get_key_state(Key::S), KeyState::Pressed) { +        camera.position -= direction * options.camera_speed * delta_time.as_secs_f32(); +    } + +    if matches!(keys.get_key_state(Key::A), KeyState::Pressed) { +        let cam_left = -direction.cross(&Vec3::UP).normalize(); + +        camera.position += cam_left * options.camera_speed * delta_time.as_secs_f32(); +    } + +    if matches!(keys.get_key_state(Key::D), KeyState::Pressed) { +        let cam_right = direction.cross(&Vec3::UP).normalize(); + +        camera.position += cam_right * options.camera_speed * delta_time.as_secs_f32(); +    } + +    camera.target = camera.position + direction; +} + +#[derive(Debug, Component)] +struct CursorState +{ +    last_pos: Vec2<f64>, +    current_pitch: f64, +    current_yaw: f64, +    first_mouse: bool, +} + +impl Default for CursorState +{ +    fn default() -> Self +    { +        Self { +            last_pos: Vec2::default(), +            current_pitch: 0.0, +            current_yaw: 0.0, +            first_mouse: true, +        } +    } +}  | 
