1use crate::object::{Transform, TransformSerializer};
2use serde::{Deserialize, Serialize};
3
4#[derive(Serialize, Deserialize)]
5pub struct CameraSerializer {
6 transform: TransformSerializer,
7 fov: f32,
8 width: f32,
9 height: f32,
10 near: f32,
11 far: f32,
12 view: [[f32; 4]; 4],
13 projection: [[f32; 4]; 4],
14}
15
16#[derive(Copy, Clone)]
17pub struct Camera {
18 pub transform: Transform,
19 pub fov: f32,
20 pub width: f32,
21 pub height: f32,
22 pub near: f32,
23 pub far: f32,
24 pub view: [[f32; 4]; 4],
25 pub projection: [[f32; 4]; 4],
26}
27
28
29impl Camera {
30 pub fn new(
31 position: Option<[f32; 3]>,
32 rotation: Option<[f32; 3]>, fov: Option<f32>, aspect: Option<f32>,
35 near: Option<f32>,
36 far: Option<f32>
37 ) -> Self {
38 let mut c = Self {
39 transform: {
40 let mut t = Transform::new();
41 t.set_position(position.unwrap_or_else(|| [0.0, 0.0, 0.0]));
42 t.set_rotation(rotation.unwrap_or_else(|| [0.0, 0.0, 0.0]));
43 t
44 },
45 fov: fov.unwrap_or_else(|| 90.0).to_radians(),
46 width: aspect.unwrap_or_else(|| 1920.0),
47 height: aspect.unwrap_or_else(|| 1080.0),
48 near: near.unwrap_or_else(|| 0.1),
49 far: far.unwrap_or_else(|| 1024.0),
50 view: [[0.0; 4]; 4],
51 projection: [[0.0; 4]; 4],
52 };
53 c.update_matrices();
54 c
55 }
56
57 pub fn default() -> Self {
58 Camera::new(None, None, None, None, None, None)
59 }
60
61 pub fn from_serializer(serializer: CameraSerializer) -> Self {
62 Self {
63 transform: Transform::from_serializer(serializer.transform),
64 fov: serializer.fov,
65 width: serializer.width,
66 height: serializer.height,
67 near: serializer.near,
68 far: serializer.far,
69 view: serializer.view,
70 projection: serializer.projection,
71 }
72 }
73
74 pub fn to_serializer(&self) -> CameraSerializer {
75 CameraSerializer {
76 transform: self.transform.to_serializer(),
77 fov: self.fov,
78 width: self.width,
79 height: self.height,
80 near: self.near,
81 far: self.far,
82 view: self.view,
83 projection: self.projection,
84 }
85 }
86
87 pub fn update_matrices(&mut self) {
88 self.view = Camera::view_matrix(
89 &self.transform.get_position().into(),
90 &self.calculate_direction_vector(),
91 &[0.0, 1.0, 0.0],
92 );
93 self.projection = Camera::projection_matrix(
94 self.fov,
95 self.width / self.height,
96 self.near,
97 self.far,
98 );
99 }
100
101 pub fn calculate_direction_vector(&self) -> [f32; 3] {
102 let pitch = self.transform.rotation[0]; let yaw = self.transform.rotation[1]; let x = yaw.sin() * pitch.cos();
106 let y = pitch.sin();
107 let z = yaw.cos() * pitch.cos();
108
109 [-x, y, -z] }
111
112
113 fn projection_matrix(fov: f32, aspect: f32, near: f32, far: f32) -> [[f32; 4]; 4] {
114 let f = 1.0 / (fov / 2.0).tan();
115 [
116 [f / aspect, 0.0, 0.0, 0.0],
117 [0.0, f, 0.0, 0.0],
118 [0.0, 0.0, (far + near) / (near - far), -1.0],
119 [0.0, 0.0, (2.0 * far * near) / (near - far), 0.0],
120 ]
121 }
122
123 fn view_matrix(position: &[f32; 3], direction: &[f32; 3], up: &[f32; 3]) -> [[f32; 4]; 4] {
124 let f = {
125 let len = (direction[0] * direction[0] + direction[1] * direction[1] + direction[2] * direction[2]).sqrt();
126 [-direction[0] / len, -direction[1] / len, -direction[2] / len] };
128
129 let s = [
130 up[1] * f[2] - up[2] * f[1],
131 up[2] * f[0] - up[0] * f[2],
132 up[0] * f[1] - up[1] * f[0],
133 ];
134 let s_norm = {
135 let len = (s[0] * s[0] + s[1] * s[1] + s[2] * s[2]).sqrt();
136 [s[0] / len, s[1] / len, s[2] / len]
137 };
138
139 let u = [
140 f[1] * s_norm[2] - f[2] * s_norm[1],
141 f[2] * s_norm[0] - f[0] * s_norm[2],
142 f[0] * s_norm[1] - f[1] * s_norm[0],
143 ];
144
145 let p = [
146 -position[0] * s_norm[0] - position[1] * s_norm[1] - position[2] * s_norm[2],
147 -position[0] * u[0] - position[1] * u[1] - position[2] * u[2],
148 -position[0] * f[0] - position[1] * f[1] - position[2] * f[2],
149 ];
150
151 [
152 [s_norm[0], u[0], f[0], 0.0],
153 [s_norm[1], u[1], f[1], 0.0],
154 [s_norm[2], u[2], f[2], 0.0],
155 [p[0], p[1], p[2], 1.0],
156 ]
157 }
158
159 pub fn get_view_matrix(&self) -> [[f32; 4]; 4] {
160 Camera::view_matrix(
161 &self.transform.get_position().into(),
162 &self.calculate_direction_vector(),
163 &[0.0, 1.0, 0.0],
164 )
165 }
166
167 pub fn get_projection_matrix(&self) -> [[f32; 4]; 4] {
168 Camera::projection_matrix(
169 self.fov,
170 self.width / self.height,
171 self.near,
172 self.far,
173 )
174 }
175
176 pub fn get_position(&self) -> [f32; 3] {
177 self.transform.get_position().into()
178 }
179
180 pub fn get_rotation(&self) -> [f32; 3] {
181 self.transform.get_rotation().into()
182 }
183
184 pub fn get_fov(&self) -> f32 {
185 self.fov.clone()
186 }
187
188 pub fn get_aspect(&self) -> (f32, f32) {
189 (self.width.clone(), self.height.clone())
190 }
191
192 pub fn get_near(&self) -> f32 {
193 self.near.clone()
194 }
195
196 pub fn get_far(&self) -> f32 {
197 self.far.clone()
198 }
199
200 pub fn get_view(&self) -> [[f32; 4]; 4] {
201 self.view.clone()
202 }
203
204 pub fn get_projection(&self) -> [[f32; 4]; 4] {
205 self.projection.clone()
206 }
207
208 pub fn set_position(&mut self, position: [f32; 3]) {
209 self.transform.set_position(position);
210 self.update_matrices();
211 }
212
213 pub fn set_rotation(&mut self, rotation: [f32; 3]) {
214 self.transform.set_rotation(rotation);
215 self.update_matrices();
216 }
217
218 pub fn set_fov(&mut self, fov: f32) {
219 self.fov = fov;
220 self.update_matrices();
221 }
222
223 pub fn set_aspect(&mut self, width: f32, heigth: f32) {
224 self.width = width;
225 self.height = heigth;
226 self.update_matrices();
227 }
228
229 pub fn set_near(&mut self, near: f32) {
230 self.near = near;
231 self.update_matrices();
232 }
233
234 pub fn set_far(&mut self, far: f32) {
235 self.far = far;
236 self.update_matrices();
237 }
238}