Create a material type for loading materials
This commit is contained in:
parent
dabc051b58
commit
792596078d
|
@ -10,7 +10,7 @@ anyhow = "1.0.75"
|
||||||
base64 = "0.21.4"
|
base64 = "0.21.4"
|
||||||
edict = "0.5.0"
|
edict = "0.5.0"
|
||||||
glam = "0.24.1"
|
glam = "0.24.1"
|
||||||
gltf = "1.3.0"
|
gltf = { version = "1.3.0", features = ["KHR_materials_pbrSpecularGlossiness"] }
|
||||||
image = "0.24.7"
|
image = "0.24.7"
|
||||||
percent-encoding = "2.3.0"
|
percent-encoding = "2.3.0"
|
||||||
thiserror = "1.0.48"
|
thiserror = "1.0.48"
|
||||||
|
|
|
@ -12,3 +12,6 @@ pub use loader::*;
|
||||||
|
|
||||||
pub mod model;
|
pub mod model;
|
||||||
pub use model::*;
|
pub use model::*;
|
||||||
|
|
||||||
|
pub mod material;
|
||||||
|
pub use material::*;
|
|
@ -2,7 +2,7 @@ use std::sync::Arc;
|
||||||
|
|
||||||
use base64::Engine;
|
use base64::Engine;
|
||||||
|
|
||||||
use crate::{ResourceLoader, LoaderError, Mesh, Model, MeshVertexAttribute, VertexAttributeData, Resource};
|
use crate::{ResourceLoader, LoaderError, Mesh, Model, MeshVertexAttribute, VertexAttributeData, Resource, Material, PbrRoughness};
|
||||||
|
|
||||||
impl From<gltf::Error> for LoaderError {
|
impl From<gltf::Error> for LoaderError {
|
||||||
fn from(value: gltf::Error) -> Self {
|
fn from(value: gltf::Error) -> Self {
|
||||||
|
@ -30,7 +30,7 @@ impl ModelLoader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_node(&self, buffers: &Vec<Vec<u8>>, node: gltf::Node<'_>) -> Vec<Mesh> {
|
fn process_node(&self, buffers: &Vec<Vec<u8>>, materials: &Vec<Material>, node: gltf::Node<'_>) -> Vec<Mesh> {
|
||||||
let mut meshes = vec![];
|
let mut meshes = vec![];
|
||||||
if let Some(mesh) = node.mesh() {
|
if let Some(mesh) = node.mesh() {
|
||||||
for prim in mesh.primitives() {
|
for prim in mesh.primitives() {
|
||||||
|
@ -73,12 +73,14 @@ impl ModelLoader {
|
||||||
new_mesh.indices = Some(indices);
|
new_mesh.indices = Some(indices);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
prim.material().
|
||||||
|
|
||||||
meshes.push(new_mesh);
|
meshes.push(new_mesh);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for child in node.children() {
|
for child in node.children() {
|
||||||
let mut child_meshes = self.process_node(buffers, child);
|
let mut child_meshes = self.process_node(buffers, materials, child);
|
||||||
meshes.append(&mut child_meshes);
|
meshes.append(&mut child_meshes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,10 +111,18 @@ impl ResourceLoader for ModelLoader {
|
||||||
// TODO: Read in multiple scenes
|
// TODO: Read in multiple scenes
|
||||||
let scene = gltf.scenes().next().unwrap();
|
let scene = gltf.scenes().next().unwrap();
|
||||||
|
|
||||||
// TODO: materials
|
// Load the materials
|
||||||
|
let materials: Vec<Material> = gltf.materials()
|
||||||
|
.map(|mat| Material {
|
||||||
|
double_sided: mat.double_sided(),
|
||||||
|
name: mat.name().map(|s| s.to_string()),
|
||||||
|
shader_uuid: None,
|
||||||
|
pbr: Some(PbrRoughness::from(mat.pbr_metallic_roughness())),
|
||||||
|
texture: None
|
||||||
|
}).collect();
|
||||||
|
|
||||||
let meshes: Vec<Mesh> = scene.nodes()
|
let meshes: Vec<Mesh> = scene.nodes()
|
||||||
.map(|node| self.process_node(&buffers, node))
|
.map(|node| self.process_node(&buffers, &materials, node))
|
||||||
.flatten().collect();
|
.flatten().collect();
|
||||||
|
|
||||||
Ok(Arc::new(Resource::with_data(path, Model::new(meshes))))
|
Ok(Arc::new(Resource::with_data(path, Model::new(meshes))))
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
use crate::{Texture, ResHandle};
|
||||||
|
|
||||||
|
/// PBR metallic roughness
|
||||||
|
#[derive(Clone, Debug, Default)]
|
||||||
|
pub struct PbrRoughness {
|
||||||
|
/// The rgba base color of the PBR material
|
||||||
|
pub base_color: [f32; 4],
|
||||||
|
/// The metalness of the material
|
||||||
|
/// From 0.0 (non-metal) to 1.0 (metal)
|
||||||
|
pub metallic: f32,
|
||||||
|
/// The roughness of the material
|
||||||
|
/// From 0.0 (smooth) to 1.0 (rough)
|
||||||
|
pub roughness: f32,
|
||||||
|
// TODO: base_color_texture and metallic_roughness_texture
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<gltf::material::PbrMetallicRoughness<'_>> for PbrRoughness {
|
||||||
|
fn from(value: gltf::material::PbrMetallicRoughness) -> Self {
|
||||||
|
PbrRoughness {
|
||||||
|
base_color: value.base_color_factor(),
|
||||||
|
metallic: value.metallic_factor(),
|
||||||
|
roughness: value.roughness_factor(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Default)]
|
||||||
|
pub struct PbrGlossiness {
|
||||||
|
/// The rgba diffuse color of the material
|
||||||
|
pub diffuse_color: [f32; 4],
|
||||||
|
// The base color texture
|
||||||
|
// pub diffuse_texture // TODO
|
||||||
|
pub specular: [f32; 3],
|
||||||
|
/// The glossiness factor of the material.
|
||||||
|
/// From 0.0 (no glossiness) to 1.0 (full glossiness)
|
||||||
|
pub glossiness: f32,
|
||||||
|
// pub glossiness_texture // TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Default)]
|
||||||
|
pub struct Material {
|
||||||
|
pub shader_uuid: Option<u64>,
|
||||||
|
pub name: Option<String>,
|
||||||
|
pub double_sided: bool,
|
||||||
|
pub pbr_roughness: PbrRoughness,
|
||||||
|
pub pbr_glossiness: Option<PbrGlossiness>,
|
||||||
|
pub alpha_cutoff: Option<f32>,
|
||||||
|
pub alpha_mode: gltf::material::AlphaMode,
|
||||||
|
|
||||||
|
pub texture: Option<ResHandle<Texture>>,
|
||||||
|
}
|
|
@ -1,5 +1,7 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use crate::{Material, ResHandle};
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub enum VertexAttributeData {
|
pub enum VertexAttributeData {
|
||||||
|
@ -35,6 +37,8 @@ pub enum MeshVertexAttribute {
|
||||||
TexCoords,
|
TexCoords,
|
||||||
Weights, // TODO: Animation
|
Weights, // TODO: Animation
|
||||||
MorphTargets, // TODO: Animation
|
MorphTargets, // TODO: Animation
|
||||||
|
/// Used during loading of the Mesh to process the materials taht it
|
||||||
|
MaterialRef,
|
||||||
Other(String),
|
Other(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,6 +46,7 @@ pub enum MeshVertexAttribute {
|
||||||
pub struct Mesh {
|
pub struct Mesh {
|
||||||
pub attributes: HashMap<MeshVertexAttribute, VertexAttributeData>,
|
pub attributes: HashMap<MeshVertexAttribute, VertexAttributeData>,
|
||||||
pub indices: Option<Vec<u32>>,
|
pub indices: Option<Vec<u32>>,
|
||||||
|
material: Option<ResHandle<Material>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Mesh {
|
impl Mesh {
|
||||||
|
@ -70,6 +75,10 @@ impl Mesh {
|
||||||
self.attributes.get(&MeshVertexAttribute::TexCoords)
|
self.attributes.get(&MeshVertexAttribute::TexCoords)
|
||||||
.map(|p| p.as_vec2())
|
.map(|p| p.as_vec2())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn material(&self) -> ResHandle<Material> {
|
||||||
|
self.material.clone().expect("This mesh is missing a material!")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Default)]
|
#[derive(Clone, Default)]
|
||||||
|
|
|
@ -16,6 +16,9 @@ pub struct Resource<T: Send + Sync + 'static> {
|
||||||
pub state: ResourceState,
|
pub state: ResourceState,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A helper type to make it easier to use resources
|
||||||
|
pub type ResHandle<T> = Arc<Resource<T>>;
|
||||||
|
|
||||||
impl<T: Send + Sync + 'static> Resource<T> {
|
impl<T: Send + Sync + 'static> Resource<T> {
|
||||||
/// Create the resource with data, its assumed the state is `Ready`
|
/// Create the resource with data, its assumed the state is `Ready`
|
||||||
pub fn with_data(path: &str, data: T) -> Self {
|
pub fn with_data(path: &str, data: T) -> Self {
|
||||||
|
|
Loading…
Reference in New Issue