diff options
Diffstat (limited to 'exporter/src/bin/gltf.rs')
-rw-r--r-- | exporter/src/bin/gltf.rs | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/exporter/src/bin/gltf.rs b/exporter/src/bin/gltf.rs new file mode 100644 index 0000000..fb6b72d --- /dev/null +++ b/exporter/src/bin/gltf.rs @@ -0,0 +1,99 @@ +#![feature(array_chunks)] +use anyhow::anyhow; +use glam::{Affine3A, Mat4}; +use gltf::Glb; +use log::warn; +use std::{borrow::Cow, env::args, fs::File, io::BufReader}; +use unity_tools::{ + classes::{ + gameobject::GameObject, + mesh_renderer::{MeshRenderer, SkinnedMeshRenderer}, + transform::Transform, + }, + serialized_file::SerializedFile, + unityfs::UnityFS, +}; + +fn main() -> anyhow::Result<()> { + env_logger::init_from_env("LOG"); + let file = || BufReader::new(File::open(args().nth(1).unwrap()).unwrap()); + let mut fs = UnityFS::open(file())?; + + let cabfile = fs + .find_main_file() + .ok_or(anyhow!("no CAB file found"))? + .to_owned(); + + let mut cab = fs.read(&cabfile)?; + let mut file = SerializedFile::read(&mut cab)?; + let gameobjects = file + .objects + .iter() + .filter(|ob| file.get_object_type_tree(ob).unwrap().type_string == "GameObject") + .cloned() + .collect::<Vec<_>>(); + + // let mut root_tr = Transform::from_value(file.read_object(ob)?)?; + // while !root_tr.father.is_null() { + // root_tr = root_tr.father.load(&mut file)?; + // } + // eprintln!("{root_tr:?}"); + + let mut root = gltf_json::Root::default(); + + for ob in gameobjects { + let go = file.read_object(ob)?.parse::<GameObject>()?; + for comp in go.components { + let ob = comp.load(&mut file)?; + let mut global_transform = Affine3A::default(); + match ob.class_name().unwrap().as_str() { + "Transform" => { + let mut tr = ob.parse::<Transform>()?; + let mut transforms = Vec::new(); + loop { + transforms.push( + Mat4::from_translation(tr.local_position) + * Mat4::from_scale(tr.local_scale) + * Mat4::from_quat(tr.local_rotation), + ); + if tr.father.is_null() { + break; + } else { + tr = tr.father.load(&mut file)?; + } + } + global_transform = + Affine3A::from_mat4(transforms.into_iter().reduce(|a, b| a * b).unwrap()) + } + "SkinnedMeshRenderer" => { + let mr = ob.parse::<SkinnedMeshRenderer>()?; + } + "MeshRenderer" => { + let mr = ob.parse::<MeshRenderer>()?; + } + x => warn!("unknown component {x:?}"), + } + } + } + + let json_string = gltf_json::serialize::to_string(&root).expect("Serialization error"); + let mut json_offset = json_string.len(); + align_to_multiple_of_four(&mut json_offset); + let glb = Glb { + header: gltf::binary::Header { + magic: *b"glTF", + version: 2, + length: json_offset as u32, + }, + bin: None, + json: Cow::Owned(json_string.into_bytes()), + }; + let writer = std::fs::File::create("triangle.glb").expect("I/O error"); + glb.to_writer(writer).expect("glTF binary output error"); + + Ok(()) +} + +fn align_to_multiple_of_four(n: &mut usize) { + *n = (*n + 3) & !3; +} |