bone names

This commit is contained in:
Robin Appelman 2023-12-29 16:48:19 +01:00
commit c58d911bf6
7 changed files with 63 additions and 28 deletions

View file

@ -18,9 +18,7 @@ fn main() -> Result<(), vmdl::ModelError> {
let _vvd = Vvd::read(&data)?; let _vvd = Vvd::read(&data)?;
for bone in mdl.bones { for bone in mdl.bones {
dbg!(bone.flags); println!("{}: from {} at {:?}", bone.name, bone.parent, bone.rot);
dbg!(bone.rot);
dbg!(bone.quaternion);
} }
// let model = Model::from_parts(mdl, vtx, vvd); // let model = Model::from_parts(mdl, vtx, vvd);

View file

@ -252,8 +252,10 @@ fn model_to_model(model: &Model, loader: &Loader, skin: usize) -> CpuModel {
let transforms = model let transforms = model
.bones() .bones()
.filter(|bone| bone.name == "root")
.next()
.map(|bone| Mat4::from(cgmath::Quaternion::from(bone.rot))) .map(|bone| Mat4::from(cgmath::Quaternion::from(bone.rot)))
.fold(Mat4::identity(), |a, b| a * b); .unwrap_or_else(|| Matrix4::identity());
let geometries = model let geometries = model
.meshes() .meshes()

View file

@ -203,20 +203,6 @@ impl<'a> Mesh<'a> {
} }
} }
fn read_indexes<I: Iterator<Item = usize> + 'static, T: Readable>(
indexes: I,
data: &[u8],
) -> impl Iterator<Item = Result<T, ModelError>> + '_ {
indexes
.map(|index| {
data.get(index..).ok_or_else(|| ModelError::OutOfBounds {
data: type_name::<T>(),
offset: index,
})
})
.map(|data| data.and_then(|data| T::read(data)))
}
fn index_range(index: i32, count: i32, size: usize) -> impl Iterator<Item = usize> { fn index_range(index: i32, count: i32, size: usize) -> impl Iterator<Item = usize> {
(0..count as usize) (0..count as usize)
.map(move |i| i * size) .map(move |i| i * size)

View file

@ -6,10 +6,7 @@ pub use raw::*;
use std::mem::size_of; use std::mem::size_of;
use crate::vvd::Vertex; use crate::vvd::Vertex;
use crate::{ use crate::{read_relative, read_relative_iter, FixedString, ModelError, ReadRelative, Readable};
read_indexes, read_relative, read_relative_iter, FixedString, ModelError, ReadRelative,
Readable,
};
type Result<T> = std::result::Result<T, ModelError>; type Result<T> = std::result::Result<T, ModelError>;
@ -44,7 +41,7 @@ impl Mdl {
let skin_table = read_relative::<u16, _>(data, header.skin_reference_indexes())?; let skin_table = read_relative::<u16, _>(data, header.skin_reference_indexes())?;
let bones = read_indexes(header.bone_indexes(), data).collect::<Result<_>>()?; let bones = read_relative(data, header.bone_indexes())?;
Ok(Mdl { Ok(Mdl {
name, name,
bones, bones,

View file

@ -1,5 +1,4 @@
use crate::mdl::raw::*; use crate::mdl::raw::*;
use crate::mdl::Bone;
use crate::{index_range, Vector}; use crate::{index_range, Vector};
use std::mem::size_of; use std::mem::size_of;
@ -211,7 +210,7 @@ impl StudioHeader {
} }
pub fn bone_indexes(&self) -> impl Iterator<Item = usize> { pub fn bone_indexes(&self) -> impl Iterator<Item = usize> {
index_range(self.bone_offset, self.bone_count, size_of::<Bone>()) index_range(self.bone_offset, self.bone_count, size_of::<BoneHeader>())
} }
pub fn bone_controller_indexes(&self) -> impl Iterator<Item = usize> { pub fn bone_controller_indexes(&self) -> impl Iterator<Item = usize> {

View file

@ -1,4 +1,4 @@
use crate::{index_range, FixedString}; use crate::{index_range, FixedString, ModelError, ReadRelative};
use crate::{Quaternion, RadianEuler, Vector}; use crate::{Quaternion, RadianEuler, Vector};
use bitflags::bitflags; use bitflags::bitflags;
use bytemuck::{Pod, Zeroable}; use bytemuck::{Pod, Zeroable};
@ -9,7 +9,7 @@ pub mod header2;
#[derive(Debug, Clone, Copy, Zeroable, Pod)] #[derive(Debug, Clone, Copy, Zeroable, Pod)]
#[repr(C)] #[repr(C)]
pub struct Bone { pub struct BoneHeader {
pub sz_name_index: i32, pub sz_name_index: i32,
pub parent: i32, // parent bone pub parent: i32, // parent bone
pub bone_controller: [i32; 6], // bone controller index, -1 == none pub bone_controller: [i32; 6], // bone controller index, -1 == none
@ -33,6 +33,60 @@ pub struct Bone {
reserved: [i32; 8], // remove as appropriate reserved: [i32; 8], // remove as appropriate
} }
static_assertions::const_assert_eq!(size_of::<BoneHeader>(), 216);
#[derive(Debug, Clone)]
#[repr(C)]
pub struct Bone {
pub name: String,
pub parent: i32, // parent bone
pub bone_controller: [i32; 6], // bone controller index, -1 == none
pub pos: Vector,
pub quaternion: Quaternion,
pub rot: RadianEuler,
pub pos_scale: Vector,
pub rot_scale: Vector,
pub pose_to_bone: [[f32; 3]; 4], // 3x4 matrix
pub q_alignment: Quaternion,
pub flags: BoneFlags,
pub proc_type: i32,
pub proc_index: i32, // procedural rule
pub physics_bone: i32, // index into physically simulated bone
pub surface_prop_idx: i32, // index into string table for property name
pub contents: i32, // See BSPFlags.h for the contents flags
}
impl ReadRelative for Bone {
type Header = BoneHeader;
fn read(data: &[u8], header: Self::Header) -> Result<Self, ModelError> {
let name_bytes = data
.get(header.sz_name_index as usize..)
.unwrap_or_default();
Ok(Bone {
name: String::read(name_bytes, ())?,
parent: header.parent,
bone_controller: header.bone_controller,
pos: header.pos,
quaternion: header.quaternion,
rot: header.rot,
pos_scale: header.pos_scale,
rot_scale: header.rot_scale,
pose_to_bone: header.pose_to_bone,
q_alignment: header.q_alignment,
flags: header.flags,
proc_type: header.proc_type,
proc_index: header.proc_index,
physics_bone: header.physics_bone,
surface_prop_idx: header.surface_prop_idx,
contents: header.contents,
})
}
}
#[derive(Zeroable, Pod, Copy, Clone, Debug)] #[derive(Zeroable, Pod, Copy, Clone, Debug)]
#[repr(C)] #[repr(C)]
pub struct BoneFlags(u32); pub struct BoneFlags(u32);

View file

@ -2,7 +2,6 @@ use crate::{ModelError, StringError};
use arrayvec::ArrayString; use arrayvec::ArrayString;
use bytemuck::{Pod, Zeroable}; use bytemuck::{Pod, Zeroable};
use cgmath::{Deg, Euler, Rad, Rotation3, Vector3}; use cgmath::{Deg, Euler, Rad, Rotation3, Vector3};
use std::f32::consts::PI;
use std::fmt; use std::fmt;
use std::fmt::{Display, Formatter}; use std::fmt::{Display, Formatter};
use std::ops::{Add, Mul}; use std::ops::{Add, Mul};