diff --git a/engine/src/scene/general/camera.rs b/engine/src/scene/general/camera.rs index bc3b4cf..4183a0f 100644 --- a/engine/src/scene/general/camera.rs +++ b/engine/src/scene/general/camera.rs @@ -1,11 +1,12 @@ use crate::prelude::*; use utilities::prelude::cgmath::{ - vec3, EuclideanSpace, InnerSpace, Matrix4, One, Point3, Rad, Vector3, Zero, + EuclideanSpace, InnerSpace, Matrix4, One, Point3, Rad, Vector3, Zero, vec3, }; #[derive(Clone)] pub struct Camera { eye_offset: Vector3, + eye_dir: Vector3, center: Vector3, center_offset: Vector3, up_vector: Vector3, @@ -15,6 +16,7 @@ pub struct Camera { eye_rotation: f32, view: Matrix4, + look_at: bool, update: bool, } @@ -23,6 +25,7 @@ impl Camera { pub fn new(fov: f32) -> Camera { let mut me = Camera { eye_offset: Vector3::zero(), + eye_dir: Vector3::unit_y(), center: Vector3::zero(), center_offset: Vector3::zero(), up_vector: vec3(0.0, 0.0, 1.0), @@ -32,6 +35,7 @@ impl Camera { eye_rotation: 0.0, view: Matrix4::one(), + look_at: true, update: true, }; @@ -41,6 +45,11 @@ impl Camera { me } + pub fn look_at(&mut self, look_at: bool) { + self.look_at = look_at; + self.update = true; + } + pub fn set_fov(&mut self, fov: f32) { let fovy = fov.to_radians() / 2.0; @@ -94,10 +103,15 @@ impl Camera { } // view matrix handling - pub fn eye_position(&self) -> Vector3 { + fn eye_position(&self) -> Vector3 { rotate_z(self.eye_offset, self.eye_rotation) + self.center + self.center_offset } + pub fn set_eye_dir(&mut self, eye_dir: Vector3) { + self.eye_dir = eye_dir; + self.update = true; + } + pub fn view_matrix(&mut self) -> Matrix4 { if self.update { self.calculate_view_matrix(); @@ -112,11 +126,19 @@ impl Camera { pub fn calculate_view_matrix(&mut self) { self.update = false; - self.view = Matrix4::look_at_rh( - Point3::from_vec(self.eye_position()), - Point3::from_vec(self.center + self.center_offset), - self.up_vector, - ); + self.view = if self.look_at { + Matrix4::look_at_rh( + Point3::from_vec(self.eye_position()), + Point3::from_vec(self.center + self.center_offset), + self.up_vector, + ) + } else { + Matrix4::look_to_rh( + Point3::from_vec(self.center + self.center_offset), + self.eye_dir, + self.up_vector, + ) + }; } pub fn tan(&self) -> f32 { @@ -140,6 +162,11 @@ impl Camera { self.up_vector } + pub fn set_up(&mut self, up: Vector3) { + self.up_vector = up; + self.update = true; + } + // calculation helper pub fn add_rotation(&mut self, rotation: f32) { self.eye_rotation += rotation; diff --git a/examples/simple_window/src/main.rs b/examples/simple_window/src/main.rs index 911ed58..1bfc2cf 100644 --- a/examples/simple_window/src/main.rs +++ b/examples/simple_window/src/main.rs @@ -1,9 +1,12 @@ -use std::path::Path; +use std::{path::Path, time::Duration}; use anyhow::Result; use ecs::*; -use engine::prelude::{cgmath::vec3, *}; +use engine::prelude::{ + cgmath::{Deg, Matrix3, Vector3, vec3}, + *, +}; use skybox::SkyBox; fn main() -> Result<()> { @@ -12,7 +15,7 @@ fn main() -> Result<()> { Engine::new::(EngineCreateInfo::default(), &mut world_builder)?; world_builder.add_system(GameState::update); - world_builder.resources.insert(GameState::Startup); + world_builder.resources.insert(GameState::default()); // let dir = Path::new("C:/Users/M.Huebner/Downloads/Space Skybox Generator/Export"); let dir = Path::new("/home/michaelh/Sync/skybox"); @@ -32,13 +35,17 @@ fn main() -> Result<()> { let view = world_builder.resources.get_mut::().view_mut(); let camera = view.camera_mut(); - camera.set_eye_offset(vec3(0.0, 1.0, 0.0)); + camera.look_at(false); + camera.set_center(vec3(0.0, 0.0, 0.0)); + camera.set_eye_dir(Vector3::unit_y()); view.update_buffer()?; world_builder.build().run() } +#[derive(Default)] enum GameState { + #[default] Startup, Loading, Menu, @@ -47,8 +54,10 @@ enum GameState { impl GameState { fn update(world: &mut World) -> Result { - match world.resources.get_mut_unchecked::() { - GameState::Startup => (), + let me = world.resources.get_mut_unchecked::(); + + match me { + GameState::Startup => *me = GameState::Game(Game { start: world.now() }), GameState::Loading => (), GameState::Menu => (), GameState::Game(game) => game.update(world)?, @@ -71,10 +80,24 @@ impl EventConsumer for GameState { } } -struct Game {} +struct Game { + start: Duration, +} impl Game { fn update(&mut self, world: &mut World) -> Result<()> { + let now = world.now(); + let view = world.resources.get_mut::().view_mut(); + let camera = view.camera_mut(); + + camera.set_eye_dir( + Matrix3::from_angle_z(Deg((now.as_secs_f32() - self.start.as_secs_f32()) + * 36.0 + * 2.0)) + * Vector3::unit_y(), + ); + view.update_buffer()?; + Ok(()) }