feat: properly implement GTLF/GLB loading
This commit is contained in:
1 parent
8baf537be9
commit
b285671165
1 file changed
+56
-30
+56
-30
@@ -1,7 +1,8 @@
|
|||||||
use crate::loaders::mesh_loader::{MeshFileLoader, MeshInfo};
|
use crate::loaders::mesh_loader::{MeshFileLoader, MeshInfo};
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use nalgebra::{Matrix4, OMatrix, RowVector4};
|
use gltf::buffer::Data;
|
||||||
|
use nalgebra::{Matrix4, Vector4};
|
||||||
|
|
||||||
pub struct GltfLoader;
|
pub struct GltfLoader;
|
||||||
|
|
||||||
@@ -10,53 +11,33 @@ impl GltfLoader {
|
|||||||
pub fn traverse_node(
|
pub fn traverse_node(
|
||||||
node: &gltf::Node,
|
node: &gltf::Node,
|
||||||
parent_transform: &Matrix4<f32>,
|
parent_transform: &Matrix4<f32>,
|
||||||
buffers: &[Vec<u8>],
|
buffers: &Vec<Data>,
|
||||||
vertices: &mut Vec<[f32; 3]>,
|
vertices: &mut Vec<[f32; 3]>,
|
||||||
normals: &mut Vec<[f32; 3]>,
|
normals: &mut Vec<[f32; 3]>,
|
||||||
uvs: &mut Vec<[f32; 3]>,
|
uvs: &mut Vec<[f32; 3]>,
|
||||||
indices: &mut Vec<u32>
|
indices: &mut Vec<u32>
|
||||||
) {
|
) {
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl MeshFileLoader for GltfLoader {
|
|
||||||
fn load_mesh(&self, path: &Path) -> Result<MeshInfo> {
|
|
||||||
let (document, buffers, _) = gltf::import(path)?;
|
|
||||||
|
|
||||||
let mut vertices = Vec::new();
|
|
||||||
let mut normals = Vec::new();
|
|
||||||
let mut uvs = Vec::new();
|
|
||||||
let mut indices = Vec::<u32>::new();
|
|
||||||
|
|
||||||
let scenes = document.scenes();
|
|
||||||
|
|
||||||
// We need to iterate through scenes and apply the transforms from each scene to their
|
|
||||||
// corresponding vertices.
|
|
||||||
println!("Parsing {} scenes from {:?}", scenes.len(), path);
|
|
||||||
for scene in scenes {
|
|
||||||
for node in scene.nodes() {
|
|
||||||
let transform = node.transform().matrix()
|
let transform = node.transform().matrix()
|
||||||
.iter()
|
.iter()
|
||||||
.flatten()
|
.flatten()
|
||||||
.cloned()
|
.cloned()
|
||||||
.collect::<Vec<f32>>();
|
.collect::<Vec<f32>>();
|
||||||
let matrix = Matrix4::from_row_slice(transform.as_slice());
|
let matrix = Matrix4::from_column_slice(transform.as_slice());
|
||||||
println!("Scene has transform: {}", matrix);
|
let full_transform = parent_transform * matrix;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for mesh in document.meshes() {
|
if let Some(mesh) = node.mesh() {
|
||||||
|
// Read the mesh and apply the current transformation to every vertex
|
||||||
for primitive in mesh.primitives() {
|
for primitive in mesh.primitives() {
|
||||||
// Read the primitives as vertices and indices,
|
|
||||||
// and register a material for the primitive as well
|
|
||||||
let vert_offset = vertices.len() as u32;
|
let vert_offset = vertices.len() as u32;
|
||||||
|
|
||||||
let reader = primitive.reader(|buffer_index| Some(&buffers[buffer_index.index()]));
|
let reader = primitive.reader(|buffer_index| Some(&buffers[buffer_index.index()]));
|
||||||
|
|
||||||
if let Some(positions) = reader.read_positions() {
|
if let Some(positions) = reader.read_positions() {
|
||||||
for position in positions {
|
for position in positions {
|
||||||
vertices.push([position[0], position[2], -position[1]]);
|
// Transform into a Vector4, apply transform, push as 3D slice
|
||||||
|
let pos_vec = Vector4::new(position[0], position[1], position[2], 1.0);
|
||||||
|
let transformed = full_transform * pos_vec;
|
||||||
|
vertices.push([transformed.x, transformed.y, transformed.z]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,6 +61,51 @@ impl MeshFileLoader for GltfLoader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Process all child nodes as well
|
||||||
|
for child in node.children() {
|
||||||
|
Self::traverse_node(
|
||||||
|
&child,
|
||||||
|
&full_transform,
|
||||||
|
&buffers,
|
||||||
|
vertices,
|
||||||
|
normals,
|
||||||
|
uvs,
|
||||||
|
indices
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MeshFileLoader for GltfLoader {
|
||||||
|
fn load_mesh(&self, path: &Path) -> Result<MeshInfo> {
|
||||||
|
let (document, buffers, _) = gltf::import(path)?;
|
||||||
|
|
||||||
|
let mut vertices = Vec::new();
|
||||||
|
let mut normals = Vec::new();
|
||||||
|
let mut uvs = Vec::new();
|
||||||
|
let mut indices = Vec::<u32>::new();
|
||||||
|
|
||||||
|
let scenes = document.scenes();
|
||||||
|
|
||||||
|
// We need to iterate through scenes and apply the transforms from each scene to their
|
||||||
|
// corresponding vertices.
|
||||||
|
println!("Parsing {} scenes from {:?}", scenes.len(), path);
|
||||||
|
for scene in scenes {
|
||||||
|
for node in scene.nodes() {
|
||||||
|
// Read through the nodes and get all vertex information.
|
||||||
|
// Even if there are multiple scenes, we're treating the whole file as a single mesh.
|
||||||
|
Self::traverse_node(
|
||||||
|
&node,
|
||||||
|
&Matrix4::identity(),
|
||||||
|
&buffers,
|
||||||
|
&mut vertices,
|
||||||
|
&mut normals,
|
||||||
|
&mut uvs,
|
||||||
|
&mut indices
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok(MeshInfo {
|
Ok(MeshInfo {
|
||||||
vertices,
|
vertices,
|
||||||
indices,
|
indices,
|
||||||
|
|||||||
Reference in new issue
Block a user