mirror of
https://codeberg.org/icewind/vmdl.git
synced 2026-06-03 16:44:11 +02:00
cleanup animation value reading a bit
This commit is contained in:
parent
28a78f5311
commit
20bd028b8a
3 changed files with 47 additions and 48 deletions
|
|
@ -7,6 +7,7 @@ use crate::{
|
|||
use bitflags::bitflags;
|
||||
use bytemuck::{Pod, Zeroable};
|
||||
use cgmath::Matrix4;
|
||||
use itertools::Itertools;
|
||||
use std::mem::size_of;
|
||||
|
||||
#[derive(Debug, Clone, Copy, Zeroable, Pod)]
|
||||
|
|
@ -172,20 +173,21 @@ fn read_animation_values(
|
|||
frame: usize,
|
||||
base_pointers: AnimationValuePointer,
|
||||
) -> Result<[f32; 3], ModelError> {
|
||||
let mut result = [0.0; 3];
|
||||
for (out, base_pointer) in result.iter_mut().zip(base_pointers.0) {
|
||||
if base_pointer == 0 {
|
||||
*out = 0.0;
|
||||
} else {
|
||||
let header: ValueHeader = read_single(data, base_pointer)?;
|
||||
let values = FrameValues {
|
||||
header,
|
||||
data: &data[base_pointer as usize..],
|
||||
};
|
||||
*out = values.get(frame as u8).map(|val| val as f32)?;
|
||||
}
|
||||
}
|
||||
Ok(result)
|
||||
let [x, y, z] = base_pointers
|
||||
.0
|
||||
.map::<_, Result<_, ModelError>>(|base_pointer| {
|
||||
if base_pointer == 0 {
|
||||
Ok(0.0)
|
||||
} else {
|
||||
let header = read_single(data, base_pointer)?;
|
||||
let values = FrameValues {
|
||||
header,
|
||||
data: &data[base_pointer as usize..],
|
||||
};
|
||||
Ok(values.get(frame as u8)? as f32)
|
||||
}
|
||||
});
|
||||
Ok([x?, y?, z?])
|
||||
}
|
||||
|
||||
/// I hate this data structure
|
||||
|
|
@ -208,7 +210,7 @@ impl FrameValues<'_> {
|
|||
pub fn get(&self, index: u8) -> Result<i16, ModelError> {
|
||||
if self.header.total <= index {
|
||||
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 = FrameValues {
|
||||
header: next_header,
|
||||
|
|
@ -224,7 +226,7 @@ impl FrameValues<'_> {
|
|||
} else {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
|
@ -286,9 +288,9 @@ impl RotationData {
|
|||
if let RotationData::Animated(values) = self {
|
||||
values.iter_mut().for_each(|value| {
|
||||
*value = RadianEuler {
|
||||
x: value.x * scale.x,
|
||||
y: value.y * scale.y,
|
||||
z: value.z * scale.z,
|
||||
roll: value.roll * scale.roll,
|
||||
pitch: value.pitch * scale.pitch,
|
||||
yaw: value.yaw * scale.yaw,
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -298,9 +300,9 @@ impl RotationData {
|
|||
if let RotationData::Animated(values) = self {
|
||||
values.iter_mut().for_each(|value| {
|
||||
*value = RadianEuler {
|
||||
x: value.x + base.x,
|
||||
y: value.y + base.y,
|
||||
z: value.z + base.z,
|
||||
roll: value.roll + base.roll,
|
||||
pitch: value.pitch + base.pitch,
|
||||
yaw: value.yaw + base.yaw,
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -389,7 +391,7 @@ fn read_animation(
|
|||
let value_data = &data[offset..];
|
||||
let values: Vec<RadianEuler> = (0..frames)
|
||||
.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>>()?;
|
||||
RotationData::from(values)
|
||||
} else {
|
||||
|
|
@ -404,7 +406,7 @@ fn read_animation(
|
|||
let value_data = &data[position_offset..];
|
||||
let values = (0..frames)
|
||||
.map(|frame| read_animation_values(value_data, frame, pointers))
|
||||
.map(|r| r.map(Vector::from))
|
||||
.map_ok(Vector::from)
|
||||
.collect::<Result<_, ModelError>>()?;
|
||||
PositionData::PositionValues(values)
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -139,9 +139,9 @@ impl ReadRelative for Bone {
|
|||
rot: header.rot,
|
||||
pos_scale: header.pos_scale,
|
||||
rot_scale: RadianEuler {
|
||||
x: header.rot_scale[2],
|
||||
y: header.rot_scale[0],
|
||||
z: header.rot_scale[1],
|
||||
roll: header.rot_scale[2],
|
||||
pitch: header.rot_scale[0],
|
||||
yaw: header.rot_scale[1],
|
||||
},
|
||||
pose_to_bone: header.pose_to_bone,
|
||||
q_alignment: header.q_alignment,
|
||||
|
|
|
|||
|
|
@ -161,12 +161,9 @@ impl Mul<RadianEuler> for Quaternion {
|
|||
#[derive(Debug, Clone, Copy, Zeroable, Pod, Default)]
|
||||
#[repr(C)]
|
||||
pub struct RadianEuler {
|
||||
/// Roll
|
||||
pub x: f32,
|
||||
/// Pitch
|
||||
pub y: f32,
|
||||
/// Yaw
|
||||
pub z: f32,
|
||||
pub roll: f32,
|
||||
pub pitch: f32,
|
||||
pub yaw: f32,
|
||||
}
|
||||
|
||||
impl RadianEuler {
|
||||
|
|
@ -180,9 +177,9 @@ impl RadianEuler {
|
|||
}
|
||||
|
||||
Self {
|
||||
x: clamp(self.x),
|
||||
y: clamp(self.y),
|
||||
z: clamp(self.z),
|
||||
roll: clamp(self.roll),
|
||||
pitch: clamp(self.pitch),
|
||||
yaw: clamp(self.yaw),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -190,9 +187,9 @@ impl RadianEuler {
|
|||
impl From<RadianEuler> for Euler<Rad<f32>> {
|
||||
fn from(e: RadianEuler) -> Self {
|
||||
Euler {
|
||||
x: Rad(e.x),
|
||||
y: Rad(e.y),
|
||||
z: Rad(e.z),
|
||||
x: Rad(e.roll),
|
||||
y: Rad(e.pitch),
|
||||
z: Rad(e.yaw),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -200,18 +197,18 @@ impl From<RadianEuler> for Euler<Rad<f32>> {
|
|||
impl From<RadianEuler> for Euler<Deg<f32>> {
|
||||
fn from(e: RadianEuler) -> Self {
|
||||
Euler {
|
||||
x: Rad(e.x).into(),
|
||||
y: Rad(e.y).into(),
|
||||
z: Rad(e.z).into(),
|
||||
x: Rad(e.roll).into(),
|
||||
y: Rad(e.pitch).into(),
|
||||
z: Rad(e.yaw).into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RadianEuler> for cgmath::Quaternion<f32> {
|
||||
fn from(value: RadianEuler) -> Self {
|
||||
let (sy, cy) = Rad::sin_cos(Rad(value.z * 0.5));
|
||||
let (sp, cp) = Rad::sin_cos(Rad(value.y * 0.5));
|
||||
let (sr, cr) = Rad::sin_cos(Rad(-value.x * 0.5));
|
||||
let (sy, cy) = Rad::sin_cos(Rad(value.yaw * 0.5));
|
||||
let (sp, cp) = Rad::sin_cos(Rad(value.pitch * 0.5));
|
||||
let (sr, cr) = Rad::sin_cos(Rad(-value.roll * 0.5));
|
||||
|
||||
let sr_cp = sr * cp;
|
||||
let cr_sp = cr * sp;
|
||||
|
|
@ -245,9 +242,9 @@ impl Mul<f32> for RadianEuler {
|
|||
|
||||
fn mul(self, rhs: f32) -> Self::Output {
|
||||
RadianEuler {
|
||||
x: self.x * rhs,
|
||||
y: self.y * rhs,
|
||||
z: self.z * rhs,
|
||||
roll: self.roll * rhs,
|
||||
pitch: self.pitch * rhs,
|
||||
yaw: self.yaw * rhs,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue