diff --git a/crates/viewer/src/camera.rs b/crates/viewer/src/camera.rs index 8ae4d3e..b4f20b4 100644 --- a/crates/viewer/src/camera.rs +++ b/crates/viewer/src/camera.rs @@ -1,5 +1,5 @@ use crate::controls::*; -use math::cgmath::{InnerSpace, Matrix3, Matrix4, Point3, Rad, Vector3, Zero}; +use math::cgmath::{Deg, InnerSpace, Matrix3, Matrix4, Point3, Rad, Vector3, Zero}; use math::clamp; const MIN_ORBITAL_CAMERA_DISTANCE: f32 = 0.5; @@ -7,13 +7,37 @@ const TARGET_MOVEMENT_SPEED: f32 = 0.003; const ROTATION_SPEED_DEG: f32 = 0.4; pub const DEFAULT_FPS_MOVE_SPEED: f32 = 6.0; +pub const DEFAULT_FOV: f32 = 45.0; +pub const DEFAULT_Z_NEAR: f32 = 0.01; +pub const DEFAULT_Z_FAR: f32 = 100.0; + #[derive(Debug, Clone, Copy)] -pub enum Camera { + +pub struct Camera { + mode: Mode, + pub fov: Deg, + pub z_near: f32, + pub z_far: f32, +} + +impl Default for Camera { + fn default() -> Self { + Self { + mode: Default::default(), + fov: Deg(DEFAULT_FOV), + z_near: DEFAULT_Z_NEAR, + z_far: DEFAULT_Z_FAR, + } + } +} + +#[derive(Debug, Clone, Copy)] +enum Mode { Orbital(Orbital), Fps(Fps), } -impl Default for Camera { +impl Default for Mode { fn default() -> Self { Self::Orbital(Default::default()) } @@ -21,49 +45,51 @@ impl Default for Camera { impl Camera { pub fn update(&mut self, input: &InputState, delta_time_secs: f32) { - match self { - Self::Orbital(c) => c.update(input, delta_time_secs), - Self::Fps(c) => c.update(input, delta_time_secs), + match &mut self.mode { + Mode::Orbital(c) => c.update(input, delta_time_secs), + Mode::Fps(c) => c.update(input, delta_time_secs), } } pub fn position(&self) -> Point3 { - match self { - Self::Orbital(c) => c.position(), - Self::Fps(c) => c.position(), + match self.mode { + Mode::Orbital(c) => c.position(), + Mode::Fps(c) => c.position(), } } pub fn target(&self) -> Point3 { - match self { - Self::Orbital(c) => c.target(), - Self::Fps(c) => c.target(), + match self.mode { + Mode::Orbital(c) => c.target(), + Mode::Fps(c) => c.target(), } } pub fn to_orbital(self) -> Self { - match self { - Self::Orbital(_) => self, - Self::Fps(c) => Self::Orbital(c.into()), - } + let mode = match self.mode { + Mode::Orbital(_) => self.mode, + Mode::Fps(c) => Mode::Orbital(c.into()), + }; + Self { mode, ..self } } pub fn to_fps(self) -> Self { - match self { - Self::Fps(_) => self, - Self::Orbital(c) => Self::Fps(c.into()), - } + let mode = match self.mode { + Mode::Fps(_) => self.mode, + Mode::Orbital(c) => Mode::Fps(c.into()), + }; + Self { mode, ..self } } pub fn set_move_speed(&mut self, move_speed: f32) { - if let Self::Fps(c) = self { + if let Mode::Fps(c) = &mut self.mode { c.move_speed = move_speed; } } } #[derive(Debug, Clone, Copy)] -pub struct Orbital { +struct Orbital { theta: f32, phi: f32, r: f32, @@ -158,7 +184,7 @@ impl Orbital { } #[derive(Debug, Clone, Copy)] -pub struct Fps { +struct Fps { position: Point3, direction: Vector3, move_speed: f32, diff --git a/crates/viewer/src/gui.rs b/crates/viewer/src/gui.rs index 72e4772..9054b66 100644 --- a/crates/viewer/src/gui.rs +++ b/crates/viewer/src/gui.rs @@ -1,8 +1,9 @@ use crate::camera::Camera; use crate::renderer::{OutputMode, RendererSettings, ToneMapMode, DEFAULT_BLOOM_STRENGTH}; -use crate::DEFAULT_FPS_MOVE_SPEED; +use crate::{DEFAULT_FOV, DEFAULT_FPS_MOVE_SPEED, DEFAULT_Z_FAR, DEFAULT_Z_NEAR}; use egui::{ClippedPrimitive, Context, TexturesDelta, Ui, ViewportId, Widget}; use egui_winit::State as EguiWinit; +use math::cgmath::Deg; use model::{metadata::*, PlaybackState}; use vulkan::winit::event::WindowEvent; use vulkan::winit::window::Window as WinitWindow; @@ -142,6 +143,18 @@ impl Gui { self.state.camera_mode } + pub fn camera_fov(&self) -> Deg { + Deg(self.state.camera_fov) + } + + pub fn camera_z_near(&self) -> f32 { + self.state.camera_z_near + } + + pub fn camera_z_far(&self) -> f32 { + self.state.camera_z_far + } + pub fn camera_move_speed(&self) -> f32 { self.state.camera_move_speed } @@ -247,14 +260,37 @@ fn build_camera_details_window(ui: &mut Ui, state: &mut State, camera: Option, @@ -383,7 +422,6 @@ impl State { ssao_kernel_size_index: self.ssao_kernel_size_index, ssao_enabled: self.ssao_enabled, camera_mode: self.camera_mode, - camera_move_speed: self.camera_move_speed, ..Default::default() } } @@ -413,6 +451,9 @@ impl Default for State { camera_mode: CameraMode::Orbital, camera_move_speed: DEFAULT_FPS_MOVE_SPEED, + camera_fov: DEFAULT_FOV, + camera_z_near: DEFAULT_Z_NEAR, + camera_z_far: DEFAULT_Z_FAR, reset_camera: false, hdr_enabled: None, diff --git a/crates/viewer/src/main.rs b/crates/viewer/src/main.rs index 24d7e33..54e9919 100644 --- a/crates/viewer/src/main.rs +++ b/crates/viewer/src/main.rs @@ -140,6 +140,9 @@ fn run(config: Config, enable_debug: bool, path: Option) { gui::CameraMode::Fps => camera.to_fps(), }; + camera.fov = gui.camera_fov(); + camera.z_near = gui.camera_z_near(); + camera.z_far = gui.camera_z_far(); camera.set_move_speed(gui.camera_move_speed()); if !gui.is_hovered() { diff --git a/crates/viewer/src/renderer/mod.rs b/crates/viewer/src/renderer/mod.rs index 524c796..f605798 100644 --- a/crates/viewer/src/renderer/mod.rs +++ b/crates/viewer/src/renderer/mod.rs @@ -22,7 +22,7 @@ use ash::{vk, Device}; use egui::{ClippedPrimitive, TextureId}; use egui_ash_renderer::{DynamicRendering, Options, Renderer as GuiRenderer}; use environment::Environment; -use math::cgmath::{Deg, Matrix4, SquareMatrix, Vector3}; +use math::cgmath::{Matrix4, SquareMatrix, Vector3}; use model_crate::Model; use std::cell::RefCell; use std::mem::size_of; @@ -1030,12 +1030,13 @@ impl Renderer { Vector3::new(0.0, 1.0, 0.0), ); - const Z_NEAR: f32 = 0.01; - const Z_FAR: f32 = 100.0; - let proj = math::perspective(Deg(45.0), aspect, Z_NEAR, Z_FAR); + let z_near = camera.z_near; + let z_far = camera.z_far; + + let proj = math::perspective(camera.fov, aspect, z_near, z_far); let inverted_proj = proj.invert().unwrap(); - let ubo = CameraUBO::new(view, proj, inverted_proj, camera.position(), Z_NEAR, Z_FAR); + let ubo = CameraUBO::new(view, proj, inverted_proj, camera.position(), z_near, z_far); let buffer = &mut self.camera_uniform_buffers[frame_index]; unsafe { let data_ptr = buffer.map_memory();