animation data

This commit is contained in:
Robin Appelman 2023-12-30 22:23:52 +01:00
commit a264e1c939
7 changed files with 172 additions and 15 deletions

View file

@ -18,17 +18,17 @@ fn main() -> Result<(), vmdl::ModelError> {
let data = fs::read(path.with_extension("vvd"))?;
let _vvd = Vvd::read(&data)?;
println!("{}", mdl.surface_prop);
println!("{:?}", mdl.key_values);
for bone in mdl.bones {
println!(
"{}: from {} at\n\t{:?}\n\t{:?}",
bone.name,
bone.parent,
bone.quaternion,
bone.pose_to_bone.rotation()
);
}
println!("{:?}", mdl.header.flags);
dbg!(mdl.local_animations);
// for bone in mdl.bones {
// println!(
// "{}: from {} at\n\t{:?}\n\t{:?}",
// bone.name,
// bone.parent,
// bone.quaternion,
// bone.pose_to_bone.rotation()
// );
// }
// let model = Model::from_parts(mdl, vtx, vvd);
// for strip in model.vertex_strips() {

View file

@ -251,6 +251,7 @@ fn model_to_model(model: &Model, loader: &Loader, skin: usize) -> CpuModel {
let skin = model.skin_tables().nth(skin).unwrap();
let transforms = model.root_transform();
let transforms = Matrix4::identity();
let geometries = model
.meshes()

View file

@ -6,7 +6,7 @@ pub mod vtx;
pub mod vvd;
pub use crate::mdl::Mdl;
use crate::mdl::{Bone, TextureInfo};
use crate::mdl::{Bone, PoseParameterDescription, TextureInfo};
pub use crate::vtx::Vtx;
use crate::vvd::Vertex;
pub use crate::vvd::Vvd;
@ -144,6 +144,10 @@ impl Model {
pub fn surface_prop(&self) -> &str {
self.mdl.surface_prop.as_str()
}
pub fn poses(&self) -> impl Iterator<Item = &PoseParameterDescription> {
self.mdl.pose_parameters.iter()
}
}
pub struct SkinTable<'a> {

View file

@ -23,6 +23,8 @@ pub struct Mdl {
pub skin_table: Vec<u16>,
pub surface_prop: String,
pub key_values: Option<String>,
pub local_animations: Vec<AnimationDescription>,
pub pose_parameters: Vec<PoseParameterDescription>,
}
impl Mdl {
@ -49,6 +51,8 @@ impl Mdl {
let key_values = (header.key_value_size > 0)
.then(|| read_single(data, header.key_value_index))
.transpose()?;
let local_animations = read_relative(data, header.local_animation_indexes())?;
let pose_parameters = read_relative(data, header.local_pose_param_indexes())?;
Ok(Mdl {
name,
@ -70,6 +74,8 @@ impl Mdl {
header,
surface_prop,
key_values,
pose_parameters,
local_animations,
})
}
}

135
src/mdl/raw/animation.rs Normal file
View file

@ -0,0 +1,135 @@
use crate::{ModelError, ReadRelative};
use bitflags::bitflags;
use bytemuck::{Pod, Zeroable};
use std::mem::size_of;
#[derive(Debug, Clone, Copy, Zeroable, Pod)]
#[repr(C)]
pub struct PoseParameterDescriptionHeader {
name_index: i32,
flags: i32,
start: f32,
end: f32,
loop_range: f32,
}
static_assertions::const_assert_eq!(size_of::<PoseParameterDescriptionHeader>(), 20);
#[derive(Clone, Debug)]
pub struct PoseParameterDescription {
pub name: String,
pub flags: i32,
pub start: f32,
pub end: f32,
pub loop_range: f32,
}
impl ReadRelative for PoseParameterDescription {
type Header = PoseParameterDescriptionHeader;
fn read(data: &[u8], header: Self::Header) -> Result<Self, ModelError> {
let name_bytes = data
.get(header.name_index as usize..)
.ok_or(ModelError::OutOfBounds {
data: "pose name",
offset: header.name_index as usize,
})?;
Ok(PoseParameterDescription {
name: String::read(name_bytes, ())?,
flags: header.flags,
start: header.start,
end: header.end,
loop_range: header.loop_range,
})
}
}
#[derive(Debug, Clone, Copy, Zeroable, Pod)]
#[repr(C)]
pub struct AnimationDescriptionHeader {
base_ptr: i32,
name_offset: i32,
fps: f32,
flags: i32,
frame_count: i32,
movement_count: i32,
movement_offset: i32,
_padding: [i32; 6],
animation_block: i32,
animation_index: i32,
ik_rule_count: i32,
ik_rule_offset: i32,
animation_block_ik_rule_index: i32,
local_hierarchy_count: i32,
local_hierarchy_offset: i32,
section_offset: i32,
section_frames: i32,
zero_frame_span: i16,
zero_frame_count: i16,
zero_frame_offset: i32,
zero_frame_stall_time: f32,
}
static_assertions::const_assert_eq!(size_of::<AnimationDescriptionHeader>(), 100);
#[derive(Clone, Debug)]
pub struct AnimationDescription {
pub name: String,
pub fps: f32,
pub frame_count: i32,
}
impl ReadRelative for AnimationDescription {
type Header = AnimationDescriptionHeader;
fn read(data: &[u8], header: Self::Header) -> Result<Self, ModelError> {
let name_bytes =
data.get(dbg!(header.name_offset) as usize..)
.ok_or(ModelError::OutOfBounds {
data: "animation name",
offset: header.name_offset as usize,
})?;
Ok(AnimationDescription {
name: String::read(name_bytes, ())?,
fps: header.fps,
frame_count: header.frame_count,
})
}
}
#[derive(Debug, Clone, Copy, Zeroable, Pod)]
#[repr(C)]
pub struct AnimationHeader {
bone: u8,
flags: AnimationFlags,
next_offset: u16,
}
#[derive(Zeroable, Pod, Copy, Clone, Debug)]
#[repr(C)]
pub struct AnimationFlags(u8);
bitflags! {
impl AnimationFlags: u8 {
/// Vector48
const STUDIO_ANIM_RAWPOS = 0x00000001;
/// Quaternion48
const STUDIO_ANIM_RAWROT = 0x00000002;
/// mstudioanim_valueptr_t
const STUDIO_ANIM_ANIMPOS = 0x00000004;
/// mstudioanim_valueptr_t
const STUDIO_ANIM_ANIMROT = 0x00000008;
const STUDIO_ANIM_DELTA = 0x00000010;
/// Quaternion64
const STUDIO_ANIM_RAWROT2 = 0x00000020;
}
}

View file

@ -220,7 +220,11 @@ impl StudioHeader {
}
pub fn local_animation_indexes(&self) -> impl Iterator<Item = usize> {
index_range(self.local_animation_offset, self.local_animation_count, 1)
index_range(
self.local_animation_offset,
self.local_animation_count,
size_of::<AnimationDescriptionHeader>(),
)
}
pub fn local_sequence_indexes(&self) -> impl Iterator<Item = usize> {
@ -292,7 +296,11 @@ impl StudioHeader {
}
pub fn local_pose_param_indexes(&self) -> impl Iterator<Item = usize> {
index_range(self.local_pose_param_index, self.local_pose_param_count, 1)
index_range(
self.local_pose_param_index,
self.local_pose_param_count,
size_of::<PoseParameterDescriptionHeader>(),
)
}
pub fn ik_lock_indexes(&self) -> impl Iterator<Item = usize> {

View file

@ -1,12 +1,15 @@
use crate::Vector;
use crate::{index_range, FixedString};
use crate::{ModelError, ReadRelative, Vector};
use bitflags::bitflags;
use bytemuck::{Pod, Zeroable};
use std::mem::size_of;
mod animation;
mod bones;
pub mod header;
pub mod header2;
pub use animation::*;
pub use bones::*;
#[derive(Debug, Clone, Copy, Zeroable, Pod)]