diff --git a/src/loaders/gltf_loader.rs b/src/loaders/gltf_loader.rs index b61c0c0..845694c 100644 --- a/src/loaders/gltf_loader.rs +++ b/src/loaders/gltf_loader.rs @@ -1,7 +1,8 @@ use crate::loaders::mesh_loader::{MeshFileLoader, MeshInfo}; use anyhow::Result; use std::path::Path; -use nalgebra::{Matrix4, OMatrix, RowVector4}; +use gltf::buffer::Data; +use nalgebra::{Matrix4, Vector4}; pub struct GltfLoader; @@ -10,53 +11,33 @@ impl GltfLoader { pub fn traverse_node( node: &gltf::Node, parent_transform: &Matrix4, - buffers: &[Vec], + buffers: &Vec, vertices: &mut Vec<[f32; 3]>, normals: &mut Vec<[f32; 3]>, uvs: &mut Vec<[f32; 3]>, indices: &mut Vec ) { + let transform = node.transform().matrix() + .iter() + .flatten() + .cloned() + .collect::>(); + let matrix = Matrix4::from_column_slice(transform.as_slice()); + let full_transform = parent_transform * matrix; - } -} - -impl MeshFileLoader for GltfLoader { - fn load_mesh(&self, path: &Path) -> Result { - 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::::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() - .iter() - .flatten() - .cloned() - .collect::>(); - let matrix = Matrix4::from_row_slice(transform.as_slice()); - println!("Scene has 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() { - // Read the primitives as vertices and indices, - // and register a material for the primitive as well let vert_offset = vertices.len() as u32; let reader = primitive.reader(|buffer_index| Some(&buffers[buffer_index.index()])); if let Some(positions) = reader.read_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 { + 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::::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 { vertices, indices,