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

Separate the model header updating, and add test

This adds the model file for c0201e0038_top but everything but the
header parts are zeroed out to prevent possible copyright infringement.
This commit is contained in:
Joshua Goins 2024-02-25 10:25:54 -05:00
parent 3389f62340
commit ed5a9b52b1
3 changed files with 54 additions and 28 deletions

Binary file not shown.

View file

@ -13,7 +13,7 @@ use crate::model_vertex_declarations::{vertex_element_parser, VERTEX_ELEMENT_SIZ
pub const NUM_VERTICES: u32 = 17; pub const NUM_VERTICES: u32 = 17;
#[binrw] #[binrw]
#[derive(Debug)] #[derive(Debug, Clone, PartialEq)]
#[brw(little)] #[brw(little)]
pub struct ModelFileHeader { pub struct ModelFileHeader {
pub version: u32, pub version: u32,
@ -42,7 +42,7 @@ pub struct ModelFileHeader {
#[binrw] #[binrw]
#[brw(repr = u8)] #[brw(repr = u8)]
#[derive(Debug, Clone)] #[derive(Debug, Clone, PartialEq)]
enum ModelFlags1 { enum ModelFlags1 {
DustOcclusionEnabled = 0x80, DustOcclusionEnabled = 0x80,
SnowOcclusionEnabled = 0x40, SnowOcclusionEnabled = 0x40,
@ -56,7 +56,7 @@ enum ModelFlags1 {
#[binrw] #[binrw]
#[brw(repr = u8)] #[brw(repr = u8)]
#[derive(Debug, Clone)] #[derive(Debug, Clone, PartialEq)]
enum ModelFlags2 { enum ModelFlags2 {
None = 0x0, None = 0x0,
Unknown2 = 0x80, Unknown2 = 0x80,
@ -70,7 +70,7 @@ enum ModelFlags2 {
} }
#[binrw] #[binrw]
#[derive(Debug, Clone)] #[derive(Debug, Clone, PartialEq)]
#[br(import { vertex_declaration_count: u16 })] #[br(import { vertex_declaration_count: u16 })]
#[allow(dead_code)] #[allow(dead_code)]
pub struct ModelHeader { pub struct ModelHeader {
@ -126,7 +126,7 @@ pub struct ModelHeader {
} }
#[binrw] #[binrw]
#[derive(Debug, Clone)] #[derive(Debug, Clone, PartialEq)]
#[allow(dead_code)] #[allow(dead_code)]
struct MeshLod { struct MeshLod {
mesh_index: u16, mesh_index: u16,
@ -161,7 +161,7 @@ struct MeshLod {
} }
#[binrw] #[binrw]
#[derive(Debug, Clone)] #[derive(Debug, Clone, PartialEq)]
#[allow(dead_code)] #[allow(dead_code)]
struct Mesh { struct Mesh {
#[brw(pad_after = 2)] #[brw(pad_after = 2)]
@ -182,7 +182,7 @@ struct Mesh {
} }
#[binrw] #[binrw]
#[derive(Debug, Clone)] #[derive(Debug, Clone, PartialEq)]
#[allow(dead_code)] #[allow(dead_code)]
struct Submesh { struct Submesh {
index_offset: u32, index_offset: u32,
@ -195,7 +195,7 @@ struct Submesh {
} }
#[binrw] #[binrw]
#[derive(Debug, Clone)] #[derive(Debug, Clone, PartialEq)]
#[allow(dead_code)] #[allow(dead_code)]
struct BoneTable { struct BoneTable {
bone_indices: [u16; 64], bone_indices: [u16; 64],
@ -205,7 +205,7 @@ struct BoneTable {
} }
#[binrw] #[binrw]
#[derive(Debug, Clone)] #[derive(Debug, Clone, PartialEq)]
#[allow(dead_code)] #[allow(dead_code)]
struct BoundingBox { struct BoundingBox {
min: [f32; 4], min: [f32; 4],
@ -213,7 +213,7 @@ struct BoundingBox {
} }
#[binrw] #[binrw]
#[derive(Debug, Clone)] #[derive(Debug, Clone, PartialEq)]
#[allow(dead_code)] #[allow(dead_code)]
struct TerrainShadowMesh { struct TerrainShadowMesh {
index_count: u32, index_count: u32,
@ -227,7 +227,7 @@ struct TerrainShadowMesh {
} }
#[binrw] #[binrw]
#[derive(Debug, Clone)] #[derive(Debug, Clone, PartialEq)]
#[allow(dead_code)] #[allow(dead_code)]
struct TerrainShadowSubmesh { struct TerrainShadowSubmesh {
index_offset: u32, index_offset: u32,
@ -237,7 +237,7 @@ struct TerrainShadowSubmesh {
} }
#[binrw] #[binrw]
#[derive(Debug, Clone)] #[derive(Debug, Clone, PartialEq)]
#[allow(dead_code)] #[allow(dead_code)]
struct Shape { struct Shape {
string_offset: u32, string_offset: u32,
@ -246,7 +246,7 @@ struct Shape {
} }
#[binrw] #[binrw]
#[derive(Debug, Clone)] #[derive(Debug, Clone, PartialEq)]
#[allow(dead_code)] #[allow(dead_code)]
struct ShapeMesh { struct ShapeMesh {
mesh_index_offset: u32, mesh_index_offset: u32,
@ -255,7 +255,7 @@ struct ShapeMesh {
} }
#[binrw] #[binrw]
#[derive(Debug, Clone)] #[derive(Debug, Clone, PartialEq)]
#[allow(dead_code)] #[allow(dead_code)]
struct ShapeValue { struct ShapeValue {
base_indices_index: u16, base_indices_index: u16,
@ -263,7 +263,7 @@ struct ShapeValue {
} }
#[binrw] #[binrw]
#[derive(Debug, Clone)] #[derive(Debug, Clone, PartialEq)]
#[allow(dead_code)] #[allow(dead_code)]
#[br(import {file_header: &ModelFileHeader})] #[br(import {file_header: &ModelFileHeader})]
#[brw(little)] #[brw(little)]
@ -329,7 +329,7 @@ struct ModelData {
} }
#[binrw] #[binrw]
#[derive(Debug, Clone)] #[derive(Debug, Clone, PartialEq)]
#[allow(dead_code)] #[allow(dead_code)]
struct ElementId { struct ElementId {
element_id: u32, element_id: u32,
@ -338,7 +338,7 @@ struct ElementId {
rotate: [f32; 3], rotate: [f32; 3],
} }
#[derive(Clone, Copy)] #[derive(Clone, Copy, PartialEq)]
#[repr(C)] #[repr(C)]
pub struct Vertex { pub struct Vertex {
pub position: [f32; 3], pub position: [f32; 3],
@ -376,6 +376,7 @@ pub struct SubMesh {
pub index_offset: u32 pub index_offset: u32
} }
#[derive(Clone)]
pub struct Part { pub struct Part {
mesh_index: u16, mesh_index: u16,
pub vertices: Vec<Vertex>, pub vertices: Vec<Vertex>,
@ -384,10 +385,12 @@ pub struct Part {
pub submeshes: Vec<SubMesh> pub submeshes: Vec<SubMesh>
} }
#[derive(Clone)]
pub struct Lod { pub struct Lod {
pub parts: Vec<Part>, pub parts: Vec<Part>,
} }
#[derive(Clone)]
pub struct MDL { pub struct MDL {
file_header: ModelFileHeader, file_header: ModelFileHeader,
model_data: ModelData, model_data: ModelData,
@ -634,18 +637,20 @@ impl MDL {
self.model_data.meshes[part.mesh_index as usize].vertex_count = part.vertices.len() as u16; self.model_data.meshes[part.mesh_index as usize].vertex_count = part.vertices.len() as u16;
self.model_data.meshes[part.mesh_index as usize].index_count = part.indices.len() as u32; self.model_data.meshes[part.mesh_index as usize].index_count = part.indices.len() as u32;
self.update_headers();
}
pub(crate) fn update_headers(&mut self) {
// update values // update values
for i in 0..self.file_header.lod_count { for i in 0..self.file_header.lod_count {
let mut vertex_offset = 0; let mut vertex_offset = 0;
let mut index_count = 0;
for j in self.model_data.lods[i as usize].mesh_index for j in self.model_data.lods[i as usize].mesh_index
..self.model_data.lods[i as usize].mesh_index + self.model_data.lods[i as usize].mesh_count ..self.model_data.lods[i as usize].mesh_index + self.model_data.lods[i as usize].mesh_count
{ {
let mesh = &mut self.model_data.meshes[j as usize]; let mesh = &mut self.model_data.meshes[j as usize];
mesh.start_index = index_count; mesh.start_index = self.model_data.submeshes[mesh.submesh_index as usize].index_offset;
index_count += mesh.index_count;
for i in 0..mesh.vertex_stream_count as usize { for i in 0..mesh.vertex_stream_count as usize {
mesh.vertex_buffer_offsets[i] = vertex_offset; mesh.vertex_buffer_offsets[i] = vertex_offset;
@ -674,14 +679,16 @@ impl MDL {
total_index_buffer_size += index_count * size_of::<u16>() as u32; total_index_buffer_size += index_count * size_of::<u16>() as u32;
} }
// Unknown padding? // TODO: this can definitely be written better
let mut index_padding = 16 - total_index_buffer_size % 16; let mut index_padding = total_index_buffer_size % 16;
if index_padding == 16 { if index_padding == 0 {
index_padding = 0; index_padding = 16;
} else {
index_padding = 16 - index_padding;
} }
lod.vertex_buffer_size = total_vertex_buffer_size; lod.vertex_buffer_size = total_vertex_buffer_size;
lod.index_buffer_size = total_index_buffer_size + index_padding; lod.index_buffer_size = total_index_buffer_size.wrapping_add(index_padding);
} }
// update lod values // update lod values
@ -906,8 +913,11 @@ impl ModelData {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::fs::read;
use std::io::Cursor; use std::io::Cursor;
use std::mem::size_of; use std::mem::size_of;
use std::path::PathBuf;
use crate::dat::FileType::Model;
use crate::model::{MDL, ModelFileHeader}; use crate::model::{MDL, ModelFileHeader};
use crate::model_vertex_declarations::{VERTEX_ELEMENT_SIZE, VertexElement}; use crate::model_vertex_declarations::{VERTEX_ELEMENT_SIZE, VertexElement};
@ -957,4 +967,20 @@ mod tests {
assert_eq!(272, example_header2.calculate_stack_size()); assert_eq!(272, example_header2.calculate_stack_size());
} }
#[test]
fn test_update_headers() {
let mut d = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
d.push("resources/tests");
d.push("c0201e0038_top_zeroed.mdl");
let mut mdl = MDL::from_existing(&read(d).unwrap()).unwrap();
let old_mdl = mdl.clone();
mdl.update_headers();
// There should be no changes
assert_eq!(mdl.file_header, old_mdl.file_header);
assert_eq!(mdl.model_data, old_mdl.model_data);
}
} }

View file

@ -24,7 +24,7 @@ pub enum VertexType {
#[binrw] #[binrw]
#[brw(repr = u8)] #[brw(repr = u8)]
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug, PartialEq)]
pub enum VertexUsage { pub enum VertexUsage {
Position = 0, Position = 0,
BlendWeights = 1, BlendWeights = 1,
@ -37,7 +37,7 @@ pub enum VertexUsage {
} }
#[binrw] #[binrw]
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug, PartialEq)]
#[allow(dead_code)] #[allow(dead_code)]
#[brw(little)] #[brw(little)]
pub struct VertexElement { pub struct VertexElement {
@ -51,7 +51,7 @@ pub struct VertexElement {
pub const VERTEX_ELEMENT_SIZE: usize = std::mem::size_of::<VertexElement>() + 3; pub const VERTEX_ELEMENT_SIZE: usize = std::mem::size_of::<VertexElement>() + 3;
#[derive(Clone, Debug)] #[derive(Clone, Debug, PartialEq)]
pub struct VertexDeclaration { pub struct VertexDeclaration {
pub elements: Vec<VertexElement>, pub elements: Vec<VertexElement>,
} }