Skip to main content

mraphics_core/math/
camera.rs

1use std::f32::consts::PI;
2
3use nalgebra::{Isometry3, Matrix4, Perspective3, Point3, Vector3};
4
5pub trait Camera {
6    fn view_mat_data(&self) -> &[u8];
7    fn projection_mat_data(&self) -> &[u8];
8
9    fn look_at(&mut self, target: &Point3<f32>);
10    fn set_center(&mut self, center: &Vector3<f32>);
11
12    fn set_aspect(&mut self, aspect: f32);
13}
14
15pub struct PerspectiveCamera {
16    pub view_transform: Isometry3<f32>,
17    view_mat: Matrix4<f32>,
18
19    pub up: Vector3<f32>,
20    center: Vector3<f32>,
21
22    pub proj_transform: Perspective3<f32>,
23    proj_mat: Matrix4<f32>,
24}
25
26impl PerspectiveCamera {
27    pub fn center(&self) -> &Vector3<f32> {
28        &self.center
29    }
30
31    pub fn set_rotation(&mut self, rotarion: &Vector3<f32>) {
32        self.view_transform =
33            Isometry3::new(self.view_transform.translation.vector, rotarion.clone());
34        self.view_mat = self.view_transform.to_homogeneous();
35    }
36
37    pub fn set_far(&mut self, far: f32) {
38        self.proj_transform.set_zfar(far);
39        self.proj_mat = self.proj_transform.to_homogeneous();
40    }
41
42    pub fn set_near(&mut self, near: f32) {
43        self.proj_transform.set_znear(near);
44        self.proj_mat = self.proj_transform.to_homogeneous();
45    }
46
47    pub fn set_fov_rad(&mut self, fov_rad: f32) {
48        self.proj_transform.set_zfar(fov_rad);
49        self.proj_mat = self.proj_transform.to_homogeneous();
50    }
51}
52
53impl Default for PerspectiveCamera {
54    fn default() -> Self {
55        let (far, near, aspect, fov_rad) = (1000.0, 0.1, 1.0, PI / 4.0);
56        let (center, rotation) = (Vector3::new(0.0, 0.0, 10.0), Vector3::new(0.0, 0.0, 0.0));
57        let (view_transform, proj_transform) = (
58            Isometry3::new(-center, rotation),
59            Perspective3::new(aspect, fov_rad, near, far),
60        );
61
62        Self {
63            view_mat: view_transform.to_homogeneous(),
64            view_transform,
65            proj_mat: proj_transform.to_homogeneous(),
66            proj_transform,
67
68            up: Vector3::y(),
69            center,
70        }
71    }
72}
73
74impl Camera for PerspectiveCamera {
75    fn view_mat_data(&self) -> &[u8] {
76        bytemuck::cast_slice(self.view_mat.as_slice())
77    }
78
79    fn projection_mat_data(&self) -> &[u8] {
80        bytemuck::cast_slice(self.proj_mat.as_slice())
81    }
82
83    fn look_at(&mut self, target: &Point3<f32>) {
84        self.view_transform = Isometry3::look_at_rh(
85            &Point3::from_slice(&self.center.as_slice()),
86            target,
87            &self.up,
88        );
89        self.view_mat = self.view_transform.to_homogeneous();
90    }
91
92    fn set_center(&mut self, center: &Vector3<f32>) {
93        self.center.copy_from(&center);
94        self.view_transform.translation.vector.copy_from(&-center);
95        self.view_mat = self.view_transform.to_homogeneous();
96    }
97
98    fn set_aspect(&mut self, aspect: f32) {
99        self.proj_transform.set_aspect(aspect);
100        self.proj_mat = self.proj_transform.to_homogeneous();
101    }
102}