Simplify process of FBX model conversion.

This commit is contained in:
Piotr Siuszko 2023-12-29 15:06:28 +01:00
parent 4868671e78
commit c46de6ebae
3 changed files with 40 additions and 50 deletions

View File

@ -23,6 +23,7 @@ opt-level = 2
clap = { version = "4.4", features = ["derive"] } clap = { version = "4.4", features = ["derive"] }
flate2 = "1.0" flate2 = "1.0"
gltf = "1.4.0" gltf = "1.4.0"
pathdiff = "0.2.1"
rayon = "1.8.0" rayon = "1.8.0"
regex = "1.10.2" regex = "1.10.2"
tar = "0.4" tar = "0.4"

View File

@ -6,7 +6,6 @@ use std::fs::File;
use std::io::BufRead; use std::io::BufRead;
use std::io::BufReader; use std::io::BufReader;
use std::path::Path; use std::path::Path;
use std::path::PathBuf;
#[derive(Clone)] #[derive(Clone)]
pub struct Asset { pub struct Asset {
@ -34,9 +33,9 @@ impl Asset {
} }
let file = File::open(&self.path).unwrap(); let file = File::open(&self.path).unwrap();
let buf_reader = BufReader::new(file); let buf_reader = BufReader::new(file);
let search = buf_reader.lines().into_iter().find(|s| { let search = buf_reader.lines().find(|s| {
let ss = s.as_ref().unwrap(); let ss = s.as_ref().unwrap();
return ss.contains("m_Texture") && ss.contains("guid: "); ss.contains("m_Texture") && ss.contains("guid: ")
}); });
if let Some(line) = search { if let Some(line) = search {
let line = line.unwrap_or_default(); let line = line.unwrap_or_default();
@ -65,7 +64,7 @@ impl Asset {
} }
} }
pub fn from_path(entry: &DirEntry, output_dir: &PathBuf) -> Option<Asset> { pub fn from_path(entry: &DirEntry, output_dir: &Path) -> Option<Asset> {
let root_file = entry.path(); let root_file = entry.path();
if !root_file.is_dir() { if !root_file.is_dir() {
return None; return None;

View File

@ -56,7 +56,7 @@ impl Unpacker {
.par_bridge() .par_bridge()
.for_each_with(sender, |s, entry| { .for_each_with(sender, |s, entry| {
let entry = entry.unwrap(); let entry = entry.unwrap();
let asset = crate::asset::Asset::from_path(&entry, &output_dir.to_path_buf()); let asset = crate::asset::Asset::from_path(&entry, output_dir);
if let Some(asset) = asset { if let Some(asset) = asset {
let extension = &asset.extension.clone().unwrap_or_default(); let extension = &asset.extension.clone().unwrap_or_default();
if !ignored_extensions.contains(extension) { if !ignored_extensions.contains(extension) {
@ -75,19 +75,19 @@ impl Unpacker {
.assets .assets
.clone() .clone()
.into_iter() .into_iter()
.filter(|a| &a.asset_type == &AssetType::FbxModel) .filter(|a| a.asset_type == AssetType::FbxModel)
.collect(); .collect();
let prefabs: Vec<Asset> = self let prefabs: Vec<Asset> = self
.assets .assets
.clone() .clone()
.into_iter() .into_iter()
.filter(|a| &a.asset_type == &AssetType::Prefab) .filter(|a| a.asset_type == AssetType::Prefab)
.collect(); .collect();
let materials: Vec<Asset> = self let materials: Vec<Asset> = self
.assets .assets
.clone() .clone()
.into_iter() .into_iter()
.filter(|a| &a.asset_type == &AssetType::Material) .filter(|a| a.asset_type == AssetType::Material)
.collect(); .collect();
println!( println!(
"There are {} models, {} prefabs and {} materials", "There are {} models, {} prefabs and {} materials",
@ -96,7 +96,7 @@ impl Unpacker {
materials.len() materials.len()
); );
prefabs.par_iter().for_each(|prefab|{ prefabs.par_iter().for_each(|prefab| {
let path = Path::new(&prefab.path); let path = Path::new(&prefab.path);
let prefab_content = fs::read_to_string(path).unwrap(); let prefab_content = fs::read_to_string(path).unwrap();
let matching_materials: Vec<Asset> = materials let matching_materials: Vec<Asset> = materials
@ -115,11 +115,9 @@ impl Unpacker {
let material = matching_materials.first().unwrap(); let material = matching_materials.first().unwrap();
let model: &Asset = matching_models.first().unwrap(); let model: &Asset = matching_models.first().unwrap();
let texture_guid: Option<String> = material.try_get_mat_texture_guid(); let texture_guid: Option<String> = material.try_get_mat_texture_guid();
let texture_asset: &Asset = match &texture_guid { let texture_asset: &Asset = match &texture_guid {
Some(guid) => { Some(guid) => self.assets.iter().find(|a| guid.eq(&a.guid)).unwrap(),
self.assets.iter().find(|a| guid.eq(&a.guid)).unwrap()
}
None => return, None => return,
}; };
// here we should read gltf file and replace material texture with Uri based on texture_asset // here we should read gltf file and replace material texture with Uri based on texture_asset
@ -180,11 +178,10 @@ impl Unpacker {
let copy_meta_files = self.args.copy_meta_files; let copy_meta_files = self.args.copy_meta_files;
let tmp_path = Path::new("./tmp_dir"); let tmp_path = Path::new("./tmp_dir");
let mapping_arc = Arc::new(&self.assets);
let tmp_dir = Arc::new(tmp_path); let tmp_dir = Arc::new(tmp_path);
fs::create_dir(output_dir).unwrap(); fs::create_dir(output_dir).unwrap();
mapping_arc.par_iter().for_each(|asset| { self.assets.par_iter().for_each(|asset| {
let asset_hash = &asset.guid; let asset_hash = &asset.guid;
let path = Path::new(&asset.path); let path = Path::new(&asset.path);
let source_asset = Path::new(&*tmp_dir).join(asset_hash).join("asset"); let source_asset = Path::new(&*tmp_dir).join(asset_hash).join("asset");
@ -201,47 +198,40 @@ impl Unpacker {
panic!("SOURCE ASSET DOES NOT EXIST: {}", source_asset.display()); panic!("SOURCE ASSET DOES NOT EXIST: {}", source_asset.display());
} }
if self.args.fbx_to_gltf.is_some() && &asset.asset_type == &AssetType::FbxModel { if self.args.fbx_to_gltf.is_some() && asset.asset_type == AssetType::FbxModel {
process_fbx_file( self.process_fbx_file(&source_asset, path);
&source_asset,
path,
&self.args.fbx_to_gltf.clone().unwrap(),
);
} else { } else {
process_non_fbx_file(&source_asset, path); fs::rename(source_asset, path).unwrap();
} }
}); });
fs::remove_dir_all(Path::new(&*tmp_dir)).unwrap(); fs::remove_dir_all(Path::new(&*tmp_dir)).unwrap();
}
fn process_fbx_file(source_asset: &Path, result_path: &Path, tool: &PathBuf) { fn process_fbx_file(&self, source_asset: &Path, result_path: &Path) {
let out_path = result_path.with_extension(""); let tool = self.args.fbx_to_gltf.clone().unwrap();
println!( let out_path = result_path.with_extension("");
"{:?}", println!(
&[ "{:?}",
"--input", &[
source_asset.to_str().unwrap(), "--input",
"--output", source_asset.to_str().unwrap(),
out_path.to_str().unwrap() "--output",
] out_path.to_str().unwrap()
); ]
let output = Command::new(tool) );
.args([ let output = Command::new(tool)
"--input", .args([
source_asset.to_str().unwrap(), "--input",
"-b", source_asset.to_str().unwrap(),
"--output", "-b",
out_path.to_str().unwrap(), "--output",
]) out_path.to_str().unwrap(),
.output() ])
.unwrap(); .output()
let output_result = String::from_utf8_lossy(&output.stdout); .unwrap();
println!("output: {}", output_result); let output_result = String::from_utf8_lossy(&output.stdout);
} println!("output: {}", output_result);
fn process_non_fbx_file(source_asset: &Path, result_path: &Path) {
fs::rename(source_asset, result_path).unwrap();
}
} }
fn extract_archive(archive_path: &Path, extract_to: &Path) -> io::Result<()> { fn extract_archive(archive_path: &Path, extract_to: &Path) -> io::Result<()> {