#![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::>(); // 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::()?; 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::()?; 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::()?; } "MeshRenderer" => { let mr = ob.parse::()?; } 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; }