1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
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;
}
|