use super::{mesh::Mesh, skin::Skin}; use anyhow::Result; use utilities::prelude::cgmath::{prelude::*, Matrix4}; use gltf; use std::collections::HashMap; use std::ops::Deref; use std::sync::RwLock; #[derive(Debug)] pub struct Node { pub index: usize, name: String, children: Vec, pub mesh_index: Option, pub skin_index: Option, matrix: Matrix4, final_transform: RwLock>, } impl Node { pub fn new( gltf_node: gltf::Node<'_>, mesh_index: Option, skin_index: Option, ) -> Result { let matrix: Matrix4 = gltf_node.transform().matrix().into(); let name = match gltf_node.name() { Some(name_str) => name_str.to_string(), None => "unnamed".to_string(), }; Ok(Node { index: gltf_node.index(), name, children: gltf_node.children().map(|node| node.index()).collect(), mesh_index, skin_index, matrix, final_transform: RwLock::new(Matrix4::identity()), }) } pub fn update_transform( &self, nodes: &HashMap, parent_transform: &Matrix4, meshes: &mut Vec, skins: &mut Vec, ) -> Result<()> { *self .final_transform .write() .map_err(|_| anyhow::Error::msg("Gltf: Failed locking final_transform of Node"))? = *parent_transform * self.matrix; if let Some(index) = self.mesh_index { meshes[index].set_model_matrix( self.final_transform .read() .map_err(|_| { anyhow::Error::msg("Gltf: Failed locking final_transform of Node") })? .clone(), ); } if let Some(index) = self.skin_index { skins[index].set_global_transform( self.final_transform .read() .map_err(|_| { anyhow::Error::msg("Gltf: Failed locking final_transform of Node") })? .clone(), )?; } for node_id in &self.children { if let Some(child) = nodes.get(node_id) { child.update_transform( nodes, self.final_transform .read() .map_err(|_| { anyhow::Error::msg("Gltf: Failed locking final_transform of Node") })? .deref(), meshes, skins, )?; } } Ok(()) } pub fn final_transform(&self) -> Matrix4 { self.final_transform .read() .expect("reading from final transform should never fail") .clone() } pub fn children(&self) -> &Vec { &self.children } pub fn name(&self) -> &String { &self.name } pub fn matrix(&self) -> Matrix4 { self.matrix } }