summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHampusM <hampus@hampusmat.com>2024-08-20 20:30:52 +0200
committerHampusM <hampus@hampusmat.com>2024-08-20 20:33:14 +0200
commitcb05930d35134b269314e514f9a69ec3e40f279e (patch)
tree547596cb571e507caf9fdc86a1166c90ad3808f4
parent5a55864c8c3448262932203e30055249494d96c8 (diff)
feat(engine): make fly camera more flexible
-rw-r--r--engine/src/camera/fly.rs166
1 files changed, 92 insertions, 74 deletions
diff --git a/engine/src/camera/fly.rs b/engine/src/camera/fly.rs
index 5b55cec..6bd5876 100644
--- a/engine/src/camera/fly.rs
+++ b/engine/src/camera/fly.rs
@@ -4,13 +4,54 @@ use ecs::system::{Into, System};
use ecs::{Component, Query};
use glfw::window::{Key, KeyState};
-use crate::camera::Camera;
+use crate::camera::{Active as ActiveCamera, Camera};
use crate::delta_time::DeltaTime;
use crate::event::Update as UpdateEvent;
use crate::input::{Cursor, CursorFlags, Keys};
use crate::transform::Position;
+use crate::util::builder;
use crate::vector::{Vec2, Vec3};
+builder! {
+/// A fly camera.
+#[builder(name = Builder, derives = (Debug))]
+#[derive(Debug, Component)]
+#[non_exhaustive]
+pub struct Fly {
+ pub current_pitch: f64,
+ pub current_yaw: f64,
+ pub speed: f32,
+}
+}
+
+impl Fly
+{
+ pub fn builder() -> Builder
+ {
+ Builder::default()
+ }
+}
+
+impl Default for Fly
+{
+ fn default() -> Self
+ {
+ Self::builder().build()
+ }
+}
+
+impl Default for Builder
+{
+ fn default() -> Self
+ {
+ Self {
+ current_yaw: -90.0,
+ current_pitch: 0.0,
+ speed: 3.0,
+ }
+ }
+}
+
/// Fly camera extension.
pub struct Extension(pub Options);
@@ -20,13 +61,9 @@ impl ecs::extension::Extension for Extension
{
collector.add_system(
UpdateEvent,
- update.into_system().initialize((
- CursorState {
- current_yaw: -90.0,
- ..Default::default()
- },
- self.0,
- )),
+ update
+ .into_system()
+ .initialize((CursorState::default(), self.0)),
);
}
}
@@ -34,12 +71,11 @@ impl ecs::extension::Extension for Extension
#[derive(Debug, Component)]
pub struct Options
{
- pub camera_speed: f32,
pub mouse_sensitivity: f32,
}
fn update(
- camera_query: Query<(Camera, Position)>,
+ camera_query: Query<(Camera, Position, Fly, ActiveCamera)>,
keys: Single<Keys>,
cursor: Single<Cursor>,
cursor_flags: Single<CursorFlags>,
@@ -48,91 +84,73 @@ fn update(
options: Local<Options>,
)
{
- let Some((mut camera, mut camera_pos)) = camera_query.iter().next() else {
- #[cfg(feature = "debug")]
- tracing::warn!("No camera");
+ for (mut camera, mut camera_pos, mut fly_camera, _) in &camera_query {
+ if cursor.has_moved && cursor_flags.is_first_move.flag {
+ #[cfg(feature = "debug")]
+ tracing::debug!("First cursor move");
- return;
- };
+ cursor_state.last_pos = cursor.position;
+ }
- if cursor.has_moved && cursor_flags.is_first_move.flag {
- println!("First cursor move");
+ let delta_time = delta_time.duration;
- cursor_state.last_pos = cursor.position;
- }
-
- 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;
- 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;
- cursor_state.last_pos = cursor.position;
+ x_offset *= f64::from(options.mouse_sensitivity);
+ y_offset *= f64::from(options.mouse_sensitivity);
- x_offset *= f64::from(options.mouse_sensitivity);
- y_offset *= f64::from(options.mouse_sensitivity);
+ fly_camera.current_yaw += x_offset;
+ fly_camera.current_pitch += y_offset;
- cursor_state.current_yaw += x_offset;
- cursor_state.current_pitch += y_offset;
+ fly_camera.current_pitch = fly_camera.current_pitch.clamp(-89.0, 89.0);
- cursor_state.current_pitch = cursor_state.current_pitch.clamp(-89.0, 89.0);
+ // TODO: This casting to a f32 from a f64 is horrible. fix it
+ #[allow(clippy::cast_possible_truncation)]
+ let direction = Vec3 {
+ x: (fly_camera.current_yaw.to_radians().cos()
+ * fly_camera.current_pitch.to_radians().cos()) as f32,
+ y: fly_camera.current_pitch.to_radians().sin() as f32,
+ z: (fly_camera.current_yaw.to_radians().sin()
+ * fly_camera.current_pitch.to_radians().cos()) as f32,
+ }
+ .normalize();
- // 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();
- let cam_right = direction.cross(&Vec3::UP).normalize();
+ camera.global_up = cam_right.cross(&direction).normalize();
- camera.global_up = cam_right.cross(&direction).normalize();
+ if matches!(keys.get_key_state(Key::W), KeyState::Pressed) {
+ camera_pos.position +=
+ direction * fly_camera.speed * delta_time.as_secs_f32();
+ }
- if matches!(keys.get_key_state(Key::W), KeyState::Pressed) {
- camera_pos.position +=
- direction * options.camera_speed * delta_time.as_secs_f32();
- }
+ if matches!(keys.get_key_state(Key::S), KeyState::Pressed) {
+ camera_pos.position -=
+ direction * fly_camera.speed * delta_time.as_secs_f32();
+ }
- if matches!(keys.get_key_state(Key::S), KeyState::Pressed) {
- camera_pos.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();
- if matches!(keys.get_key_state(Key::A), KeyState::Pressed) {
- let cam_left = -direction.cross(&Vec3::UP).normalize();
+ camera_pos.position += cam_left * fly_camera.speed * delta_time.as_secs_f32();
+ }
- camera_pos.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();
- if matches!(keys.get_key_state(Key::D), KeyState::Pressed) {
- let cam_right = direction.cross(&Vec3::UP).normalize();
+ camera_pos.position +=
+ cam_right * fly_camera.speed * delta_time.as_secs_f32();
+ }
- camera_pos.position +=
- cam_right * options.camera_speed * delta_time.as_secs_f32();
+ camera.target = camera_pos.position + direction;
}
-
- camera.target = camera_pos.position + direction;
}
-#[derive(Debug, Component)]
+#[derive(Debug, Default, Component)]
struct CursorState
{
last_pos: Vec2<f64>,
- current_pitch: f64,
- current_yaw: f64,
-}
-
-impl Default for CursorState
-{
- fn default() -> Self
- {
- Self {
- last_pos: Vec2::default(),
- current_pitch: 0.0,
- current_yaw: 0.0,
- }
- }
}