basic vvd

This commit is contained in:
Robin Appelman 2022-03-11 19:38:35 +01:00
commit fc98416aa3
5 changed files with 137 additions and 17 deletions

View file

@ -185,7 +185,7 @@ impl StripHeader {
index_range(
self.bone_state_change_offset,
self.bone_state_change_count,
todo!(),
1,
)
}
}

View file

@ -1,16 +0,0 @@
use binrw::BinRead;
pub const MDL_VERSION: i32 = 7;
#[derive(Debug, Clone, BinRead)]
pub struct Header {
pub id: i32,
pub version: i32,
pub checksum: [u8; 4],
pub lod_count: i32,
pub lod_vertex_count: [i32; 8],
pub fixup_count: i32,
pub fixup_index: i32,
pub vertex_index: i32,
pub tangent_index: i32,
}

37
src/vvd/mod.rs Normal file
View file

@ -0,0 +1,37 @@
mod raw;
use crate::vvd::raw::VvdHeader;
use crate::ModelError;
use binrw::BinReaderExt;
pub use raw::{BoneWeight, Tangent, Vertex};
use std::io::Cursor;
type Result<T> = std::result::Result<T, ModelError>;
#[derive(Debug, Clone)]
pub struct Vvd {
pub header: VvdHeader,
pub vertices: Vec<Vertex>,
}
impl Vvd {
pub fn read(data: &[u8]) -> Result<Self> {
let mut reader = Cursor::new(data);
let header: VvdHeader = reader.read_le()?;
Ok(Vvd {
vertices: header
.vertex_indexes(0)
.unwrap()
.map(|index| {
let data = data.get(index..).ok_or_else(|| ModelError::OutOfBounds {
data: "Vertex",
offset: index,
})?;
let mut reader = Cursor::new(data);
Ok(reader.read_le()?)
})
.collect::<Result<_>>()?,
header,
})
}
}

92
src/vvd/raw.rs Normal file
View file

@ -0,0 +1,92 @@
use crate::{index_range, Vector};
use binrw::BinRead;
use std::mem::size_of;
pub const MDL_VERSION: i32 = 7;
#[derive(Debug, Clone, BinRead)]
pub struct VvdHeader {
pub id: i32,
pub version: i32,
pub checksum: [u8; 4],
pub lod_count: i32,
lod_vertex_count: [i32; 8],
fixup_count: i32,
fixup_index: i32,
vertex_index: i32,
tangent_index: i32,
}
impl VvdHeader {
pub fn fixup_indexes(&self) -> impl Iterator<Item = usize> {
index_range(
self.fixup_index,
self.fixup_count,
size_of::<VertexFileFixup>(),
)
}
pub fn vertex_indexes(&self, lod: i32) -> Option<impl Iterator<Item = usize>> {
if lod > 0 && lod > self.fixup_count {
todo!("lod fixup not supported")
}
if lod < self.lod_count {
Some(index_range(
self.vertex_index,
self.lod_vertex_count[lod as usize],
size_of::<Vertex>(),
))
} else {
None
}
}
pub fn tangent_indexes(&self, lod: i32) -> Option<impl Iterator<Item = usize>> {
if lod > 0 && lod > self.fixup_count {
todo!("lod fixup not supported")
}
if lod < self.lod_count {
Some(index_range(
self.tangent_index,
self.lod_vertex_count[lod as usize],
size_of::<Vertex>(),
))
} else {
None
}
}
}
#[derive(Debug, Clone, BinRead)]
pub struct VertexFileFixup {
pub lod: i32,
pub source_vertex_id: i32,
pub vertex_count: i32,
}
#[derive(Debug, Clone, BinRead)]
pub struct Vertex {
pub bone_weights: BoneWeight,
pub position: Vector,
pub normal: Vector,
pub texture_coordinates: [f32; 2],
}
static_assertions::const_assert_eq!(size_of::<Vertex>(), 48);
#[derive(Debug, Clone, BinRead)]
pub struct BoneWeight {
pub weight: [f32; 3],
pub bone: [u8; 3],
pub bone_count: u8,
}
static_assertions::const_assert_eq!(size_of::<BoneWeight>(), 16);
#[derive(Debug, Clone, BinRead)]
pub struct Tangent {
pub x: f32,
pub y: f32,
pub z: f32,
pub w: f32,
}

View file

@ -1,6 +1,7 @@
use std::fs::read;
use vmdl::mdl::Mdl;
use vmdl::vtx::Vtx;
use vmdl::vvd::Vvd;
#[test]
fn parse_mdl() {
@ -13,3 +14,9 @@ fn parse_vtx() {
let data = read("data/barrel01.dx90.vtx").unwrap();
Vtx::read(&data).unwrap();
}
#[test]
fn parse_vvd() {
let data = read("data/barrel01.vvd").unwrap();
Vvd::read(&data).unwrap();
}