Create simple keyboard controlled free fly camera
ci/woodpecker/push/build Pipeline was successful Details

This commit is contained in:
SeanOMik 2023-10-24 20:03:27 -04:00
parent 4191a463f5
commit 249b87afed
Signed by: SeanOMik
GPG Key ID: 568F326C7EB33ACB
7 changed files with 149 additions and 11 deletions

View File

@ -2313,6 +2313,7 @@ version = "0.1.0"
dependencies = [
"anyhow",
"async-std",
"edict",
"fps_counter",
"lyra-engine",
"tracing",

View File

@ -11,5 +11,6 @@ anyhow = "1.0.75"
async-std = "1.12.0"
tracing = "0.1.37"
fps_counter = "2.0.0"
edict = "0.5.0"
[workspace]

View File

@ -0,0 +1,122 @@
use std::ops::Deref;
use edict::{World, Component};
use lyra_engine::{math::{Vec3, Angle, Quat}, input::{InputButtons, KeyCode, MouseMotion}, ecs::{SimpleSystem, components::camera::CameraComponent, EventQueue}, game::Game, plugin::Plugin};
use tracing::debug;
#[derive(Clone, Component)]
pub struct FreeFlyCamera {
pub speed: f32,
pub look_speed: f32,
pub look_with_keys: bool
}
impl Default for FreeFlyCamera {
fn default() -> Self {
Self {
speed: 0.07,
look_speed: 0.01,
look_with_keys: false
}
}
}
impl FreeFlyCamera {
pub fn new(speed: f32, look_speed: f32, look_with_keys: bool) -> Self {
Self {
speed,
look_speed,
look_with_keys
}
}
}
pub struct FreeFlyCameraController;
impl SimpleSystem for FreeFlyCameraController {
fn execute_mut(&mut self, world: &mut World) -> anyhow::Result<()> {
let mut camera_rot = Vec3::default();
let keys = world.get_resource::<InputButtons<KeyCode>>()
.map(|r| r.deref().clone());
if keys.is_none() {
return Ok(());
}
let keys = keys.unwrap();
if keys.is_pressed(KeyCode::Left) {
camera_rot.y += 1.0;
}
if keys.is_pressed(KeyCode::Right) {
camera_rot.y -= 1.0;
}
if keys.is_pressed(KeyCode::Up) {
camera_rot.x += 1.0;
}
if keys.is_pressed(KeyCode::Down) {
camera_rot.x -= 1.0;
}
if keys.is_pressed(KeyCode::E) {
camera_rot.z -= 1.0;
}
if keys.is_pressed(KeyCode::Q) {
camera_rot.z += 1.0;
}
let camera_rot = camera_rot.normalize();
for (cam, fly) in world.query_mut::<(&mut CameraComponent, &mut FreeFlyCamera)>().iter_mut() {
let forward = cam.transform.forward();
let left = cam.transform.left();
let up = cam.transform.up();
let mut velocity = Vec3::ZERO;
if keys.is_pressed(KeyCode::A) {
velocity -= left;
}
if keys.is_pressed(KeyCode::D) {
velocity += left;
}
if keys.is_pressed(KeyCode::W) {
velocity += forward;
}
if keys.is_pressed(KeyCode::S) {
velocity -= forward;
}
if keys.is_pressed(KeyCode::C) {
velocity += up;
}
if keys.is_pressed(KeyCode::Z) {
velocity -= up;
}
if velocity != Vec3::ZERO {
cam.transform.translation += velocity.normalize() * fly.speed;
}
if !camera_rot.is_nan() {
let look_velocity = camera_rot.normalize() * fly.look_speed;
cam.transform.rotation *= Quat::from_rotation_x(look_velocity.x) * Quat::from_rotation_y(look_velocity.y) * Quat::from_rotation_z(look_velocity.z);
}
}
Ok(())
}
}
impl Plugin for FreeFlyCameraController {
fn setup(&self, game: &mut Game) {
game.with_system("free_fly_camera_controller", FreeFlyCameraController, &[]);
}
}

View File

@ -1,9 +1,11 @@
use lyra_engine::{math, ecs::{World, components::{transform::TransformComponent, camera::CameraComponent, model::ModelComponent}, EventQueue}, math::Transform, input::{KeyCode, InputButtons, MouseMotion}, game::Game};
use lyra_engine::{math::{self, Vec3}, ecs::{World, components::{transform::TransformComponent, camera::CameraComponent, model::ModelComponent}, EventQueue, SimpleSystem, Component}, math::Transform, input::{KeyCode, InputButtons, MouseMotion}, game::Game, plugin::Plugin, render::window::{CursorGrabMode, WindowOptions}, change_tracker::Ct};
use lyra_engine::assets::{ResourceManager, Model};
use tracing::debug;
mod free_fly_camera;
use free_fly_camera::{FreeFlyCameraController, FreeFlyCamera};
/* pub const VERTICES: &[Vertex] = &[
Vertex { position: [-0.0868241, 0.49240386, 0.0], tex_coords: [0.4131759, 0.00759614], }, // A
Vertex { position: [-0.49513406, 0.06958647, 0.0], tex_coords: [0.0048659444, 0.43041354], }, // B
@ -46,8 +48,8 @@ async fn main() {
let mut camera = CameraComponent::new_3d();
camera.transform.translation += math::Vec3::new(0.0, 0.0, 7.5);
//camera.transform.rotate_y(Angle::Degrees(-25.0));
camera.transform.rotate_z(math::Angle::Degrees(-90.0));
world.spawn((camera,));
//camera.transform.rotate_z(math::Angle::Degrees(-90.0));
world.spawn(( camera, FreeFlyCamera::default() ));
Ok(())
};
@ -156,7 +158,7 @@ async fn main() {
};
let jiggle_plugin = move |game: &mut Game| {
game.with_system("jiggle", jiggle_system, &["input"]);
//game.with_system("jiggle", jiggle_system, &["input"]);
};
Game::initialize().await
@ -164,5 +166,6 @@ async fn main() {
.with_startup_system(setup_sys)
//.with_plugin(fps_plugin)
.with_plugin(jiggle_plugin)
.with_plugin(FreeFlyCameraController)
.run().await;
}

View File

@ -139,6 +139,7 @@ pub struct CursorEnteredWindow;
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct CursorLeftWindow;
#[derive(Clone)]
pub struct InputButtons<T: Clone + Hash + Eq + PartialEq + 'static> {
// the u64 as the key is the hashed value of T. this makes it easier to
// search for a button and see its state

View File

@ -56,7 +56,17 @@ impl Transform {
/// Get the forward vector of the Transform.
pub fn forward(&self) -> Vec3 {
self.rotation * ONE_V3
(self.rotation * -Vec3::Z).normalize()
}
/// Get the left vector of the Transform.
pub fn left(&self) -> Vec3 {
(self.rotation * Vec3::X).normalize()
}
/// Get the up vector of the Transform.
pub fn up(&self) -> Vec3 {
(self.rotation * Vec3::Y).normalize()
}
/// Rotate this transform using a Quaternion

View File

@ -66,13 +66,13 @@ impl RenderCamera {
match camera.mode {
CameraProjectionMode::Perspective => {
let position = camera.transform.translation;
let target = camera.transform.rotation * glam::Vec3::new(0.0, 0.0, -1.0);
let target = target.normalize();
let forward = camera.transform.forward();
let up = camera.transform.up();
let view = glam::Mat4::look_to_rh(
position,
target,
glam::Vec3::new(0.0, 1.0, 0.0)
forward,
up
);
let proj = glam::Mat4::perspective_rh_gl(camera.fov.to_radians(), self.aspect, self.znear, self.zfar);