engine/gltf-loader/src/node.rs
2024-08-23 13:22:09 +02:00

125 lines
3.3 KiB
Rust

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<usize>,
pub mesh_index: Option<usize>,
pub skin_index: Option<usize>,
matrix: Matrix4<f32>,
final_transform: RwLock<Matrix4<f32>>,
}
impl Node {
pub fn new(
gltf_node: gltf::Node<'_>,
mesh_index: Option<usize>,
skin_index: Option<usize>,
) -> Result<Node> {
let matrix: Matrix4<f32> = 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<usize, Node>,
parent_transform: &Matrix4<f32>,
meshes: &mut Vec<Mesh>,
skins: &mut Vec<Skin>,
) -> 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<f32> {
self.final_transform
.read()
.expect("reading from final transform should never fail")
.clone()
}
pub fn children(&self) -> &Vec<usize> {
&self.children
}
pub fn name(&self) -> &String {
&self.name
}
pub fn matrix(&self) -> Matrix4<f32> {
self.matrix
}
}