Loading mesh metadata
parent
52e1b71038
commit
5687dff5db
154
src/main.rs
154
src/main.rs
|
@ -15,28 +15,144 @@ use std::io::Read;
|
|||
use std::path::Path;
|
||||
use std::time::Duration;
|
||||
|
||||
pub struct Iqm {
|
||||
version: u32,
|
||||
filesize: u32,
|
||||
flags: u32,
|
||||
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;
|
||||
}
|
||||
|
||||
pub fn parse_iqm (input: &[u8]) -> IResult<&[u8], Iqm> {
|
||||
#[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 IqmModel {
|
||||
header: IqmHeader,
|
||||
text: Vec <u8>,
|
||||
meshes: Vec <IqmMesh>,
|
||||
}
|
||||
|
||||
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 (input, filesize) = le_u32 (input)?;
|
||||
let (input, flags) = le_u32 (input)?;
|
||||
let mut input = input;
|
||||
let mut fields = [0; 27];
|
||||
fields [0] = version;
|
||||
|
||||
Ok ((input, Iqm {
|
||||
version,
|
||||
filesize,
|
||||
flags,
|
||||
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 IqmModel {
|
||||
pub fn from_slice (input: &[u8]) -> IqmModel {
|
||||
let header = IqmHeader::from_slice (input).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])
|
||||
};
|
||||
|
||||
let meshes = {
|
||||
let mut meshes = vec! [];
|
||||
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 ();
|
||||
|
||||
let offset = meshes_offset + i * mesh_size;
|
||||
let mesh_slice = &input [offset..offset + mesh_size];
|
||||
|
||||
meshes.push (IqmMesh::from_slice (mesh_slice).unwrap ().1);
|
||||
}
|
||||
meshes
|
||||
};
|
||||
|
||||
IqmModel {
|
||||
header,
|
||||
text,
|
||||
meshes,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load_small_file <P> (name: P) -> Vec <u8>
|
||||
where P: AsRef <Path>
|
||||
|
@ -364,9 +480,19 @@ mod tests {
|
|||
#[test]
|
||||
pub fn iqm () {
|
||||
let data = load_small_file ("pumpking.iqm");
|
||||
let model = parse_iqm (&data [..]).unwrap ().1;
|
||||
|
||||
assert_eq! (model.filesize, 90368);
|
||||
assert_eq! (model.flags, 0);
|
||||
{
|
||||
let model = IqmHeader::from_slice (&data [..]).unwrap ().1;
|
||||
|
||||
assert_eq! (model.fields [1], 90368);
|
||||
assert_eq! (model.fields [2], 0);
|
||||
assert_eq! (model.fields [iqm_consts::VERSION], 2);
|
||||
}
|
||||
|
||||
{
|
||||
let model = IqmModel::from_slice (&data [..]);
|
||||
|
||||
println! ("{:?}", model.meshes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue