wgpu_3dgs_viewer/
camera.rs1use std::ops::Range;
2
3use glam::*;
4
5pub trait CameraTrait {
9 fn view(&self) -> Mat4;
11
12 fn projection(&self, aspect_ratio: f32) -> Mat4;
14}
15
16#[derive(Debug, Clone)]
18pub struct Camera {
19 pub pos: Vec3,
21 pub z: Range<f32>,
23 pub vertical_fov: f32,
25 pub pitch: f32,
27 pub yaw: f32,
29}
30
31impl Camera {
32 pub const UP: Vec3 = Vec3::Y;
34
35 pub const PITCH_LIMIT: Range<f32> =
37 -std::f32::consts::FRAC_PI_2 + 1e-6..std::f32::consts::FRAC_PI_2 - 1e-6;
38
39 pub fn new(z: Range<f32>, vertical_fov: f32) -> Self {
41 Self {
42 pos: Vec3::ZERO,
43 z,
44 vertical_fov,
45 pitch: 0.0,
46 yaw: 0.0,
47 }
48 }
49
50 pub fn move_by(&mut self, forward: f32, right: f32) {
52 self.pos += self.get_forward() * forward + self.get_right() * right;
53 }
54
55 pub fn move_up(&mut self, up: f32) {
57 self.pos += Self::UP * up;
58 }
59
60 pub fn pitch_by(&mut self, delta: f32) {
62 self.pitch = (self.pitch + delta).clamp(Self::PITCH_LIMIT.start, Self::PITCH_LIMIT.end);
63 }
64
65 pub fn yaw_by(&mut self, delta: f32) {
67 self.yaw = (self.yaw + delta).rem_euclid(2.0 * std::f32::consts::PI);
68 }
69
70 pub fn get_forward(&self) -> Vec3 {
72 Vec3::new(
73 self.pitch.cos() * self.yaw.sin(),
74 self.pitch.sin(),
75 self.pitch.cos() * self.yaw.cos(),
76 )
77 }
78
79 pub fn get_right(&self) -> Vec3 {
81 self.get_forward().cross(Self::UP).normalize()
82 }
83}
84
85impl CameraTrait for Camera {
86 fn view(&self) -> Mat4 {
87 Mat4::look_to_rh(self.pos, self.get_forward(), Self::UP)
88 }
89
90 fn projection(&self, aspect_ratio: f32) -> Mat4 {
91 Mat4::perspective_rh(self.vertical_fov, aspect_ratio, self.z.start, self.z.end)
92 }
93}