smpl_gloss_integration/
codec.rs

1use gloss_hecs::{Entity, EntityBuilder};
2use gloss_renderer::scene::Scene;
3use gloss_utils::bshare::ToNdArray;
4use log::info;
5use nd::concatenate;
6use ndarray as nd;
7use smpl_core::{
8    codec::codec::SmplCodec,
9    common::{
10        animation::{AnimWrap, Animation},
11        betas::Betas,
12        metadata::smpl_metadata,
13        pose::{Pose, PoseG},
14        pose_override::PoseOverride,
15        pose_retarget::RetargetPoseYShift,
16        smpl_params::SmplParams,
17        vertex_offsets::VertexOffsets,
18    },
19    conversions::{pose_chunked::PoseChunked, pose_remap::PoseRemap},
20    AppBackend,
21};
22use smpl_utils::log;
23use std::cmp::Ordering;
24/// Creates a ``SmplCodec`` from an entity by extracting components from it or
25/// creates a ``gloss_hecs::EntityBuilder`` from the ``SmplCodec``
26pub trait SmplCodecGloss {
27    fn from_entity(entity: &Entity, scene: &Scene, max_texture_size: Option<u32>) -> SmplCodec;
28    fn to_entity_builder(&self) -> EntityBuilder;
29}
30/// Trait implementation for `SmplCodec`
31impl SmplCodecGloss for SmplCodec {
32    #[allow(clippy::too_many_lines)]
33    #[allow(clippy::cast_possible_truncation)]
34    #[allow(clippy::cast_possible_wrap)]
35    fn from_entity(entity: &Entity, scene: &Scene, _max_texture_size: Option<u32>) -> SmplCodec {
36        let mut codec = SmplCodec::default();
37        let smpl_params = scene.get_comp::<&SmplParams>(entity).expect("Entity should have SmplParams component");
38        let smpl_version = smpl_params.smpl_type as i32;
39        let gender = smpl_params.gender as i32;
40        codec.smpl_version = smpl_version;
41        codec.gender = gender;
42        if let Ok(betas) = scene.get_comp::<&Betas>(entity) {
43            codec.shape_parameters = Some(betas.betas.clone().to_ndarray());
44        }
45        if scene.world.has::<Pose>(*entity).unwrap() && !scene.world.has::<Animation>(*entity).unwrap() {
46            log!("we are writing a pose in the codec");
47            let pose = scene.get_comp::<&Pose>(entity).unwrap();
48            let metadata = smpl_metadata(&smpl_params.smpl_type);
49            let chunked = PoseChunked::new(&pose, &metadata);
50            codec.body_translation = Some(chunked.global_trans.to_ndarray());
51            if chunked.global_orient.is_some() && chunked.body_pose.is_some() {
52                let body_pose_with_root = concatenate(
53                    nd::Axis(0),
54                    &[
55                        chunked.global_orient.unwrap().to_ndarray().view(),
56                        chunked.body_pose.unwrap().to_ndarray().view(),
57                    ],
58                )
59                .unwrap();
60                codec.body_pose = Some(body_pose_with_root.insert_axis(nd::Axis(0)));
61            }
62            if chunked.jaw_pose.is_some() && chunked.left_eye_pose.is_some() && chunked.right_eye_pose.is_some() {
63                let head_pose = concatenate(
64                    nd::Axis(0),
65                    &[
66                        chunked.jaw_pose.unwrap().to_ndarray().view(),
67                        chunked.left_eye_pose.unwrap().to_ndarray().view(),
68                        chunked.right_eye_pose.unwrap().to_ndarray().view(),
69                    ],
70                )
71                .unwrap();
72                codec.head_pose = Some(head_pose.insert_axis(nd::Axis(0)));
73            }
74            if let Some(left_hand_pose) = chunked.left_hand_pose {
75                codec.left_hand_pose = Some(left_hand_pose.to_ndarray().insert_axis(nd::Axis(0)));
76            }
77            if let Some(right_hand_pose) = chunked.right_hand_pose {
78                codec.right_hand_pose = Some(right_hand_pose.to_ndarray().insert_axis(nd::Axis(0)));
79            }
80        } else if scene.world.has::<Animation>(*entity).unwrap() {
81            log!("we are writing a animation in the codec");
82            let anim = scene.get_comp::<&Animation>(entity).unwrap();
83            let metadata = smpl_metadata(&smpl_params.smpl_type);
84            let nr_frames = anim.num_animation_frames();
85            let mut full_body_translation = nd::Array2::<f32>::zeros((nr_frames, 3));
86            let mut full_body_pose = nd::Array3::<f32>::zeros((nr_frames, metadata.num_body_joints + 1, 3));
87            let mut full_head_pose = nd::Array3::<f32>::zeros((nr_frames, metadata.num_face_joints, 3));
88            let mut full_left_hand_pose = nd::Array3::<f32>::zeros((nr_frames, metadata.num_hand_joints, 3));
89            let mut full_right_hand_pose = nd::Array3::<f32>::zeros((nr_frames, metadata.num_hand_joints, 3));
90            for time_idx in 0..anim.num_animation_frames() {
91                let mut pose: PoseG<AppBackend> = anim.get_pose_at_idx(time_idx);
92                let pose_remap = PoseRemap::new(pose.smpl_type, smpl_params.smpl_type);
93                pose = pose_remap.remap(&pose);
94                if let Ok(ref pose_mask) = scene.get_comp::<&PoseOverride>(entity) {
95                    let mut new_pose_mask = PoseOverride::clone(pose_mask);
96                    pose.apply_mask(&mut new_pose_mask);
97                }
98                if let Ok(ref pose_retarget) = scene.get_comp::<&RetargetPoseYShift>(entity) {
99                    let mut pose_retarget_local = RetargetPoseYShift::clone(pose_retarget);
100                    pose_retarget_local.apply(&mut pose);
101                }
102                let chunked = PoseChunked::new(&pose, &metadata);
103                full_body_translation
104                    .index_axis_mut(nd::Axis(0), time_idx)
105                    .assign(&chunked.global_trans.to_ndarray().to_shape(3).unwrap());
106                if chunked.global_orient.is_some() && chunked.body_pose.is_some() {
107                    let body_pose_with_root = concatenate(
108                        nd::Axis(0),
109                        &[
110                            chunked.global_orient.unwrap().to_ndarray().view(),
111                            chunked.body_pose.unwrap().to_ndarray().view(),
112                        ],
113                    )
114                    .unwrap();
115                    full_body_pose.index_axis_mut(nd::Axis(0), time_idx).assign(&body_pose_with_root);
116                }
117                if chunked.jaw_pose.is_some() && chunked.left_eye_pose.is_some() && chunked.right_eye_pose.is_some() {
118                    let head_pose = concatenate(
119                        nd::Axis(0),
120                        &[
121                            chunked.jaw_pose.unwrap().to_ndarray().view(),
122                            chunked.left_eye_pose.unwrap().to_ndarray().view(),
123                            chunked.right_eye_pose.unwrap().to_ndarray().view(),
124                        ],
125                    )
126                    .unwrap();
127                    full_head_pose.index_axis_mut(nd::Axis(0), time_idx).assign(&head_pose);
128                }
129                if let Some(left_hand_pose) = chunked.left_hand_pose {
130                    full_left_hand_pose
131                        .index_axis_mut(nd::Axis(0), time_idx)
132                        .assign(&left_hand_pose.to_ndarray());
133                }
134                if let Some(right_hand_pose) = chunked.right_hand_pose {
135                    full_right_hand_pose
136                        .index_axis_mut(nd::Axis(0), time_idx)
137                        .assign(&right_hand_pose.to_ndarray());
138                }
139            }
140            codec.frame_count = nr_frames as i32;
141            codec.frame_rate = Some(anim.config.fps);
142            codec.body_translation = Some(full_body_translation);
143            codec.body_pose = Some(full_body_pose);
144            codec.head_pose = Some(full_head_pose);
145            codec.left_hand_pose = Some(full_left_hand_pose);
146            codec.right_hand_pose = Some(full_right_hand_pose);
147        }
148        codec
149    }
150    fn to_entity_builder(&self) -> EntityBuilder {
151        let mut builder = EntityBuilder::new();
152        let smpl_params = SmplParams::new_from_smpl_codec(self);
153        info!("Found smpl_params in the .smpl file");
154        builder.add(smpl_params);
155        let betas = Betas::new_from_smpl_codec(self);
156        if let Some(betas) = betas {
157            info!("Found betas in the .smpl file");
158            builder.add(betas);
159        }
160        match self.frame_count.cmp(&1) {
161            Ordering::Greater => {
162                let anim = Animation::new_from_smpl_codec(self, AnimWrap::default()).expect("The framecount is >1 so the animation should be valid");
163                info!("Found animation in the .smpl file");
164                builder.add(anim);
165            }
166            Ordering::Equal => {
167                let pose = Pose::new_from_smpl_codec(self).expect("The framecount is =1 so the pose should be valid");
168                info!("Found pose in the .smpl file");
169                builder.add(pose);
170            }
171            Ordering::Less => {}
172        }
173        let offsets = VertexOffsets::new_from_smpl_codec(self);
174        if let Some(offsets) = offsets {
175            info!("Found vertex offsets in the .smpl file");
176            builder.add(offsets);
177        }
178        builder
179    }
180}