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"
dependencies = [
"glam",
"raidillon_assets",
"raidillon_core",
"raidillon_ecs",
"raidillon_glium",
"raidillon_platform",
]

View file

@ -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))
};
}
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;
pub type ModelManagerRef = Rc<RefCell<Box<dyn ModelManager>>>;
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>;
}

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 current_event: Event<()>,
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::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<ModelManagerRef>,
winit_event: Option<Event<()>>,
}
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(),

View file

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

View file

@ -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<Event<()>>,
pub platform_context: PlatformContext,
}
pub trait System {

View file

@ -13,3 +13,5 @@ impl Transform {
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]
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"

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::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) {}

View file

@ -12,7 +12,7 @@ use raidillon_assets::model_manager::ModelID;
/// Glium platform asset manager implementation.
pub struct GliumAssetManager {
pub models: HashMap<PathBuf, Model>,
pub models: HashMap<ModelID, Model>,
facade: Box<dyn Facade>,
}
@ -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 {

View file

@ -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();
}
_ => {},

View file

@ -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,
};

View file

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

View file

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