158 lines
4.7 KiB
Rust
158 lines
4.7 KiB
Rust
use crate::model;
|
|
|
|
pub fn load_stl(path: std::path::PathBuf) -> model::Model {
|
|
let name = path.file_name().map(|v| v.to_string_lossy().to_string());
|
|
|
|
let mut file = std::fs::File::open(path).unwrap();
|
|
let stl = stl::read_stl(&mut file).unwrap();
|
|
|
|
let mut vertices = Vec::new();
|
|
let mut indices = Vec::new();
|
|
|
|
for tri in stl.triangles.iter() {
|
|
indices.push(vertices.len() as u32);
|
|
vertices.push(model::BasicVertex {
|
|
position: tri.v1.into(),
|
|
});
|
|
indices.push(vertices.len() as u32);
|
|
vertices.push(model::BasicVertex {
|
|
position: tri.v2.into(),
|
|
});
|
|
indices.push(vertices.len() as u32);
|
|
vertices.push(model::BasicVertex {
|
|
position: tri.v3.into(),
|
|
});
|
|
}
|
|
|
|
model::Model {
|
|
name: name.clone(),
|
|
objects: vec![model::Object {
|
|
name,
|
|
transform: Default::default(),
|
|
meshes: vec![model::Mesh { vertices, indices }],
|
|
children: vec![],
|
|
}],
|
|
}
|
|
}
|
|
|
|
pub fn load_gltf(path: std::path::PathBuf) -> model::Model {
|
|
let name = path.file_name().map(|v| v.to_string_lossy().to_string());
|
|
let (document, buffers, _images) = gltf::import(path).unwrap();
|
|
|
|
let buffers = buffers.into_iter().map(|v| v.to_vec()).collect();
|
|
|
|
let loader = GltfLoader {
|
|
name,
|
|
document,
|
|
buffers,
|
|
};
|
|
|
|
loader.load()
|
|
}
|
|
|
|
pub struct GltfLoader {
|
|
pub name: Option<String>,
|
|
pub document: gltf::Document,
|
|
pub buffers: Vec<Vec<u8>>,
|
|
}
|
|
|
|
impl GltfLoader {
|
|
pub fn load(mut self) -> model::Model {
|
|
let mut model = model::Model {
|
|
name: self.name.clone(),
|
|
objects: vec![],
|
|
};
|
|
|
|
for scene in self.document.scenes() {
|
|
for node in scene.nodes() {
|
|
model.objects.push(self.load_node(node, glam::Vec3::ONE));
|
|
}
|
|
}
|
|
|
|
model
|
|
}
|
|
|
|
pub fn load_buffers(model: &gltf::Gltf) -> Vec<Vec<u8>> {
|
|
let mut buffer_data = Vec::<Vec<u8>>::new();
|
|
for buffer in model.buffers() {
|
|
match buffer.source() {
|
|
gltf::buffer::Source::Bin => {
|
|
buffer_data.push(model.blob.as_deref().unwrap().into());
|
|
}
|
|
_ => panic!("URI buffer sources are unsupported"),
|
|
}
|
|
}
|
|
buffer_data
|
|
}
|
|
|
|
pub fn load_node(&self, node: gltf::Node, parent_scale: glam::Vec3) -> model::Object {
|
|
let (translation, orientation, scale) = node.transform().decomposed();
|
|
|
|
let orientation = glam::Quat::from_array(orientation);
|
|
let rotation = orientation.to_euler(glam::EulerRot::XYZ);
|
|
|
|
let scale: glam::Vec3 = scale.into();
|
|
let scale = scale * parent_scale;
|
|
|
|
let transform = model::Transform {
|
|
position: translation.into(),
|
|
rotation: rotation.into(),
|
|
scale,
|
|
};
|
|
|
|
let mut object = model::Object {
|
|
name: node.name().map(str::to_string),
|
|
transform,
|
|
meshes: vec![],
|
|
children: vec![],
|
|
};
|
|
|
|
if let Some(mesh) = node.mesh() {
|
|
for primitive in mesh.primitives() {
|
|
object.meshes.push(self.load_primitive_mesh(primitive));
|
|
}
|
|
}
|
|
|
|
for child in node.children() {
|
|
object.children.push(self.load_node(child, scale));
|
|
}
|
|
|
|
object
|
|
}
|
|
|
|
pub fn load_primitive_mesh(&self, primitive: gltf::Primitive) -> model::Mesh {
|
|
use gltf::mesh::util::{ReadIndices, ReadTexCoords};
|
|
if primitive.mode() != gltf::mesh::Mode::Triangles {
|
|
panic!("glTF primitive must be triangle list");
|
|
}
|
|
|
|
let reader = primitive.reader(|buffer| Some(&self.buffers[buffer.index()]));
|
|
let positions = reader.read_positions().unwrap();
|
|
let mut normals = reader.read_normals().unwrap();
|
|
|
|
let tex_coords = reader.read_tex_coords(0).unwrap();
|
|
let mut tex_coords = if let ReadTexCoords::F32(tex_coords) = tex_coords {
|
|
tex_coords
|
|
} else {
|
|
panic!("only f32 texture coordinates are supported")
|
|
};
|
|
|
|
let mut vertices = Vec::new();
|
|
for position in positions {
|
|
let normal = normals.next().unwrap();
|
|
let tex_coords = tex_coords.next().unwrap();
|
|
vertices.push(model::BasicVertex {
|
|
position: position.into(),
|
|
});
|
|
}
|
|
|
|
let indices = match reader.read_indices().unwrap() {
|
|
ReadIndices::U32(indices) => indices.collect(),
|
|
ReadIndices::U16(indices) => indices.map(|i| i as u32).collect(),
|
|
ReadIndices::U8(indices) => indices.map(|i| i as u32).collect(),
|
|
};
|
|
|
|
model::Mesh { vertices, indices }
|
|
}
|
|
}
|