diff options
| author | Micha White <botahamec@outlook.com> | 2022-09-24 18:20:46 -0400 |
|---|---|---|
| committer | Micha White <botahamec@outlook.com> | 2022-09-24 18:20:46 -0400 |
| commit | c29555bddac1c0027bf6e15d91e219adaa088065 (patch) | |
| tree | 59e671e4ded20b58027987053e207e4fe6a51307 /src/camera.rs | |
| parent | 7f364d2642784fcffea730b1f168270ce907a27c (diff) | |
Implemented a camera
Diffstat (limited to 'src/camera.rs')
| -rw-r--r-- | src/camera.rs | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/src/camera.rs b/src/camera.rs new file mode 100644 index 0000000..2eb1730 --- /dev/null +++ b/src/camera.rs @@ -0,0 +1,95 @@ +use cgmath::{Matrix4, Vector3}; + +#[derive(Clone, Copy, Debug, PartialEq)] +pub struct Camera { + position: (f32, f32), + zoom: f32, + rotation: f32, + inverse_aspect_ratio: f32, +} + +pub(crate) type CameraUniform = [[f32; 4]; 4]; + +#[allow(clippy::cast_precision_loss)] +fn inverse_aspect_ratio(width: u32, height: u32) -> f32 { + (height as f32) / (width as f32) +} + +impl Camera { + /// Create a new camera, with a position of (0, 0), and a zoom of 1.0 + pub(crate) fn from_size(width: u32, height: u32) -> Self { + Self { + position: (0.0, 0.0), + zoom: 1.0, + rotation: 0.0, + inverse_aspect_ratio: inverse_aspect_ratio(width, height), + } + } + + /// Get the camera's current x position + #[must_use] + pub const fn x(&self) -> f32 { + self.position.0 + } + + /// Get the camera's current y position + #[must_use] + pub const fn y(&self) -> f32 { + self.position.1 + } + + /// Get the camera's current zoom + #[must_use] + pub const fn zoom(&self) -> f32 { + self.zoom + } + + /// Set the position of the camera + pub fn set_position(&mut self, x: f32, y: f32) { + self.position = (x, y); + } + + /// Set the aspect ratio of the camera + pub fn set_zoom(&mut self, zoom: f32) { + self.zoom = zoom; + } + + /// Set the aspect ratio of the camera + pub(crate) fn set_size(&mut self, width: u32, height: u32) { + self.inverse_aspect_ratio = inverse_aspect_ratio(width, height); + } + + #[allow(clippy::wrong_self_convention)] + pub(crate) fn to_matrix(&mut self) -> [[f32; 4]; 4] { + let cos_theta = self.rotation.cos(); + let sin_theta = self.rotation.sin(); + + let x_axis = Vector3::new(cos_theta, -sin_theta, 0.0); + let y_axis = Vector3::new(sin_theta, cos_theta, 0.0); + let z_axis = Vector3::new(0.0, 0.0, 1.0); + + let eye = Vector3::new(self.position.0, self.position.1, 0.0); + let x_dot = -cgmath::dot(x_axis, eye); + let y_dot = -cgmath::dot(y_axis, eye); + let z_dot = -cgmath::dot(z_axis, eye); + + #[rustfmt::skip] + let view_matrix = Matrix4::new( + x_axis.x, y_axis.x, z_axis.x, 0.0, + x_axis.y, y_axis.y, z_axis.y, 0.0, + x_axis.x, y_axis.y, z_axis.z, 0.0, + x_dot, y_dot, z_dot, 1.0 + ); + + #[rustfmt::skip] + // TODO implement more scaling coordinate systems + let projection_matrix = Matrix4::new( + self.inverse_aspect_ratio, 0.0, 0.0, 0.0, + 0.0, self.zoom, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 1.0 + ); + + (projection_matrix * view_matrix).into() + } +} |
