Improve camera control to get a look at the scene

This commit is contained in:
hodasemi 2025-03-12 15:24:39 +01:00
parent e824cf8837
commit 994e6c4522
5 changed files with 114 additions and 33 deletions

View file

@ -41,10 +41,9 @@ impl AssetManager {
#[inline]
fn find_gltf_file(&self, name: &str) -> Option<&AssetPath> {
match self.gltf_file_map.get(name) {
Some(file) => Some(file),
None => self.glb_file_map.get(name),
}
self.gltf_file_map
.get(name)
.or_else(|| self.glb_file_map.get(name))
}
pub fn insert_cached_assets(&self, cache: &AssetCache) -> Result<()> {

View file

@ -134,8 +134,13 @@ impl FreeSpaceControl {
}
pub fn update(&mut self, now: Duration) {
let diff = match self.last_update {
Some(last_update) => now - last_update,
let diff = match &mut self.last_update {
Some(last_update) => {
let diff = now - *last_update;
*last_update = now;
diff
}
None => {
self.last_update = Some(now);
return;

View file

@ -1,3 +1,5 @@
use std::time::Duration;
use crate::prelude::{cgmath::*, *};
use anyhow::Result;
use context::prelude::cgmath::num_traits::clamp;
@ -29,12 +31,16 @@ pub struct FreeCameraControl {
mouse_position: (u32, u32),
velocity: Vector3<f32>,
hold_info: Option<HoldInfo>,
last_update: Option<Duration>,
}
impl FreeCameraControl {
const SCALE: f32 = 0.3;
const DEFAULT_DIR: Vector3<f32> = vec3(0.0, 1.0, 0.0);
const SPEED: f32 = 2.0;
pub fn new(view: &mut View) -> Result<Self> {
view.camera_mut().look_at(false);
@ -48,20 +54,50 @@ impl FreeCameraControl {
mouse_position: (0, 0),
velocity: Vector3::zero(),
hold_info: None,
last_update: None,
})
}
pub fn roll(&mut self, _view: &mut View) -> Result<()> {
todo!()
pub fn forward_back(&mut self, factor: f32) {
self.velocity.y += factor;
}
pub fn pitch(&mut self, _view: &mut View) -> Result<()> {
todo!()
pub fn left_right(&mut self, factor: f32) {
self.velocity.x += factor;
}
pub fn yaw(&mut self, _view: &mut View) -> Result<()> {
todo!()
pub fn up_down(&mut self, factor: f32) {
self.velocity.z += factor;
}
pub fn update(&mut self, now: Duration, view: &mut View) -> Result<()> {
let diff = match &mut self.last_update {
Some(last_update) => {
let diff = now - *last_update;
*last_update = now;
diff
}
None => {
self.last_update = Some(now);
return Ok(());
}
};
let current_center = view.camera().center();
let new_center = current_center
+ diff.as_secs_f32()
* Self::SPEED
* Matrix3::from_angle_z(self.yaw)
* Matrix3::from_angle_x(self.roll)
* self.velocity;
view.camera_mut().set_center(new_center);
view.update_buffer()
}
pub fn mouse_down(&mut self) {
@ -88,18 +124,6 @@ impl FreeCameraControl {
Ok(())
}
pub fn forward_back(&mut self, _view: &mut View) -> Result<()> {
todo!()
}
pub fn left_right(&mut self, _view: &mut View) -> Result<()> {
todo!()
}
pub fn up_down(&mut self, _view: &mut View) -> Result<()> {
todo!()
}
fn update_camera(&self, view: &mut View) -> Result<()> {
view.camera_mut().set_eye_dir(
Matrix3::from_angle_z(self.yaw) * Matrix3::from_angle_x(self.roll) * Self::DEFAULT_DIR,

View file

@ -4,7 +4,7 @@ use anyhow::Result;
use ecs::*;
use engine::prelude::{
cgmath::{Vector3, Vector4},
cgmath::{Vector3, Vector4, vec4},
*,
};
@ -85,7 +85,14 @@ impl InputSettings {
pub struct Game;
impl Game {
pub fn update(&mut self, _world: &mut World) -> Result<()> {
pub fn update(&mut self, world: &mut World) -> Result<()> {
let now = world.now();
let mut resources = world.resources.multi_mut();
let scene = resources.get::<Scene>();
let camera_control = resources.get::<FreeCameraControl>();
camera_control.update(now, scene.view_mut())?;
Ok(())
}
@ -94,6 +101,46 @@ impl Game {
let (fighter_object, resources) = world.entity_resources(player.0)?;
match event {
EngineEvent::MouseButtonDown(MouseButton::Left) => {
let camera_control = resources.get_mut::<FreeCameraControl>();
camera_control.mouse_down();
}
EngineEvent::MouseButtonUp(MouseButton::Left) => {
let camera_control = resources.get_mut::<FreeCameraControl>();
camera_control.mouse_release();
}
EngineEvent::MouseMotion(x, y) => {
let mut resources = resources.multi_mut();
let scene = resources.get::<Scene>();
let camera_control = resources.get::<FreeCameraControl>();
camera_control.mouse_move(x, y, scene.view_mut())?;
}
EngineEvent::KeyDown(key) => {
let camera_control = resources.get_mut::<FreeCameraControl>();
match key {
Keycode::W => camera_control.forward_back(1.0),
Keycode::A => camera_control.left_right(-1.0),
Keycode::S => camera_control.forward_back(-1.0),
Keycode::D => camera_control.left_right(1.0),
_ => (),
}
}
EngineEvent::KeyUp(key) => {
let camera_control = resources.get_mut::<FreeCameraControl>();
match key {
Keycode::W => camera_control.forward_back(-1.0),
Keycode::A => camera_control.left_right(1.0),
Keycode::S => camera_control.forward_back(1.0),
Keycode::D => camera_control.left_right(-1.0),
_ => (),
}
}
EngineEvent::JoystickAxis(joystick, axis_index, value) => {
let normalized = value as f32 * (i16::MAX as f32).recip();
let input_settings = resources.get::<InputSettings>();
@ -132,13 +179,13 @@ impl Game {
EmptyFilter,
)?;
world_builder.add_update("camera_position", 1_000, Self::camera_update, EmptyFilter)?;
// world_builder.add_update("camera_position", 1_000, Self::camera_update, EmptyFilter)?;
Ok(())
}
pub fn setup_scene(world: &mut World) -> Result<()> {
let mut fighter = AssetHandler::create(world).create_entity("fighter")?;
let mut fighter = AssetHandler::create(world).create_entity("craft_cargoA")?;
fighter.insert_component(FreeSpaceControl::new(FreeSpaceControlSettings::default()));
let player = PlayerEntity(world.add_entity(fighter)?);
@ -166,13 +213,15 @@ impl Game {
_entity: Entity,
control: &mut FreeSpaceControl,
) -> Result<()> {
const DEFAULT_CENTER: Vector4<f32> = vec4(0.0, 0.0, 0.0, 1.0);
let scene = world.resources.get_mut::<Scene>();
let view = scene.view_mut();
view.camera_mut()
.set_center((control.translation() * Vector4::unit_w()).truncate());
.set_center((control.translation() * DEFAULT_CENTER).truncate());
view.camera_mut()
.set_eye_dir(control.rotation() * Vector3::unit_y());
.set_eye_dir(control.rotation() * Vector3::unit_x());
view.update_buffer()
}

View file

@ -14,13 +14,17 @@ use skybox::SkyBox;
fn main() -> Result<()> {
let mut world_builder = World::builder();
Engine::new::<GameState>(EngineCreateInfo::default(), &mut world_builder)?;
let mut engine_ci = EngineCreateInfo::default();
engine_ci.resource_base_path = "/home/michaelh/Sync/space_game/".to_string();
engine_ci.asset_directories.gltf_file_directory = "objects".into();
engine_ci.raytracing_info.recursion_depth = 30;
Engine::new::<GameState>(engine_ci, &mut world_builder)?;
world_builder.add_system(GameState::update);
world_builder.resources.insert(GameState::default());
// let dir = Path::new("C:/Users/M.Huebner/Downloads/skybox");
let dir = Path::new("/home/michaelh/Sync/skybox");
let dir = Path::new("/home/michaelh/Sync/space_game/skybox");
SkyBox::new(
&mut world_builder,
[