use super::skinning::{
compute_inverse_bind_transforms, compute_skinning_transforms as math_skin_xforms, joint_local_to_skel_space,
joint_skel_to_world,
};
use super::topology::Topology;
use super::types::ReadSkeleton;
#[derive(Debug, Clone)]
pub struct SkeletonResolver {
skeleton: ReadSkeleton,
topology: Topology,
inverse_bind_transforms: Vec<[f64; 16]>,
}
impl SkeletonResolver {
pub fn new(skeleton: ReadSkeleton) -> Self {
let topology = Topology::from_joint_paths(&skeleton.joints);
let inverse_bind_transforms = compute_inverse_bind_transforms(&skeleton.bind_transforms);
Self {
skeleton,
topology,
inverse_bind_transforms,
}
}
pub fn skeleton(&self) -> &ReadSkeleton {
&self.skeleton
}
pub fn joint_order(&self) -> &[String] {
&self.skeleton.joints
}
pub fn topology(&self) -> &Topology {
&self.topology
}
pub fn joint_world_bind_transforms(&self) -> &[[f64; 16]] {
&self.skeleton.bind_transforms
}
pub fn inverse_bind_transforms(&self) -> &[[f64; 16]] {
&self.inverse_bind_transforms
}
pub fn joint_local_to_skel_space(&self, local: &[[f64; 16]]) -> Vec<[f64; 16]> {
joint_local_to_skel_space(local, &self.topology)
}
pub fn joint_skel_to_world(&self, skel: &[[f64; 16]], skel_local_to_world: &[f64; 16]) -> Vec<[f64; 16]> {
joint_skel_to_world(skel, skel_local_to_world)
}
pub fn compute_skinning_transforms_from_world(&self, joint_world: &[[f64; 16]]) -> Vec<[f64; 16]> {
math_skin_xforms(joint_world, &self.inverse_bind_transforms)
}
pub fn compute_skinning_transforms_from_local(
&self,
joint_local: &[[f64; 16]],
skel_local_to_world: &[f64; 16],
) -> Vec<[f64; 16]> {
let skel = self.joint_local_to_skel_space(joint_local);
let world = self.joint_skel_to_world(&skel, skel_local_to_world);
math_skin_xforms(&world, &self.inverse_bind_transforms)
}
pub fn rest_pose_local(&self) -> &[[f64; 16]] {
&self.skeleton.rest_transforms
}
pub fn rest_pose_skel_space(&self) -> Vec<[f64; 16]> {
joint_local_to_skel_space(&self.skeleton.rest_transforms, &self.topology)
}
}