use std::error::Error; use std::fs::read_to_string; use std::path::Path; use engine::camera::fly::{ Extension as FlyCameraExtension, Fly as FlyCamera, Options as FlyCameraOptions, }; use engine::camera::{Active as ActiveCamera, Camera}; use engine::color::Color; use engine::data_types::dimens::Dimens; use engine::ecs::phase::START as START_PHASE; use engine::ecs::sole::Single; use engine::file_format::wavefront::mtl::parse as parse_mtl; use engine::file_format::wavefront::obj::parse as parse_obj; use engine::input::Extension as InputExtension; use engine::lighting::{AttenuationParams, GlobalLight, PointLight}; use engine::material::{Builder as MaterialBuilder, Flags as MaterialFlags}; use engine::renderer::opengl::Extension as OpenglRendererExtension; use engine::transform::Position; use engine::vector::Vec3; use engine::window::{ Builder as WindowBuilder, CursorMode, Extension as WindowExtension, Window, }; use engine::Engine; use tracing::Level; use tracing_subscriber::FmtSubscriber; const WINDOW_SIZE: Dimens = Dimens { width: 1920, height: 1080 }; const YELLOW: Color = Color { red: 0.988235294118, green: 0.941176470588, blue: 0.0274509803922, }; const RESOURCE_DIR: &str = "res"; fn main() -> Result<(), Box> { let subscriber = FmtSubscriber::builder() .with_max_level(Level::TRACE) .finish(); tracing::subscriber::set_global_default(subscriber)?; let mut engine = Engine::new(); let teapot_obj = parse_obj(&read_to_string(Path::new(RESOURCE_DIR).join("teapot.obj"))?)?; let teapot_mat_name = teapot_obj .faces .first() .and_then(|face| face.material_name.as_ref()); let teapot_mats = teapot_obj.read_and_parse_material_libs(parse_mtl)?; let teapot_mat = teapot_mats .into_iter() .find(|mat| Some(&mat.name) == teapot_mat_name) .ok_or("Teapot material was not found")?; engine.spawn(( teapot_obj.to_mesh()?, teapot_mat.material, Position::from(Vec3 { x: 1.6, y: 0.0, z: 0.0 }), )); engine.spawn(( PointLight::builder() .position(Vec3 { x: -6.0, y: 3.0, z: 3.0 }) .diffuse(YELLOW) .attenuation_params(AttenuationParams { linear: 0.045, quadratic: 0.0075, ..Default::default() }) .build(), Position::from(Vec3 { x: -6.0, y: 3.0, z: 3.0 }), parse_obj(&read_to_string(Path::new(RESOURCE_DIR).join("cube.obj"))?)? .to_mesh()?, MaterialBuilder::new().ambient(YELLOW * 5.0).build(), MaterialFlags::builder().use_ambient_color(true).build(), )); engine.spawn(( Camera::default(), Position { position: Vec3 { x: 0.0, y: 0.0, z: 3.0 }, }, ActiveCamera, FlyCamera::default(), )); engine.add_sole(GlobalLight::default())?; engine.register_system(*START_PHASE, prepare_window); engine.add_extension(OpenglRendererExtension::default()); engine.add_extension( WindowExtension::new(WindowBuilder::default().multisampling_sample_count(8)) .window_title("Game") .window_size(WINDOW_SIZE), ); engine.add_extension(FlyCameraExtension(FlyCameraOptions { mouse_sensitivity: 0.2, })); engine.add_extension(InputExtension::default()); engine.start(); Ok(()) } fn prepare_window(window: Single) { window.set_cursor_mode(CursorMode::Disabled).unwrap(); }