surface prop and keyvalues

This commit is contained in:
Robin Appelman 2023-12-29 20:22:31 +01:00
commit 44e7671fdb
4 changed files with 35 additions and 10 deletions

View file

@ -17,6 +17,8 @@ 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{:?}",

View file

@ -10,7 +10,7 @@ use crate::mdl::{Bone, TextureInfo};
pub use crate::vtx::Vtx;
use crate::vvd::Vertex;
pub use crate::vvd::Vvd;
use bytemuck::{pod_read_unaligned, Pod};
use bytemuck::{pod_read_unaligned, Contiguous, Pod};
use cgmath::{Matrix4, SquareMatrix};
pub use error::*;
pub use handle::Handle;
@ -140,6 +140,10 @@ impl Model {
.map(Matrix4::from)
.unwrap_or_else(Matrix4::identity)
}
pub fn surface_prop(&self) -> &str {
self.mdl.surface_prop.as_str()
}
}
pub struct SkinTable<'a> {
@ -229,6 +233,19 @@ fn read_relative<T: ReadRelative, I: Iterator<Item = usize>>(
read_relative_iter(data, indexes).collect()
}
fn read_single<T: ReadRelative, I: TryInto<usize>>(data: &[u8], index: I) -> Result<T, ModelError> {
let index = index.try_into().map_err(|_| ModelError::OutOfBounds {
data: type_name::<T>(),
offset: usize::MAX_VALUE,
})?;
let data = data.get(index..).ok_or_else(|| ModelError::OutOfBounds {
data: type_name::<T>(),
offset: index,
})?;
let header = <T::Header as Readable>::read(data)?;
T::read(data, header)
}
trait Readable: Sized {
fn read(data: &[u8]) -> Result<Self, ModelError>;
}

View file

@ -6,7 +6,9 @@ pub use raw::*;
use std::mem::size_of;
use crate::vvd::Vertex;
use crate::{read_relative, read_relative_iter, FixedString, ModelError, ReadRelative, Readable};
use crate::{
read_relative, read_relative_iter, read_single, FixedString, ModelError, ReadRelative, Readable,
};
type Result<T> = std::result::Result<T, ModelError>;
@ -19,6 +21,8 @@ pub struct Mdl {
pub textures: Vec<TextureInfo>,
pub texture_paths: Vec<String>,
pub skin_table: Vec<u16>,
pub surface_prop: String,
pub key_values: Option<String>,
}
impl Mdl {
@ -40,8 +44,12 @@ impl Mdl {
}
let skin_table = read_relative::<u16, _>(data, header.skin_reference_indexes())?;
let bones = read_relative(data, header.bone_indexes())?;
let surface_prop = read_single(data, header.surface_prop_index)?;
let key_values = (header.key_value_size > 0)
.then(|| read_single(data, header.key_value_index))
.transpose()?;
Ok(Mdl {
name,
bones,
@ -60,6 +68,8 @@ impl Mdl {
texture_paths,
skin_table,
header,
surface_prop,
key_values,
})
}
}

View file

@ -107,13 +107,13 @@ pub struct StudioHeader {
* from the start of the file.
*/
// Surface property value (single null-terminated string)
surface_prop_index: i32,
pub(crate) surface_prop_index: i32,
// Unusual: In this one index comes first, then count.
// Key-value mdl is a series of strings. If you can't find
// what you're interested in, check the associated PHY file as well.
key_value_index: i32,
key_value_count: i32,
pub(crate) key_value_index: i32,
pub(crate) key_value_size: i32,
// More inverse-kinematics
// mstudioiklock_t
@ -295,10 +295,6 @@ impl StudioHeader {
index_range(self.local_pose_param_index, self.local_pose_param_count, 1)
}
pub fn key_value_indexes(&self) -> impl Iterator<Item = usize> {
index_range(self.key_value_index, self.key_value_count, 1)
}
pub fn ik_lock_indexes(&self) -> impl Iterator<Item = usize> {
index_range(self.ik_lock_index, self.ik_lock_count, 1)
}