108 lines
2.8 KiB
Rust
108 lines
2.8 KiB
Rust
use utilities::prelude::cgmath;
|
|
use utilities::prelude::cgmath::prelude::{One, SquareMatrix};
|
|
|
|
use anyhow::Result;
|
|
|
|
use gltf;
|
|
|
|
use std::collections::HashMap;
|
|
use std::{cmp::Ordering, sync::Mutex};
|
|
|
|
#[derive(Debug)]
|
|
pub struct Skin {
|
|
pub index: usize,
|
|
pub root_joint_id: usize,
|
|
|
|
inverse_global_transform: Mutex<cgmath::Matrix4<f32>>,
|
|
inverse_bind_matrices: HashMap<usize, cgmath::Matrix4<f32>>,
|
|
joints: Vec<usize>,
|
|
}
|
|
|
|
impl Skin {
|
|
pub fn new(
|
|
gltf_skin: &gltf::Skin<'_>,
|
|
node_index: usize,
|
|
buffers: &Vec<gltf::buffer::Data>,
|
|
) -> Result<Skin> {
|
|
let reader = gltf_skin.reader(|buffer| Some(&buffers[buffer.index()]));
|
|
|
|
let ibms: Vec<cgmath::Matrix4<f32>> = match reader.read_inverse_bind_matrices() {
|
|
Some(ibms) => ibms.map(|ibm| ibm.into()).collect(),
|
|
None => {
|
|
return Err(anyhow::Error::msg(
|
|
"Gltf: Skin does not contain a inverse bind matrix",
|
|
))
|
|
}
|
|
};
|
|
|
|
let mut ibm_map = HashMap::new();
|
|
let mut nodes = Vec::new();
|
|
|
|
for (index, node) in gltf_skin.joints().enumerate() {
|
|
ibm_map.insert(node.index(), ibms[index]);
|
|
nodes.push(node.index());
|
|
}
|
|
|
|
let root_joint_id = match gltf_skin.skeleton() {
|
|
Some(node) => node.index(),
|
|
None => node_index,
|
|
};
|
|
|
|
Ok(Skin {
|
|
index: gltf_skin.index(),
|
|
root_joint_id,
|
|
|
|
inverse_global_transform: Mutex::new(cgmath::Matrix4::one()),
|
|
inverse_bind_matrices: ibm_map,
|
|
joints: nodes,
|
|
})
|
|
}
|
|
|
|
pub fn ibm(&self, node_id: usize) -> Option<&cgmath::Matrix4<f32>> {
|
|
self.inverse_bind_matrices.get(&node_id)
|
|
}
|
|
|
|
pub fn joints(&self) -> &Vec<usize> {
|
|
&self.joints
|
|
}
|
|
|
|
pub fn set_global_transform(&self, global_transform: cgmath::Matrix4<f32>) -> Result<()> {
|
|
if let Some(inverse) = global_transform.invert() {
|
|
*self.inverse_global_transform.lock().map_err(|_| {
|
|
anyhow::Error::msg("Gltf: Failed locking inverse_global_transform of Skin")
|
|
})? = inverse;
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub fn inverse_global_transform(&self) -> Result<cgmath::Matrix4<f32>> {
|
|
Ok(self
|
|
.inverse_global_transform
|
|
.lock()
|
|
.map_err(|_| {
|
|
anyhow::Error::msg("Gltf: Failed locking inverse_global_transform of Skin")
|
|
})?
|
|
.clone())
|
|
}
|
|
}
|
|
|
|
impl Ord for Skin {
|
|
fn cmp(&self, other: &Self) -> Ordering {
|
|
self.index.cmp(&other.index)
|
|
}
|
|
}
|
|
|
|
impl PartialOrd for Skin {
|
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
|
Some(self.cmp(other))
|
|
}
|
|
}
|
|
|
|
impl PartialEq for Skin {
|
|
fn eq(&self, other: &Self) -> bool {
|
|
self.index == other.index
|
|
}
|
|
}
|
|
|
|
impl Eq for Skin {}
|