use super::DepthCalculation; use bevy_math::Mat4; use bevy_reflect::{Reflect, ReflectDeserialize}; use serde::{Deserialize, Serialize}; pub trait CameraProjection { fn get_projection_matrix(&self) -> Mat4; fn update(&mut self, width: usize, height: usize); fn depth_calculation(&self) -> DepthCalculation; } #[derive(Debug, Clone, Reflect)] pub struct PerspectiveProjection { pub fov: f32, pub aspect_ratio: f32, pub near: f32, pub far: f32, } impl CameraProjection for PerspectiveProjection { fn get_projection_matrix(&self) -> Mat4 { Mat4::perspective_rh(self.fov, self.aspect_ratio, self.near, self.far) } fn update(&mut self, width: usize, height: usize) { self.aspect_ratio = width as f32 / height as f32; } fn depth_calculation(&self) -> DepthCalculation { DepthCalculation::Distance } } impl Default for PerspectiveProjection { fn default() -> Self { PerspectiveProjection { fov: std::f32::consts::PI / 4.0, near: 1.0, far: 1000.0, aspect_ratio: 1.0, } } } // TODO: make this a component instead of a property #[derive(Debug, Clone, Reflect, Serialize, Deserialize)] #[reflect_value(Serialize, Deserialize)] pub enum WindowOrigin { Center, BottomLeft, } #[derive(Debug, Clone, Reflect)] pub struct OrthographicProjection { pub left: f32, pub right: f32, pub bottom: f32, pub top: f32, pub near: f32, pub far: f32, pub window_origin: WindowOrigin, } impl CameraProjection for OrthographicProjection { fn get_projection_matrix(&self) -> Mat4 { Mat4::orthographic_rh( self.left, self.right, self.bottom, self.top, self.near, self.far, ) } fn update(&mut self, width: usize, height: usize) { match self.window_origin { WindowOrigin::Center => { let half_width = width as f32 / 2.0; let half_height = height as f32 / 2.0; self.left = -half_width; self.right = half_width; self.top = half_height; self.bottom = -half_height; } WindowOrigin::BottomLeft => { self.left = 0.0; self.right = width as f32; self.top = height as f32; self.bottom = 0.0; } } } fn depth_calculation(&self) -> DepthCalculation { DepthCalculation::ZDifference } } impl Default for OrthographicProjection { fn default() -> Self { OrthographicProjection { left: 0.0, right: 0.0, bottom: 0.0, top: 0.0, near: 0.0, far: 1000.0, window_origin: WindowOrigin::Center, } } }