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> {}