This commit is contained in:
Robin Appelman 2023-12-30 22:57:25 +01:00
commit 50144ca1dd
8 changed files with 45 additions and 18 deletions

View file

@ -19,16 +19,12 @@ fn main() -> Result<(), vmdl::ModelError> {
let _vvd = Vvd::read(&data)?;
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()
// );
// }
for bone in mdl.bones {
println!(
"{}: from {} at\n\t{:?}\n\t{:?}",
bone.name, bone.parent, bone.quaternion, bone.q_alignment
);
}
// let model = Model::from_parts(mdl, vtx, vvd);
// for strip in model.vertex_strips() {

View file

@ -262,7 +262,8 @@ fn model_to_model(model: &Model, loader: &Loader, skin: usize) -> CpuModel {
let positions: Vec<Vec3> = mesh
.vertices()
.map(|vertex| map_coords(vertex.position + offset) * 10.0)
.map(|vertex| model.vertex_to_world_space(vertex))
.map(|position| map_coords(position) * 10.0)
.map(|vertex: Vec3| (transforms * vertex.extend(1.0)).truncate())
.collect();
let normals: Vec<Vec3> = mesh.vertices().map(|vertex| vertex.normal.into()).collect();

View file

@ -148,6 +148,16 @@ impl Model {
pub fn poses(&self) -> impl Iterator<Item = &PoseParameterDescription> {
self.mdl.pose_parameters.iter()
}
pub fn vertex_to_world_space(&self, vertex: &Vertex) -> Vector {
let mut pos = vertex.position;
for weights in vertex.bone_weights.weights() {
if let Some(bone) = self.mdl.bones.get(weights.bone_id as usize) {
pos = pos.transformed(bone.pose_to_bone);
}
}
pos
}
}
pub struct SkinTable<'a> {

View file

@ -16,6 +16,7 @@ type Result<T> = std::result::Result<T, ModelError>;
pub struct Mdl {
pub name: FixedString<64>,
pub header: StudioHeader,
pub header2: Option<StudioHeader2>,
pub bones: Vec<Bone>,
pub body_parts: Vec<BodyPart>,
pub textures: Vec<TextureInfo>,
@ -30,6 +31,10 @@ pub struct Mdl {
impl Mdl {
pub fn read(data: &[u8]) -> Result<Self> {
let header = <StudioHeader as Readable>::read(data)?;
let header2 = header
.header2_index()
.map(|index| read_single(data, index))
.transpose()?;
let name = header.name.try_into()?;
let mut textures = read_relative_iter(data, header.texture_indexes())
.collect::<Result<Vec<TextureInfo>>>()?;
@ -72,6 +77,7 @@ impl Mdl {
texture_paths,
skin_table,
header,
header2,
surface_prop,
key_values,
pose_parameters,

View file

@ -1,5 +1,6 @@
use crate::mdl::raw::*;
use crate::{index_range, Vector};
use crate::mdl::StudioHeader2;
use crate::{index_range, read_single, Vector};
use std::mem::size_of;
pub const FILETYPE_ID: i32 = i32::from_be_bytes(*b"IDST");
@ -201,7 +202,7 @@ bitflags! {
}
impl StudioHeader {
pub fn header2_index(&self) -> Option<usize> {
pub(crate) fn header2_index(&self) -> Option<usize> {
(self.studio_hdr2_index > 0)
.then_some(self.studio_hdr2_index)
.and_then(|index| usize::try_from(index).ok())

View file

@ -1,6 +1,10 @@
use crate::ReadableRelative;
use bytemuck::{Pod, Zeroable};
use std::ops::Range;
pub struct StudioHHeader2 {
#[derive(Debug, Clone, Copy, Zeroable, Pod)]
#[repr(C)]
pub struct StudioHeader2 {
source_bone_transform_count: i32,
source_bone_transform_index: i32,
@ -15,11 +19,13 @@ pub struct StudioHHeader2 {
bone_flex_driver_count: i32,
bone_flex_driver_index: i32,
#[allow(dead_code)]
reserved: [i32; 56],
_reserved1: [i32; 32],
_reserved2: [i32; 24],
}
impl StudioHHeader2 {
impl ReadableRelative for StudioHeader2 {}
impl StudioHeader2 {
pub fn source_bone_transforms(&self) -> Range<i32> {
self.source_bone_transform_index
..(self.source_bone_transform_index + self.source_bone_transform_count)

View file

@ -1,7 +1,7 @@
use crate::{ModelError, StringError};
use arrayvec::ArrayString;
use bytemuck::{Pod, Zeroable};
use cgmath::{Deg, Euler, Matrix3, Matrix4, Rad, Rotation3, Vector3};
use cgmath::{Deg, Euler, Matrix3, Matrix4, Rad, Rotation3, Vector3, Vector4};
use std::fmt;
use std::fmt::{Display, Formatter};
use std::ops::{Add, Mul};
@ -38,6 +38,12 @@ impl Vector {
pub fn iter(&self) -> impl Iterator<Item = f32> {
[self.x, self.y, self.z].into_iter()
}
pub fn transformed<T: Into<Matrix4<f32>>>(&self, transform: T) -> Vector {
let transform = transform.into();
let transformed = transform * Vector4::new(self.x, self.y, self.z, 1.0);
transformed.truncate().into()
}
}
impl From<Vector> for [f32; 3] {

View file

@ -95,6 +95,7 @@ impl BoneWeights {
}
}
#[derive(Clone, Debug)]
pub struct BoneWeight {
pub bone_id: u8,
pub weight: f32,