cleanup animation value reading a bit

This commit is contained in:
Robin Appelman 2024-12-31 00:11:38 +01:00
commit 20bd028b8a
3 changed files with 47 additions and 48 deletions

View file

@ -7,6 +7,7 @@ use crate::{
use bitflags::bitflags; use bitflags::bitflags;
use bytemuck::{Pod, Zeroable}; use bytemuck::{Pod, Zeroable};
use cgmath::Matrix4; use cgmath::Matrix4;
use itertools::Itertools;
use std::mem::size_of; use std::mem::size_of;
#[derive(Debug, Clone, Copy, Zeroable, Pod)] #[derive(Debug, Clone, Copy, Zeroable, Pod)]
@ -172,20 +173,21 @@ fn read_animation_values(
frame: usize, frame: usize,
base_pointers: AnimationValuePointer, base_pointers: AnimationValuePointer,
) -> Result<[f32; 3], ModelError> { ) -> Result<[f32; 3], ModelError> {
let mut result = [0.0; 3]; let [x, y, z] = base_pointers
for (out, base_pointer) in result.iter_mut().zip(base_pointers.0) { .0
if base_pointer == 0 { .map::<_, Result<_, ModelError>>(|base_pointer| {
*out = 0.0; if base_pointer == 0 {
} else { Ok(0.0)
let header: ValueHeader = read_single(data, base_pointer)?; } else {
let values = FrameValues { let header = read_single(data, base_pointer)?;
header, let values = FrameValues {
data: &data[base_pointer as usize..], header,
}; data: &data[base_pointer as usize..],
*out = values.get(frame as u8).map(|val| val as f32)?; };
} Ok(values.get(frame as u8)? as f32)
} }
Ok(result) });
Ok([x?, y?, z?])
} }
/// I hate this data structure /// I hate this data structure
@ -208,7 +210,7 @@ impl FrameValues<'_> {
pub fn get(&self, index: u8) -> Result<i16, ModelError> { pub fn get(&self, index: u8) -> Result<i16, ModelError> {
if self.header.total <= index { if self.header.total <= index {
let offset_count = self.header.valid + 1; let offset_count = self.header.valid + 1;
let offset = (offset_count as usize) * size_of::<u16>(); let offset = (offset_count as usize) * size_of::<ValueHeader>();
let next_header: ValueHeader = read_single(self.data, offset)?; let next_header: ValueHeader = read_single(self.data, offset)?;
let next = FrameValues { let next = FrameValues {
header: next_header, header: next_header,
@ -224,7 +226,7 @@ impl FrameValues<'_> {
} else { } else {
self.header.valid self.header.valid
}; };
let offset = (offset_count as usize) * size_of::<u16>(); let offset = (offset_count as usize) * size_of::<i16>();
read_single(self.data, offset) read_single(self.data, offset)
} }
} }
@ -286,9 +288,9 @@ impl RotationData {
if let RotationData::Animated(values) = self { if let RotationData::Animated(values) = self {
values.iter_mut().for_each(|value| { values.iter_mut().for_each(|value| {
*value = RadianEuler { *value = RadianEuler {
x: value.x * scale.x, roll: value.roll * scale.roll,
y: value.y * scale.y, pitch: value.pitch * scale.pitch,
z: value.z * scale.z, yaw: value.yaw * scale.yaw,
} }
}); });
} }
@ -298,9 +300,9 @@ impl RotationData {
if let RotationData::Animated(values) = self { if let RotationData::Animated(values) = self {
values.iter_mut().for_each(|value| { values.iter_mut().for_each(|value| {
*value = RadianEuler { *value = RadianEuler {
x: value.x + base.x, roll: value.roll + base.roll,
y: value.y + base.y, pitch: value.pitch + base.pitch,
z: value.z + base.z, yaw: value.yaw + base.yaw,
} }
}); });
} }
@ -389,7 +391,7 @@ fn read_animation(
let value_data = &data[offset..]; let value_data = &data[offset..];
let values: Vec<RadianEuler> = (0..frames) let values: Vec<RadianEuler> = (0..frames)
.map(|frame| read_animation_values(value_data, frame, pointers)) .map(|frame| read_animation_values(value_data, frame, pointers))
.map(|r| r.map(|[y, z, x]| RadianEuler { x, z, y })) .map_ok(|[pitch, yaw, roll]| RadianEuler { roll, yaw, pitch })
.collect::<Result<_, ModelError>>()?; .collect::<Result<_, ModelError>>()?;
RotationData::from(values) RotationData::from(values)
} else { } else {
@ -404,7 +406,7 @@ fn read_animation(
let value_data = &data[position_offset..]; let value_data = &data[position_offset..];
let values = (0..frames) let values = (0..frames)
.map(|frame| read_animation_values(value_data, frame, pointers)) .map(|frame| read_animation_values(value_data, frame, pointers))
.map(|r| r.map(Vector::from)) .map_ok(Vector::from)
.collect::<Result<_, ModelError>>()?; .collect::<Result<_, ModelError>>()?;
PositionData::PositionValues(values) PositionData::PositionValues(values)
} else { } else {

View file

@ -139,9 +139,9 @@ impl ReadRelative for Bone {
rot: header.rot, rot: header.rot,
pos_scale: header.pos_scale, pos_scale: header.pos_scale,
rot_scale: RadianEuler { rot_scale: RadianEuler {
x: header.rot_scale[2], roll: header.rot_scale[2],
y: header.rot_scale[0], pitch: header.rot_scale[0],
z: header.rot_scale[1], yaw: header.rot_scale[1],
}, },
pose_to_bone: header.pose_to_bone, pose_to_bone: header.pose_to_bone,
q_alignment: header.q_alignment, q_alignment: header.q_alignment,

View file

@ -161,12 +161,9 @@ impl Mul<RadianEuler> for Quaternion {
#[derive(Debug, Clone, Copy, Zeroable, Pod, Default)] #[derive(Debug, Clone, Copy, Zeroable, Pod, Default)]
#[repr(C)] #[repr(C)]
pub struct RadianEuler { pub struct RadianEuler {
/// Roll pub roll: f32,
pub x: f32, pub pitch: f32,
/// Pitch pub yaw: f32,
pub y: f32,
/// Yaw
pub z: f32,
} }
impl RadianEuler { impl RadianEuler {
@ -180,9 +177,9 @@ impl RadianEuler {
} }
Self { Self {
x: clamp(self.x), roll: clamp(self.roll),
y: clamp(self.y), pitch: clamp(self.pitch),
z: clamp(self.z), yaw: clamp(self.yaw),
} }
} }
} }
@ -190,9 +187,9 @@ impl RadianEuler {
impl From<RadianEuler> for Euler<Rad<f32>> { impl From<RadianEuler> for Euler<Rad<f32>> {
fn from(e: RadianEuler) -> Self { fn from(e: RadianEuler) -> Self {
Euler { Euler {
x: Rad(e.x), x: Rad(e.roll),
y: Rad(e.y), y: Rad(e.pitch),
z: Rad(e.z), z: Rad(e.yaw),
} }
} }
} }
@ -200,18 +197,18 @@ impl From<RadianEuler> for Euler<Rad<f32>> {
impl From<RadianEuler> for Euler<Deg<f32>> { impl From<RadianEuler> for Euler<Deg<f32>> {
fn from(e: RadianEuler) -> Self { fn from(e: RadianEuler) -> Self {
Euler { Euler {
x: Rad(e.x).into(), x: Rad(e.roll).into(),
y: Rad(e.y).into(), y: Rad(e.pitch).into(),
z: Rad(e.z).into(), z: Rad(e.yaw).into(),
} }
} }
} }
impl From<RadianEuler> for cgmath::Quaternion<f32> { impl From<RadianEuler> for cgmath::Quaternion<f32> {
fn from(value: RadianEuler) -> Self { fn from(value: RadianEuler) -> Self {
let (sy, cy) = Rad::sin_cos(Rad(value.z * 0.5)); let (sy, cy) = Rad::sin_cos(Rad(value.yaw * 0.5));
let (sp, cp) = Rad::sin_cos(Rad(value.y * 0.5)); let (sp, cp) = Rad::sin_cos(Rad(value.pitch * 0.5));
let (sr, cr) = Rad::sin_cos(Rad(-value.x * 0.5)); let (sr, cr) = Rad::sin_cos(Rad(-value.roll * 0.5));
let sr_cp = sr * cp; let sr_cp = sr * cp;
let cr_sp = cr * sp; let cr_sp = cr * sp;
@ -245,9 +242,9 @@ impl Mul<f32> for RadianEuler {
fn mul(self, rhs: f32) -> Self::Output { fn mul(self, rhs: f32) -> Self::Output {
RadianEuler { RadianEuler {
x: self.x * rhs, roll: self.roll * rhs,
y: self.y * rhs, pitch: self.pitch * rhs,
z: self.z * rhs, yaw: self.yaw * rhs,
} }
} }
} }