diff --git a/src/main.rs b/src/main.rs index 8602e60..38ccbeb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -45,6 +45,29 @@ mod iqm_consts { pub const OFS_EXTENSIONS: usize = 26; } +mod iqm_types { + pub const POSITION: u32 = 0; + pub const TEXCOORD: u32 = 1; + pub const NORMAL: u32 = 2; + pub const TANGENT: u32 = 3; + pub const BLENDINDEXES: u32 = 4; + pub const BLENDWEIGHTS: u32 = 5; + pub const COLOR: u32 = 6; + pub const CUSTOM: u32 = 0x10; +} + +mod iqm_formats { + pub const BYTE: u32 = 0; + pub const UBYTE: u32 = 1; + pub const SHORT: u32 = 2; + pub const USHORT: u32 = 3; + pub const INT: u32 = 4; + pub const UINT: u32 = 5; + pub const HALF: u32 = 6; + pub const FLOAT: u32 = 7; + pub const DOUBLE: u32 = 8; +} + #[derive (Debug)] pub struct IqmMesh { name: u32, @@ -61,10 +84,22 @@ pub struct IqmHeader { } #[derive (Debug)] -pub struct IqmModel { +pub struct IqmVertexArray { + va_type: u32, + va_flags: u32, + va_format: u32, + va_size: u32, + va_offset: u32, +} + +#[derive (Debug)] +pub struct IqmModel <'a> { + data: &'a [u8], + header: IqmHeader, text: Vec , meshes: Vec , + vertexarrays: Vec , } impl IqmHeader { @@ -120,38 +155,111 @@ impl IqmMesh { } } -impl IqmModel { - pub fn from_slice (input: &[u8]) -> IqmModel { - let header = IqmHeader::from_slice (input).unwrap ().1; +impl IqmVertexArray { + pub fn from_slice (input: &[u8]) -> IResult <&[u8], IqmVertexArray> { + let mut result = IqmVertexArray { + va_type: 0, + va_flags: 0, + va_format: 0, + va_size: 0, + va_offset: 0, + }; + + let mut input = input; + for field in [ + &mut result.va_type, + &mut result.va_flags, + &mut result.va_format, + &mut result.va_size, + &mut result.va_offset, + ].iter_mut () { + let (i, f) = le_u32 (input)?; + input = i; + **field = f; + } + + Ok ((input, result)) + } +} + +impl <'a> IqmModel <'a> { + pub fn from_slice (data: &'a [u8]) -> IqmModel <'a> { + let header = IqmHeader::from_slice (data).unwrap ().1; let text = { let offset: usize = header.fields [iqm_consts::OFS_TEXT].try_into ().unwrap (); let num: usize = header.fields [iqm_consts::NUM_TEXT].try_into ().unwrap (); - Vec::from (&input [offset..offset + num]) + Vec::from (&data [offset..offset + num]) }; let meshes = { - let mut meshes = vec! []; + let num: usize = header.fields [iqm_consts::NUM_MESHES].try_into ().unwrap (); + let mut meshes = Vec::with_capacity (num); let mesh_size = 6 * 4; let meshes_offset: usize = header.fields [iqm_consts::OFS_MESHES].try_into ().unwrap (); - for i in 0..header.fields [iqm_consts::NUM_MESHES] { - let i: usize = i.try_into ().unwrap (); - + for i in 0..num { let offset = meshes_offset + i * mesh_size; - let mesh_slice = &input [offset..offset + mesh_size]; + let mesh_slice = &data [offset..offset + mesh_size]; meshes.push (IqmMesh::from_slice (mesh_slice).unwrap ().1); } meshes }; + let vertexarrays = { + let num: usize = header.fields [iqm_consts::NUM_VERTEXARRAYS].try_into ().unwrap (); + let mut vertexarrays = Vec::with_capacity (num); + let vertexarray_size = 5 * 4; + let vertexarrays_offset: usize = header.fields [iqm_consts::OFS_VERTEXARRAYS].try_into ().unwrap (); + + for i in 0..num { + let offset = vertexarrays_offset + i * vertexarray_size; + let vertexarray_slice = &data [offset..offset + vertexarray_size]; + + vertexarrays.push (IqmVertexArray::from_slice (vertexarray_slice).unwrap ().1); + } + + vertexarrays + }; + IqmModel { + data, + header, text, meshes, + vertexarrays, } } + + pub fn get_vertex_slice (&self, + mesh_index: usize, vertexarray_index: usize + ) -> &[u8] + { + let vertexarray = &self.vertexarrays [vertexarray_index]; + let bytes_per_float = 4; + let stride = bytes_per_float * vertexarray.va_size; + + let mesh = &self.meshes [mesh_index]; + let offset: usize = (vertexarray.va_offset + stride * mesh.first_vertex).try_into ().unwrap (); + let num_bytes: usize = (stride * mesh.num_vertexes).try_into ().unwrap (); + + &self.data [offset..offset + num_bytes] + } + + pub fn get_index_slice (&self, mesh_index: usize) -> &[u8] { + let mesh = &self.meshes [mesh_index]; + let bytes_per_u32 = 4; + let indexes_per_tri = 3; + let stride = bytes_per_u32 * indexes_per_tri; + + let offset: usize = (self.header.fields [iqm_consts::OFS_TRIANGLES] + stride * mesh.first_triangle).try_into ().unwrap (); + + let num_bytes: usize = (stride * mesh.num_triangles).try_into ().unwrap (); + + &self.data [offset..offset + num_bytes] + } } pub fn load_small_file

(name: P) -> Vec @@ -424,23 +532,36 @@ fn main () { 1.0, 1.0, ]; + let model_data = load_small_file ("pumpking.iqm"); + let model = IqmModel::from_slice (&model_data [..]); + let vertex_slice = model.get_vertex_slice (0, 0); + let index_slice = model.get_index_slice (0); + let id_mat: Vec = vec! [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, ]; + let view_mat: Vec = vec! [ + 0.3125, 0.0, 0.0, 0.0, + 0.0, 0.5, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 1.0, + ]; let indexes: Vec = vec! [0, 1, 2]; const FALSE_U8: u8 = 0; unsafe { gl::EnableVertexAttribArray (attrs ["pos"]); - let stride = 4 * 2; - gl::VertexAttribPointer (attrs ["pos"], 2, gl::FLOAT, FALSE_U8, stride, &tri_mesh [0] as *const f32 as *const c_void); + let num_coords = 3; + let stride = 4 * num_coords; - gl::UniformMatrix4fv (unis ["viewproj"], 1, FALSE_U8, &id_mat [0]); + gl::VertexAttribPointer (attrs ["pos"], num_coords, gl::FLOAT, FALSE_U8, stride, &vertex_slice [0] as *const u8 as *const c_void); + + gl::UniformMatrix4fv (unis ["viewproj"], 1, FALSE_U8, &view_mat [0]); gl::UniformMatrix4fv (unis ["model"], 1, FALSE_U8, &id_mat [0]); } @@ -463,8 +584,9 @@ fn main () { unsafe { gl::ClearColor (1.0f32, 0.0f32, 1.0f32, 1.0f32); gl::Clear (gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT); + gl::Disable (gl::CULL_FACE); - gl::DrawElements (gl::TRIANGLES, 3, gl::UNSIGNED_SHORT, &indexes [0] as *const u16 as *const c_void); + gl::DrawElements (gl::TRIANGLES, (model.meshes [0].num_triangles * 3) as i32, gl::UNSIGNED_INT, &index_slice [0] as *const u8 as *const c_void); } window.gl_swap_window (); @@ -493,6 +615,7 @@ mod tests { let model = IqmModel::from_slice (&data [..]); println! ("{:?}", model.meshes); + println! ("{:?}", model.vertexarrays); } } }