mirror of
https://codeberg.org/icewind/vmdl.git
synced 2026-06-03 16:44:11 +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> + '_> {
|
pub fn vertex_strip_indices(&self) -> impl Iterator<Item = impl Iterator<Item = usize> + '_> {
|
||||||
let mdl_meshes = self
|
let mesh_vertex_offsets = self
|
||||||
.mdl
|
.mdl
|
||||||
.body_parts
|
.body_parts
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|part| part.models.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
|
let vtx_meshes = self
|
||||||
.vtx
|
.vtx
|
||||||
|
|
@ -53,17 +59,16 @@ impl Model {
|
||||||
.flat_map(|lod| lod.meshes.iter());
|
.flat_map(|lod| lod.meshes.iter());
|
||||||
|
|
||||||
vtx_meshes
|
vtx_meshes
|
||||||
.zip(mdl_meshes)
|
.zip(mesh_vertex_offsets)
|
||||||
.flat_map(|(vtx_mesh, mdl_mesh)| {
|
.flat_map(|(vtx_mesh, vertex_offset)| {
|
||||||
vtx_mesh
|
vtx_mesh
|
||||||
.strip_groups
|
.strip_groups
|
||||||
.iter()
|
.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 group_indices = &strip_group.indices;
|
||||||
let vertices = &strip_group.vertices;
|
let vertices = &strip_group.vertices;
|
||||||
let mesh_vertex_offset = mdl_mesh.vertex_offset as usize;
|
|
||||||
strip_group.strips.iter().cloned().map(move |strip| {
|
strip_group.strips.iter().cloned().map(move |strip| {
|
||||||
strip
|
strip
|
||||||
.indices()
|
.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| i * size)
|
||||||
.map(move |i| index as usize + i)
|
.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::*;
|
pub use raw::header2::*;
|
||||||
|
|
||||||
use crate::mdl::raw::{BodyPartHeader, Bone, MeshHeader, ModelHeader};
|
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 binrw::BinReaderExt;
|
||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
|
|
||||||
|
|
@ -47,21 +47,12 @@ pub struct BodyPart {
|
||||||
pub models: Vec<Model>,
|
pub models: Vec<Model>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BodyPart {
|
impl ReadRelative for BodyPart {
|
||||||
pub fn read(data: &[u8], header: BodyPartHeader) -> Result<Self> {
|
type Header = BodyPartHeader;
|
||||||
|
|
||||||
|
fn read(data: &[u8], header: Self::Header) -> Result<Self> {
|
||||||
Ok(BodyPart {
|
Ok(BodyPart {
|
||||||
models: header
|
models: read_relative(data, header.model_indexes())?,
|
||||||
.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<_>>()?,
|
|
||||||
name_index: header.name_index,
|
name_index: header.name_index,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -73,26 +64,19 @@ pub struct Model {
|
||||||
pub ty: i32,
|
pub ty: i32,
|
||||||
pub bounding_radius: f32,
|
pub bounding_radius: f32,
|
||||||
pub meshes: Vec<Mesh>,
|
pub meshes: Vec<Mesh>,
|
||||||
|
pub vertex_offset: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Model {
|
impl ReadRelative for Model {
|
||||||
pub fn read(data: &[u8], header: ModelHeader) -> Result<Self> {
|
type Header = ModelHeader;
|
||||||
|
|
||||||
|
fn read(data: &[u8], header: Self::Header) -> Result<Self> {
|
||||||
Ok(Model {
|
Ok(Model {
|
||||||
meshes: header
|
meshes: read_relative(data, header.mesh_indexes())?,
|
||||||
.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<_>>()?,
|
|
||||||
name: header.name,
|
name: header.name,
|
||||||
ty: header.ty,
|
ty: header.ty,
|
||||||
bounding_radius: header.bounding_radius,
|
bounding_radius: header.bounding_radius,
|
||||||
|
vertex_offset: header.vertex_index,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -102,8 +86,10 @@ pub struct Mesh {
|
||||||
pub vertex_offset: i32,
|
pub vertex_offset: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Mesh {
|
impl ReadRelative for Mesh {
|
||||||
pub fn read(_data: &[u8], header: MeshHeader) -> Result<Self> {
|
type Header = MeshHeader;
|
||||||
|
|
||||||
|
fn read(_data: &[u8], header: Self::Header) -> Result<Self> {
|
||||||
Ok(Mesh {
|
Ok(Mesh {
|
||||||
vertex_offset: header.vertex_index,
|
vertex_offset: header.vertex_index,
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,7 @@ pub struct ModelHeader {
|
||||||
mesh_count: i32,
|
mesh_count: i32,
|
||||||
mesh_index: i32,
|
mesh_index: i32,
|
||||||
vertex_count: i32,
|
vertex_count: i32,
|
||||||
vertex_index: i32,
|
pub vertex_index: i32,
|
||||||
tangent_index: i32,
|
tangent_index: i32,
|
||||||
attachment_count: i32,
|
attachment_count: i32,
|
||||||
attachment_index: i32,
|
attachment_index: i32,
|
||||||
|
|
|
||||||
129
src/vtx/mod.rs
129
src/vtx/mod.rs
|
|
@ -1,6 +1,6 @@
|
||||||
mod raw;
|
mod raw;
|
||||||
|
|
||||||
use crate::ModelError;
|
use crate::{read_relative, ModelError, ReadRelative};
|
||||||
use binrw::BinReaderExt;
|
use binrw::BinReaderExt;
|
||||||
use itertools::Either;
|
use itertools::Either;
|
||||||
use raw::*;
|
use raw::*;
|
||||||
|
|
@ -45,21 +45,12 @@ pub struct BodyPart {
|
||||||
pub models: Vec<Model>,
|
pub models: Vec<Model>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BodyPart {
|
impl ReadRelative for BodyPart {
|
||||||
fn read(data: &[u8], header: BodyPartHeader) -> Result<Self> {
|
type Header = BodyPartHeader;
|
||||||
|
|
||||||
|
fn read(data: &[u8], header: Self::Header) -> Result<Self> {
|
||||||
Ok(BodyPart {
|
Ok(BodyPart {
|
||||||
models: header
|
models: read_relative(data, header.model_indexes())?,
|
||||||
.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<_>>()?,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -69,21 +60,12 @@ pub struct Model {
|
||||||
pub lods: Vec<ModelLod>,
|
pub lods: Vec<ModelLod>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Model {
|
impl ReadRelative for Model {
|
||||||
fn read(data: &[u8], header: ModelHeader) -> Result<Self> {
|
type Header = ModelHeader;
|
||||||
|
|
||||||
|
fn read(data: &[u8], header: Self::Header) -> Result<Self> {
|
||||||
Ok(Model {
|
Ok(Model {
|
||||||
lods: header
|
lods: read_relative(data, header.lod_indexes())?,
|
||||||
.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<_>>()?,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -94,21 +76,12 @@ pub struct ModelLod {
|
||||||
pub switch_point: f32,
|
pub switch_point: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ModelLod {
|
impl ReadRelative for ModelLod {
|
||||||
fn read(data: &[u8], header: ModelLodHeader) -> Result<Self> {
|
type Header = ModelLodHeader;
|
||||||
|
|
||||||
|
fn read(data: &[u8], header: Self::Header) -> Result<Self> {
|
||||||
Ok(ModelLod {
|
Ok(ModelLod {
|
||||||
meshes: header
|
meshes: read_relative(data, header.mesh_indexes())?,
|
||||||
.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<_>>()?,
|
|
||||||
switch_point: header.switch_point,
|
switch_point: header.switch_point,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -120,21 +93,12 @@ pub struct Mesh {
|
||||||
pub flags: MeshFlags,
|
pub flags: MeshFlags,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Mesh {
|
impl ReadRelative for Mesh {
|
||||||
fn read(data: &[u8], header: MeshHeader) -> Result<Self> {
|
type Header = MeshHeader;
|
||||||
|
|
||||||
|
fn read(data: &[u8], header: Self::Header) -> Result<Self> {
|
||||||
Ok(Mesh {
|
Ok(Mesh {
|
||||||
strip_groups: header
|
strip_groups: read_relative(data, header.strip_group_indexes())?,
|
||||||
.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<_>>()?,
|
|
||||||
flags: header.flags,
|
flags: header.flags,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -149,43 +113,14 @@ pub struct StripGroup {
|
||||||
pub flags: StripGroupFlags,
|
pub flags: StripGroupFlags,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StripGroup {
|
impl ReadRelative for StripGroup {
|
||||||
fn read(data: &[u8], header: StripGroupHeader) -> Result<Self> {
|
type Header = StripGroupHeader;
|
||||||
|
|
||||||
|
fn read(data: &[u8], header: Self::Header) -> Result<Self> {
|
||||||
Ok(StripGroup {
|
Ok(StripGroup {
|
||||||
vertices: header
|
vertices: read_relative(data, header.vertex_indexes())?,
|
||||||
.vertex_indexes()
|
strips: read_relative(data, header.strip_indexes())?,
|
||||||
.map(|index| {
|
indices: read_relative(data, header.index_indexes())?,
|
||||||
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<_>>()?,
|
|
||||||
flags: header.flags,
|
flags: header.flags,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -199,15 +134,19 @@ pub struct Strip {
|
||||||
indices: Range<usize>,
|
indices: Range<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Strip {
|
impl ReadRelative for Strip {
|
||||||
fn read(_data: &[u8], header: StripHeader) -> Result<Self> {
|
type Header = StripHeader;
|
||||||
|
|
||||||
|
fn read(_data: &[u8], header: Self::Header) -> Result<Self> {
|
||||||
Ok(Strip {
|
Ok(Strip {
|
||||||
vertices: header.vertex_indexes(),
|
vertices: header.vertex_indexes(),
|
||||||
indices: header.index_indexes(),
|
indices: header.index_indexes(),
|
||||||
flags: header.flags,
|
flags: header.flags,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Strip {
|
||||||
pub fn vertices(&self) -> impl Iterator<Item = usize> + 'static {
|
pub fn vertices(&self) -> impl Iterator<Item = usize> + 'static {
|
||||||
self.vertices.clone()
|
self.vertices.clone()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue