smpl_gloss_integration/
codec.rs1use 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;
24pub trait SmplCodecGloss {
27 fn from_entity(entity: &Entity, scene: &Scene, max_texture_size: Option<u32>) -> SmplCodec;
28 fn to_entity_builder(&self) -> EntityBuilder;
29}
30impl 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}