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:
parent
835b48ff5b
commit
0b0850c574
2 changed files with 62 additions and 45 deletions
|
@ -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()?;
|
||||||
|
|
106
src/model.rs
106
src/model.rs
|
@ -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());
|
||||||
|
|
Loading…
Add table
Reference in a new issue