vigilant_lamp/engine/
camera.rs1use crate::{math::{array_ext::NumArray, matrix::{Matrix4}, quaternion::Quaternion32}};
2
3pub trait Camera {
5 fn projection_matrix (&self, width: u32, height: u32) -> Matrix4<f32>;
6
7 fn get_position (&self) -> &NumArray<f32, 3>;
8 fn get_rotation (&self) -> &Quaternion32;
9
10 fn get_position_mut (&mut self) -> &mut NumArray<f32, 3>;
11 fn get_rotation_mut (&mut self) -> &mut Quaternion32;
12
13 fn set_position (&mut self, value: NumArray<f32, 3>);
14 fn set_rotation (&mut self, value: Quaternion32);
15
16 fn translate (&mut self, x: f32, y: f32, z: f32) {
17 self.set_position(*self.get_position() + NumArray([x, y, z]))
18 }
19
20 fn rotate (&mut self, roll: f32, pitch: f32, yaw: f32) {
21 let nw = *self.get_rotation() * Quaternion32::from_angles(roll, pitch, yaw);
22 self.set_rotation(nw.unit())
23 }
24
25 fn view_matrix (&self) -> Matrix4<f32> {
26 let position = Matrix4::new([
27 NumArray([1., 0., 0., -self.get_position().x()]),
28 NumArray([0., 1., 0., -self.get_position().y()]),
29 NumArray([0., 0., 1., -self.get_position().z()]),
30 NumArray([0., 0., 0., 1.])
31 ]);
32
33 self.get_rotation().rot_matrix4().T() * position
34 }
36
37 fn camera_matrix (&self, width: u32, height: u32) -> Matrix4<f32> {
38 self.projection_matrix(width, height) * self.view_matrix()
39 }
40}
41
42pub struct PerspectiveCamera {
44 pub fov: f32,
45 pub z_near: f32,
46 pub z_far: f32,
47
48 pub position: NumArray<f32, 3>,
49 pub rotation: Quaternion32
50}
51
52impl PerspectiveCamera {
53 pub fn new (fov: f32, z_near: f32, z_far: f32) -> PerspectiveCamera {
54 PerspectiveCamera { fov, z_near, z_far, position: NumArray::zero(), rotation: Quaternion32::zero_rotation() }
55 }
56}
57
58impl Camera for PerspectiveCamera {
59 fn get_position(&self) -> &NumArray<f32, 3> {
60 &self.position
61 }
62
63 fn get_rotation(&self) -> &Quaternion32 {
64 &self.rotation
65 }
66
67 fn get_position_mut (&mut self) -> &mut NumArray<f32, 3> {
68 &mut self.position
69 }
70
71 fn get_rotation_mut (&mut self) -> &mut Quaternion32 {
72 &mut self.rotation
73 }
74
75 fn set_position(&mut self, value: NumArray<f32, 3>) {
76 self.position = value
77 }
78
79 fn set_rotation(&mut self, value: Quaternion32) {
80 self.rotation = value
81 }
82
83 fn projection_matrix (&self, width: u32, height: u32) -> Matrix4<f32> {
84 let aspect = (width as f32) / (height as f32);
85 let h = (self.fov * 0.5).tan();
86
87 let zp = self.z_far + self.z_near;
88 let zm = self.z_far - self.z_near;
89
90 let rm00 = 1.0 / (h * aspect);
91 let rm11 = 1.0 / h;
92
93 Matrix4::new([
94 NumArray([rm00, 0., 0., 0.]),
95 NumArray([0., rm11, 0., 0.]),
96 NumArray([0., 0., -zp / zm, -2. * self.z_far * self.z_near / zm]),
97 NumArray([0., 0., -1., 0.])
98 ])
99 }
100}