summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHampusM <hampus@hampusmat.com>2023-11-27 20:51:26 +0100
committerHampusM <hampus@hampusmat.com>2023-11-27 20:51:59 +0100
commitd3f8b55aa971d1ef00345e80bc40365927bf08e5 (patch)
treee540378ba74323f59c994daeb88e4f0d0c910fb4
parentfe975af71dbb7c615a1e36920c6b8df3d41d1bdb (diff)
feat(engine): add support for custom camera implementations
-rw-r--r--engine/src/camera.rs102
-rw-r--r--engine/src/lib.rs23
-rw-r--r--engine/src/renderer/mod.rs34
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(