diff --git a/Cargo.lock b/Cargo.lock index 308e9da..0c0aafe 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1271,7 +1271,9 @@ name = "raidillon_game" version = "0.1.0" dependencies = [ "glam", + "raidillon_assets", "raidillon_core", + "raidillon_ecs", "raidillon_glium", "raidillon_platform", ] diff --git a/asset/src/lib.rs b/asset/src/lib.rs index f0349ac..617ced9 100644 --- a/asset/src/lib.rs +++ b/asset/src/lib.rs @@ -1,10 +1,22 @@ pub mod model_manager; + +use std::path::PathBuf; pub use crate::model_manager::{ModelManager, ModelManagerRef}; pub use crate::model_manager::ModelID; + #[macro_export] macro_rules! include_shader { ($path:expr) => { include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/../assets/shaders/", $path)) }; -} \ No newline at end of file +} + +pub fn model_path(path: &str) -> PathBuf { + let manifest_dir = env!("CARGO_MANIFEST_DIR"); + PathBuf::from(manifest_dir) + .join("..") + .join("assets") + .join("models") + .join(path) +} diff --git a/asset/src/model_manager.rs b/asset/src/model_manager.rs index 4f1a9bb..2989a3b 100644 --- a/asset/src/model_manager.rs +++ b/asset/src/model_manager.rs @@ -4,14 +4,14 @@ use std::path::{Path, PathBuf}; use std::rc::Rc; pub type ModelManagerRef = Rc>>; -pub type ModelID = PathBuf; +pub type ModelID = &'static str; /// The asset manager trait of Raidillon. pub trait ModelManager: Any { /// Loads a gltf model to VRAM. - fn load_gltf(&mut self, path: &Path); + fn load_gltf(&mut self, id: ModelID, path: &Path); /// Unloads the loaded model from VRAM. - fn unload_model(&mut self, path: &Path); + fn unload_model(&mut self, id: ModelID); fn get_model(&self, id: &ModelID) -> Option<&dyn Any>; } diff --git a/assets/models/monkey.bin b/assets/models/monkey.bin new file mode 100644 index 0000000..e7992f3 Binary files /dev/null and b/assets/models/monkey.bin differ diff --git a/assets/models/monkey.gltf b/assets/models/monkey.gltf new file mode 100644 index 0000000..d3e2438 --- /dev/null +++ b/assets/models/monkey.gltf @@ -0,0 +1,104 @@ +{ + "asset":{ + "generator":"Khronos glTF Blender I/O v4.4.56", + "version":"2.0" + }, + "scene":0, + "scenes":[ + { + "name":"Scene", + "nodes":[ + 0 + ] + } + ], + "nodes":[ + { + "mesh":0, + "name":"Suzanne" + } + ], + "meshes":[ + { + "name":"Suzanne", + "primitives":[ + { + "attributes":{ + "POSITION":0, + "NORMAL":1, + "TEXCOORD_0":2 + }, + "indices":3 + } + ] + } + ], + "accessors":[ + { + "bufferView":0, + "componentType":5126, + "count":1966, + "max":[ + 1.3671875, + 0.984375, + 0.8515625 + ], + "min":[ + -1.3671875, + -0.984375, + -0.8515625 + ], + "type":"VEC3" + }, + { + "bufferView":1, + "componentType":5126, + "count":1966, + "type":"VEC3" + }, + { + "bufferView":2, + "componentType":5126, + "count":1966, + "type":"VEC2" + }, + { + "bufferView":3, + "componentType":5123, + "count":2904, + "type":"SCALAR" + } + ], + "bufferViews":[ + { + "buffer":0, + "byteLength":23592, + "byteOffset":0, + "target":34962 + }, + { + "buffer":0, + "byteLength":23592, + "byteOffset":23592, + "target":34962 + }, + { + "buffer":0, + "byteLength":15728, + "byteOffset":47184, + "target":34962 + }, + { + "buffer":0, + "byteLength":5808, + "byteOffset":62912, + "target":34963 + } + ], + "buffers":[ + { + "byteLength":68720, + "uri":"monkey.bin" + } + ] +} diff --git a/assets/models/pink-monkey.bin b/assets/models/pink-monkey.bin new file mode 100644 index 0000000..2db4596 Binary files /dev/null and b/assets/models/pink-monkey.bin differ diff --git a/assets/models/pink-monkey.gltf b/assets/models/pink-monkey.gltf new file mode 100644 index 0000000..a27e895 --- /dev/null +++ b/assets/models/pink-monkey.gltf @@ -0,0 +1,121 @@ +{ + "asset":{ + "generator":"Khronos glTF Blender I/O v4.0.44", + "version":"2.0" + }, + "scene":0, + "scenes":[ + { + "name":"Scene", + "nodes":[ + 0 + ] + } + ], + "nodes":[ + { + "mesh":0, + "name":"Suzanne" + } + ], + "materials":[ + { + "doubleSided":true, + "name":"Material.001", + "pbrMetallicRoughness":{ + "baseColorFactor":[ + 0.8002749681472778, + 0, + 0.07706787437200546, + 1 + ], + "metallicFactor":0, + "roughnessFactor":0.5 + } + } + ], + "meshes":[ + { + "name":"Suzanne", + "primitives":[ + { + "attributes":{ + "POSITION":0, + "NORMAL":1, + "TEXCOORD_0":2 + }, + "indices":3, + "material":0 + } + ] + } + ], + "accessors":[ + { + "bufferView":0, + "componentType":5126, + "count":1966, + "max":[ + 1.3671875, + 0.984375, + 0.8515625 + ], + "min":[ + -1.3671875, + -0.984375, + -0.8515625 + ], + "type":"VEC3" + }, + { + "bufferView":1, + "componentType":5126, + "count":1966, + "type":"VEC3" + }, + { + "bufferView":2, + "componentType":5126, + "count":1966, + "type":"VEC2" + }, + { + "bufferView":3, + "componentType":5123, + "count":2904, + "type":"SCALAR" + } + ], + "bufferViews":[ + { + "buffer":0, + "byteLength":23592, + "byteOffset":0, + "target":34962 + }, + { + "buffer":0, + "byteLength":23592, + "byteOffset":23592, + "target":34962 + }, + { + "buffer":0, + "byteLength":15728, + "byteOffset":47184, + "target":34962 + }, + { + "buffer":0, + "byteLength":5808, + "byteOffset":62912, + "target":34963 + } + ], + "buffers":[ + { + "byteLength":68720, + "uri":"pink-monkey.bin" + } + ] +} diff --git a/assets/models/tree.bin b/assets/models/tree.bin new file mode 100644 index 0000000..e782621 Binary files /dev/null and b/assets/models/tree.bin differ diff --git a/assets/models/tree.gltf b/assets/models/tree.gltf new file mode 100644 index 0000000..51bf9ed --- /dev/null +++ b/assets/models/tree.gltf @@ -0,0 +1,140 @@ +{ + "asset":{ + "generator":"Khronos glTF Blender I/O v4.4.56", + "version":"2.0" + }, + "scene":0, + "scenes":[ + { + "name":"Scene", + "nodes":[ + 0 + ] + } + ], + "nodes":[ + { + "mesh":0, + "name":"tree01", + "scale":[ + 0.009999999776482582, + 0.009999999776482582, + 0.009999999776482582 + ] + } + ], + "materials":[ + { + "name":"Mat", + "pbrMetallicRoughness":{ + "baseColorTexture":{ + "index":0 + }, + "metallicFactor":0 + } + } + ], + "meshes":[ + { + "name":"tree01_1", + "primitives":[ + { + "attributes":{ + "POSITION":0, + "NORMAL":1, + "TEXCOORD_0":2 + }, + "indices":3, + "material":0 + } + ] + } + ], + "textures":[ + { + "sampler":0, + "source":0 + } + ], + "images":[ + { + "mimeType":"image/png", + "name":"tree_texture", + "uri":"tree_texture.png" + } + ], + "accessors":[ + { + "bufferView":0, + "componentType":5126, + "count":395, + "max":[ + 123.4296646118164, + 509.0864562988281, + 168.36563110351562 + ], + "min":[ + -184.9799346923828, + 0, + -155.37196350097656 + ], + "type":"VEC3" + }, + { + "bufferView":1, + "componentType":5126, + "count":395, + "type":"VEC3" + }, + { + "bufferView":2, + "componentType":5126, + "count":395, + "type":"VEC2" + }, + { + "bufferView":3, + "componentType":5123, + "count":471, + "type":"SCALAR" + } + ], + "bufferViews":[ + { + "buffer":0, + "byteLength":4740, + "byteOffset":0, + "target":34962 + }, + { + "buffer":0, + "byteLength":4740, + "byteOffset":4740, + "target":34962 + }, + { + "buffer":0, + "byteLength":3160, + "byteOffset":9480, + "target":34962 + }, + { + "buffer":0, + "byteLength":942, + "byteOffset":12640, + "target":34963 + } + ], + "samplers":[ + { + "magFilter":9729, + "minFilter":9987 + } + ], + "buffers":[ + { + "byteLength":13584, + "uri":"tree.bin" + } + ] +} diff --git a/assets/models/tree_texture.png b/assets/models/tree_texture.png new file mode 100644 index 0000000..f5726d4 Binary files /dev/null and b/assets/models/tree_texture.png differ diff --git a/platform/src/context.rs b/core/src/context.rs similarity index 77% rename from platform/src/context.rs rename to core/src/context.rs index ff3072b..01db2f9 100644 --- a/platform/src/context.rs +++ b/core/src/context.rs @@ -4,4 +4,6 @@ use raidillon_assets::{ModelManagerRef, ModelManager}; pub struct PlatformContext { pub current_event: Event<()>, pub asset_manager: ModelManagerRef, + pub frame_width: f32, + pub frame_height: f32, } diff --git a/core/src/engine.rs b/core/src/engine.rs index eae1e74..6eb000f 100644 --- a/core/src/engine.rs +++ b/core/src/engine.rs @@ -4,31 +4,25 @@ use winit::event::Event; use crate::SceneManager; use crate::system::{SystemContext, SystemManager}; use raidillon_assets::{ModelManager, ModelManagerRef}; +use crate::context::PlatformContext; pub struct Engine { pub scene_manager: SceneManager, pub system_manager: SystemManager, - pub assets_model_manager: Option, - winit_event: Option>, } impl Engine { - /// Initialize the engine. - /// Engine is expected to be initialized after the platform, so reasonably - /// it takes platform-dependent structures while being initialized. pub fn new() -> Self { let scene_manager = SceneManager::new(); let system_manager = SystemManager::new(); Self { scene_manager, system_manager, - assets_model_manager: None, - winit_event: None, } } - /// Run the first frame, load the world. - pub fn initialize(&mut self) { + /// Initialize systems, load the world. + pub fn initialize(&mut self, platform_context: PlatformContext) { // Engine Loading Stage 1: initialize systems for (system_id, system) in self.system_manager.systems.iter_mut() { system.initialize(); @@ -36,7 +30,7 @@ impl Engine { let mut ctx = SystemContext { scene: self.scene_manager.current_mut(), - event: self.winit_event.clone(), + platform_context, }; // Engine Loading Stage 2: load world @@ -45,11 +39,11 @@ impl Engine { } } - /// Runs every frame - pub fn update(&mut self) { + /// Update the engine + pub fn update(&mut self, platform_context: PlatformContext) { let mut ctx = SystemContext { scene: self.scene_manager.current_mut(), - event: self.winit_event.clone(), + platform_context, }; for (system_id, system) in self.system_manager.systems.iter_mut() { @@ -57,14 +51,6 @@ impl Engine { } } - pub fn set_winit_event(&mut self, event: Event<()>) { - self.winit_event = Some(event); - } - - pub fn set_model_manager(&mut self, model_manager: ModelManagerRef) { - self.assets_model_manager = Some(model_manager); - } - // pub fn build_system_context(&mut self) -> SystemContext { // SystemContext { // scene: self.scene_manager.current_mut(), diff --git a/core/src/lib.rs b/core/src/lib.rs index 0527964..6fddfd0 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -1,6 +1,7 @@ mod scene; mod engine; pub mod system; +pub mod context; pub use scene::{Scene, SceneManager}; pub use engine::Engine; diff --git a/core/src/system.rs b/core/src/system.rs index 7bc5a94..4412d7b 100644 --- a/core/src/system.rs +++ b/core/src/system.rs @@ -1,11 +1,12 @@ use crate::Scene; use indexmap::IndexMap; use winit::event::Event; +use crate::context::PlatformContext; pub struct SystemContext<'a> { // TODO: time delta etc. pub scene: &'a mut Scene, - pub event: Option>, + pub platform_context: PlatformContext, } pub trait System { diff --git a/ecs/src/components.rs b/ecs/src/components.rs index 83bc7df..758f0f4 100644 --- a/ecs/src/components.rs +++ b/ecs/src/components.rs @@ -13,3 +13,5 @@ impl Transform { Mat4::from_scale_rotation_translation(self.scale, self.rotation, self.translation) } } + +pub struct ModelHandle(pub ModelID); diff --git a/game/Cargo.toml b/game/Cargo.toml index 835bf39..e8fac5f 100644 --- a/game/Cargo.toml +++ b/game/Cargo.toml @@ -10,5 +10,7 @@ glium = ["raidillon_glium"] [dependencies] raidillon_core = { path = "../core" } raidillon_platform = { path = "../platform" } +raidillon_assets = { path = "../asset" } +raidillon_ecs = { path = "../ecs" } raidillon_glium = { path = "../glium_platform", optional = true } -glam = "0.30.5" \ No newline at end of file +glam = "0.30.5" diff --git a/game/src/main.rs b/game/src/main.rs index e0403c7..e4d1136 100644 --- a/game/src/main.rs +++ b/game/src/main.rs @@ -1,11 +1,16 @@ -use glam::Vec3; +use std::path::Path; +use glam::{Quat, Vec3}; use raidillon_core::{Engine, Scene, System}; use raidillon_core::system::SystemContext; use raidillon_platform::{Platform, Camera}; - +use raidillon_assets::model_path; +use raidillon_ecs::components::ModelHandle; +use raidillon_ecs::Transform; #[cfg(feature = "glium")] use raidillon_glium::GliumPlatform; +const TEST_GLTF: &str = "pink-monkey.gltf"; + const RENDERING_TEST_SYSTEM: &str = "rendering_test_system"; struct RenderingTestSystem; @@ -17,12 +22,23 @@ impl System for RenderingTestSystem { center: Vec3::ZERO, up: Vec3::Y, fovy: 60_f32.to_radians(), - aspect: 1920 as f32 / 1080 as f32, // FIXME + aspect: ctx.platform_context.frame_width / ctx.platform_context.frame_height, znear: 0.1, zfar: 100.0, },)); - // TODO: Load a sample glTF file + let mut am = ctx.platform_context.asset_manager.borrow_mut(); + + am.load_gltf(TEST_GLTF, &model_path(TEST_GLTF)); + + ctx.scene.world.spawn(( + Transform { + translation: Vec3::new(0.0, 0.0, 0.0), + rotation: Quat::IDENTITY, + scale: Vec3::new(1.0, 1.0, 1.0), + }, + ModelHandle(TEST_GLTF), + )); } fn update(&mut self, ctx: &mut SystemContext) {} diff --git a/glium_platform/src/assets.rs b/glium_platform/src/assets.rs index 6d33887..1b3b4e1 100644 --- a/glium_platform/src/assets.rs +++ b/glium_platform/src/assets.rs @@ -12,7 +12,7 @@ use raidillon_assets::model_manager::ModelID; /// Glium platform asset manager implementation. pub struct GliumAssetManager { - pub models: HashMap, + pub models: HashMap, facade: Box, } @@ -27,13 +27,13 @@ impl GliumAssetManager { } impl ModelManager for GliumAssetManager { - fn load_gltf(&mut self, path: &Path) { + fn load_gltf(&mut self, id: ModelID, path: &Path) { let model = load_gltf(path, self.facade.as_ref()).unwrap(); - self.models.insert(path.to_path_buf(), model); + self.models.insert(id, model); } - fn unload_model(&mut self, path: &Path) { - self.models.remove(&path.to_path_buf()); + fn unload_model(&mut self, id: ModelID) { + self.models.remove(&id); } // fn get_model(&mut self, path: &Path) -> &Self::Model { diff --git a/glium_platform/src/platform.rs b/glium_platform/src/platform.rs index 69b0735..9a491c2 100644 --- a/glium_platform/src/platform.rs +++ b/glium_platform/src/platform.rs @@ -2,7 +2,7 @@ use std::cell::RefCell; use std::rc::Rc; use std::str::FromStr; use std::sync::{Arc, RwLock}; -use raidillon_platform::Platform; +use raidillon_platform::{Platform, PlatformContext}; use glium::winit::event_loop::EventLoop; use glium::winit::window::Window; use glium::backend::glutin::Display; @@ -40,7 +40,6 @@ impl Platform for GliumPlatform { let asset_manager: ModelManagerRef = Rc::new(RefCell::new(Box::new(GliumAssetManager::new(Box::new(display.clone()))))); let mut rendering_system_manager = RenderingSystemManager::new(); - engine.set_model_manager(asset_manager.clone()); // Install rendering systems rendering_system_manager.add_system( @@ -59,7 +58,14 @@ impl Platform for GliumPlatform { } fn run(mut self) { - self.engine.initialize(); + let (w, h): (u32, u32) = self.window.inner_size().into(); + let ctx = PlatformContext { + current_event: Event::AboutToWait, + asset_manager: self.asset_manager.clone(), + frame_width: w as f32, + frame_height: h as f32, + }; + self.engine.initialize(ctx); let _ = &self.event_loop.run(move |event, el| { match event { Event::WindowEvent { event, .. } => match event { @@ -69,7 +75,7 @@ impl Platform for GliumPlatform { }, WindowEvent::RedrawRequested => { let mut target = self.display.draw(); - target.clear_color(0.0, 0.0, 0.0, 1.0); + target.clear_color_and_depth((0.1, 0.1, 0.15, 1.0), 1.0); // TODO: let mut context; let mut context = RenderingContext { scene: self.engine.scene_manager.current_mut(), @@ -85,8 +91,13 @@ impl Platform for GliumPlatform { _ => {}, }, Event::AboutToWait => { - self.engine.set_winit_event(event.clone()); - self.engine.update(); + let ctx = PlatformContext { + current_event: event.clone(), + asset_manager: self.asset_manager.clone(), + frame_width: w as f32, + frame_height: h as f32, + }; + self.engine.update(ctx); self.window.request_redraw(); } _ => {}, diff --git a/glium_platform/src/render/basic.rs b/glium_platform/src/render/basic.rs index 66ffadf..60e7621 100644 --- a/glium_platform/src/render/basic.rs +++ b/glium_platform/src/render/basic.rs @@ -9,6 +9,7 @@ pub use raidillon_platform::Camera; use glam::Vec3; use glium::uniforms::{MagnifySamplerFilter, MinifySamplerFilter, SamplerWrapFunction}; use raidillon_ecs::{Transform, ModelID}; +use raidillon_ecs::components::ModelHandle; use crate::model::Model; /// A basic renderer pipeline step. @@ -65,8 +66,8 @@ impl RenderingSystem for BasicMeshRenderingSystem { let asset_manager = ctx.asset_manager.borrow(); - for (_, (tr, mh)) in ctx.scene.world.query::<(&Transform, &ModelID)>().iter() { - let model = match asset_manager.get_model(mh) { + for (_, (tr, mh)) in ctx.scene.world.query::<(&Transform, &ModelHandle)>().iter() { + let model = match asset_manager.get_model(&mh.0) { Some(model) => model, _ => continue, }; diff --git a/platform/src/lib.rs b/platform/src/lib.rs index 0750166..3ff1a65 100644 --- a/platform/src/lib.rs +++ b/platform/src/lib.rs @@ -3,3 +3,4 @@ mod camera; pub use platform::Platform; pub use camera::Camera; +pub use raidillon_core::context::PlatformContext; diff --git a/platform/src/platform.rs b/platform/src/platform.rs index b0250e4..3e0309f 100644 --- a/platform/src/platform.rs +++ b/platform/src/platform.rs @@ -1,5 +1,6 @@ use raidillon_assets::ModelManager; use raidillon_core::Engine; +use crate::PlatformContext; pub trait Platform { /// Initialize platform.