use std::sync::Arc;
use glam::Mat4;
use crate::{
buffer::helpers::u8_to_f32_vec,
gltf::{
buffers::accessor::accessor_to_bytes,
error::{AwsmGltfError, Result},
},
AwsmRenderer,
};
use super::GltfPopulateContext;
impl AwsmRenderer {
#[allow(clippy::only_used_in_recursion)]
pub(super) fn populate_gltf_node_skin<'a, 'b: 'a, 'c: 'a>(
&'a mut self,
ctx: &'c GltfPopulateContext,
gltf_node: &'b gltf::Node<'b>,
) -> Result<()> {
mark_gltf_node_as_joint(ctx, gltf_node)?;
if let Some(skin) = gltf_node.skin() {
let mut joints = Vec::with_capacity(skin.joints().len());
let node_to_transform = &ctx.key_lookups.lock().unwrap().node_index_to_transform;
for joint_node in skin.joints() {
let transform_key = *node_to_transform.get(&joint_node.index()).ok_or(
AwsmGltfError::SkinJointTransformNotFound(joint_node.index()),
)?;
joints.push(transform_key);
}
let inverse_bind_matrices = match skin.inverse_bind_matrices() {
Some(accessor) => {
let bytes = accessor_to_bytes(&accessor, &ctx.data.buffers.raw)?;
let values = u8_to_f32_vec(&bytes);
let matrices = values
.chunks(16)
.map(Mat4::from_cols_slice)
.collect::<Vec<_>>();
if matrices.len() != skin.joints().len() {
return Err(AwsmGltfError::InvalidSkinInverseBindMatrixCount {
matrix_count: matrices.len(),
joint_count: skin.joints().len(),
});
}
Some(matrices)
}
None => None,
};
ctx.node_to_skin_transform.lock().unwrap().insert(
gltf_node.index(),
Arc::new((joints, inverse_bind_matrices.unwrap_or_default())),
);
}
for child in gltf_node.children() {
self.populate_gltf_node_skin(ctx, &child)?;
}
Ok(())
}
}
fn mark_gltf_node_as_joint(ctx: &GltfPopulateContext, gltf_node: &gltf::Node) -> Result<()> {
if let Some(skin) = gltf_node.skin() {
let mut transform_is_joint = ctx.transform_is_joint.lock().unwrap();
let node_to_transform = &ctx.key_lookups.lock().unwrap().node_index_to_transform;
for joint_node in skin.joints() {
let transform_key = node_to_transform.get(&joint_node.index()).unwrap();
transform_is_joint.insert(*transform_key);
}
}
for child in gltf_node.children() {
mark_gltf_node_as_joint(ctx, &child)?;
}
Ok(())
}