From c3473b9507355c6c2928e7622a7be044e3fd4517 Mon Sep 17 00:00:00 2001 From: _ <> Date: Sun, 16 Feb 2020 22:38:34 +0000 Subject: [PATCH] :recycle: Extract iqm.rs --- src/iqm.rs | 260 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 260 +--------------------------------------------------- 2 files changed, 263 insertions(+), 257 deletions(-) create mode 100644 src/iqm.rs diff --git a/src/iqm.rs b/src/iqm.rs new file mode 100644 index 0000000..6bf812b --- /dev/null +++ b/src/iqm.rs @@ -0,0 +1,260 @@ +use nom::{ + IResult, + bytes::complete::{tag}, + number::complete::{le_u32}, +}; + +use std::convert::TryInto; + +mod iqm_consts { + pub const VERSION: usize = 0; + pub const FILESIZE: usize = 1; + pub const FLAGS: usize = 2; + pub const NUM_TEXT: usize = 3; + pub const OFS_TEXT: usize = 4; + pub const NUM_MESHES: usize = 5; + pub const OFS_MESHES: usize = 6; + pub const NUM_VERTEXARRAYS: usize = 7; + pub const NUM_VERTEXES: usize = 8; + pub const OFS_VERTEXARRAYS: usize = 9; + pub const NUM_TRIANGLES: usize = 10; + pub const OFS_TRIANGLES: usize = 11; + pub const OFS_ADJACENCY: usize = 12; + pub const NUM_JOINTS: usize = 13; + pub const OFS_JOINTS: usize = 14; + pub const NUM_POSES: usize = 15; + pub const OFS_POSES: usize = 16; + pub const NUM_ANIMS: usize = 17; + pub const OFS_ANIMS: usize = 18; + pub const NUM_FRAMES: usize = 19; + pub const NUM_FRAMECHANNELS: usize = 20; + pub const OFS_FRAMES: usize = 21; + pub const OFS_BOUNDS: usize = 22; + pub const NUM_COMMENT: usize = 23; + pub const OFS_COMMENT: usize = 24; + pub const NUM_EXTENSIONS: usize = 25; + 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 { + pub name: u32, + pub material: u32, + pub first_vertex: u32, + pub num_vertexes: u32, + pub first_triangle: u32, + pub num_triangles: u32, +} + +#[derive (Debug)] +pub struct IqmHeader { + fields: [u32; 27], +} + +#[derive (Debug)] +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 , + pub meshes: Vec , + vertexarrays: Vec , +} + +impl IqmHeader { + pub fn from_slice (input: &[u8]) -> IResult <&[u8], IqmHeader> { + let (input, _) = tag (b"INTERQUAKEMODEL\0")(input)?; + let (input, version) = le_u32 (input)?; + + // I only know how to parse version 2 + assert_eq! (version, 2); + + let mut input = input; + let mut fields = [0; 27]; + fields [0] = version; + + for index in 1..fields.len () { + let (i, h) = le_u32 (input)?; + input = i; + fields [usize::from (index)] = h; + } + + Ok ((input, IqmHeader { + fields, + })) + } +} + +impl IqmMesh { + pub fn from_slice (input: &[u8]) -> IResult <&[u8], IqmMesh> { + let mut result = IqmMesh { + name: 0, + material: 0, + first_vertex: 0, + num_vertexes: 0, + first_triangle: 0, + num_triangles: 0, + }; + + let mut input = input; + for field in [ + &mut result.name, + &mut result.material, + &mut result.first_vertex, + &mut result.num_vertexes, + &mut result.first_triangle, + &mut result.num_triangles, + ].iter_mut () { + let (i, f) = le_u32 (input)?; + input = i; + **field = f; + } + + Ok ((input, result)) + } +} + +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 (&data [offset..offset + num]) + }; + + let meshes = { + 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..num { + let offset = meshes_offset + i * mesh_size; + let mesh_slice = &data [offset..offset + mesh_size]; + + meshes.push (IqmMesh::from_slice (mesh_slice).unwrap ().1); + } + meshes + }; + + //println! ("{:?}", 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]; + + let vertexarray = IqmVertexArray::from_slice (vertexarray_slice).unwrap ().1; + + //println! ("{:?}", vertexarray); + + vertexarrays.push (vertexarray); + } + + vertexarrays + }; + + IqmModel { + data, + + header, + text, + meshes, + vertexarrays, + } + } + + pub fn get_vertex_slice (&self, + vertexarray_index: usize + ) -> &[u8] + { + let vertexarray = &self.vertexarrays [vertexarray_index]; + let bytes_per_float = 4; + let stride = bytes_per_float * vertexarray.va_size; + //assert_eq! (stride, 12); + + let offset: usize = (vertexarray.va_offset).try_into ().unwrap (); + let num_bytes: usize = (stride * self.header.fields [iqm_consts::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] + } +} diff --git a/src/main.rs b/src/main.rs index 59e7bc6..8af3d95 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,9 +1,4 @@ -use glam::{Mat4, Vec3, Vec4, Quat}; -use nom::{ - IResult, - bytes::complete::{tag}, - number::complete::{le_u32}, -}; +use glam::{Mat4, Vec3, Vec4}; use sdl2::event::Event; use sdl2::keyboard::{Keycode, Scancode}; @@ -15,258 +10,9 @@ use std::io::Read; use std::path::Path; use std::time::{Duration, Instant}; -mod iqm_consts { - pub const VERSION: usize = 0; - pub const FILESIZE: usize = 1; - pub const FLAGS: usize = 2; - pub const NUM_TEXT: usize = 3; - pub const OFS_TEXT: usize = 4; - pub const NUM_MESHES: usize = 5; - pub const OFS_MESHES: usize = 6; - pub const NUM_VERTEXARRAYS: usize = 7; - pub const NUM_VERTEXES: usize = 8; - pub const OFS_VERTEXARRAYS: usize = 9; - pub const NUM_TRIANGLES: usize = 10; - pub const OFS_TRIANGLES: usize = 11; - pub const OFS_ADJACENCY: usize = 12; - pub const NUM_JOINTS: usize = 13; - pub const OFS_JOINTS: usize = 14; - pub const NUM_POSES: usize = 15; - pub const OFS_POSES: usize = 16; - pub const NUM_ANIMS: usize = 17; - pub const OFS_ANIMS: usize = 18; - pub const NUM_FRAMES: usize = 19; - pub const NUM_FRAMECHANNELS: usize = 20; - pub const OFS_FRAMES: usize = 21; - pub const OFS_BOUNDS: usize = 22; - pub const NUM_COMMENT: usize = 23; - pub const OFS_COMMENT: usize = 24; - pub const NUM_EXTENSIONS: usize = 25; - pub const OFS_EXTENSIONS: usize = 26; -} +mod iqm; -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, - material: u32, - first_vertex: u32, - num_vertexes: u32, - first_triangle: u32, - num_triangles: u32, -} - -#[derive (Debug)] -pub struct IqmHeader { - fields: [u32; 27], -} - -#[derive (Debug)] -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 { - pub fn from_slice (input: &[u8]) -> IResult <&[u8], IqmHeader> { - let (input, _) = tag (b"INTERQUAKEMODEL\0")(input)?; - let (input, version) = le_u32 (input)?; - - // I only know how to parse version 2 - assert_eq! (version, 2); - - let mut input = input; - let mut fields = [0; 27]; - fields [0] = version; - - for index in 1..fields.len () { - let (i, h) = le_u32 (input)?; - input = i; - fields [usize::from (index)] = h; - } - - Ok ((input, IqmHeader { - fields, - })) - } -} - -impl IqmMesh { - pub fn from_slice (input: &[u8]) -> IResult <&[u8], IqmMesh> { - let mut result = IqmMesh { - name: 0, - material: 0, - first_vertex: 0, - num_vertexes: 0, - first_triangle: 0, - num_triangles: 0, - }; - - let mut input = input; - for field in [ - &mut result.name, - &mut result.material, - &mut result.first_vertex, - &mut result.num_vertexes, - &mut result.first_triangle, - &mut result.num_triangles, - ].iter_mut () { - let (i, f) = le_u32 (input)?; - input = i; - **field = f; - } - - Ok ((input, result)) - } -} - -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 (&data [offset..offset + num]) - }; - - let meshes = { - 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..num { - let offset = meshes_offset + i * mesh_size; - let mesh_slice = &data [offset..offset + mesh_size]; - - meshes.push (IqmMesh::from_slice (mesh_slice).unwrap ().1); - } - meshes - }; - - //println! ("{:?}", 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]; - - let vertexarray = IqmVertexArray::from_slice (vertexarray_slice).unwrap ().1; - - //println! ("{:?}", vertexarray); - - vertexarrays.push (vertexarray); - } - - vertexarrays - }; - - IqmModel { - data, - - header, - text, - meshes, - vertexarrays, - } - } - - pub fn get_vertex_slice (&self, - vertexarray_index: usize - ) -> &[u8] - { - let vertexarray = &self.vertexarrays [vertexarray_index]; - let bytes_per_float = 4; - let stride = bytes_per_float * vertexarray.va_size; - //assert_eq! (stride, 12); - - let offset: usize = (vertexarray.va_offset).try_into ().unwrap (); - let num_bytes: usize = (stride * self.header.fields [iqm_consts::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] - } -} +use iqm::IqmModel; pub fn load_small_file

(name: P) -> Vec where P: AsRef