Skip to content

Commit

Permalink
Add char clip samples to savemilo and fix saving uncompressed data
Browse files Browse the repository at this point in the history
  • Loading branch information
PikminGuts92 committed Feb 9, 2025
1 parent 3c964c9 commit 2ec5523
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 9 deletions.
27 changes: 26 additions & 1 deletion apps/cli/scene_tool/src/apps/savemilo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use thiserror::Error;

use grim::{Platform, SystemInfo};
use grim::io::*;
use grim::scene::{Object, ObjectDir, ObjectReadWrite, PackedObject, Tex};
use grim::scene::{EncodedSamples, Object, ObjectDir, ObjectReadWrite, PackedObject, Tex};
use grim::texture::{Bitmap, Image, swap_image_bytes, write_rgba_to_file};


Expand Down Expand Up @@ -85,6 +85,30 @@ impl SubApp for SaveMiloApp {
convert_textures(&mut obj_dir, &in_sys_info, &out_sys_info);
}

// Uncompress animations
for obj in obj_dir.get_entries_mut() {
if let Object::CharClipSamples(ccs) = obj {
println!("Name: {}", &ccs.name);

for cbs in [&mut ccs.one, &mut ccs.full] {
match &cbs.samples {
EncodedSamples::Compressed(bones, samples) => {
println!("\tStart: {} bones, {} samples", bones.len(), samples.len());
},
_ => {}
}

let samples = cbs.decode_samples(&in_sys_info);
println!("\tDecoded: {} samples", samples.len());

cbs.samples = EncodedSamples::Uncompressed(samples);

cbs.generate_bones_from_samples();
cbs.recompute_sizes();
}
}
}

if in_sys_info.version.ne(&out_sys_info.version) {
println!("Converting milo version from {:?} to {:?}", in_sys_info.version, out_sys_info.version);
}
Expand Down Expand Up @@ -112,6 +136,7 @@ fn unpack_entries(milo_dir: &mut ObjectDir, info: &SystemInfo, all: bool) {
}

let supported_types = [
"CharClipSamples",
"CubeTex",
"Group",
"Mat",
Expand Down
38 changes: 34 additions & 4 deletions core/grim/src/scene/char_bones_samples/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,14 @@ pub(crate) fn load_char_bones_samples_header(char_bones_samples: &mut CharBonesS
bones.push((name, weight));
}

char_bones_samples.bones = bones
.iter()
.map(|(name, weight)| CharBone {
symbol: name.to_owned(),
weight: *weight,
})
.collect();

// Read offset values
for i in 0..count_size {
let v = reader.read_uint32()?;
Expand Down Expand Up @@ -187,8 +195,14 @@ pub(crate) fn save_char_bones_samples_header(char_bones_samples: &CharBonesSampl
}

pub(crate) fn save_char_bones_samples_data(char_bones_samples: &CharBonesSamples, writer: &mut Box<BinaryStream>, version: u32) -> Result<(), Box<dyn Error>> {
let EncodedSamples::Uncompressed(samples) = &char_bones_samples.samples else {
unimplemented!("Unable to write uncompressed samples")
let samples = match &char_bones_samples.samples {
EncodedSamples::Uncompressed(samples) => samples,
EncodedSamples::Compressed(_, raw_samples) => {
for raw_sample in raw_samples {
writer.write_bytes(raw_sample)?;
}
return Ok(());
}
};

let empty_vector3 = Vector3::default();
Expand All @@ -206,6 +220,12 @@ pub(crate) fn save_char_bones_samples_data(char_bones_samples: &CharBonesSamples
save_quat_packed
};

let write_rot = if char_bones_samples.compression == 0 {
save_rot
} else {
save_rot_packed
};

let (sample_count, pos_samples, quat_samples, rotz_samples) = samples
.iter()
.fold((0, Vec::new(), Vec::new(), Vec::new()), |(mut sample_count, mut pos_samples, mut quat_samples, mut rotz_samples), s| {
Expand Down Expand Up @@ -259,12 +279,22 @@ pub(crate) fn save_char_bones_samples_data(char_bones_samples: &CharBonesSamples
.or_else(|| rotz.last());

if let Some(sample) = sample {
writer.write_float32(*sample)?;
write_rot(*sample, writer)?;
} else {
writer.write_float32(0.0)?;
write_rot(0.0, writer)?;
}
}
}

Ok(())
}

fn save_rot(value: f32, writer: &mut Box<BinaryStream>) -> Result<(), Box<dyn Error>> {
writer.write_float32(value)
}

fn save_rot_packed(value: f32, writer: &mut Box<BinaryStream>) -> Result<(), Box<dyn Error>> {
// Convert to signed short and write
let s = ((value / 1080.) * 32767.0).round() as i16;
writer.write_int16(s)
}
14 changes: 11 additions & 3 deletions core/grim/src/scene/char_bones_samples/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,9 +126,9 @@ impl CharBonesSamples {
self.bones = match &self.samples {
EncodedSamples::Compressed(bones, _) => bones.to_vec(),
EncodedSamples::Uncompressed(samples) => {
let (pos, quat) = samples
let (pos, quat, rotz) = samples
.iter()
.fold((Vec::new(), Vec::new()), |(mut pos, mut quat), s| {
.fold((Vec::new(), Vec::new(), Vec::new()), |(mut pos, mut quat, mut rotz), s| {
if let Some((w, _)) = s.pos {
pos.push(CharBone {
symbol: format!("{}.pos", s.symbol),
Expand All @@ -143,12 +143,20 @@ impl CharBonesSamples {
});
}

(pos, quat)
if let Some((w, _)) = s.rotz {
rotz.push(CharBone {
symbol: format!("{}.rotz", s.symbol),
weight: w,
});
}

(pos, quat, rotz)
});

pos
.into_iter()
.chain(quat)
.chain(rotz)
.collect()
},
};
Expand Down
3 changes: 2 additions & 1 deletion core/grim/src/scene/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ impl Object {
Object::Anim(obj) => obj,
Object::BandPlacer(obj) => obj,
Object::Cam(obj) => obj,
Object::CharClipSamples(obj) => obj,
Object::ColorPalette(obj) => obj,
Object::CubeTex(obj) => obj,
Object::Draw(obj) => obj,
Expand All @@ -114,7 +115,7 @@ impl Object {
Object::Tex(obj) => obj,
Object::Trans(obj) => obj,
Object::TransAnim(obj) => obj,
_ => todo!("Test"),
_ => todo!("Can't pack \"{}\" yet!", self.get_type()),
};

let mut data = Vec::new();
Expand Down

0 comments on commit 2ec5523

Please sign in to comment.