mirror of
https://codeberg.org/icewind/vmdl.git
synced 2026-06-03 08:34:23 +02:00
animation data
This commit is contained in:
parent
38e44207ea
commit
a264e1c939
7 changed files with 172 additions and 15 deletions
|
|
@ -18,17 +18,17 @@ fn main() -> Result<(), vmdl::ModelError> {
|
||||||
let data = fs::read(path.with_extension("vvd"))?;
|
let data = fs::read(path.with_extension("vvd"))?;
|
||||||
let _vvd = Vvd::read(&data)?;
|
let _vvd = Vvd::read(&data)?;
|
||||||
|
|
||||||
println!("{}", mdl.surface_prop);
|
println!("{:?}", mdl.header.flags);
|
||||||
println!("{:?}", mdl.key_values);
|
dbg!(mdl.local_animations);
|
||||||
for bone in mdl.bones {
|
// for bone in mdl.bones {
|
||||||
println!(
|
// println!(
|
||||||
"{}: from {} at\n\t{:?}\n\t{:?}",
|
// "{}: from {} at\n\t{:?}\n\t{:?}",
|
||||||
bone.name,
|
// bone.name,
|
||||||
bone.parent,
|
// bone.parent,
|
||||||
bone.quaternion,
|
// bone.quaternion,
|
||||||
bone.pose_to_bone.rotation()
|
// bone.pose_to_bone.rotation()
|
||||||
);
|
// );
|
||||||
}
|
// }
|
||||||
|
|
||||||
// let model = Model::from_parts(mdl, vtx, vvd);
|
// let model = Model::from_parts(mdl, vtx, vvd);
|
||||||
// for strip in model.vertex_strips() {
|
// for strip in model.vertex_strips() {
|
||||||
|
|
|
||||||
|
|
@ -251,6 +251,7 @@ fn model_to_model(model: &Model, loader: &Loader, skin: usize) -> CpuModel {
|
||||||
let skin = model.skin_tables().nth(skin).unwrap();
|
let skin = model.skin_tables().nth(skin).unwrap();
|
||||||
|
|
||||||
let transforms = model.root_transform();
|
let transforms = model.root_transform();
|
||||||
|
let transforms = Matrix4::identity();
|
||||||
|
|
||||||
let geometries = model
|
let geometries = model
|
||||||
.meshes()
|
.meshes()
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ pub mod vtx;
|
||||||
pub mod vvd;
|
pub mod vvd;
|
||||||
|
|
||||||
pub use crate::mdl::Mdl;
|
pub use crate::mdl::Mdl;
|
||||||
use crate::mdl::{Bone, TextureInfo};
|
use crate::mdl::{Bone, PoseParameterDescription, TextureInfo};
|
||||||
pub use crate::vtx::Vtx;
|
pub use crate::vtx::Vtx;
|
||||||
use crate::vvd::Vertex;
|
use crate::vvd::Vertex;
|
||||||
pub use crate::vvd::Vvd;
|
pub use crate::vvd::Vvd;
|
||||||
|
|
@ -144,6 +144,10 @@ impl Model {
|
||||||
pub fn surface_prop(&self) -> &str {
|
pub fn surface_prop(&self) -> &str {
|
||||||
self.mdl.surface_prop.as_str()
|
self.mdl.surface_prop.as_str()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn poses(&self) -> impl Iterator<Item = &PoseParameterDescription> {
|
||||||
|
self.mdl.pose_parameters.iter()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct SkinTable<'a> {
|
pub struct SkinTable<'a> {
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,8 @@ pub struct Mdl {
|
||||||
pub skin_table: Vec<u16>,
|
pub skin_table: Vec<u16>,
|
||||||
pub surface_prop: String,
|
pub surface_prop: String,
|
||||||
pub key_values: Option<String>,
|
pub key_values: Option<String>,
|
||||||
|
pub local_animations: Vec<AnimationDescription>,
|
||||||
|
pub pose_parameters: Vec<PoseParameterDescription>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Mdl {
|
impl Mdl {
|
||||||
|
|
@ -49,6 +51,8 @@ impl Mdl {
|
||||||
let key_values = (header.key_value_size > 0)
|
let key_values = (header.key_value_size > 0)
|
||||||
.then(|| read_single(data, header.key_value_index))
|
.then(|| read_single(data, header.key_value_index))
|
||||||
.transpose()?;
|
.transpose()?;
|
||||||
|
let local_animations = read_relative(data, header.local_animation_indexes())?;
|
||||||
|
let pose_parameters = read_relative(data, header.local_pose_param_indexes())?;
|
||||||
|
|
||||||
Ok(Mdl {
|
Ok(Mdl {
|
||||||
name,
|
name,
|
||||||
|
|
@ -70,6 +74,8 @@ impl Mdl {
|
||||||
header,
|
header,
|
||||||
surface_prop,
|
surface_prop,
|
||||||
key_values,
|
key_values,
|
||||||
|
pose_parameters,
|
||||||
|
local_animations,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
135
src/mdl/raw/animation.rs
Normal file
135
src/mdl/raw/animation.rs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -220,7 +220,11 @@ impl StudioHeader {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn local_animation_indexes(&self) -> impl Iterator<Item = usize> {
|
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> {
|
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> {
|
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> {
|
pub fn ik_lock_indexes(&self) -> impl Iterator<Item = usize> {
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,15 @@
|
||||||
use crate::Vector;
|
|
||||||
use crate::{index_range, FixedString};
|
use crate::{index_range, FixedString};
|
||||||
|
use crate::{ModelError, ReadRelative, Vector};
|
||||||
use bitflags::bitflags;
|
use bitflags::bitflags;
|
||||||
use bytemuck::{Pod, Zeroable};
|
use bytemuck::{Pod, Zeroable};
|
||||||
use std::mem::size_of;
|
use std::mem::size_of;
|
||||||
|
|
||||||
|
mod animation;
|
||||||
mod bones;
|
mod bones;
|
||||||
pub mod header;
|
pub mod header;
|
||||||
pub mod header2;
|
pub mod header2;
|
||||||
|
|
||||||
|
pub use animation::*;
|
||||||
pub use bones::*;
|
pub use bones::*;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Zeroable, Pod)]
|
#[derive(Debug, Clone, Copy, Zeroable, Pod)]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue