smpl_core/common/
pose_retarget.rs

1use super::pose::Pose;
2/// After adding a pose or a animation, we align the avatar to the floor and
3/// store the tallness that it has; this is the most naive way of retargetting
4#[derive(Clone, Copy)]
5pub struct RetargetPoseYShift {
6    pub y_shift: f32,
7    pub dist_chest_to_feet: f32,
8    pub currently_applied_y_shift: f32,
9}
10impl RetargetPoseYShift {
11    pub fn new(y_shift: f32, dist_chest_to_feet: f32) -> Self {
12        Self {
13            y_shift,
14            dist_chest_to_feet,
15            currently_applied_y_shift: 0.0,
16        }
17    }
18    pub fn update(&mut self, new_height: f32) {
19        let old_height = self.dist_chest_to_feet;
20        let diff = new_height - old_height;
21        self.dist_chest_to_feet = new_height;
22        self.y_shift += -diff;
23    }
24    #[allow(clippy::missing_panics_doc)]
25    pub fn apply(&mut self, pose: &mut Pose) {
26        if pose.non_retargeted_pose.is_none() {
27            pose.non_retargeted_pose = Some(Box::new(pose.clone()));
28        }
29        pose.global_trans[1] = pose.non_retargeted_pose.as_ref().unwrap().global_trans[1] + self.y_shift;
30        self.currently_applied_y_shift = self.y_shift;
31        pose.retargeted = true;
32    }
33    #[allow(clippy::missing_panics_doc)]
34    pub fn remove_retarget(&self, pose: &mut Pose) {
35        if pose.non_retargeted_pose.is_some() {
36            let original = *pose.non_retargeted_pose.take().unwrap();
37            pose.clone_from(&original);
38        }
39        pose.retargeted = false;
40    }
41}