From bbbbb7cd02c00f475ad08e949a486f3bbeccd12f Mon Sep 17 00:00:00 2001 From: Joshua Goins Date: Fri, 22 Sep 2023 17:42:04 -0400 Subject: [PATCH] Add the last missing pieces for model writing This isn't a complete 1-to-1 yet, and still untested. However the general idea is there now. --- src/model.rs | 127 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 124 insertions(+), 3 deletions(-) diff --git a/src/model.rs b/src/model.rs index 80b2ca3..9829c75 100755 --- a/src/model.rs +++ b/src/model.rs @@ -4,7 +4,7 @@ use std::io::{Cursor, Seek, SeekFrom, Write}; use std::ptr::write; -use binrw::{BinResult, binrw, BinWrite}; +use binrw::{BinResult, binrw, BinWrite, BinWriterExt}; use binrw::BinRead; use binrw::BinReaderExt; use half::f16; @@ -317,6 +317,7 @@ pub struct Vertex { } pub struct Part { + mesh_index: u16, pub vertices: Vec, pub indices: Vec, pub material_index: u16 @@ -432,7 +433,7 @@ impl MDL { + model.meshes[j as usize].vertex_buffer_offsets [element.stream as usize] + element.offset as u32 - + model.meshes[i as usize].vertex_buffer_strides + + model.meshes[j as usize].vertex_buffer_strides // TODO: is j really correct? this might fix the broken LoDs [element.stream as usize] as u32 * k as u32) as u64, @@ -521,7 +522,7 @@ impl MDL { indices.push(cursor.read_le::().ok()?); } - parts.push(Part { vertices, indices, material_index }); + parts.push(Part { mesh_index: j, vertices, indices, material_index }); } lods.push(Lod { parts }); @@ -560,6 +561,106 @@ impl MDL { } self.model_data.write(&mut cursor).ok()?; + + for (l, lod) in self.lods.iter().enumerate() { + for (i, part) in lod.parts.iter().enumerate() { + for (k, vert) in part.vertices.iter().enumerate() { + let declaration = &self.vertex_declarations[i]; + + for element in &declaration.elements { + cursor + .seek(SeekFrom::Start( + (self.model_data.lods[l as usize].vertex_data_offset + + self.model_data.meshes[part.mesh_index as usize].vertex_buffer_offsets + [element.stream as usize] + + element.offset as u32 + + self.model_data.meshes[part.mesh_index as usize].vertex_buffer_strides + [element.stream as usize] + as u32 + * k as u32) as u64, + )) + .ok()?; + + match element.vertex_usage { + VertexUsage::Position => { + match element.vertex_type { + VertexType::Half4 => { + MDL::write_single4(&mut cursor, &MDL::pad_slice(&vert.position)).ok()?; + } + VertexType::Single3 => { + MDL::write_single3(&mut cursor, &vert.position).ok()?; + } + _ => { + panic!("Unexpected vertex type for position: {:#?}", element.vertex_type); + } + } + } + VertexUsage::BlendWeights => { + match element.vertex_type { + VertexType::ByteFloat4 => { + MDL::write_single4(&mut cursor, &vert.bone_weight).ok()?; + } + _ => { + panic!("Unexpected vertex type for blendweight: {:#?}", element.vertex_type); + } + } + } + VertexUsage::BlendIndices => { + match element.vertex_type { + VertexType::UInt => { + MDL::write_uint(&mut cursor, &vert.bone_id).ok()?; + } + _ => { + panic!("Unexpected vertex type for blendindice: {:#?}", element.vertex_type); + } + } + } + VertexUsage::Normal => { + match element.vertex_type { + VertexType::Half4 => { + MDL::write_single4(&mut cursor, &MDL::pad_slice(&vert.normal)).ok()?; + } + VertexType::Single3 => { + MDL::write_single3(&mut cursor, &vert.normal).ok()?; + } + _ => { + panic!("Unexpected vertex type for normal: {:#?}", element.vertex_type); + } + } + } + VertexUsage::UV => { + match element.vertex_type { + VertexType::Half4 => { + //MDL::write_half4(&mut cursor, &MDL::pad_slice(&vert.uv)).ok()?; + } + VertexType::Single4 => { + MDL::write_single4(&mut cursor, &MDL::pad_slice(&vert.uv)).ok()?; + } + _ => { + panic!("Unexpected vertex type for uv: {:#?}", element.vertex_type); + } + } + } + VertexUsage::Tangent2 => {} + VertexUsage::Tangent1 => {} + VertexUsage::Color => {} + } + } + } + + cursor + .seek(SeekFrom::Start( + (self.file_header.index_offsets[i as usize] + + (self.model_data.meshes[part.mesh_index as usize].start_index * 2)) + as u64, + )) + .ok()?; + + for indice in &part.indices { + cursor.write_le(&indice).ok()?; + } + } + } } Some(buffer) @@ -588,11 +689,31 @@ impl MDL { cursor.read_le::<[u8; 4]>() } + fn write_uint(cursor: &mut T, vec: &[u8; 4]) -> BinResult<()> { + cursor.write_le(vec) + } + fn read_single3(cursor: &mut Cursor<&MemoryBuffer>) -> BinResult<[f32; 3]> { cursor.read_le::<[f32; 3]>() } + fn write_single3(cursor: &mut T, vec: &[f32; 3]) -> BinResult<()> { + cursor.write_le(vec) + } + fn read_single4(cursor: &mut Cursor<&MemoryBuffer>) -> BinResult<[f32; 4]> { cursor.read_le::<[f32; 4]>() } + + fn write_single4(cursor: &mut T, vec: &[f32; 4]) -> BinResult<()> { + cursor.write_le(vec) + } + + fn pad_slice(small_slice: &[f32; N]) -> [f32; 4] { + let mut bigger_slice: [f32; 4] = [0.0, 0.0, 0.0, 0.0]; + for i in 0..N { + bigger_slice[i] = small_slice[i]; + } + return bigger_slice; + } }