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