aboutsummaryrefslogtreecommitdiff
path: root/exporter/src/bin/gltf.rs
diff options
context:
space:
mode:
Diffstat (limited to 'exporter/src/bin/gltf.rs')
-rw-r--r--exporter/src/bin/gltf.rs99
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;
+}