1use super::math::{Mat4, Trs, lerp3, multiply, nlerp};
2use super::skeleton::Skeleton;
3
4#[derive(Clone, Debug, PartialEq)]
5pub struct Pose {
6 locals: Vec<Trs>,
7}
8
9impl Pose {
10 pub fn rest(skeleton: &Skeleton) -> Self {
11 Self {
12 locals: skeleton.joints().iter().map(|joint| joint.rest).collect(),
13 }
14 }
15
16 pub fn reset(&mut self, skeleton: &Skeleton) {
17 self.locals.clear();
18 self.locals
19 .extend(skeleton.joints().iter().map(|joint| joint.rest));
20 }
21
22 pub fn locals(&self) -> &[Trs] {
23 &self.locals
24 }
25
26 pub fn locals_mut(&mut self) -> &mut [Trs] {
27 &mut self.locals
28 }
29
30 pub fn mix(&mut self, other: &Pose, weight: f32) {
31 if weight <= 0.0 {
32 return;
33 }
34 if weight >= 1.0 {
35 self.locals.clone_from(&other.locals);
36 return;
37 }
38 for (local, target) in self.locals.iter_mut().zip(&other.locals) {
39 local.translation = lerp3(local.translation, target.translation, weight);
40 local.rotation = nlerp(local.rotation, target.rotation, weight);
41 local.scale = lerp3(local.scale, target.scale, weight);
42 }
43 }
44
45 pub fn globals(&self, skeleton: &Skeleton) -> Vec<Mat4> {
46 let mut out = Vec::with_capacity(self.locals.len());
47 self.globals_into(skeleton, &mut out);
48 out
49 }
50
51 fn globals_into(&self, skeleton: &Skeleton, out: &mut Vec<Mat4>) {
52 let root = skeleton.root();
53 out.clear();
54 for (joint, local) in skeleton.joints().iter().zip(&self.locals) {
55 let parent = match joint.parent {
56 Some(parent) => out[parent],
57 None => root,
58 };
59 out.push(multiply(&parent, &local.matrix()));
60 }
61 }
62
63 pub fn palette(&self, skeleton: &Skeleton) -> Vec<Mat4> {
64 let mut out = Vec::new();
65 self.palette_into(skeleton, &mut out);
66 out
67 }
68
69 pub fn palette_into(&self, skeleton: &Skeleton, out: &mut Vec<Mat4>) {
70 self.globals_into(skeleton, out);
71 for (global, inverse) in out.iter_mut().zip(skeleton.inverse_binds()) {
72 *global = multiply(global, inverse);
73 }
74 }
75}