use lyra_engine::{assets::{gltf::Gltf, ResourceManager}, ecs::query::{Res, ResMut, View}, game::Game, input::{Action, ActionHandler, ActionKind, ActionMapping, ActionMappingId, ActionSource, InputActionPlugin, KeyCode, LayoutId, MouseAxis, MouseInput}, math::{self, Quat, Transform, Vec3}, render::light::{directional::DirectionalLight, PointLight}, scene::{CameraComponent, FreeFlyCamera, FreeFlyCameraPlugin, ACTLBL_LOOK_LEFT_RIGHT, ACTLBL_LOOK_ROLL, ACTLBL_LOOK_UP_DOWN, ACTLBL_MOVE_FORWARD_BACKWARD, ACTLBL_MOVE_LEFT_RIGHT, ACTLBL_MOVE_UP_DOWN}, DeltaTime}; use rand::Rng; use tracing::info; const MAX_POINT_LIGHT_RANGE: f32 = 1.0; const MIN_POINT_LIGHT_RANGE: f32 = 0.5; const POINT_LIGHT_MAX_INTENSITY: f32 = 1.0; const POINT_LIGHT_MIN_INTENSITY: f32 = 0.3; const POINT_LIGHT_CUBE_SCALE: f32 = 0.2; const POINT_LIGHT_NUM: u32 = 500; const POINT_LIGHT_MAX_X: f32 = 9.0; const POINT_LIGHT_MIN_X: f32 = -9.0; const POINT_LIGHT_MAX_Y: f32 = 3.0; const POINT_LIGHT_MIN_Y: f32 = 0.5; const POINT_LIGHT_MAX_Z: f32 = 4.0; const POINT_LIGHT_MIN_Z: f32 = -5.0; #[async_std::main] async fn main() { let action_handler_plugin = |game: &mut Game| { let action_handler = ActionHandler::builder() .add_layout(LayoutId::from(0)) .add_action(ACTLBL_MOVE_FORWARD_BACKWARD, Action::new(ActionKind::Axis)) .add_action(ACTLBL_MOVE_LEFT_RIGHT, Action::new(ActionKind::Axis)) .add_action(ACTLBL_MOVE_UP_DOWN, Action::new(ActionKind::Axis)) .add_action(ACTLBL_LOOK_LEFT_RIGHT, Action::new(ActionKind::Axis)) .add_action(ACTLBL_LOOK_UP_DOWN, Action::new(ActionKind::Axis)) .add_action(ACTLBL_LOOK_ROLL, Action::new(ActionKind::Axis)) .add_action("Debug", Action::new(ActionKind::Button)) .add_mapping(ActionMapping::builder(LayoutId::from(0), ActionMappingId::from(0)) .bind(ACTLBL_MOVE_FORWARD_BACKWARD, &[ ActionSource::Keyboard(KeyCode::W).into_binding_modifier(1.0), ActionSource::Keyboard(KeyCode::S).into_binding_modifier(-1.0) ]) .bind(ACTLBL_MOVE_LEFT_RIGHT, &[ ActionSource::Keyboard(KeyCode::A).into_binding_modifier(-1.0), ActionSource::Keyboard(KeyCode::D).into_binding_modifier(1.0) ]) .bind(ACTLBL_MOVE_UP_DOWN, &[ ActionSource::Keyboard(KeyCode::C).into_binding_modifier(1.0), ActionSource::Keyboard(KeyCode::Z).into_binding_modifier(-1.0) ]) .bind(ACTLBL_LOOK_LEFT_RIGHT, &[ ActionSource::Mouse(MouseInput::Axis(MouseAxis::X)).into_binding(), ActionSource::Keyboard(KeyCode::Left).into_binding_modifier(-1.0), ActionSource::Keyboard(KeyCode::Right).into_binding_modifier(1.0), ]) .bind(ACTLBL_LOOK_UP_DOWN, &[ ActionSource::Mouse(MouseInput::Axis(MouseAxis::Y)).into_binding(), ActionSource::Keyboard(KeyCode::Up).into_binding_modifier(-1.0), ActionSource::Keyboard(KeyCode::Down).into_binding_modifier(1.0), ]) .bind(ACTLBL_LOOK_ROLL, &[ ActionSource::Keyboard(KeyCode::E).into_binding_modifier(-1.0), ActionSource::Keyboard(KeyCode::Q).into_binding_modifier(1.0), ]) .bind("Debug", &[ ActionSource::Keyboard(KeyCode::B).into_binding(), ]) .finish() ).finish(); let world = game.world_mut(); world.add_resource(action_handler); game.with_plugin(InputActionPlugin); }; Game::initialize().await .with_plugin(lyra_engine::DefaultPlugins) .with_plugin(setup_scene_plugin) .with_plugin(action_handler_plugin) .with_plugin(camera_debug_plugin) .with_plugin(FreeFlyCameraPlugin) .run().await; } fn setup_scene_plugin(game: &mut Game) { let fps_counter = |mut counter: ResMut, delta: Res| -> anyhow::Result<()> { let tick = counter.tick(); info!("FPS: {}, frame time: {}", tick, **delta); Ok(()) }; game.with_system("fps_counter", fps_counter, &[]); let world = game.world_mut(); world.add_resource(fps_counter::FPSCounter::new()); let resman = world.get_resource_mut::(); let cube_gltf = resman.request::("../assets/texture-sep/texture-sep.gltf").unwrap(); cube_gltf.wait_recurse_dependencies_load(); let cube_mesh = &cube_gltf.data_ref() .unwrap().meshes[0]; let sponza_model = resman.request::("../assets/sponza/Sponza.gltf").unwrap(); drop(resman); sponza_model.wait_recurse_dependencies_load(); let sponza_scene = &sponza_model.data_ref() .unwrap().scenes[0]; world.spawn(( sponza_scene.clone(), Transform::from_xyz(0.0, 0.0, 0.0), )); { let mut light_tran = Transform::from_xyz(1.5, 2.5, 0.0); light_tran.scale = Vec3::new(0.5, 0.5, 0.5); light_tran.rotate_x(math::Angle::Degrees(-45.0)); light_tran.rotate_y(math::Angle::Degrees(25.0)); world.spawn(( DirectionalLight { enabled: true, color: Vec3::ONE, intensity: 0.15 //..Default::default() }, light_tran, )); } let x_range = POINT_LIGHT_MIN_X..POINT_LIGHT_MAX_X; let y_range = POINT_LIGHT_MIN_Y..POINT_LIGHT_MAX_Y; let z_range = POINT_LIGHT_MIN_Z..POINT_LIGHT_MAX_Z; let mut rand = rand::thread_rng(); let mut rand_vec3 = || -> Vec3 { let x = rand.gen_range(x_range.clone()); let y = rand.gen_range(y_range.clone()); let z = rand.gen_range(z_range.clone()); Vec3::new(x, y, z) }; let mut rand = rand::thread_rng(); for _ in 0..POINT_LIGHT_NUM { let range = rand.gen_range(MIN_POINT_LIGHT_RANGE..MAX_POINT_LIGHT_RANGE); let intensity = rand.gen_range(POINT_LIGHT_MIN_INTENSITY..POINT_LIGHT_MAX_INTENSITY); let color = rand_vec3().normalize(); world.spawn(( PointLight { enabled: true, color, intensity, range, ..Default::default() }, Transform::new( rand_vec3(), Quat::IDENTITY, Vec3::new(POINT_LIGHT_CUBE_SCALE, POINT_LIGHT_CUBE_SCALE, POINT_LIGHT_CUBE_SCALE), ), cube_mesh.clone(), )); } let mut camera = CameraComponent::new_3d(); // these values were taken by manually positioning the camera in the scene. camera.transform = Transform::new( Vec3::new(-10.0, 0.94, -0.28), Quat::from_xyzw(0.03375484, -0.7116095, 0.0342693, 0.70092666), Vec3::ONE ); world.spawn(( camera, FreeFlyCamera::default() )); } fn camera_debug_plugin(game: &mut Game) { let sys = |handler: Res, view: View<&mut CameraComponent>| -> anyhow::Result<()> { if handler.was_action_just_pressed("Debug") { for mut cam in view.into_iter() { cam.debug = !cam.debug; } } Ok(()) }; game.with_system("camera_debug_trigger", sys, &[]); }