From 36fa7a9dea68be631f8e1383d3c98d29f23ffeca Mon Sep 17 00:00:00 2001 From: marceline-cramer Date: Tue, 15 Feb 2022 17:13:24 -0700 Subject: [PATCH] Decouple model handles from Renderer --- src/model.rs | 49 +++++++++++++++++++++---------------------------- src/renderer.rs | 29 +++++++++++++++++++++++++---- 2 files changed, 46 insertions(+), 32 deletions(-) diff --git a/src/model.rs b/src/model.rs index aae82d8..635c97d 100644 --- a/src/model.rs +++ b/src/model.rs @@ -4,6 +4,12 @@ use crate::pool::{MaterialData, TextureData}; use crate::renderer::Renderer; use crate::scene::MeshInstance; +pub trait OnLoad { + fn load_mesh(&mut self, mesh_data: &MeshData) -> MeshHandle; + fn load_texture(&mut self, texture_data: &TextureData) -> TextureHandle; + fn load_material(&mut self, material_data: &MaterialData) -> MaterialHandle; +} + pub struct BasicMesh { pub mesh_handle: MeshHandle, pub material_handle: MaterialHandle, @@ -24,7 +30,7 @@ pub struct ObjModel { } impl ObjModel { - pub fn load(ren: &mut Renderer) -> Self { + pub fn load(mut on_load: impl OnLoad) -> Self { use tobj::*; let model_data = include_bytes!("assets/viking_room/model.obj").to_vec(); @@ -64,7 +70,7 @@ impl ObjModel { indices.extend(m.mesh.indices.iter().map(|i| i + index_base)); let mesh_data = MeshData { vertices, indices }; - let mesh_handle = ren.mesh_pool.allocate(&ren.device, &mesh_data); + let mesh_handle = on_load.load_mesh(&mesh_data); let albedo_data = include_bytes!("assets/viking_room/albedo.png"); let albedo = image::load_from_memory(albedo_data).unwrap(); @@ -85,14 +91,10 @@ impl ObjModel { data: albedo_rgba, }; - let albedo = ren - .texture_pool - .allocate(&ren.device, &ren.queue, &albedo_data); + let albedo = on_load.load_texture(&albedo_data); let material_data = MaterialData { albedo }; - let material_handle = - ren.material_pool - .allocate(&ren.device, &ren.texture_pool, &material_data); + let material_handle = on_load.load_material(&material_data); let mesh = BasicMesh { mesh_handle, @@ -111,12 +113,12 @@ pub struct GltfModel { } impl GltfModel { - pub fn load(ren: &mut Renderer) -> Self { + pub fn load(on_load: impl OnLoad) -> Self { use gltf::*; let model_data = include_bytes!("assets/DamagedHelmet.glb"); let model = Gltf::from_slice(model_data.as_slice()).unwrap(); - let loader = GltfLoader::load(&model, ren); + let loader = GltfLoader::load(&model, on_load); Self { meshes: loader.meshes, @@ -130,21 +132,21 @@ impl GltfModel { } } -pub struct GltfLoader<'a> { +pub struct GltfLoader<'a, T: OnLoad> { pub model: &'a gltf::Gltf, pub buffers: Vec>, - pub ren: &'a mut Renderer, + pub on_load: T, pub meshes: Vec, } -impl<'a> GltfLoader<'a> { - pub fn load(model: &'a gltf::Gltf, ren: &'a mut Renderer) -> Self { +impl<'a, T: OnLoad> GltfLoader<'a, T> { + pub fn load(model: &'a gltf::Gltf, on_load: T) -> Self { let buffers = Self::load_buffers(model); let mut loader = Self { model, buffers, - ren, + on_load, meshes: Default::default(), }; @@ -199,11 +201,7 @@ impl<'a> GltfLoader<'a> { let base_color = pbr.base_color_texture().unwrap().texture(); let albedo = self.load_texture(base_color); - let material_data = MaterialData { albedo }; - - self.ren - .material_pool - .allocate(&self.ren.device, &self.ren.texture_pool, &material_data) + self.on_load.load_material(&MaterialData { albedo }) } pub fn load_texture(&mut self, texture: gltf::Texture) -> TextureHandle { @@ -234,15 +232,11 @@ impl<'a> GltfLoader<'a> { rgba }; - let data = TextureData { + self.on_load.load_texture(&TextureData { width: dimensions.0, height: dimensions.1, data: rgba, - }; - - self.ren - .texture_pool - .allocate(&self.ren.device, &self.ren.queue, &data) + }) } pub fn load_primitive_mesh(&mut self, primitive: gltf::Primitive) -> MeshHandle { @@ -281,8 +275,7 @@ impl<'a> GltfLoader<'a> { ReadIndices::U8(indices) => indices.map(|i| i as u32).collect(), }; - let mesh_data = MeshData { vertices, indices }; - self.ren.mesh_pool.allocate(&self.ren.device, &mesh_data) + self.on_load.load_mesh(&MeshData { vertices, indices }) } } diff --git a/src/renderer.rs b/src/renderer.rs index b6665a4..c651731 100644 --- a/src/renderer.rs +++ b/src/renderer.rs @@ -1,8 +1,10 @@ use super::camera::Camera; use super::commands::{Command, CommandSet}; -use super::mesh::Vertex; -use super::pool::{MaterialPool, MeshGroup, MeshPool, TexturePool}; -use super::scene::{Scene, PointLight}; +use super::mesh::{MeshData, Vertex}; +use super::pool::*; +use super::scene::{PointLight, Scene}; +use crate::handle::*; +use crate::model::OnLoad; use wgpu::util::DeviceExt; pub struct Renderer { @@ -255,7 +257,10 @@ impl Renderer { bytemuck::cast_slice(&[self.camera_uniform]), ); - let Scene { meshes, point_lights } = scene; + let Scene { + meshes, + point_lights, + } = scene; let mesh_commands = CommandSet::build(meshes); // TODO persistent staging buffer (write_buffer creates a new one per call) @@ -349,6 +354,22 @@ impl Renderer { } } +impl OnLoad for &mut Renderer { + fn load_mesh(&mut self, mesh_data: &MeshData) -> MeshHandle { + self.mesh_pool.allocate(&self.device, mesh_data) + } + + fn load_texture(&mut self, texture_data: &TextureData) -> TextureHandle { + self.texture_pool + .allocate(&self.device, &self.queue, texture_data) + } + + fn load_material(&mut self, material_data: &MaterialData) -> MaterialHandle { + self.material_pool + .allocate(&self.device, &self.texture_pool, material_data) + } +} + #[repr(C)] #[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)] struct CameraUniform {