1
Fork 0
mirror of https://github.com/redstrate/Physis.git synced 2025-04-21 20:27:46 +00:00

Use custom binrw parsers/writers for VertexDeclarations

Eventually I want to consolidate the model headers, and this makes it,
so we only need a ModelFileHeader::read or write call without a separate
step.
This commit is contained in:
Joshua Goins 2023-12-13 17:19:02 -05:00
parent 835b48ff5b
commit 0b0850c574
2 changed files with 62 additions and 45 deletions

View file

@ -387,6 +387,7 @@ impl DatFile {
lod_count: model_file_info.num_lods, lod_count: model_file_info.num_lods,
index_buffer_streaming_enabled: model_file_info.index_buffer_streaming_enabled, index_buffer_streaming_enabled: model_file_info.index_buffer_streaming_enabled,
has_edge_geometry: model_file_info.edge_geometry_enabled, has_edge_geometry: model_file_info.edge_geometry_enabled,
vertex_declarations: Vec::new()
}; };
buffer.seek(SeekFrom::Start(0)).ok()?; buffer.seek(SeekFrom::Start(0)).ok()?;

View file

@ -4,7 +4,7 @@
use std::io::{Cursor, Seek, SeekFrom, Write}; use std::io::{Cursor, Seek, SeekFrom, Write};
use std::mem::size_of; use std::mem::size_of;
use binrw::{binrw, BinWrite, BinWriterExt}; use binrw::{BinResult, binrw, BinWrite, BinWriterExt};
use binrw::BinRead; use binrw::BinRead;
use binrw::BinReaderExt; use binrw::BinReaderExt;
use crate::{ByteBuffer, ByteSpan}; use crate::{ByteBuffer, ByteSpan};
@ -16,7 +16,7 @@ const END_OF_STREAM: u8 = 0xFF;
#[derive(Debug)] #[derive(Debug)]
#[brw(little)] #[brw(little)]
pub struct ModelFileHeader { pub struct ModelFileHeader {
pub(crate) version: u32, pub version: u32,
pub stack_size: u32, pub stack_size: u32,
pub runtime_size: u32, pub runtime_size: u32,
@ -38,6 +38,10 @@ pub struct ModelFileHeader {
#[bw(map = | x: & bool | -> u8 { if * x { 1 } else { 0 } })] #[bw(map = | x: & bool | -> u8 { if * x { 1 } else { 0 } })]
#[brw(pad_after = 1)] #[brw(pad_after = 1)]
pub has_edge_geometry: bool, pub has_edge_geometry: bool,
#[br(args(vertex_declaration_count), parse_with = vertex_element_parser)]
#[bw(write_with = vertex_element_writer)]
pub vertex_declarations: Vec<VertexDeclaration>
} }
#[binrw] #[binrw]
@ -294,7 +298,7 @@ enum VertexUsage {
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
#[allow(dead_code)] #[allow(dead_code)]
#[brw(little)] #[brw(little)]
struct VertexElement { pub struct VertexElement {
stream: u8, stream: u8,
offset: u8, offset: u8,
vertex_type: VertexType, vertex_type: VertexType,
@ -338,14 +342,60 @@ pub struct Lod {
pub parts: Vec<Part>, pub parts: Vec<Part>,
} }
#[derive(Clone)] #[binrw::parser(reader, endian)]
struct VertexDeclaration { fn vertex_element_parser(count: u16) -> BinResult<Vec<VertexDeclaration>> {
elements: Vec<VertexElement>, let mut vertex_declarations: Vec<VertexDeclaration> =
vec![
VertexDeclaration { elements: vec![] };
count.into()
];
for declaration in &mut vertex_declarations {
let mut element = VertexElement::read_options(reader, endian, ()).unwrap();
loop {
declaration.elements.push(element);
element = VertexElement::read_options(reader, endian, ())?;
if element.stream == END_OF_STREAM {
break;
}
}
let to_seek = 17 * 8 - (declaration.elements.len() + 1) * 8;
reader.seek(SeekFrom::Current(to_seek as i64))?;
}
Ok(vertex_declarations)
}
#[binrw::writer(writer, endian)]
fn vertex_element_writer(
declarations: &Vec<VertexDeclaration>,
) -> BinResult<()> {
// write vertex declarations
for declaration in declarations {
for element in &declaration.elements {
element.write_options(writer, endian, ())?;
}
writer.write_all(&[END_OF_STREAM])?;
// We have a -1 here like we do in read, because writing the EOF (255) pushes our cursor forward.
let to_seek = 17 * 8 - (declaration.elements.len()) * 8 - 1;
writer.seek(SeekFrom::Current(to_seek as i64))?;
}
Ok(())
}
#[derive(Clone, Debug)]
pub struct VertexDeclaration {
pub elements: Vec<VertexElement>,
} }
pub struct MDL { pub struct MDL {
file_header: ModelFileHeader, file_header: ModelFileHeader,
vertex_declarations: Vec<VertexDeclaration>,
model_data: ModelData, model_data: ModelData,
pub lods: Vec<Lod>, pub lods: Vec<Lod>,
@ -358,28 +408,6 @@ impl MDL {
let mut cursor = Cursor::new(buffer); let mut cursor = Cursor::new(buffer);
let model_file_header = ModelFileHeader::read(&mut cursor).unwrap(); let model_file_header = ModelFileHeader::read(&mut cursor).unwrap();
let mut vertex_declarations: Vec<VertexDeclaration> =
vec![
VertexDeclaration { elements: vec![] };
model_file_header.vertex_declaration_count as usize
];
for declaration in &mut vertex_declarations {
let mut element = VertexElement::read(&mut cursor).unwrap();
loop {
declaration.elements.push(element);
element = VertexElement::read(&mut cursor).unwrap();
if element.stream == END_OF_STREAM {
break;
}
}
let to_seek = 17 * 8 - (declaration.elements.len() + 1) * 8;
cursor.seek(SeekFrom::Current(to_seek as i64)).ok()?;
}
let model = ModelData::read(&mut cursor).unwrap(); let model = ModelData::read(&mut cursor).unwrap();
let mut affected_bone_names = vec![]; let mut affected_bone_names = vec![];
@ -422,7 +450,7 @@ impl MDL {
for j in model.lods[i as usize].mesh_index for j in model.lods[i as usize].mesh_index
..model.lods[i as usize].mesh_index + model.lods[i as usize].mesh_count ..model.lods[i as usize].mesh_index + model.lods[i as usize].mesh_count
{ {
let declaration = &vertex_declarations[j as usize]; let declaration = &model_file_header.vertex_declarations[j as usize];
let vertex_count = model.meshes[j as usize].vertex_count; let vertex_count = model.meshes[j as usize].vertex_count;
let material_index = model.meshes[j as usize].material_index; let material_index = model.meshes[j as usize].material_index;
@ -587,7 +615,6 @@ impl MDL {
Some(MDL { Some(MDL {
file_header: model_file_header, file_header: model_file_header,
vertex_declarations,
model_data: model, model_data: model,
lods, lods,
affected_bone_names, affected_bone_names,
@ -734,24 +761,11 @@ impl MDL {
// write file header // write file header
self.file_header.write(&mut cursor).ok()?; self.file_header.write(&mut cursor).ok()?;
// write vertex declarations
for declaration in &self.vertex_declarations {
for element in &declaration.elements {
element.write(&mut cursor).ok()?;
}
cursor.write_all(&[END_OF_STREAM]).ok()?;
// We have a -1 here like we do in read, because writing the EOF (255) pushes our cursor forward.
let to_seek = 17 * 8 - (declaration.elements.len()) * 8 - 1;
cursor.seek(SeekFrom::Current(to_seek as i64)).ok()?;
}
self.model_data.write(&mut cursor).ok()?; self.model_data.write(&mut cursor).ok()?;
for (l, lod) in self.lods.iter().enumerate() { for (l, lod) in self.lods.iter().enumerate() {
for part in lod.parts.iter() { for part in lod.parts.iter() {
let declaration = &self.vertex_declarations[part.mesh_index as usize]; let declaration = &self.file_header.vertex_declarations[part.mesh_index as usize];
for (k, vert) in part.vertices.iter().enumerate() { for (k, vert) in part.vertices.iter().enumerate() {
for element in &declaration.elements { for element in &declaration.elements {
@ -910,6 +924,7 @@ mod tests {
lod_count: 0, lod_count: 0,
index_buffer_streaming_enabled: false, index_buffer_streaming_enabled: false,
has_edge_geometry: false, has_edge_geometry: false,
vertex_declarations: Vec::new(),
}; };
assert_eq!(816, example_header.calculate_stack_size()); assert_eq!(816, example_header.calculate_stack_size());
@ -927,6 +942,7 @@ mod tests {
lod_count: 0, lod_count: 0,
index_buffer_streaming_enabled: false, index_buffer_streaming_enabled: false,
has_edge_geometry: false, has_edge_geometry: false,
vertex_declarations: Vec::new()
}; };
assert_eq!(272, example_header2.calculate_stack_size()); assert_eq!(272, example_header2.calculate_stack_size());