diff --git a/src/model.rs b/src/model.rs index 3a59e69..e555f54 100755 --- a/src/model.rs +++ b/src/model.rs @@ -11,10 +11,7 @@ use binrw::BinReaderExt; use binrw::{binrw, BinWrite, BinWriterExt}; use crate::common_file_operations::{read_bool_from, write_bool_as}; -use crate::model_vertex_declarations::{ - vertex_element_parser, vertex_element_writer, VertexDeclaration, VertexType, VertexUsage, - VERTEX_ELEMENT_SIZE, -}; +use crate::model_vertex_declarations::{vertex_element_parser, vertex_element_writer, VertexDeclaration, VertexType, VertexUsage, VERTEX_ELEMENT_SIZE}; use crate::{ByteBuffer, ByteSpan}; pub const NUM_VERTICES: u32 = 17; @@ -290,9 +287,9 @@ struct ShapeValue { #[allow(dead_code)] #[br(import {file_header: &ModelFileHeader})] #[brw(little)] -struct ModelData { +pub struct ModelData { #[br(args { vertex_declaration_count: file_header.vertex_declaration_count })] - header: ModelHeader, + pub header: ModelHeader, #[br(count = header.element_id_count)] element_ids: Vec, @@ -373,7 +370,7 @@ struct ElementId { rotate: [f32; 3], } -#[derive(Clone, Copy, PartialEq)] +#[derive(Clone, Copy, PartialEq, Debug)] #[repr(C)] pub struct Vertex { pub position: [f32; 3], @@ -403,14 +400,14 @@ impl Default for Vertex { } } -#[derive(Clone, Copy)] +#[derive(Debug, Clone, Copy)] #[repr(C)] pub struct NewShapeValue { pub base_index: u32, pub replacing_vertex: Vertex, } -#[derive(Clone, Copy)] +#[derive(Debug, Clone, Copy)] #[repr(C)] pub struct SubMesh { submesh_index: usize, @@ -418,32 +415,35 @@ pub struct SubMesh { pub index_offset: u32, } -#[derive(Clone)] +#[derive(Debug, Clone)] pub struct Shape { pub name: String, pub morphed_vertices: Vec, } /// Corresponds to a "Mesh" in an LOD -#[derive(Clone)] +#[derive(Debug, Clone)] pub struct Part { mesh_index: u16, pub vertices: Vec, + /// Indexed by VertexElement::stream + pub vertex_streams: Vec>, + pub vertex_stream_strides: Vec, pub indices: Vec, pub material_index: u16, pub submeshes: Vec, pub shapes: Vec, } -#[derive(Clone)] +#[derive(Debug, Clone)] pub struct Lod { pub parts: Vec, } -#[derive(Clone)] +#[derive(Debug, Clone)] pub struct MDL { file_header: ModelFileHeader, - model_data: ModelData, + pub model_data: ModelData, pub lods: Vec, pub affected_bone_names: Vec, @@ -551,13 +551,7 @@ impl MDL { MDL::read_byte_float4(&mut cursor).unwrap(); } VertexType::Byte4 => { - let bytes = MDL::read_byte4(&mut cursor).unwrap(); - vertices[k as usize].bone_weight = [ - f32::from(bytes[0]), - f32::from(bytes[1]), - f32::from(bytes[2]), - f32::from(bytes[3]), - ]; + vertices[k as usize].bone_weight = MDL::read_tangent(&mut cursor).unwrap(); } VertexType::UnsignedShort4 => { let bytes = MDL::read_unsigned_short4(&mut cursor).unwrap(); @@ -779,6 +773,33 @@ impl MDL { } } + let mut vertex_streams = vec![]; + let mut vertex_stream_strides = vec![]; + let mesh = &model.meshes[j as usize]; + for stream in 0..mesh.vertex_stream_count { + let mut vertex_data = vec![]; + let stride = mesh.vertex_buffer_strides[stream as usize]; + for z in 0..mesh.vertex_count { + // TODO: read the entire vertex data into a buffer + // Handle the offsets within Novus itself + cursor + .seek(SeekFrom::Start( + (model.lods[i as usize].vertex_data_offset + + model.meshes[j as usize].vertex_buffer_offsets + [stream as usize] + + (z as u32 * stride as u32)) as u64, + )) + .ok()?; + + for _ in 0..stride { + vertex_data.push(cursor.read_le::().ok()?); + } + } + + vertex_streams.push(vertex_data); + vertex_stream_strides.push(mesh.vertex_buffer_strides[stream as usize] as usize); + } + parts.push(Part { mesh_index: j, vertices, @@ -786,6 +807,8 @@ impl MDL { material_index, submeshes, shapes, + vertex_streams, + vertex_stream_strides }); } @@ -1019,6 +1042,13 @@ impl MDL { match element.vertex_usage { VertexUsage::Position => match element.vertex_type { + VertexType::Single4 => { + MDL::write_single4( + &mut cursor, + &MDL::pad_slice(&vert.position, 1.0), + ) + .ok()?; + } VertexType::Half4 => { MDL::write_half4( &mut cursor, @@ -1041,6 +1071,10 @@ impl MDL { MDL::write_byte_float4(&mut cursor, &vert.bone_weight) .ok()?; } + VertexType::Byte4 => { + MDL::write_byte_float42(&mut cursor, &vert.bone_weight) + .ok()?; // TODO: WRONG! + } _ => { panic!( "Unexpected vertex type for blendweight: {:#?}", diff --git a/src/model_file_operations.rs b/src/model_file_operations.rs index f4f1161..c7f3e5e 100644 --- a/src/model_file_operations.rs +++ b/src/model_file_operations.rs @@ -32,6 +32,18 @@ impl MDL { ]) } + pub(crate) fn write_byte_float42( + cursor: &mut T, + vec: &[f32; 4], + ) -> BinResult<()> { + cursor.write_le::<[u8; 4]>(&[ + (vec[0]).round() as u8, + (vec[1]).round() as u8, + (vec[2]).round() as u8, + (vec[3]).round() as u8, + ]) + } + pub(crate) fn read_tangent(cursor: &mut Cursor) -> Option<[f32; 4]> { Some([ (f32::from(cursor.read_le::().ok()?) * 2.0 / MAX_BYTE_FLOAT - 1.0),