diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/bin/gltf.rs | 81 | ||||
-rw-r--r-- | src/bin/meshes.rs | 13 | ||||
-rw-r--r-- | src/bin/textures.rs | 18 | ||||
-rw-r--r-- | src/classes/streaminginfo.rs | 31 |
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) + } +} |