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 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 {
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue