diff options
Diffstat (limited to 'engine/src/model/asset.rs')
| -rw-r--r-- | engine/src/model/asset.rs | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/engine/src/model/asset.rs b/engine/src/model/asset.rs new file mode 100644 index 0000000..070200d --- /dev/null +++ b/engine/src/model/asset.rs @@ -0,0 +1,82 @@ +use std::collections::HashSet; +use std::fs::read_to_string; +use std::path::{Path, PathBuf}; + +use crate::asset::{Assets, Submitter as AssetSubmitter}; +use crate::material::asset::Map as MaterialAssetMap; +use crate::model::{Materials, Spec}; + +#[derive(Debug, Clone)] +#[non_exhaustive] +pub struct Settings {} + +pub fn add_importers(assets: &mut Assets) +{ + assets.set_importer(["obj"], import_wavefront_obj_asset); +} + +fn import_wavefront_obj_asset( + asset_submitter: &mut AssetSubmitter<'_>, + path: &Path, + _settings: Option<&'_ Settings>, +) -> Result<(), Error> +{ + let obj = crate::file_format::wavefront::obj::parse( + &read_to_string(path) + .map_err(|err| Error::ReadFailed(err, path.to_path_buf()))?, + )?; + + let mesh = obj.to_mesh()?; + + let mesh_asset = asset_submitter.submit_store_named("mesh", mesh); + + let mut material_asset_map_assets = + Vec::with_capacity(obj.mtl_libs.iter().flatten().count()); + + for mtl_lib_path in obj.mtl_libs.iter().flatten() { + let mtl_lib_asset = + asset_submitter.submit_load_other::<MaterialAssetMap>(mtl_lib_path.as_path()); + + material_asset_map_assets.push(mtl_lib_asset); + } + + let material_names = obj + .faces + .into_iter() + .map(|face| face.material_name) + .flatten() + .fold( + (HashSet::<String>::new(), Vec::<String>::new()), + |(mut pushed_mat_names, mut unique_mat_names), material_name| { + if pushed_mat_names.contains(&material_name) { + return (pushed_mat_names, unique_mat_names); + } + + unique_mat_names.push(material_name.clone()); + pushed_mat_names.insert(material_name); + + (pushed_mat_names, unique_mat_names) + }, + ) + .1; + + asset_submitter.submit_store( + Spec::builder() + .mesh(mesh_asset) + .materials(Materials::Maps(material_asset_map_assets)) + .material_names(material_names) + .build(), + ); + + Ok(()) +} + +#[derive(Debug, thiserror::Error)] +enum Error +{ + #[error("Failed to read file {}", .1.display())] + ReadFailed(#[source] std::io::Error, PathBuf), + + #[error(transparent)] + Other(#[from] crate::file_format::wavefront::obj::Error), +} |
