model_converter/src/main.rs

260 lines
6.6 KiB
Rust

use std::{
fs::File,
io::Write,
};
use glam::{
Mat4,
Vec3,
};
fn main () {
let (document, buffers, _images) = gltf::import ("input.glb").unwrap ();
let buffer = buffers.get (0).unwrap ();
let mut vertexes = Vec::default ();
let mut triangles = Vec::default ();
let mut meshes = Vec::default ();
let mut texts = String::default ();
for node in document.nodes () {
let mesh = match node.mesh () {
None => continue,
Some (x) => x,
};
let m = gltf_node_get_mat4 (&node);
for prim in mesh.primitives () {
assert_eq! (prim.mode (), gltf::mesh::Mode::Triangles);
let indices = prim.indices ().unwrap ();
let indices_view = indices.view ().unwrap ();
let indices_offset = indices.offset () + indices_view.offset ();
let indices_slice = &buffer [indices_offset..(indices_offset + indices.count () * 2)];
let pos = prim.get (&gltf::Semantic::Positions).unwrap ();
let pos_view = pos.view ().unwrap ();
let pos_offset = pos.offset () + pos_view.offset ();
let pos_slice = &buffer [pos_offset..(pos_offset + pos.count () * 4 * 3)];
let first_vertex = vertexes.len ();
let mesh = iqm::Mesh {
name: u32::try_from (texts.len ()).unwrap (),
material: 0,
first_vertex: u32::try_from (first_vertex).unwrap (),
num_vertexes: u32::try_from (indices_slice.len () / 2).unwrap (),
// num_vertexes: u32::try_from (3).unwrap (),
first_triangle: u32::try_from (triangles.len ()).unwrap (),
num_triangles: u32::try_from (indices_slice.len () / 6).unwrap (),
//num_triangles: u32::try_from (1).unwrap (),
};
texts.push_str ("\0");
meshes.push (mesh);
for chunk in indices_slice.chunks_exact (2 * 3) {
let read_idx = |i: usize| u16::from_le_bytes ([chunk [i * 2 + 0], chunk [i * 2 + 1]]);
let idxs = [
read_idx (0),
read_idx (1),
read_idx (2),
];
let read_pos_coord = |i| f32::from_le_bytes ([
pos_slice [i * 4 + 0],
pos_slice [i * 4 + 1],
pos_slice [i * 4 + 2],
pos_slice [i * 4 + 3],
]);
let read_pos = move |i| {
let i = usize::try_from (i).unwrap ();
m.transform_point3 (Vec3::new (
read_pos_coord (i * 3 + 0),
read_pos_coord (i * 3 + 1),
read_pos_coord (i * 3 + 2),
))
};
let verts = [
read_pos (idxs [0]),
read_pos (idxs [2]),
read_pos (idxs [1]),
];
let tri_start = u32::try_from (vertexes.len ()).unwrap ();
triangles.push ([
tri_start + 0,
tri_start + 1,
tri_start + 2,
]);
for v in verts {
vertexes.push (v.to_array ());
}
}
}
}
let vertexes = vertexes;
let triangles = triangles;
let meshes = meshes;
let texts = texts;
let num_vertexes = u32::try_from (vertexes.len ()).unwrap ();
let num_triangles = u32::try_from (triangles.len ()).unwrap ();
let num_text = texts.len ();
let num_text = u32::try_from (num_text).unwrap ();
let num_meshes = u32::try_from (meshes.len ()).unwrap ();
let num_vertexarrays = 1u32;
let header_len = 124u32;
let ofs_meshes = header_len;
let ofs_vertexarrays = ofs_meshes + num_meshes * 6 * 4;
let ofs_triangles = ofs_vertexarrays + num_vertexarrays * 5 * 4 + num_vertexes * 3 * 4;
let ofs_text = ofs_triangles + num_triangles * 3 * 4;
let filesize = ofs_text + num_text;
let mut f = File::create ("output.iqm").unwrap ();
f.write_all (b"INTERQUAKEMODEL\0").unwrap ();
f.write_all (&(2u32.to_le_bytes ())).unwrap ();
// filesize
f.write_all (&(filesize.to_le_bytes ())).unwrap ();
// flags
f.write_all (&(0u32.to_le_bytes ())).unwrap ();
// num_text, ofs_text
f.write_all (&(num_text.to_le_bytes ())).unwrap ();
f.write_all (&(ofs_text.to_le_bytes ())).unwrap ();
// num_meshes, ofs_meshes
f.write_all (&(num_meshes.to_le_bytes ())).unwrap ();
f.write_all (&(ofs_meshes.to_le_bytes ())).unwrap ();
// num_vertexarrays, num_vertexes, ofs_vertexarrays
f.write_all (&(num_vertexarrays.to_le_bytes ())).unwrap ();
f.write_all (&(num_vertexes.to_le_bytes ())).unwrap ();
f.write_all (&(ofs_vertexarrays.to_le_bytes ())).unwrap ();
// num_triangles, ofs_triangles, ofs_adjacency
f.write_all (&(num_triangles.to_le_bytes ())).unwrap ();
f.write_all (&(ofs_triangles.to_le_bytes ())).unwrap ();
f.write_all (&(0u32.to_le_bytes ())).unwrap ();
// num_joints, ofs_joints
f.write_all (&(0u32.to_le_bytes ())).unwrap ();
f.write_all (&(0u32.to_le_bytes ())).unwrap ();
// num_poses, ofs_poses
f.write_all (&(0u32.to_le_bytes ())).unwrap ();
f.write_all (&(0u32.to_le_bytes ())).unwrap ();
// num_anims, ofs_anims
f.write_all (&(0u32.to_le_bytes ())).unwrap ();
f.write_all (&(0u32.to_le_bytes ())).unwrap ();
// num_frames, num_framechannels, ofs_frames, ofs_bounds
f.write_all (&(0u32.to_le_bytes ())).unwrap ();
f.write_all (&(0u32.to_le_bytes ())).unwrap ();
f.write_all (&(0u32.to_le_bytes ())).unwrap ();
f.write_all (&(0u32.to_le_bytes ())).unwrap ();
// num_comment, ofs_comment
f.write_all (&(0u32.to_le_bytes ())).unwrap ();
f.write_all (&(0u32.to_le_bytes ())).unwrap ();
// num_extensions, ofs_extensions
f.write_all (&(0u32.to_le_bytes ())).unwrap ();
f.write_all (&(0u32.to_le_bytes ())).unwrap ();
// Meshes
for mesh in meshes {
f.write_all (&(mesh.name.to_le_bytes ())).unwrap ();
f.write_all (&(mesh.material.to_le_bytes ())).unwrap ();
f.write_all (&(mesh.first_vertex.to_le_bytes ())).unwrap ();
f.write_all (&(mesh.num_vertexes.to_le_bytes ())).unwrap ();
f.write_all (&(mesh.first_triangle.to_le_bytes ())).unwrap ();
f.write_all (&(mesh.num_triangles.to_le_bytes ())).unwrap ();
}
// Vertex arrays
// type
f.write_all (&(0u32.to_le_bytes ())).unwrap ();
// flags
f.write_all (&(0u32.to_le_bytes ())).unwrap ();
// format
f.write_all (&(7u32.to_le_bytes ())).unwrap ();
// size
f.write_all (&(3u32.to_le_bytes ())).unwrap ();
// offset
f.write_all (&((ofs_vertexarrays + 5 * 4 * 1).to_le_bytes ())).unwrap ();
// Vertexes
for t in vertexes {
for x in t {
f.write_all (&(f32::to_le_bytes (x))).unwrap ();
}
}
// Triangles
for t in triangles {
for x in t {
f.write_all (&(u32::to_le_bytes (x))).unwrap ();
}
}
// Text
f.write_all (texts.as_bytes ()).unwrap ();
}
fn gltf_node_get_mat4 (node: &gltf::Node) -> Mat4 {
Mat4::from_cols_array_2d (&node.transform ().matrix ())
}
/// IQM structures as written to disk
mod iqm {
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,
}
struct VertexArray {
r#type: u32,
flags: u32,
format: u32,
size: u32,
offset: u32,
}
struct Triangle {
vertex: [u32; 3],
}
struct Vertex {
position: [f32; 3],
}
}