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