aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/bin/gltf.rs81
-rw-r--r--src/bin/meshes.rs13
-rw-r--r--src/bin/textures.rs18
-rw-r--r--src/classes/streaminginfo.rs31
4 files changed, 114 insertions, 29 deletions
diff --git a/src/bin/gltf.rs b/src/bin/gltf.rs
new file mode 100644
index 0000000..c6ce39d
--- /dev/null
+++ b/src/bin/gltf.rs
@@ -0,0 +1,81 @@
+#![feature(array_chunks)]
+use anyhow::anyhow;
+use std::{
+ env::args,
+ fs::{File, create_dir_all},
+ io::{BufReader, BufWriter, Seek, SeekFrom, Write},
+};
+use unity_tools::{
+ classes::mesh::{Mesh, VertexDataChannel},
+ object::{parser::FromValue, read::read_value},
+ serialized_file::read_serialized_file,
+ 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 mut fs2 = UnityFS::open(file())?;
+
+ let mut i = 0;
+ create_dir_all("/tmp/a").unwrap();
+
+ let cabfile = fs
+ .nodes()
+ .iter()
+ .find(|n| !n.name.ends_with(".resource") && !n.name.ends_with(".resS"))
+ .ok_or(anyhow!("no CAB file found"))?
+ .to_owned();
+ // let ressfile = fs2
+ // .nodes()
+ // .iter()
+ // .find(|n| n.name.ends_with(".resS"))
+ // .cloned();
+
+ let mut cab = fs.read(&cabfile)?;
+ // let mut ress = ressfile.map(|p| fs2.read(&p)).transpose()?;
+ let file = read_serialized_file(&mut cab)?;
+ for ob in file.objects {
+ cab.seek(SeekFrom::Start(ob.data_offset))?;
+ let typetree = if ob.type_id < 0 {
+ unimplemented!()
+ } else {
+ &file.types[ob.type_id as usize]
+ };
+ if let Some(typetree) = &typetree.type_tree {
+ if typetree.type_string != "Mesh" {
+ continue;
+ }
+ let value = read_value(typetree, file.endianness, &mut cab)?;
+ let mesh = Mesh::from_value(value).unwrap();
+ // if mesh.stream_data.len() == 0 {
+ // let ress = ress.as_mut().unwrap();
+ // ress.seek(SeekFrom::Start(mesh.stream_data.offset))?;
+ // ress.by_ref()
+ // .take(mesh.stream_data.size as u64)
+ // .read_to_end(&mut mesh.)?;
+ // }
+ let mut obj = BufWriter::new(File::create(format!(
+ "/tmp/a/{}_{i}.obj",
+ mesh.name.replace("/", "-").replace(".", "-")
+ ))?);
+
+ let (pos_dims, positions) = mesh
+ .vertex_data
+ .read_channel(VertexDataChannel::Position)
+ .unwrap();
+ assert_eq!(pos_dims, 3);
+
+ for [x, y, z] in positions.array_chunks() {
+ writeln!(obj, "v {x} {y} {z}")?;
+ }
+ for [a, b, c] in mesh.read_indecies() {
+ writeln!(obj, "f {} {} {}", a + 1, b + 1, c + 1)?;
+ }
+ i += 1;
+ }
+ }
+
+ Ok(())
+}
diff --git a/src/bin/meshes.rs b/src/bin/meshes.rs
index c6ce39d..953f2c1 100644
--- a/src/bin/meshes.rs
+++ b/src/bin/meshes.rs
@@ -27,14 +27,8 @@ fn main() -> anyhow::Result<()> {
.find(|n| !n.name.ends_with(".resource") && !n.name.ends_with(".resS"))
.ok_or(anyhow!("no CAB file found"))?
.to_owned();
- // let ressfile = fs2
- // .nodes()
- // .iter()
- // .find(|n| n.name.ends_with(".resS"))
- // .cloned();
let mut cab = fs.read(&cabfile)?;
- // let mut ress = ressfile.map(|p| fs2.read(&p)).transpose()?;
let file = read_serialized_file(&mut cab)?;
for ob in file.objects {
cab.seek(SeekFrom::Start(ob.data_offset))?;
@@ -49,13 +43,6 @@ fn main() -> anyhow::Result<()> {
}
let value = read_value(typetree, file.endianness, &mut cab)?;
let mesh = Mesh::from_value(value).unwrap();
- // if mesh.stream_data.len() == 0 {
- // let ress = ress.as_mut().unwrap();
- // ress.seek(SeekFrom::Start(mesh.stream_data.offset))?;
- // ress.by_ref()
- // .take(mesh.stream_data.size as u64)
- // .read_to_end(&mut mesh.)?;
- // }
let mut obj = BufWriter::new(File::create(format!(
"/tmp/a/{}_{i}.obj",
mesh.name.replace("/", "-").replace(".", "-")
diff --git a/src/bin/textures.rs b/src/bin/textures.rs
index 00f3596..6cd9577 100644
--- a/src/bin/textures.rs
+++ b/src/bin/textures.rs
@@ -3,7 +3,7 @@ use log::warn;
use std::{
env::args,
fs::{File, create_dir_all},
- io::{BufReader, Read, Seek, SeekFrom},
+ io::{BufReader, Seek, SeekFrom},
};
use unity_tools::{
classes::texture2d::Texture2D,
@@ -27,14 +27,8 @@ fn main() -> anyhow::Result<()> {
.find(|n| !n.name.ends_with(".resource") && !n.name.ends_with(".resS"))
.ok_or(anyhow!("no CAB file found"))?
.to_owned();
- let ressfile = fs2
- .nodes()
- .iter()
- .find(|n| n.name.ends_with(".resS"))
- .cloned();
let mut cab = fs.read(&cabfile)?;
- let mut ress = ressfile.map(|p| fs2.read(&p)).transpose()?;
let file = read_serialized_file(&mut cab)?;
for ob in file.objects {
cab.seek(SeekFrom::Start(ob.data_offset))?;
@@ -48,13 +42,9 @@ fn main() -> anyhow::Result<()> {
continue;
}
let value = read_value(typetree, file.endianness, &mut cab)?;
- let mut texture = Texture2D::from_value(value).unwrap();
- if texture.image_data.len() == 0 {
- let ress = ress.as_mut().unwrap();
- ress.seek(SeekFrom::Start(texture.stream_data.offset))?;
- ress.by_ref()
- .take(texture.stream_data.size as u64)
- .read_to_end(&mut texture.image_data)?;
+ let mut texture = Texture2D::from_value(value)?;
+ if texture.image_data.is_empty() {
+ texture.image_data = texture.stream_data.read(&mut fs2)?;
}
let path = format!(
"/tmp/a/{}_{i}.png",
diff --git a/src/classes/streaminginfo.rs b/src/classes/streaminginfo.rs
index cb5209d..5549efc 100644
--- a/src/classes/streaminginfo.rs
+++ b/src/classes/streaminginfo.rs
@@ -1,5 +1,10 @@
-use crate::object::{Value, parser::FromValue};
-use anyhow::Result;
+use std::io::{Read, Seek, SeekFrom};
+
+use crate::{
+ object::{Value, parser::FromValue},
+ unityfs::UnityFS,
+};
+use anyhow::{Result, anyhow, bail};
use serde::Serialize;
#[derive(Debug, Serialize)]
@@ -19,3 +24,25 @@ impl FromValue for StreamingInfo {
})
}
}
+
+impl StreamingInfo {
+ pub fn read(&self, fs: &mut UnityFS<impl Read + Seek>) -> Result<Vec<u8>> {
+ if !self.path.starts_with("archive:") {
+ bail!("StreamingInfo path does not start on archive:")
+ }
+ let nodeinfo = fs
+ .nodes()
+ .iter()
+ .find(|n| self.path.ends_with(&n.name))
+ .ok_or(anyhow!("node with path {:?} not found", self.path))?
+ .to_owned();
+
+ let mut buf = Vec::new();
+
+ let mut node = fs.read(&nodeinfo)?;
+ node.seek(SeekFrom::Start(self.offset))?;
+ node.take(self.size as u64).read_to_end(&mut buf)?;
+
+ Ok(buf)
+ }
+}