gloss_renderer/components/
cam_comps.rs1use std::collections::HashMap;
4use winit::event::Touch;
5
6extern crate nalgebra as na;
7extern crate nalgebra_glm as glm;
8
9#[derive(Eq, PartialEq, Debug, Default)]
10pub enum TargetResolutionUpdate {
11 Fixed,
12 #[default]
13 WindowSize,
14}
15
16#[derive(Default)]
17pub struct TargetResolution {
18 pub width: u32,
19 pub height: u32,
20 pub update_mode: TargetResolutionUpdate,
21}
22
23#[derive(Eq, PartialEq, Debug)]
24pub enum CamMode {
25 Rotation,
26 Translation,
27}
28
29#[derive(Clone)]
32pub struct PosLookat {
33 pub position: na::Point3<f32>, pub lookat: na::Point3<f32>,
35 pub up: na::Vector3<f32>,
36}
37
38pub enum Projection {
40 WithFov(ProjectionWithFov),
42 WithIntrinsics(ProjectionWithIntrinsics),
43}
44
45#[derive(Clone)]
47pub struct ProjectionWithFov {
48 pub aspect_ratio: f32,
49 pub fovy: f32, pub near: f32,
51 pub far: f32,
52}
53
54#[derive(Clone)]
55pub struct ProjectionWithIntrinsics {
56 pub fx: f32,
57 pub fy: f32, pub cx: f32,
59 pub cy: f32,
60 pub near: f32,
63 pub far: f32,
64}
65
66pub struct CamController {
69 pub mouse_mode: CamMode,
70 pub mouse_pressed: bool,
71 pub prev_mouse_pos_valid: bool,
72 pub prev_mouse: na::Vector2<f32>,
73 pub limit_max_dist: Option<f32>,
74 pub limit_max_vertical_angle: Option<f32>,
75 pub limit_min_vertical_angle: Option<f32>,
76 pub id2active_touches: HashMap<u64, Touch>, }
79
80impl Default for PosLookat {
83 fn default() -> Self {
84 Self {
85 position: na::Point3::<f32>::new(0.0, 1.0, 3.0),
86 lookat: na::Point3::<f32>::new(0.0, 0.0, 0.0),
87 up: na::Vector3::<f32>::new(0.0, 1.0, 0.0),
88 }
89 }
90}
91impl PosLookat {
92 pub fn new(position: na::Point3<f32>, lookat: na::Point3<f32>) -> Self {
93 Self {
94 position,
95 lookat,
96 ..Default::default()
97 }
98 }
99
100 pub fn new_from_model_matrix(model_matrix: na::SimilarityMatrix3<f32>, dist_lookat: f32) -> Self {
103 let position = model_matrix.isometry.translation.vector;
104 let mat = model_matrix.isometry.to_matrix();
105 let rot: na::Matrix3<f32> = mat.fixed_view::<3, 3>(0, 0).into();
106 let axis_lookat = rot.column(1); let lookat = position + axis_lookat * dist_lookat;
108
109 let position = na::Point3::<f32>::from(position);
110 let lookat = na::Point3::<f32>::from(lookat);
111
112 Self {
113 position,
114 lookat,
115 up: na::Vector3::<f32>::new(0.0, 1.0, 0.0),
116 }
117 }
118
119 pub fn view_matrix(&self) -> na::Matrix4<f32> {
122 self.view_matrix_isometry().to_matrix()
123 }
124
125 pub fn view_matrix_isometry(&self) -> na::IsometryMatrix3<f32> {
129 na::IsometryMatrix3::<f32>::look_at_rh(&self.position, &self.lookat, &self.up)
130 }
131
132 pub fn direction(&self) -> na::Vector3<f32> {
134 (self.lookat - self.position).normalize()
135 }
136
137 pub fn model_matrix_isometry(&self) -> na::IsometryMatrix3<f32> {
141 self.view_matrix_isometry().inverse()
142 }
143
144 pub fn model_matrix(&self) -> na::Matrix4<f32> {
147 self.model_matrix_isometry().to_matrix()
148 }
149
150 pub fn cam_axes(&self) -> na::Matrix3<f32> {
154 let model_matrix = self.model_matrix();
155 let rot = model_matrix.fixed_view::<3, 3>(0, 0);
156 rot.into()
157 }
158
159 pub fn dolly(&mut self, s: f32) {
161 let eye_look_vec = self.lookat - self.position; let movement = eye_look_vec * s;
163 self.position += movement;
164 }
165
166 pub fn orbit(&mut self, rot: na::Rotation3<f32>) {
168 let model_matrix = self.model_matrix_isometry();
171
172 let trans_to_look_at = na::Translation3::from(-self.lookat);
173 let trans_back = na::Translation3::from(self.lookat);
174
175 let model_matrix_rotated = trans_back * rot * trans_to_look_at * model_matrix;
176
177 self.position = model_matrix_rotated.translation.vector.into();
179
180 let model_matrix_rotated_mat = model_matrix_rotated.to_matrix();
187 let cam_axes_after = model_matrix_rotated_mat.fixed_view::<3, 3>(0, 0);
188 let up_cam_axis = cam_axes_after.column(1);
189 let dot_up = self.up.dot(&up_cam_axis);
190 if dot_up < 0.0 {
191 self.up = -self.up;
192 }
193 }
194
195 pub fn orbit_y(&mut self, degrees: f32) {
197 let axis = na::Vector3::y_axis();
198 let rot = na::Rotation3::from_axis_angle(&axis, degrees.to_radians());
199
200 self.orbit(rot);
201 }
202
203 pub fn shift_cam(&mut self, pos: na::Point3<f32>) {
206 let displacement = pos - self.position;
207 self.position += displacement;
208 self.lookat += displacement;
209 }
210
211 pub fn shift_lookat(&mut self, pos: na::Point3<f32>) {
214 let displacement = pos - self.lookat;
215 self.position += displacement;
216 self.lookat += displacement;
217 }
218
219 pub fn dist_lookat(&self) -> f32 {
221 (self.position - self.lookat).norm()
222 }
223}
224
225impl Default for Projection {
226 fn default() -> Self {
227 Self::WithFov(ProjectionWithFov::default())
228 }
229}
230impl Projection {
231 pub fn proj_matrix(&self, width: u32, height: u32) -> na::Matrix4<f32> {
235 match self {
236 Projection::WithFov(proj) => proj.proj_matrix(),
237 Projection::WithIntrinsics(proj) => proj.proj_matrix(width, height),
238 }
239 }
240 pub fn proj_matrix_reverse_z(&self, width: u32, height: u32) -> na::Matrix4<f32> {
244 match self {
245 Projection::WithFov(proj) => proj.proj_matrix_reverse_z(),
246 Projection::WithIntrinsics(proj) => proj.proj_matrix_reverse_z(width, height),
247 }
248 }
249 pub fn near_far(&self) -> (f32, f32) {
250 match self {
251 Projection::WithFov(proj) => (proj.near, proj.far),
252 Projection::WithIntrinsics(proj) => (proj.near, proj.far),
253 }
254 }
255 pub fn set_near(&mut self, val: f32) {
256 match self {
257 Projection::WithFov(ref mut proj) => proj.near = val,
258 Projection::WithIntrinsics(ref mut proj) => proj.near = val,
259 }
260 }
261 pub fn set_far(&mut self, val: f32) {
262 match self {
263 Projection::WithFov(ref mut proj) => proj.far = val,
264 Projection::WithIntrinsics(ref mut proj) => proj.far = val,
265 }
266 }
267}
268
269impl Default for ProjectionWithFov {
271 fn default() -> Self {
272 Self {
273 aspect_ratio: 1.6,
274 fovy: 0.7, near: 0.01,
276 far: 100.0,
277 }
278 }
279}
280impl ProjectionWithFov {
281 pub fn proj_matrix(&self) -> na::Matrix4<f32> {
284 glm::perspective_rh_zo(self.aspect_ratio, self.fovy, self.near, self.far)
285 }
286 pub fn proj_matrix_reverse_z(&self) -> na::Matrix4<f32> {
291 let mat = self.proj_matrix();
301
302 let mut depth_remap = glm::TMat4::identity();
310 depth_remap[(2, 2)] = -1.0;
311 depth_remap[(2, 3)] = 1.0;
312
313 depth_remap * mat
314 }
318}
319
320impl ProjectionWithIntrinsics {
321 #[allow(clippy::cast_precision_loss)]
322 pub fn proj_matrix(&self, width: u32, height: u32) -> na::Matrix4<f32> {
323 let mut projection_matrix = na::Matrix4::<f32>::zeros();
324
325 projection_matrix[(0, 0)] = 2.0 * self.fx / width as f32;
327 projection_matrix[(1, 1)] = 2.0 * self.fy / height as f32;
328 projection_matrix[(0, 2)] = 1.0 - (2.0 * self.cx / width as f32);
329 projection_matrix[(1, 2)] = (2.0 * self.cy / height as f32) - 1.0;
330 projection_matrix[(2, 2)] = -self.far / (self.far - self.near);
334 projection_matrix[(2, 3)] = -self.far * self.near / (self.far - self.near);
335 projection_matrix[(3, 2)] = -1.0;
336 projection_matrix
337 }
338
339 pub fn proj_matrix_reverse_z(&self, width: u32, height: u32) -> na::Matrix4<f32> {
340 let mat = self.proj_matrix(width, height);
341
342 let mut depth_remap = glm::TMat4::identity();
343 depth_remap[(2, 2)] = -1.0;
344 depth_remap[(2, 3)] = 1.0;
345
346 depth_remap * mat
347 }
351}
352impl Default for CamController {
354 fn default() -> Self {
355 Self {
356 mouse_mode: CamMode::Rotation,
357 mouse_pressed: false,
358 prev_mouse_pos_valid: false,
359 prev_mouse: na::Vector2::<f32>::zeros(),
360 limit_max_dist: None,
361 limit_max_vertical_angle: None,
362 limit_min_vertical_angle: None,
363 id2active_touches: HashMap::new(),
364 }
365 }
366}
367impl CamController {
368 pub fn new(limit_max_dist: Option<f32>, limit_max_vertical_angle: Option<f32>, limit_min_vertical_angle: Option<f32>) -> Self {
369 Self {
370 limit_max_dist,
371 limit_max_vertical_angle,
372 limit_min_vertical_angle,
373 ..Default::default()
374 }
375 }
376}