1use super::ExposeHud;
2
3const MAX_FLY_SPEED: f32 = 1000000.0;
4
5pub struct ControlledCamera {
6 pub inner: blade_render::Camera,
7 pub fly_speed: f32,
8}
9
10impl Default for ControlledCamera {
11 fn default() -> Self {
12 Self {
13 inner: blade_render::Camera {
14 pos: mint::Vector3 {
15 x: 0.0,
16 y: 0.0,
17 z: 0.0,
18 },
19 rot: mint::Quaternion {
20 v: mint::Vector3 {
21 x: 0.0,
22 y: 0.0,
23 z: 0.0,
24 },
25 s: 1.0,
26 },
27 fov_y: 0.0,
28 depth: 0.0,
29 },
30 fly_speed: 0.0,
31 }
32 }
33}
34
35impl ControlledCamera {
36 pub fn get_view_matrix(&self) -> glam::Mat4 {
37 glam::Mat4::from_rotation_translation(self.inner.rot.into(), self.inner.pos.into())
38 .inverse()
39 }
40
41 pub fn get_projection_matrix(&self, aspect: f32) -> glam::Mat4 {
42 glam::Mat4::perspective_rh(self.inner.fov_y, aspect, 1.0, self.inner.depth)
43 }
44
45 pub fn move_by(&mut self, offset: glam::Vec3) {
46 let dir = glam::Quat::from(self.inner.rot) * offset;
47 self.inner.pos = (glam::Vec3::from(self.inner.pos) + dir).into();
48 }
49
50 pub fn rotate_z_by(&mut self, angle: f32) {
51 let quat = glam::Quat::from(self.inner.rot);
52 let rotation = glam::Quat::from_rotation_z(angle);
53 self.inner.rot = (quat * rotation).into();
54 }
55
56 pub fn on_key(&mut self, code: winit::keyboard::KeyCode, delta: f32) -> bool {
57 use winit::keyboard::KeyCode as Kc;
58
59 let move_offset = self.fly_speed * delta;
60 let rotate_offset_z = 1000.0 * delta;
61 match code {
62 Kc::KeyW => {
63 self.move_by(glam::Vec3::new(0.0, 0.0, -move_offset));
64 }
65 Kc::KeyS => {
66 self.move_by(glam::Vec3::new(0.0, 0.0, move_offset));
67 }
68 Kc::KeyA => {
69 self.move_by(glam::Vec3::new(-move_offset, 0.0, 0.0));
70 }
71 Kc::KeyD => {
72 self.move_by(glam::Vec3::new(move_offset, 0.0, 0.0));
73 }
74 Kc::KeyZ => {
75 self.move_by(glam::Vec3::new(0.0, -move_offset, 0.0));
76 }
77 Kc::KeyX => {
78 self.move_by(glam::Vec3::new(0.0, move_offset, 0.0));
79 }
80 Kc::KeyQ => {
81 self.rotate_z_by(rotate_offset_z);
82 }
83 Kc::KeyE => {
84 self.rotate_z_by(-rotate_offset_z);
85 }
86 _ => return false,
87 }
88
89 true
90 }
91
92 pub fn on_wheel(&mut self, delta: winit::event::MouseScrollDelta) {
93 let shift = match delta {
94 winit::event::MouseScrollDelta::LineDelta(_, lines) => lines,
95 winit::event::MouseScrollDelta::PixelDelta(position) => position.y as f32,
96 };
97 self.fly_speed = (self.fly_speed * shift.exp()).clamp(1.0, MAX_FLY_SPEED);
98 }
99}
100
101impl ExposeHud for ControlledCamera {
102 fn populate_hud(&mut self, ui: &mut egui::Ui) {
103 ui.horizontal(|ui| {
104 ui.label("Position:");
105 ui.add(egui::DragValue::new(&mut self.inner.pos.x));
106 ui.add(egui::DragValue::new(&mut self.inner.pos.y));
107 ui.add(egui::DragValue::new(&mut self.inner.pos.z));
108 });
109 ui.horizontal(|ui| {
110 ui.label("Rotation:");
111 ui.add(egui::DragValue::new(&mut self.inner.rot.v.x));
112 ui.add(egui::DragValue::new(&mut self.inner.rot.v.y));
113 ui.add(egui::DragValue::new(&mut self.inner.rot.v.z));
114 ui.add(egui::DragValue::new(&mut self.inner.rot.s));
115 });
116 ui.add(egui::Slider::new(&mut self.inner.fov_y, 0.5f32..=2.0f32).text("FOV"));
117 ui.add(
118 egui::Slider::new(&mut self.fly_speed, 1f32..=MAX_FLY_SPEED)
119 .text("Fly speed")
120 .logarithmic(true),
121 );
122 }
123}