Skip to content

Commit

Permalink
Support scale transforms for char clips
Browse files Browse the repository at this point in the history
  • Loading branch information
PikminGuts92 committed Feb 11, 2025
1 parent a7c195d commit f749261
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 14 deletions.
23 changes: 20 additions & 3 deletions core/grim/src/scene/char_bones_samples/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,13 +227,17 @@ pub(crate) fn save_char_bones_samples_data(char_bones_samples: &CharBonesSamples
save_rot_packed
};

let (sample_count, pos_samples, quat_samples, rotz_samples) = samples
let (sample_count, pos_samples, scale_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| {
.fold((0, Vec::new(), Vec::new(), Vec::new(), Vec::new()), |(mut sample_count, mut pos_samples, mut scale_samples, mut quat_samples, mut rotz_samples), s| {
if let Some((_, p)) = &s.pos {
sample_count = sample_count.max(p.len());
pos_samples.push(p);
}
if let Some((_, s)) = &s.scale {
sample_count = sample_count.max(s.len());
scale_samples.push(s);
}
if let Some((_, q)) = &s.quat {
sample_count = sample_count.max(q.len());
quat_samples.push(q);
Expand All @@ -243,7 +247,7 @@ pub(crate) fn save_char_bones_samples_data(char_bones_samples: &CharBonesSamples
rotz_samples.push(rz);
}

(sample_count, pos_samples, quat_samples, rotz_samples)
(sample_count, pos_samples, scale_samples, quat_samples, rotz_samples)
});

for i in 0..sample_count {
Expand All @@ -260,6 +264,19 @@ pub(crate) fn save_char_bones_samples_data(char_bones_samples: &CharBonesSamples
}
}

// Write scales (always packed)
for scale in scale_samples.iter() {
let sample = scale
.get(i)
.or_else(|| scale.last());

if let Some(sample) = sample {
write_vector(sample, writer)?;
} else {
write_vector(&empty_vector3, writer)?;
}
}

// Write quaternions
for quat in quat_samples.iter() {
let sample = quat
Expand Down
66 changes: 55 additions & 11 deletions core/grim/src/scene/char_bones_samples/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ pub struct CharBone4Bone {
pub struct CharBoneSample {
pub symbol: String, // Bone name
pub pos: Option<(f32, Vec<Vector3>)>,
pub scale: Option<(f32, Vec<Vector3>)>,
pub quat: Option<(f32, Vec<Quat>)>,
pub rotz: Option<(f32, Vec<f32>)>,
}
Expand Down Expand Up @@ -91,11 +92,11 @@ impl CharBonesSamples {
pub(crate) fn get_type_size2(&self, idx: u32) -> usize {
// Note: Not sure if scale ever gets compressed
const SIZES: [[usize; 6]; 4] = [
// p s q x y z
[12, 4, 16, 4, 4, 4], // 0 Uncompressed
[12, 4, 8, 2, 2, 2], // 1 Compress rots
[ 6, 4, 8, 2, 2, 2], // 2 Compress vects
[ 6, 4, 4, 2, 2, 2], // 3 Compress quats
// p s q x y z
[12, 12, 16, 4, 4, 4], // 0 Uncompressed
[12, 12, 8, 2, 2, 2], // 1 Compress rots
[ 6, 6, 8, 2, 2, 2], // 2 Compress vects
[ 6, 6, 4, 2, 2, 2], // 3 Compress quats
];

SIZES
Expand Down Expand Up @@ -126,16 +127,23 @@ impl CharBonesSamples {
self.bones = match &self.samples {
EncodedSamples::Compressed(bones, _) => bones.to_vec(),
EncodedSamples::Uncompressed(samples) => {
let (pos, quat, rotz) = samples
let (pos, scale, quat, rotz) = samples
.iter()
.fold((Vec::new(), Vec::new(), Vec::new()), |(mut pos, mut quat, mut rotz), s| {
.fold((Vec::new(), Vec::new(), Vec::new(), Vec::new()), |(mut pos, mut scale, mut quat, mut rotz), s| {
if let Some((w, _)) = s.pos {
pos.push(CharBone4Bone {
symbol: format!("{}.pos", s.symbol),
weight: w,
});
}

if let Some((w, _)) = s.scale {
scale.push(CharBone4Bone {
symbol: format!("{}.scale", s.symbol),
weight: w,
});
}

if let Some((w, _)) = s.quat {
quat.push(CharBone4Bone {
symbol: format!("{}.quat", s.symbol),
Expand All @@ -150,11 +158,12 @@ impl CharBonesSamples {
});
}

(pos, quat, rotz)
(pos, scale, quat, rotz)
});

pos
.into_iter()
.chain(scale)
.chain(quat)
.chain(rotz)
.collect()
Expand Down Expand Up @@ -194,6 +203,7 @@ impl CharBonesSamples {
// TODO: Make more efficient
let bone_name = bone.symbol.to_owned()
.replace(".pos", "")
.replace(".scale", "")
.replace(".quat", "")
.replace(".rotz", "");

Expand Down Expand Up @@ -227,7 +237,7 @@ impl CharBonesSamples {
i += s as usize;
Vector3 { x, y, z }
},
s @ _ => panic!("Unsupported .pos compression of type {}", s)
s @ _ => panic!("Unsupported .pos compression of size {}", s)
};

// Insert or append pos sample
Expand All @@ -239,6 +249,39 @@ impl CharBonesSamples {
_ => Some((bone.weight, vec![pos]))
}
},
t @ 1 => {
// scale
let scale = match self.get_type_size2(t) {
s @ 12 => {
// Read data
let x = read_f32([sample[i ], sample[i + 1], sample[i + 2], sample[i + 3]]);
let y = read_f32([sample[i + 4], sample[i + 5], sample[i + 6], sample[i + 7]]);
let z = read_f32([sample[i + 8], sample[i + 9], sample[i + 10], sample[i + 11]]);

i += s as usize;
Vector3 { x, y, z }
},
s @ 6 => {
// Read packed data
let x = read_packed_f32([sample[i ], sample[i + 1]]) * 1345.; // TODO: Investigate better constant
let y = read_packed_f32([sample[i + 2], sample[i + 3]]) * 1345.;
let z = read_packed_f32([sample[i + 4], sample[i + 5]]) * 1345.;

i += s as usize;
Vector3 { x, y, z }
},
s @ _ => panic!("Unsupported .scale compression of size {}", s)
};

// Insert or append scale sample
bone_sample.scale = match bone_sample.scale.take() {
Some((w, mut samples)) => {
samples.push(scale);
Some((w, samples))
},
_ => Some((bone.weight, vec![scale]))
}
},
t @ 2 => {
// quat
let quat = match self.get_type_size2(t) {
Expand All @@ -262,7 +305,7 @@ impl CharBonesSamples {
i += s as usize;
Quat { x, y, z, w }
},
s @ _ => panic!("Unsupported .pos compression of type {}", s)
s @ _ => panic!("Unsupported .quat compression of size {}", s)
};

// Insert or append quat sample
Expand Down Expand Up @@ -291,7 +334,7 @@ impl CharBonesSamples {
i += s as usize;
x
},
s @ _ => panic!("Unsupported .pos compression of type {}", s)
s @ _ => panic!("Unsupported .rotz compression of size {}", s)
};

// Insert or append rotz sample
Expand Down Expand Up @@ -358,6 +401,7 @@ impl CharBonesSamples {
.fold(0, |acc, s| {
acc
.max(s.pos.as_ref().map(|(_, p)| p.len()).unwrap_or_default())
.max(s.scale.as_ref().map(|(_, s)| s.len()).unwrap_or_default())
.max(s.quat.as_ref().map(|(_, q)| q.len()).unwrap_or_default())
.max(s.rotz.as_ref().map(|(_, r)| r.len()).unwrap_or_default())
}),
Expand Down

0 comments on commit f749261

Please sign in to comment.