Start working on gltf

This commit is contained in:
SeanOMik 2023-09-21 14:22:46 -04:00
parent b5079a659a
commit 38e7b543c0
Signed by: SeanOMik
GPG Key ID: 568F326C7EB33ACB
8 changed files with 170 additions and 27 deletions

85
Cargo.lock generated
View File

@ -297,6 +297,12 @@ dependencies = [
"rustc-demangle", "rustc-demangle",
] ]
[[package]]
name = "base64"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
[[package]] [[package]]
name = "bit-set" name = "bit-set"
version = "0.5.3" version = "0.5.3"
@ -890,6 +896,44 @@ dependencies = [
"web-sys", "web-sys",
] ]
[[package]]
name = "gltf"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad2dcfb6dd7a66f9eb3d181a29dcfb22d146b0bcdc2e1ed1713cbf03939a88ea"
dependencies = [
"base64",
"byteorder",
"gltf-json",
"image",
"lazy_static",
"urlencoding",
]
[[package]]
name = "gltf-derive"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2cbcea5dd47e7ad4e9ee6f040384fcd7204bbf671aa4f9e7ca7dfc9bfa1de20"
dependencies = [
"inflections",
"proc-macro2",
"quote",
"syn 2.0.26",
]
[[package]]
name = "gltf-json"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d5b810806b78dde4b71a95cc0e6fdcab34c4c617da3574df166f9987be97d03"
dependencies = [
"gltf-derive",
"serde",
"serde_derive",
"serde_json",
]
[[package]] [[package]]
name = "gpu-alloc" name = "gpu-alloc"
version = "0.5.4" version = "0.5.4"
@ -1041,6 +1085,12 @@ dependencies = [
"hashbrown 0.14.0", "hashbrown 0.14.0",
] ]
[[package]]
name = "inflections"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a257582fdcde896fd96463bf2d40eefea0580021c0712a0e2b028b60b47a837a"
[[package]] [[package]]
name = "instant" name = "instant"
version = "0.1.12" version = "0.1.12"
@ -1241,6 +1291,7 @@ name = "lyra-resource"
version = "0.0.1" version = "0.0.1"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"gltf",
"image", "image",
"thiserror", "thiserror",
"uuid", "uuid",
@ -1963,6 +2014,12 @@ dependencies = [
"windows-sys 0.48.0", "windows-sys 0.48.0",
] ]
[[package]]
name = "ryu"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
[[package]] [[package]]
name = "scoped-tls" name = "scoped-tls"
version = "1.0.1" version = "1.0.1"
@ -1994,6 +2051,28 @@ version = "1.0.185"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be9b6f69f1dfd54c3b568ffa45c310d6973a5e5148fd40cf515acaf38cf5bc31" checksum = "be9b6f69f1dfd54c3b568ffa45c310d6973a5e5148fd40cf515acaf38cf5bc31"
[[package]]
name = "serde_derive"
version = "1.0.179"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "741e124f5485c7e60c03b043f79f320bff3527f4bbf12cf3831750dc46a0ec2c"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.26",
]
[[package]]
name = "serde_json"
version = "1.0.107"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]] [[package]]
name = "sharded-slab" name = "sharded-slab"
version = "0.1.4" version = "0.1.4"
@ -2371,6 +2450,12 @@ version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
[[package]]
name = "urlencoding"
version = "2.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da"
[[package]] [[package]]
name = "uuid" name = "uuid"
version = "1.4.1" version = "1.4.1"

View File

@ -7,6 +7,7 @@ edition = "2021"
[dependencies] [dependencies]
anyhow = "1.0.75" anyhow = "1.0.75"
gltf = "1.3.0"
image = "0.24.7" image = "0.24.7"
thiserror = "1.0.48" thiserror = "1.0.48"
uuid = { version = "1.4.1", features = ["v4"] } uuid = { version = "1.4.1", features = ["v4"] }

View File

@ -9,3 +9,6 @@ pub use texture::*;
pub mod loader; pub mod loader;
pub use loader::*; pub use loader::*;
pub mod model;
pub use model::*;

View File

@ -1,6 +1,7 @@
pub mod texture; pub mod texture;
pub mod model;
use std::{io, sync::Arc, fs::File}; use std::{io, sync::Arc, fs::File, path::Path, ffi::OsStr};
use thiserror::Error; use thiserror::Error;
@ -15,7 +16,7 @@ pub enum LoaderError {
UnsupportedExtension(String), UnsupportedExtension(String),
#[error("IOError: '{0}'")] #[error("IOError: '{0}'")]
IOError(io::Error), IoError(io::Error),
// From is implemented for this field in each loader module // From is implemented for this field in each loader module
#[error("Decoding error: '{0}'")] #[error("Decoding error: '{0}'")]
@ -24,12 +25,38 @@ pub enum LoaderError {
impl From<io::Error> for LoaderError { impl From<io::Error> for LoaderError {
fn from(value: io::Error) -> Self { fn from(value: io::Error) -> Self {
LoaderError::IOError(value) LoaderError::IoError(value)
} }
} }
pub trait ResourceLoader: Send + Sync { pub trait ResourceLoader: Send + Sync {
fn extensions(&self) -> &[&str]; fn extensions(&self) -> &[&str];
fn does_support_file(&self, path: &str) -> bool;
fn does_support_file(&self, path: &str) -> bool {
match Path::new(path).extension().and_then(OsStr::to_str) {
Some(ext) => {
self.extensions().contains(&ext)
},
_ => false,
}
}
fn load(&self, path: &str) -> Result<Arc<dyn ResourceStorage>, LoaderError>; fn load(&self, path: &str) -> Result<Arc<dyn ResourceStorage>, LoaderError>;
}
#[cfg(test)]
mod tests {
use super::{*, texture::TextureLoader};
/// Ensure that `does_support_file` works
#[test]
fn check_support() {
let loader = TextureLoader::default();
let extensions = loader.extensions();
let fake_paths: Vec<String> = extensions.iter().map(|e| format!("a.{}", e)).collect();
for path in fake_paths.iter() {
assert!(loader.does_support_file(&path));
}
}
} }

View File

@ -0,0 +1,29 @@
use crate::{ResourceLoader, LoaderError};
impl From<gltf::Error> for LoaderError {
fn from(value: gltf::Error) -> Self {
LoaderError::DecodingError(value.into())
}
}
#[derive(Default)]
pub struct ModelLoader;
impl ResourceLoader for ModelLoader {
fn extensions(&self) -> &[&str] {
&[
"gltf"
]
}
fn load(&self, path: &str) -> Result<std::sync::Arc<dyn crate::ResourceStorage>, crate::LoaderError> {
// check if the file is supported by this loader
if !self.does_support_file(path) {
return Err(LoaderError::UnsupportedExtension(path.to_string()));
}
let gltf = gltf::Gltf::open(path)?;
todo!()
}
}

View File

@ -8,7 +8,7 @@ use super::{LoaderError, ResourceLoader};
impl From<ImageError> for LoaderError { impl From<ImageError> for LoaderError {
fn from(value: ImageError) -> Self { fn from(value: ImageError) -> Self {
LoaderError::DecodingError(anyhow::Error::from(value)) LoaderError::DecodingError(value.into())
} }
} }
@ -30,15 +30,6 @@ impl ResourceLoader for TextureLoader {
] ]
} }
fn does_support_file(&self, path: &str) -> bool {
match Path::new(path).extension().and_then(OsStr::to_str) {
Some(ext) => {
self.extensions().contains(&ext)
},
_ => false,
}
}
fn load(&self, path: &str) -> Result<Arc<dyn ResourceStorage>, LoaderError> { fn load(&self, path: &str) -> Result<Arc<dyn ResourceStorage>, LoaderError> {
// check if the file is supported by this loader // check if the file is supported by this loader
if !self.does_support_file(path) { if !self.does_support_file(path) {
@ -53,7 +44,7 @@ impl ResourceLoader for TextureLoader {
// load the image and construct Resource<Texture> // load the image and construct Resource<Texture>
let image = image::load_from_memory(&buf) let image = image::load_from_memory(&buf)
.map_err(|e| match e { .map_err(|e| match e {
ImageError::IoError(e) => LoaderError::IOError(e), ImageError::IoError(e) => LoaderError::IoError(e),
_ => LoaderError::DecodingError(e.into()), _ => LoaderError::DecodingError(e.into()),
})?; })?;
let texture = Texture { let texture = Texture {
@ -75,17 +66,6 @@ mod tests {
format!("{manifest}/test_files/img/{path}") format!("{manifest}/test_files/img/{path}")
} }
/// Ensure that `does_support_file` works
#[test]
fn check_support() {
let loader = TextureLoader::default();
let extensions = loader.extensions();
let fake_paths: Vec<String> = extensions.iter().map(|e| format!("a.{}", e)).collect();
for path in fake_paths.iter() {
assert!(loader.does_support_file(&path));
}
}
#[test] #[test]
fn check_unsupport() { fn check_unsupport() {
let loader = TextureLoader::default(); let loader = TextureLoader::default();

View File

@ -0,0 +1,18 @@
#[repr(C)]
#[derive(Copy, Clone, Debug)]
pub struct Vertex {
pub position: [f32; 3],
pub tex_coords: [f32; 2]
}
#[derive(Clone)]
pub struct Mesh {
pub vertices: Vec<Vertex>,
pub indices: Option<Vec<u16>>,
}
pub struct Model {
pub mesh: Mesh,
//pub material
}

View File

@ -125,7 +125,7 @@ mod tests {
assert!( assert!(
match err { match err {
// make sure the error is NotFound // make sure the error is NotFound
RequestError::Loader(LoaderError::IOError(e)) if e.kind() == io::ErrorKind::NotFound => true, RequestError::Loader(LoaderError::IoError(e)) if e.kind() == io::ErrorKind::NotFound => true,
_ => false _ => false
} }
); );