Skip to main content

pfx_core/anim/
pose.rs

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}