mirror of
https://codeberg.org/icewind/vmdl.git
synced 2026-06-03 08:34:23 +02:00
refactor relative reading
This commit is contained in:
parent
3aa5c8751b
commit
bb28ec14ea
4 changed files with 98 additions and 134 deletions
53
src/lib.rs
53
src/lib.rs
|
|
@ -37,12 +37,18 @@ impl Model {
|
|||
}
|
||||
|
||||
pub fn vertex_strip_indices(&self) -> impl Iterator<Item = impl Iterator<Item = usize> + '_> {
|
||||
let mdl_meshes = self
|
||||
let mesh_vertex_offsets = self
|
||||
.mdl
|
||||
.body_parts
|
||||
.iter()
|
||||
.flat_map(|part| part.models.iter())
|
||||
.flat_map(|model| model.meshes.iter());
|
||||
.flat_map(|model| {
|
||||
model
|
||||
.meshes
|
||||
.iter()
|
||||
.map(move |mesh| (mesh, model.vertex_offset))
|
||||
})
|
||||
.map(|(mesh, offset)| (mesh.vertex_offset + offset) as usize);
|
||||
|
||||
let vtx_meshes = self
|
||||
.vtx
|
||||
|
|
@ -53,17 +59,16 @@ impl Model {
|
|||
.flat_map(|lod| lod.meshes.iter());
|
||||
|
||||
vtx_meshes
|
||||
.zip(mdl_meshes)
|
||||
.flat_map(|(vtx_mesh, mdl_mesh)| {
|
||||
.zip(mesh_vertex_offsets)
|
||||
.flat_map(|(vtx_mesh, vertex_offset)| {
|
||||
vtx_mesh
|
||||
.strip_groups
|
||||
.iter()
|
||||
.map(move |strip_group| (strip_group, mdl_mesh))
|
||||
.map(move |strip_group| (strip_group, vertex_offset))
|
||||
})
|
||||
.flat_map(|(strip_group, mdl_mesh)| {
|
||||
.flat_map(|(strip_group, mesh_vertex_offset)| {
|
||||
let group_indices = &strip_group.indices;
|
||||
let vertices = &strip_group.vertices;
|
||||
let mesh_vertex_offset = mdl_mesh.vertex_offset as usize;
|
||||
strip_group.strips.iter().cloned().map(move |strip| {
|
||||
strip
|
||||
.indices()
|
||||
|
|
@ -104,3 +109,37 @@ fn index_range(index: i32, count: i32, size: usize) -> impl Iterator<Item = usiz
|
|||
.map(move |i| i * size)
|
||||
.map(move |i| index as usize + i)
|
||||
}
|
||||
|
||||
fn read_relative<T: ReadRelative, I: Iterator<Item = usize>>(
|
||||
data: &[u8],
|
||||
indexes: I,
|
||||
) -> Result<Vec<T>, ModelError>
|
||||
where
|
||||
<<T as ReadRelative>::Header as BinRead>::Args: Default,
|
||||
{
|
||||
indexes
|
||||
.map(|index| {
|
||||
let data = data.get(index..).ok_or_else(|| ModelError::OutOfBounds {
|
||||
data: type_name::<T>(),
|
||||
offset: index,
|
||||
})?;
|
||||
let mut reader = Cursor::new(data);
|
||||
let header = reader.read_le()?;
|
||||
T::read(data, header)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
trait ReadRelative: Sized {
|
||||
type Header: BinRead;
|
||||
|
||||
fn read(data: &[u8], header: Self::Header) -> Result<Self, ModelError>;
|
||||
}
|
||||
|
||||
impl<T: BinRead> ReadRelative for T {
|
||||
type Header = T;
|
||||
|
||||
fn read(_data: &[u8], header: Self::Header) -> Result<Self, ModelError> {
|
||||
Ok(header)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ pub use raw::header::*;
|
|||
pub use raw::header2::*;
|
||||
|
||||
use crate::mdl::raw::{BodyPartHeader, Bone, MeshHeader, ModelHeader};
|
||||
use crate::{read_indexes, FixedString, ModelError};
|
||||
use crate::{read_indexes, read_relative, FixedString, ModelError, ReadRelative};
|
||||
use binrw::BinReaderExt;
|
||||
use std::io::Cursor;
|
||||
|
||||
|
|
@ -47,21 +47,12 @@ pub struct BodyPart {
|
|||
pub models: Vec<Model>,
|
||||
}
|
||||
|
||||
impl BodyPart {
|
||||
pub fn read(data: &[u8], header: BodyPartHeader) -> Result<Self> {
|
||||
impl ReadRelative for BodyPart {
|
||||
type Header = BodyPartHeader;
|
||||
|
||||
fn read(data: &[u8], header: Self::Header) -> Result<Self> {
|
||||
Ok(BodyPart {
|
||||
models: header
|
||||
.model_indexes()
|
||||
.map(|index| {
|
||||
let data = data.get(index..).ok_or_else(|| ModelError::OutOfBounds {
|
||||
data: "Model",
|
||||
offset: index,
|
||||
})?;
|
||||
let mut reader = Cursor::new(data);
|
||||
let header = reader.read_le()?;
|
||||
Model::read(data, header)
|
||||
})
|
||||
.collect::<Result<_>>()?,
|
||||
models: read_relative(data, header.model_indexes())?,
|
||||
name_index: header.name_index,
|
||||
})
|
||||
}
|
||||
|
|
@ -73,26 +64,19 @@ pub struct Model {
|
|||
pub ty: i32,
|
||||
pub bounding_radius: f32,
|
||||
pub meshes: Vec<Mesh>,
|
||||
pub vertex_offset: i32,
|
||||
}
|
||||
|
||||
impl Model {
|
||||
pub fn read(data: &[u8], header: ModelHeader) -> Result<Self> {
|
||||
impl ReadRelative for Model {
|
||||
type Header = ModelHeader;
|
||||
|
||||
fn read(data: &[u8], header: Self::Header) -> Result<Self> {
|
||||
Ok(Model {
|
||||
meshes: header
|
||||
.mesh_indexes()
|
||||
.map(|index| {
|
||||
let data = data.get(index..).ok_or_else(|| ModelError::OutOfBounds {
|
||||
data: "Mesh",
|
||||
offset: index,
|
||||
})?;
|
||||
let mut reader = Cursor::new(data);
|
||||
let header = reader.read_le()?;
|
||||
Mesh::read(data, header)
|
||||
})
|
||||
.collect::<Result<_>>()?,
|
||||
meshes: read_relative(data, header.mesh_indexes())?,
|
||||
name: header.name,
|
||||
ty: header.ty,
|
||||
bounding_radius: header.bounding_radius,
|
||||
vertex_offset: header.vertex_index,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -102,8 +86,10 @@ pub struct Mesh {
|
|||
pub vertex_offset: i32,
|
||||
}
|
||||
|
||||
impl Mesh {
|
||||
pub fn read(_data: &[u8], header: MeshHeader) -> Result<Self> {
|
||||
impl ReadRelative for Mesh {
|
||||
type Header = MeshHeader;
|
||||
|
||||
fn read(_data: &[u8], header: Self::Header) -> Result<Self> {
|
||||
Ok(Mesh {
|
||||
vertex_offset: header.vertex_index,
|
||||
})
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ pub struct ModelHeader {
|
|||
mesh_count: i32,
|
||||
mesh_index: i32,
|
||||
vertex_count: i32,
|
||||
vertex_index: i32,
|
||||
pub vertex_index: i32,
|
||||
tangent_index: i32,
|
||||
attachment_count: i32,
|
||||
attachment_index: i32,
|
||||
|
|
|
|||
129
src/vtx/mod.rs
129
src/vtx/mod.rs
|
|
@ -1,6 +1,6 @@
|
|||
mod raw;
|
||||
|
||||
use crate::ModelError;
|
||||
use crate::{read_relative, ModelError, ReadRelative};
|
||||
use binrw::BinReaderExt;
|
||||
use itertools::Either;
|
||||
use raw::*;
|
||||
|
|
@ -45,21 +45,12 @@ pub struct BodyPart {
|
|||
pub models: Vec<Model>,
|
||||
}
|
||||
|
||||
impl BodyPart {
|
||||
fn read(data: &[u8], header: BodyPartHeader) -> Result<Self> {
|
||||
impl ReadRelative for BodyPart {
|
||||
type Header = BodyPartHeader;
|
||||
|
||||
fn read(data: &[u8], header: Self::Header) -> Result<Self> {
|
||||
Ok(BodyPart {
|
||||
models: header
|
||||
.model_indexes()
|
||||
.map(|index| {
|
||||
let data = data.get(index..).ok_or_else(|| ModelError::OutOfBounds {
|
||||
data: "Model",
|
||||
offset: index,
|
||||
})?;
|
||||
let mut reader = Cursor::new(data);
|
||||
let header = reader.read_le()?;
|
||||
Model::read(data, header)
|
||||
})
|
||||
.collect::<Result<_>>()?,
|
||||
models: read_relative(data, header.model_indexes())?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -69,21 +60,12 @@ pub struct Model {
|
|||
pub lods: Vec<ModelLod>,
|
||||
}
|
||||
|
||||
impl Model {
|
||||
fn read(data: &[u8], header: ModelHeader) -> Result<Self> {
|
||||
impl ReadRelative for Model {
|
||||
type Header = ModelHeader;
|
||||
|
||||
fn read(data: &[u8], header: Self::Header) -> Result<Self> {
|
||||
Ok(Model {
|
||||
lods: header
|
||||
.lod_indexes()
|
||||
.map(|index| {
|
||||
let data = data.get(index..).ok_or_else(|| ModelError::OutOfBounds {
|
||||
data: "ModelLod",
|
||||
offset: index,
|
||||
})?;
|
||||
let mut reader = Cursor::new(data);
|
||||
let header = reader.read_le()?;
|
||||
ModelLod::read(data, header)
|
||||
})
|
||||
.collect::<Result<_>>()?,
|
||||
lods: read_relative(data, header.lod_indexes())?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -94,21 +76,12 @@ pub struct ModelLod {
|
|||
pub switch_point: f32,
|
||||
}
|
||||
|
||||
impl ModelLod {
|
||||
fn read(data: &[u8], header: ModelLodHeader) -> Result<Self> {
|
||||
impl ReadRelative for ModelLod {
|
||||
type Header = ModelLodHeader;
|
||||
|
||||
fn read(data: &[u8], header: Self::Header) -> Result<Self> {
|
||||
Ok(ModelLod {
|
||||
meshes: header
|
||||
.mesh_indexes()
|
||||
.map(|index| {
|
||||
let data = data.get(index..).ok_or_else(|| ModelError::OutOfBounds {
|
||||
data: "Mesh",
|
||||
offset: index,
|
||||
})?;
|
||||
let mut reader = Cursor::new(data);
|
||||
let header = reader.read_le()?;
|
||||
Mesh::read(data, header)
|
||||
})
|
||||
.collect::<Result<_>>()?,
|
||||
meshes: read_relative(data, header.mesh_indexes())?,
|
||||
switch_point: header.switch_point,
|
||||
})
|
||||
}
|
||||
|
|
@ -120,21 +93,12 @@ pub struct Mesh {
|
|||
pub flags: MeshFlags,
|
||||
}
|
||||
|
||||
impl Mesh {
|
||||
fn read(data: &[u8], header: MeshHeader) -> Result<Self> {
|
||||
impl ReadRelative for Mesh {
|
||||
type Header = MeshHeader;
|
||||
|
||||
fn read(data: &[u8], header: Self::Header) -> Result<Self> {
|
||||
Ok(Mesh {
|
||||
strip_groups: header
|
||||
.strip_group_indexes()
|
||||
.map(|index| {
|
||||
let data = data.get(index..).ok_or_else(|| ModelError::OutOfBounds {
|
||||
data: "StripGroup",
|
||||
offset: index,
|
||||
})?;
|
||||
let mut reader = Cursor::new(data);
|
||||
let header = reader.read_le()?;
|
||||
StripGroup::read(data, header)
|
||||
})
|
||||
.collect::<Result<_>>()?,
|
||||
strip_groups: read_relative(data, header.strip_group_indexes())?,
|
||||
flags: header.flags,
|
||||
})
|
||||
}
|
||||
|
|
@ -149,43 +113,14 @@ pub struct StripGroup {
|
|||
pub flags: StripGroupFlags,
|
||||
}
|
||||
|
||||
impl StripGroup {
|
||||
fn read(data: &[u8], header: StripGroupHeader) -> Result<Self> {
|
||||
impl ReadRelative for StripGroup {
|
||||
type Header = StripGroupHeader;
|
||||
|
||||
fn read(data: &[u8], header: Self::Header) -> Result<Self> {
|
||||
Ok(StripGroup {
|
||||
vertices: header
|
||||
.vertex_indexes()
|
||||
.map(|index| {
|
||||
let data = data.get(index..).ok_or_else(|| ModelError::OutOfBounds {
|
||||
data: "Vertex",
|
||||
offset: index,
|
||||
})?;
|
||||
let mut reader = Cursor::new(data);
|
||||
reader.read_le().map_err(ModelError::from)
|
||||
})
|
||||
.collect::<Result<_>>()?,
|
||||
strips: header
|
||||
.strip_indexes()
|
||||
.map(|index| {
|
||||
let data = data.get(index..).ok_or_else(|| ModelError::OutOfBounds {
|
||||
data: "Strip",
|
||||
offset: index,
|
||||
})?;
|
||||
let mut reader = Cursor::new(data);
|
||||
let header = reader.read_le()?;
|
||||
Strip::read(data, header)
|
||||
})
|
||||
.collect::<Result<_>>()?,
|
||||
indices: header
|
||||
.index_indexes()
|
||||
.map(|index| {
|
||||
let data = data.get(index..).ok_or_else(|| ModelError::OutOfBounds {
|
||||
data: "VertexIndex",
|
||||
offset: index,
|
||||
})?;
|
||||
let mut reader = Cursor::new(data);
|
||||
Ok(reader.read_le()?)
|
||||
})
|
||||
.collect::<Result<_>>()?,
|
||||
vertices: read_relative(data, header.vertex_indexes())?,
|
||||
strips: read_relative(data, header.strip_indexes())?,
|
||||
indices: read_relative(data, header.index_indexes())?,
|
||||
flags: header.flags,
|
||||
})
|
||||
}
|
||||
|
|
@ -199,15 +134,19 @@ pub struct Strip {
|
|||
indices: Range<usize>,
|
||||
}
|
||||
|
||||
impl Strip {
|
||||
fn read(_data: &[u8], header: StripHeader) -> Result<Self> {
|
||||
impl ReadRelative for Strip {
|
||||
type Header = StripHeader;
|
||||
|
||||
fn read(_data: &[u8], header: Self::Header) -> Result<Self> {
|
||||
Ok(Strip {
|
||||
vertices: header.vertex_indexes(),
|
||||
indices: header.index_indexes(),
|
||||
flags: header.flags,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Strip {
|
||||
pub fn vertices(&self) -> impl Iterator<Item = usize> + 'static {
|
||||
self.vertices.clone()
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue