dotrix_core/
pose.rs

1use crate::{
2    assets::{
3        Assets,
4        skin::{ JointTransform, JointIndex, MAX_JOINTS, Skin },
5    },
6    id::Id,
7    renderer::{ Renderer, UniformBuffer },
8};
9
10use dotrix_math::{ Mat4, SquareMatrix };
11
12/// Transformed [`Skin`] state
13pub struct Pose {
14    /// Id of a Skin asset
15    pub skin: Id<Skin>,
16    /// Transformations of the [`Skin`] joints
17    pub joints: Vec<JointTransform>,
18    /// Joints transformations buffer
19    pub uniform: UniformBuffer,
20}
21
22impl Pose {
23    /// Loads the [`Pose`] into GPU buffers
24    pub fn load(&mut self, renderer: &Renderer, assets: &Assets) -> bool {
25        if let Some(skin) = assets.get(self.skin) {
26            let joints_matrices = self.matrices(&skin.index);
27            renderer.load_uniform_buffer(
28                &mut self.uniform,
29                bytemuck::cast_slice(joints_matrices.as_slice())
30            );
31            return true;
32        }
33        false
34    }
35
36    /// Returns transformation matrices in proper order and packed to be used in shaders
37    fn matrices(&self, index: &[JointIndex]) -> Vec<[[f32; 4]; 4]> {
38        let mut result = index.iter().map(|i| {
39            let joint_transform = self.joints.iter().find(|j| j.id == i.id).unwrap();
40            let global_transform = &joint_transform.global_transform;
41            let inverse_bind_matrix = i.inverse_bind_matrix;
42            inverse_bind_matrix
43                .as_ref()
44                .map(|ibmx| global_transform * ibmx)
45                .unwrap_or(*global_transform)
46                .into()
47        }).collect::<Vec<_>>();
48
49        while result.len() < MAX_JOINTS {
50            result.push(Mat4::identity().into());
51        }
52        result
53    }
54}
55
56impl From<Id<Skin>> for Pose {
57    /// Constructs new [`Pose`]
58    fn from(skin: Id<Skin>) -> Self {
59        Self {
60            skin,
61            joints: vec![JointTransform::default(); MAX_JOINTS], // 32 -> MAX_JOINTS
62            uniform: UniformBuffer::default(),
63        }
64    }
65}