diff options
author | HampusM <hampus@hampusmat.com> | 2023-11-27 20:51:26 +0100 |
---|---|---|
committer | HampusM <hampus@hampusmat.com> | 2023-11-27 20:51:59 +0100 |
commit | d3f8b55aa971d1ef00345e80bc40365927bf08e5 (patch) | |
tree | e540378ba74323f59c994daeb88e4f0d0c910fb4 /engine/src | |
parent | fe975af71dbb7c615a1e36920c6b8df3d41d1bdb (diff) |
feat(engine): add support for custom camera implementations
Diffstat (limited to 'engine/src')
-rw-r--r-- | engine/src/camera.rs | 102 | ||||
-rw-r--r-- | engine/src/lib.rs | 23 | ||||
-rw-r--r-- | engine/src/renderer/mod.rs | 34 |
3 files changed, 48 insertions, 111 deletions
diff --git a/engine/src/camera.rs b/engine/src/camera.rs index fab92f5..1bae5bb 100644 --- a/engine/src/camera.rs +++ b/engine/src/camera.rs @@ -1,99 +1,19 @@ -use crate::matrix::Matrix; use crate::vector::Vec3; -#[derive(Debug)] -pub struct Camera +pub trait Camera { - position: Vec3<f32>, - target: Vec3<f32>, -} - -impl Camera -{ - pub fn set_position(&mut self, position: Vec3<f32>) - { - self.position = position; - } - - #[must_use] - pub fn position(&self) -> &Vec3<f32> - { - &self.position - } - - #[must_use] - pub fn position_mut(&mut self) -> &mut Vec3<f32> - { - &mut self.position - } - - pub fn set_target(&mut self, target: Vec3<f32>) - { - self.target = target; - } - - #[must_use] - pub fn target(&self) -> &Vec3<f32> - { - &self.target - } + /// Returns the current camera position. + fn position(&self) -> Vec3<f32>; - /// Returns the normalized direction to the current target. - #[must_use] - pub fn target_direction(&self) -> Vec3<f32> - { - -(&self.position - &self.target).normalize() - } + /// Returns the position of the camera target. + fn target(&self) -> Vec3<f32>; - /// Returns the right direction (normalized) relative from where the camera is - /// currently looking. - #[must_use] - pub fn right(&self) -> Vec3<f32> + /// Returns the global direction upwards. + /// + /// The default implementation which returns [`Vec3::UP`] should be fine in most + /// cases. + fn up(&self) -> Vec3<f32> { - let rev_target_direction = (&self.position - &self.target).normalize(); - - Vec3::UP.cross(&rev_target_direction).normalize() - } - - /// Returns the left direction (normalized) relative from where the camera is - /// currently looking. - #[must_use] - pub fn left(&self) -> Vec3<f32> - { - -self.right() - } - - /// Returns the up direction (normalized) relative from where the camera is currently - /// looking. - #[must_use] - pub fn up(&self) -> Vec3<f32> - { - let rev_target_direction = (&self.position - &self.target).normalize(); - - rev_target_direction.cross(&self.right()) - } - - /// Returns the down direction (normalized) relative from where the camera is - /// currently looking. - #[must_use] - pub fn down(&self) -> Vec3<f32> - { - -self.up() - } - - pub(crate) fn new() -> Self - { - let position = Vec3 { x: 0.0, y: 0.0, z: 3.0 }; - - Self { position, target: Vec3::default() } - } - - pub(crate) fn as_matrix(&self) -> Matrix<f32, 4, 4> - { - let mut matrix = Matrix::new(); - - matrix.look_at(&self.position, &self.target, &Vec3::UP); - - matrix + Vec3::UP } } diff --git a/engine/src/lib.rs b/engine/src/lib.rs index c4711f2..806d7ec 100644 --- a/engine/src/lib.rs +++ b/engine/src/lib.rs @@ -33,23 +33,29 @@ pub use glfw::window::Key; pub use glfw::WindowSize; #[derive(Debug)] -pub struct Engine +pub struct Engine<CameraT> { /// Objects have to be dropped before window. Otherwise, UB. objects: BTreeMap<ObjectId, Object>, light_source: Option<LightSource>, window: Window, - renderer: Renderer, + renderer: Renderer<CameraT>, delta_time: Duration, } -impl Engine +impl<CameraT> Engine<CameraT> +where + CameraT: Camera, { /// Creates and initializes a new engine. /// /// # Errors /// Will return `Err` if window creation or window configuration fails. - pub fn new(window_size: &WindowSize, window_title: &str) -> Result<Self, Error> + pub fn new( + window_size: &WindowSize, + window_title: &str, + camera: CameraT, + ) -> Result<Self, Error> { let window_builder = WindowBuilder::new(); @@ -66,10 +72,11 @@ impl Engine .map_err(Error::ConfigureWindowFailed)?; window.set_framebuffer_size_callback(move |new_window_size| { - Renderer::set_viewport(&Vec2::ZERO, &new_window_size); + Renderer::<CameraT>::set_viewport(&Vec2::ZERO, &new_window_size); }); - let renderer = Renderer::new(&window).map_err(Error::InitializeRendererFailed)?; + let renderer = + Renderer::new(&window, camera).map_err(Error::InitializeRendererFailed)?; Ok(Self { window, @@ -156,12 +163,12 @@ impl Engine } #[must_use] - pub fn camera(&self) -> &Camera + pub fn camera(&self) -> &CameraT { self.renderer.camera() } - pub fn camera_mut(&mut self) -> &mut Camera + pub fn camera_mut(&mut self) -> &mut CameraT { self.renderer.camera_mut() } diff --git a/engine/src/renderer/mod.rs b/engine/src/renderer/mod.rs index 593b55f..2c513ff 100644 --- a/engine/src/renderer/mod.rs +++ b/engine/src/renderer/mod.rs @@ -7,6 +7,7 @@ use glfw::WindowSize; use crate::camera::Camera; use crate::color::Color; use crate::lighting::LightSource; +use crate::matrix::Matrix; use crate::object::Object; use crate::opengl::buffer::{ ArrayKind as ArrayBufferKind, @@ -26,14 +27,16 @@ use crate::vector::{Vec2, Vec3}; use crate::vertex::Vertex; #[derive(Debug)] -pub struct Renderer +pub struct Renderer<CameraT> { - camera: Camera, + camera: CameraT, } -impl Renderer +impl<CameraT> Renderer<CameraT> +where + CameraT: Camera, { - pub fn new(window: &glfw::Window) -> Result<Self, Error> + pub fn new(window: &glfw::Window, camera: CameraT) -> Result<Self, Error> { gl::load_with(|symbol| { let proc_name = unsafe { CString::from_vec_unchecked(symbol.into()) }; @@ -60,8 +63,6 @@ impl Renderer enable(Capability::DepthTest); - let camera = Camera::new(); - Ok(Self { camera }) } @@ -116,12 +117,12 @@ impl Renderer } #[must_use] - pub fn camera(&self) -> &Camera + pub fn camera(&self) -> &CameraT { &self.camera } - pub fn camera_mut(&mut self) -> &mut Camera + pub fn camera_mut(&mut self) -> &mut CameraT { &mut self.camera } @@ -232,7 +233,7 @@ pub enum Error fn apply_transformation_matrices( object: &Object, - camera: &Camera, + camera: &impl Camera, window_size: &WindowSize, shader_program_curr_bound: &CurrentlyBound<ShaderProgram>, ) @@ -243,7 +244,7 @@ fn apply_transformation_matrices( &object.transform().as_matrix(), ); - let view = camera.as_matrix(); + let view = create_view(camera); object.renderable().shader_program.set_uniform_matrix_4fv( shader_program_curr_bound, @@ -269,7 +270,7 @@ fn apply_transformation_matrices( fn apply_light( obj: &Object, light_source: Option<&LightSource>, - camera: &Camera, + camera: &impl Camera, shader_program_curr_bound: &CurrentlyBound<ShaderProgram>, ) { @@ -341,10 +342,19 @@ fn apply_light( obj.renderable().shader_program.set_uniform_vec_3fv( shader_program_curr_bound, cstr!("view_pos"), - camera.position(), + &camera.position(), ); } +fn create_view(camera: &impl Camera) -> Matrix<f32, 4, 4> +{ + let mut view = Matrix::new(); + + view.look_at(&camera.position(), &camera.target(), &camera.up()); + + view +} + #[cfg(feature = "debug")] #[tracing::instrument(skip_all)] fn opengl_debug_message_cb( |