use std::io::Read;
use byteorder::{LittleEndian, ReadBytesExt};
#[derive(Clone, Debug)]
pub struct MshMesh {
pub vertices: Vec<f32>,
pub normals: Vec<f32>,
pub texcoords: Vec<f32>,
pub faces: Vec<u32>,
}
pub fn parse(bytes: &[u8]) -> std::io::Result<MshMesh> {
let mut cur = bytes;
let nvertex = cur.read_i32::<LittleEndian>()? as usize;
let nnormal = cur.read_i32::<LittleEndian>()? as usize;
let ntexcoord = cur.read_i32::<LittleEndian>()? as usize;
let nface = cur.read_i32::<LittleEndian>()? as usize;
let mut vertices = vec![0.0f32; nvertex * 3];
cur.read_exact(bytemuck_safe_cast(&mut vertices))?;
let mut normals = vec![0.0f32; nnormal * 3];
cur.read_exact(bytemuck_safe_cast(&mut normals))?;
let mut texcoords = vec![0.0f32; ntexcoord * 2];
cur.read_exact(bytemuck_safe_cast(&mut texcoords))?;
let mut faces = vec![0i32; nface * 3];
{
for f in faces.iter_mut() {
*f = cur.read_i32::<LittleEndian>()?;
}
}
Ok(MshMesh {
vertices,
normals,
texcoords,
faces: faces.into_iter().map(|i| i as u32).collect(),
})
}
fn bytemuck_safe_cast(slice: &mut [f32]) -> &mut [u8] {
let len = std::mem::size_of_val(slice);
let ptr = slice.as_mut_ptr() as *mut u8;
unsafe { std::slice::from_raw_parts_mut(ptr, len) }
}
pub fn parse_file(path: impl AsRef<std::path::Path>) -> std::io::Result<MshMesh> {
let bytes = std::fs::read(path)?;
parse(&bytes)
}