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:
parent
3389f62340
commit
ed5a9b52b1
3 changed files with 54 additions and 28 deletions
BIN
resources/tests/c0201e0038_top_zeroed.mdl
Normal file
BIN
resources/tests/c0201e0038_top_zeroed.mdl
Normal file
Binary file not shown.
76
src/model.rs
76
src/model.rs
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -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>,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue