This commit is contained in:
reo 2025-08-30 12:55:42 +03:00
parent cc7921a5fe
commit 3692736a61
22 changed files with 447 additions and 44 deletions

2
Cargo.lock generated
View file

@ -1271,7 +1271,9 @@ name = "raidillon_game"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"glam", "glam",
"raidillon_assets",
"raidillon_core", "raidillon_core",
"raidillon_ecs",
"raidillon_glium", "raidillon_glium",
"raidillon_platform", "raidillon_platform",
] ]

View file

@ -1,10 +1,22 @@
pub mod model_manager; pub mod model_manager;
use std::path::PathBuf;
pub use crate::model_manager::{ModelManager, ModelManagerRef}; pub use crate::model_manager::{ModelManager, ModelManagerRef};
pub use crate::model_manager::ModelID; pub use crate::model_manager::ModelID;
#[macro_export] #[macro_export]
macro_rules! include_shader { macro_rules! include_shader {
($path:expr) => { ($path:expr) => {
include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/../assets/shaders/", $path)) include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/../assets/shaders/", $path))
}; };
} }
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)
}

View file

@ -4,14 +4,14 @@ use std::path::{Path, PathBuf};
use std::rc::Rc; use std::rc::Rc;
pub type ModelManagerRef = Rc<RefCell<Box<dyn ModelManager>>>; pub type ModelManagerRef = Rc<RefCell<Box<dyn ModelManager>>>;
pub type ModelID = PathBuf; pub type ModelID = &'static str;
/// The asset manager trait of Raidillon. /// The asset manager trait of Raidillon.
pub trait ModelManager: Any { pub trait ModelManager: Any {
/// Loads a gltf model to VRAM. /// 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. /// 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>; fn get_model(&self, id: &ModelID) -> Option<&dyn Any>;
} }

BIN
assets/models/monkey.bin Normal file

Binary file not shown.

104
assets/models/monkey.gltf Normal file
View file

@ -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"
}
]
}

Binary file not shown.

View file

@ -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"
}
]
}

BIN
assets/models/tree.bin Normal file

Binary file not shown.

140
assets/models/tree.gltf Normal file
View file

@ -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"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 845 B

View file

@ -4,4 +4,6 @@ use raidillon_assets::{ModelManagerRef, ModelManager};
pub struct PlatformContext { pub struct PlatformContext {
pub current_event: Event<()>, pub current_event: Event<()>,
pub asset_manager: ModelManagerRef, pub asset_manager: ModelManagerRef,
pub frame_width: f32,
pub frame_height: f32,
} }

View file

@ -4,31 +4,25 @@ use winit::event::Event;
use crate::SceneManager; use crate::SceneManager;
use crate::system::{SystemContext, SystemManager}; use crate::system::{SystemContext, SystemManager};
use raidillon_assets::{ModelManager, ModelManagerRef}; use raidillon_assets::{ModelManager, ModelManagerRef};
use crate::context::PlatformContext;
pub struct Engine { pub struct Engine {
pub scene_manager: SceneManager, pub scene_manager: SceneManager,
pub system_manager: SystemManager, pub system_manager: SystemManager,
pub assets_model_manager: Option<ModelManagerRef>,
winit_event: Option<Event<()>>,
} }
impl Engine { 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 { pub fn new() -> Self {
let scene_manager = SceneManager::new(); let scene_manager = SceneManager::new();
let system_manager = SystemManager::new(); let system_manager = SystemManager::new();
Self { Self {
scene_manager, scene_manager,
system_manager, system_manager,
assets_model_manager: None,
winit_event: None,
} }
} }
/// Run the first frame, load the world. /// Initialize systems, load the world.
pub fn initialize(&mut self) { pub fn initialize(&mut self, platform_context: PlatformContext) {
// Engine Loading Stage 1: initialize systems // Engine Loading Stage 1: initialize systems
for (system_id, system) in self.system_manager.systems.iter_mut() { for (system_id, system) in self.system_manager.systems.iter_mut() {
system.initialize(); system.initialize();
@ -36,7 +30,7 @@ impl Engine {
let mut ctx = SystemContext { let mut ctx = SystemContext {
scene: self.scene_manager.current_mut(), scene: self.scene_manager.current_mut(),
event: self.winit_event.clone(), platform_context,
}; };
// Engine Loading Stage 2: load world // Engine Loading Stage 2: load world
@ -45,11 +39,11 @@ impl Engine {
} }
} }
/// Runs every frame /// Update the engine
pub fn update(&mut self) { pub fn update(&mut self, platform_context: PlatformContext) {
let mut ctx = SystemContext { let mut ctx = SystemContext {
scene: self.scene_manager.current_mut(), scene: self.scene_manager.current_mut(),
event: self.winit_event.clone(), platform_context,
}; };
for (system_id, system) in self.system_manager.systems.iter_mut() { 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 { // pub fn build_system_context(&mut self) -> SystemContext {
// SystemContext { // SystemContext {
// scene: self.scene_manager.current_mut(), // scene: self.scene_manager.current_mut(),

View file

@ -1,6 +1,7 @@
mod scene; mod scene;
mod engine; mod engine;
pub mod system; pub mod system;
pub mod context;
pub use scene::{Scene, SceneManager}; pub use scene::{Scene, SceneManager};
pub use engine::Engine; pub use engine::Engine;

View file

@ -1,11 +1,12 @@
use crate::Scene; use crate::Scene;
use indexmap::IndexMap; use indexmap::IndexMap;
use winit::event::Event; use winit::event::Event;
use crate::context::PlatformContext;
pub struct SystemContext<'a> { pub struct SystemContext<'a> {
// TODO: time delta etc. // TODO: time delta etc.
pub scene: &'a mut Scene, pub scene: &'a mut Scene,
pub event: Option<Event<()>>, pub platform_context: PlatformContext,
} }
pub trait System { pub trait System {

View file

@ -13,3 +13,5 @@ impl Transform {
Mat4::from_scale_rotation_translation(self.scale, self.rotation, self.translation) Mat4::from_scale_rotation_translation(self.scale, self.rotation, self.translation)
} }
} }
pub struct ModelHandle(pub ModelID);

View file

@ -10,5 +10,7 @@ glium = ["raidillon_glium"]
[dependencies] [dependencies]
raidillon_core = { path = "../core" } raidillon_core = { path = "../core" }
raidillon_platform = { path = "../platform" } raidillon_platform = { path = "../platform" }
raidillon_assets = { path = "../asset" }
raidillon_ecs = { path = "../ecs" }
raidillon_glium = { path = "../glium_platform", optional = true } raidillon_glium = { path = "../glium_platform", optional = true }
glam = "0.30.5" glam = "0.30.5"

View file

@ -1,11 +1,16 @@
use glam::Vec3; use std::path::Path;
use glam::{Quat, Vec3};
use raidillon_core::{Engine, Scene, System}; use raidillon_core::{Engine, Scene, System};
use raidillon_core::system::SystemContext; use raidillon_core::system::SystemContext;
use raidillon_platform::{Platform, Camera}; use raidillon_platform::{Platform, Camera};
use raidillon_assets::model_path;
use raidillon_ecs::components::ModelHandle;
use raidillon_ecs::Transform;
#[cfg(feature = "glium")] #[cfg(feature = "glium")]
use raidillon_glium::GliumPlatform; use raidillon_glium::GliumPlatform;
const TEST_GLTF: &str = "pink-monkey.gltf";
const RENDERING_TEST_SYSTEM: &str = "rendering_test_system"; const RENDERING_TEST_SYSTEM: &str = "rendering_test_system";
struct RenderingTestSystem; struct RenderingTestSystem;
@ -17,12 +22,23 @@ impl System for RenderingTestSystem {
center: Vec3::ZERO, center: Vec3::ZERO,
up: Vec3::Y, up: Vec3::Y,
fovy: 60_f32.to_radians(), 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, znear: 0.1,
zfar: 100.0, 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) {} fn update(&mut self, ctx: &mut SystemContext) {}

View file

@ -12,7 +12,7 @@ use raidillon_assets::model_manager::ModelID;
/// Glium platform asset manager implementation. /// Glium platform asset manager implementation.
pub struct GliumAssetManager { pub struct GliumAssetManager {
pub models: HashMap<PathBuf, Model>, pub models: HashMap<ModelID, Model>,
facade: Box<dyn Facade>, facade: Box<dyn Facade>,
} }
@ -27,13 +27,13 @@ impl GliumAssetManager {
} }
impl ModelManager for 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(); 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) { fn unload_model(&mut self, id: ModelID) {
self.models.remove(&path.to_path_buf()); self.models.remove(&id);
} }
// fn get_model(&mut self, path: &Path) -> &Self::Model { // fn get_model(&mut self, path: &Path) -> &Self::Model {

View file

@ -2,7 +2,7 @@ use std::cell::RefCell;
use std::rc::Rc; use std::rc::Rc;
use std::str::FromStr; use std::str::FromStr;
use std::sync::{Arc, RwLock}; use std::sync::{Arc, RwLock};
use raidillon_platform::Platform; use raidillon_platform::{Platform, PlatformContext};
use glium::winit::event_loop::EventLoop; use glium::winit::event_loop::EventLoop;
use glium::winit::window::Window; use glium::winit::window::Window;
use glium::backend::glutin::Display; 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 asset_manager: ModelManagerRef = Rc::new(RefCell::new(Box::new(GliumAssetManager::new(Box::new(display.clone())))));
let mut rendering_system_manager = RenderingSystemManager::new(); let mut rendering_system_manager = RenderingSystemManager::new();
engine.set_model_manager(asset_manager.clone());
// Install rendering systems // Install rendering systems
rendering_system_manager.add_system( rendering_system_manager.add_system(
@ -59,7 +58,14 @@ impl Platform for GliumPlatform {
} }
fn run(mut self) { 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| { let _ = &self.event_loop.run(move |event, el| {
match event { match event {
Event::WindowEvent { event, .. } => match event { Event::WindowEvent { event, .. } => match event {
@ -69,7 +75,7 @@ impl Platform for GliumPlatform {
}, },
WindowEvent::RedrawRequested => { WindowEvent::RedrawRequested => {
let mut target = self.display.draw(); 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; // TODO: let mut context;
let mut context = RenderingContext { let mut context = RenderingContext {
scene: self.engine.scene_manager.current_mut(), scene: self.engine.scene_manager.current_mut(),
@ -85,8 +91,13 @@ impl Platform for GliumPlatform {
_ => {}, _ => {},
}, },
Event::AboutToWait => { Event::AboutToWait => {
self.engine.set_winit_event(event.clone()); let ctx = PlatformContext {
self.engine.update(); 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(); self.window.request_redraw();
} }
_ => {}, _ => {},

View file

@ -9,6 +9,7 @@ pub use raidillon_platform::Camera;
use glam::Vec3; use glam::Vec3;
use glium::uniforms::{MagnifySamplerFilter, MinifySamplerFilter, SamplerWrapFunction}; use glium::uniforms::{MagnifySamplerFilter, MinifySamplerFilter, SamplerWrapFunction};
use raidillon_ecs::{Transform, ModelID}; use raidillon_ecs::{Transform, ModelID};
use raidillon_ecs::components::ModelHandle;
use crate::model::Model; use crate::model::Model;
/// A basic renderer pipeline step. /// A basic renderer pipeline step.
@ -65,8 +66,8 @@ impl RenderingSystem for BasicMeshRenderingSystem {
let asset_manager = ctx.asset_manager.borrow(); let asset_manager = ctx.asset_manager.borrow();
for (_, (tr, mh)) in ctx.scene.world.query::<(&Transform, &ModelID)>().iter() { for (_, (tr, mh)) in ctx.scene.world.query::<(&Transform, &ModelHandle)>().iter() {
let model = match asset_manager.get_model(mh) { let model = match asset_manager.get_model(&mh.0) {
Some(model) => model, Some(model) => model,
_ => continue, _ => continue,
}; };

View file

@ -3,3 +3,4 @@ mod camera;
pub use platform::Platform; pub use platform::Platform;
pub use camera::Camera; pub use camera::Camera;
pub use raidillon_core::context::PlatformContext;

View file

@ -1,5 +1,6 @@
use raidillon_assets::ModelManager; use raidillon_assets::ModelManager;
use raidillon_core::Engine; use raidillon_core::Engine;
use crate::PlatformContext;
pub trait Platform { pub trait Platform {
/// Initialize platform. /// Initialize platform.