125 lines
3.3 KiB
Rust
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
|
|
}
|
|
}
|