oxide_engine/camera/
controller.rs1use glam::Vec3;
4use oxide_ecs::Component;
5
6use crate::ecs::World;
7use crate::input::{KeyboardInput, MouseInput};
8use oxide_math::prelude::Camera;
9
10#[derive(Component, Clone, Copy, Debug)]
11pub struct CameraComponent(pub Camera);
12
13impl Default for CameraComponent {
14 fn default() -> Self {
15 Self(Camera::new())
16 }
17}
18
19impl CameraComponent {
20 pub fn new() -> Self {
21 Self::default()
22 }
23}
24
25#[derive(Component)]
26pub struct CameraController {
27 pub speed: f32,
28 pub sensitivity: f32,
29 pub yaw: f32,
30 pub pitch: f32,
31}
32
33impl Default for CameraController {
34 fn default() -> Self {
35 Self {
36 speed: 5.0,
37 sensitivity: 0.002,
38 yaw: 0.0,
39 pitch: 0.0,
40 }
41 }
42}
43
44impl CameraController {
45 pub fn new() -> Self {
46 Self::default()
47 }
48
49 pub fn with_speed(mut self, speed: f32) -> Self {
50 self.speed = speed;
51 self
52 }
53
54 pub fn with_sensitivity(mut self, sensitivity: f32) -> Self {
55 self.sensitivity = sensitivity;
56 self
57 }
58
59 pub fn update_camera(&self, camera: &mut Camera) {
60 let rotation =
61 glam::Quat::from_rotation_y(self.yaw) * glam::Quat::from_rotation_x(self.pitch);
62 let forward = rotation * Vec3::NEG_Z;
63
64 camera.target = camera.position + forward;
65 camera.up = rotation * Vec3::Y;
66 }
67}
68
69pub fn camera_controller_system(world: &mut World) {
70 use winit::keyboard::KeyCode;
71
72 let (w, s, a, d, space, shift, dx, dy) = {
73 let keyboard = world.resource::<KeyboardInput>();
74 let mouse = world.resource::<MouseInput>();
75
76 let (dx, dy) = mouse.delta();
77
78 (
79 keyboard.pressed(KeyCode::KeyW),
80 keyboard.pressed(KeyCode::KeyS),
81 keyboard.pressed(KeyCode::KeyA),
82 keyboard.pressed(KeyCode::KeyD),
83 keyboard.pressed(KeyCode::Space),
84 keyboard.pressed(KeyCode::ShiftLeft),
85 dx,
86 dy,
87 )
88 };
89
90 let mut query = world.query::<(&mut CameraController, &mut CameraComponent)>();
91 for (controller, camera_comp) in query.iter_mut(world) {
92 let camera = &mut camera_comp.0;
93
94 controller.yaw -= dx * controller.sensitivity;
95 controller.pitch -= dy * controller.sensitivity;
96 controller.pitch = controller.pitch.clamp(
97 -std::f32::consts::FRAC_PI_2 + 0.01,
98 std::f32::consts::FRAC_PI_2 - 0.01,
99 );
100
101 let rotation = glam::Quat::from_rotation_y(controller.yaw)
102 * glam::Quat::from_rotation_x(controller.pitch);
103 let forward = rotation * Vec3::NEG_Z;
104 let right = rotation * Vec3::X;
105
106 let mut velocity = Vec3::ZERO;
107 if w {
108 velocity += forward;
109 }
110 if s {
111 velocity -= forward;
112 }
113 if a {
114 velocity -= right;
115 }
116 if d {
117 velocity += right;
118 }
119 if space {
120 velocity += Vec3::Y;
121 }
122 if shift {
123 velocity -= Vec3::Y;
124 }
125
126 if velocity != Vec3::ZERO {
127 camera.position += velocity.normalize() * controller.speed * 0.016;
128 }
129
130 controller.update_camera(camera);
131 }
132}