From 6297079ae99b3c77bb7b8df23445652273cc683c Mon Sep 17 00:00:00 2001 From: _ <> Date: Mon, 25 May 2020 18:22:06 +0000 Subject: [PATCH] :recycle: Extract IQM crate --- Cargo.lock | 9 ++ Cargo.toml | 2 + src/iqm.rs | 314 ---------------------------------------- src/lib.rs | 1 - src/renderable_model.rs | 11 +- 5 files changed, 16 insertions(+), 321 deletions(-) delete mode 100644 src/iqm.rs diff --git a/Cargo.lock b/Cargo.lock index 2bb3664..8c7249d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -99,6 +99,14 @@ dependencies = [ "adler32 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "inter_quake_model" +version = "0.1.0" +dependencies = [ + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "iota 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "iota" version = "0.2.1" @@ -209,6 +217,7 @@ dependencies = [ "float-ord 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "gl 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", "glam 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)", + "inter_quake_model 0.1.0", "iota 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "nom 5.1.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index 5bf2cf4..7811d30 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,3 +23,5 @@ partial-min-max = "0.4.0" png = "0.15.3" rand = "0.6.5" sdl2 = "0.32.2" + +inter_quake_model = {path = "../inter_quake_model"} diff --git a/src/iqm.rs b/src/iqm.rs deleted file mode 100644 index 50a63e1..0000000 --- a/src/iqm.rs +++ /dev/null @@ -1,314 +0,0 @@ -use nom::{ - IResult, - bytes::complete::{tag}, - number::complete::{le_u32}, -}; - -use std::convert::TryInto; - -pub mod consts { -use iota::iota; -iota! { - pub const VERSION: usize = iota; - , FILESIZE - , FLAGS - , NUM_TEXT - , OFS_TEXT - , NUM_MESHES - , OFS_MESHES - , NUM_VERTEXARRAYS - , NUM_VERTEXES - , OFS_VERTEXARRAYS - , NUM_TRIANGLES - , OFS_TRIANGLES - , OFS_ADJACENCY - , NUM_JOINTS - , OFS_JOINTS - , NUM_POSES - , OFS_POSES - , NUM_ANIMS - , OFS_ANIMS - , NUM_FRAMES - , NUM_FRAMECHANNELS - , OFS_FRAMES - , OFS_BOUNDS - , NUM_COMMENT - , OFS_COMMENT - , NUM_EXTENSIONS - , OFS_EXTENSIONS -} -} - -pub mod types { -iota! { - pub const POSITION: usize = iota; - , TEXCOORD - , NORMAL - , TANGENT - , BLENDINDEXES - , BLENDWEIGHTS - , COLOR -} - pub const CUSTOM: usize = 0x10; -} - -pub mod formats { -iota! { - pub const BYTE: u32 = iota; - , UBYTE - , SHORT - , USHORT - , INT - , UINT - , HALF - , FLOAT - , DOUBLE -} -} - -#[derive (Debug)] -pub struct Mesh { - 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 Header { - pub fields: [u32; 27], -} - -#[derive (Debug)] -pub struct VertexArray { - va_type: u32, - va_flags: u32, - va_format: u32, - va_size: u32, - va_offset: u32, -} - -#[derive (Debug)] -pub struct Model <'a> { - data: &'a [u8], - - pub header: Header, - text: Vec , - pub meshes: Vec , - vertexarrays: Vec , -} - -impl Header { - pub fn from_slice (input: &[u8]) -> IResult <&[u8], Header> { - 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 field in fields.iter_mut ().skip (1) { - let (i, h) = le_u32 (input)?; - input = i; - *field = h; - } - - Ok ((input, Header { - fields, - })) - } -} - -impl Mesh { - pub fn from_slice (input: &[u8]) -> IResult <&[u8], Mesh> { - let mut result = Mesh { - 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 VertexArray { - pub fn from_slice (input: &[u8]) -> IResult <&[u8], VertexArray> { - let mut result = VertexArray { - 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)) - } -} - -#[derive (Debug)] -pub enum ModelLoadErr { - ParseHeaderFailed, - ParseMeshFailed (usize), - ParseVertexArrayFailed (usize), -} - -impl <'a> Model <'a> { - pub fn from_slice (data: &'a [u8]) -> Result , ModelLoadErr> { - let header = match Header::from_slice (data) { - Ok ((_, h)) => h, - Err (_) => return Err (ModelLoadErr::ParseHeaderFailed), - }; - - let text = { - let offset: usize = header.fields [consts::OFS_TEXT].try_into ().unwrap (); - let num: usize = header.fields [consts::NUM_TEXT].try_into ().unwrap (); - Vec::from (&data [offset..offset + num]) - }; - - let meshes = { - let num: usize = header.fields [consts::NUM_MESHES].try_into ().unwrap (); - let mut meshes = Vec::with_capacity (num); - let mesh_size = 6 * 4; - let meshes_offset: usize = header.fields [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]; - - let mesh = match Mesh::from_slice (mesh_slice) { - Ok ((_, m)) => m, - Err (_) => return Err (ModelLoadErr::ParseMeshFailed (i)), - }; - - meshes.push (mesh); - } - meshes - }; - - let vertexarrays = { - let num: usize = header.fields [consts::NUM_VERTEXARRAYS].try_into ().unwrap (); - let mut vertexarrays = Vec::with_capacity (num); - let vertexarray_size = 5 * 4; - let vertexarrays_offset: usize = header.fields [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 = match VertexArray::from_slice (vertexarray_slice) { - Ok ((_, va)) => va, - Err (_) => return Err (ModelLoadErr::ParseVertexArrayFailed (i)), - }; - - vertexarrays.push (vertexarray); - } - - vertexarrays - }; - - Ok (Model { - 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 [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 [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 get_all_indexes (&self) -> &[u8] { - let bytes_per_u32 = 4; - let indexes_per_tri = 3; - let stride = bytes_per_u32 * indexes_per_tri; - - let offset: usize = self.header.fields [consts::OFS_TRIANGLES].try_into ().unwrap (); - - let num_bytes: usize = (stride * self.header.fields [consts::NUM_TRIANGLES]).try_into ().unwrap (); - - &self.data [offset..offset + num_bytes] - } - - // I don't think IQM makes any guarantees about UTF-8 - // so I will only say that the slice has no NULs - - pub fn get_mesh_name (&self, index: usize) -> &[u8] { - let mesh = &self.meshes [index]; - - let ofs: usize = (self.header.fields [consts::OFS_TEXT] + mesh.name).try_into ().unwrap (); - - // There should be an easy way to do this with CString? - let mut nul_index = None; - for (j, c) in self.data [ofs..].iter ().enumerate () { - if *c == 0 { - nul_index = Some (j); - break; - } - } - let nul_index = nul_index.unwrap (); - - &self.data [ofs..ofs + nul_index] - } -} diff --git a/src/lib.rs b/src/lib.rs index 8cdd714..3375ddf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,7 +8,6 @@ pub mod file; pub mod glezz; pub mod gl_state; pub mod gpu_buffers; -pub mod iqm; pub mod physics; pub mod renderable_model; pub mod shader; diff --git a/src/renderable_model.rs b/src/renderable_model.rs index 6513efe..6ea9787 100644 --- a/src/renderable_model.rs +++ b/src/renderable_model.rs @@ -4,7 +4,6 @@ use std::convert::TryInto; use std::ffi::c_void; use crate::gpu_buffers::*; -use crate::iqm; // Takes ownership of mesh stuff in an opaque way that's abstract // from the IQM model. IQM is zero-copy, but this is not. @@ -49,10 +48,10 @@ pub const } impl RenderableModel { - pub fn from_iqm (model: &iqm::Model) -> RenderableModel { - let pos_bytes = model.get_vertex_slice (iqm::types::POSITION); - let uv_bytes = model.get_vertex_slice (iqm::types::TEXCOORD); - let normal_bytes = model.get_vertex_slice (iqm::types::NORMAL); + pub fn from_iqm (model: &inter_quake_model::Model) -> RenderableModel { + let pos_bytes = model.get_vertex_slice (inter_quake_model::types::POSITION); + let uv_bytes = model.get_vertex_slice (inter_quake_model::types::TEXCOORD); + let normal_bytes = model.get_vertex_slice (inter_quake_model::types::NORMAL); let num_pos = pos_bytes.len () / 4; let num_uv = uv_bytes.len () / 4; @@ -147,7 +146,7 @@ pub fn renderable_from_iqm_file

(filename: P) -> RenderableModel where P: AsRef { let data = crate::file::load_small_file (filename, 1024 * 1024).unwrap (); - let model = crate::iqm::Model::from_slice (&data).unwrap (); + let model = inter_quake_model::Model::from_slice (&data).unwrap (); RenderableModel::from_iqm (&model) }