refactor relative reading

This commit is contained in:
Robin Appelman 2022-03-12 18:07:59 +01:00
commit bb28ec14ea
4 changed files with 98 additions and 134 deletions

View file

@ -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)
}
}

View file

@ -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,
})

View file

@ -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,

View file

@ -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()
}