vigilant_lamp/engine/
camera.rs

1use crate::{math::{array_ext::NumArray, matrix::{Matrix4}, quaternion::Quaternion32}};
2
3/// Element used to represent the view characteristics of a scene
4pub 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        // position * self.get_rotation().point_rot_matrix4()
35    }
36
37    fn camera_matrix (&self, width: u32, height: u32) -> Matrix4<f32> {
38        self.projection_matrix(width, height) * self.view_matrix()
39    }
40}
41
42/// Camera that represents a perspective view. It's the most common type of camera, since it's the best at emulating the way human vision works
43pub 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}