mod3d_base/
bone_pose.rs

1//a Imports
2use geo_nd::matrix;
3
4use crate::Bone;
5use crate::{Mat4, Transformation};
6
7//a BonePose
8//tp BonePose
9/// A pose of a [Bone], referring to it so that many poses can use the
10/// same [Bone].
11///
12/// A [BonePose] has a current [Transformation] which indicates how it
13/// is posed; the [Bone] contains mapping matrices for going from
14/// bone-parent space to bone space, and for going from mesh space to
15/// bone space
16pub struct BonePose<'a> {
17    /// The bone this corresponds to (within its hierarchy)
18    bone: &'a Bone,
19    /// transformation relative to bone rest
20    transformation: Transformation,
21    /// posed-bone-to-parent Mat4 derived from transformation
22    pbtp: Mat4,
23    /// Matrix mapping bone-space to mesh-space
24    animated_btm: Mat4,
25    /// Matrix mapping mesh-space to mesh-space
26    animated_mtm: Mat4,
27}
28
29//ip BonePose
30impl<'a> BonePose<'a> {
31    //fp new
32    /// Create a new pose of a bone
33    pub fn new(bone: &'a Bone) -> Self {
34        let transformation = *bone.borrow_transformation();
35        let pbtp = [0.; 16];
36        let animated_btm = [0.; 16];
37        let animated_mtm = [0.; 16];
38        Self {
39            bone,
40            transformation,
41            pbtp,
42            animated_btm,
43            animated_mtm,
44        }
45    }
46
47    //mp transformation_reset
48    /// Reset the pose transformation to that of the bone in the skeleton
49    pub fn transformation_reset(&mut self) {
50        self.transformation = *self.bone.borrow_transformation();
51    }
52
53    //mp set_transformation
54    /// Set a new pose transformation for the posed bone
55    pub fn set_transformation(&mut self, transform: Transformation) {
56        self.transformation = transform;
57        self.pbtp = self.transformation.mat4();
58    }
59
60    //mp derive_animation
61    /// Derive the animation matrices given a parent
62    /// animated-posed-bone-to-mesh matrix
63    ///
64    /// If there is no parent (is_root true) then the animated
65    /// bone-to-mesh is just the posed-bone-to-parent transformation
66    ///
67    /// If there is a parent then its pose transformation must be
68    /// preapplied to this; when this animated_btm is applied to a
69    /// vector (in this local bone space) one must first generate the vector
70    /// in the parent-bone space (by applying pbtp) and then apply
71    /// parent pbtm to generate model space
72    ///
73    /// Vectors in the model mesh space can be multiplied by the
74    /// *bone*s mtb matrix to get a vector in this local bone space,
75    /// to which the animated_btm can be applied to get a model space
76    /// vector. Hence multiplying animated_btm and bone.mtb together.
77    pub fn derive_animation(&mut self, is_root: bool, parent_animated_pbtm: &Mat4) -> &Mat4 {
78        if is_root {
79            self.animated_btm = self.pbtp;
80        } else {
81            self.animated_btm = matrix::multiply4(parent_animated_pbtm, &self.pbtp);
82        }
83        self.animated_mtm = matrix::multiply4(&self.animated_btm, &self.bone.mtb);
84        &self.animated_btm
85    }
86
87    //mp borrow_animated_mtm
88    /// Borrow the animated mesh-to-model-space matrix
89    ///
90    /// This assumes it has been derived
91    #[inline]
92    pub fn borrow_animated_mtm(&self) -> &Mat4 {
93        &self.animated_mtm
94    }
95
96    //zz All done
97}
98
99//ip Display for BonePose
100impl<'a> std::fmt::Display for BonePose<'a> {
101    fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
102        writeln!(f, "Pose")?;
103        write!(f, "  {}", self.bone)?;
104        write!(f, "  {}", self.transformation)?;
105        write!(f, "  {:?}", self.pbtp)?;
106        write!(f, "  anim_btm: {:?}", self.animated_btm)?;
107        write!(f, "  anim_mtm: {:?}", self.animated_mtm)?;
108        Ok(())
109    }
110}
111
112//ip DefaultIndentedDisplay for BonePose
113impl<'a> indent_display::DefaultIndentedDisplay for BonePose<'a> {}