summaryrefslogtreecommitdiff
path: root/engine/src/model/asset.rs
diff options
context:
space:
mode:
authorHampusM <hampus@hampusmat.com>2025-11-06 19:08:01 +0100
committerHampusM <hampus@hampusmat.com>2025-11-06 19:08:01 +0100
commitc71a7048243148003f9eb09a03ab32dfcf249f9e (patch)
tree20d7d7854f353a1f02b65cb517e543e31c37afc1 /engine/src/model/asset.rs
parent3e19baab36762b4816301dab591405d3f1561287 (diff)
refactor(engine): make models import as multiple asserts
Diffstat (limited to 'engine/src/model/asset.rs')
-rw-r--r--engine/src/model/asset.rs82
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),
+}