Skip to main content

smpl_gloss_integration/network/
serializable_components.rs

1use crate::components::GlossInterop;
2use crate::scene::SceneAnimation;
3use gloss_renderer::network::{FromSerializable, ToSerializable};
4use gloss_utils::bshare::ToNdArray;
5use num_traits::FromPrimitive;
6use serde::{Deserialize, Serialize};
7use smpl_core::common::{
8    animation::{AnimWrap, Animation, AnimationConfig, AnimationRunner},
9    betas::Betas,
10    smpl_params::SmplParams,
11    transform_sequence::TransformSequence,
12    types::{AngleType, FaceType, Gender, SmplType, UpAxis},
13};
14use std::time::Duration;
15/// Serializable version of `SmplParams` component
16#[derive(Clone, Debug, Serialize, Deserialize)]
17pub struct SerializableSmplParams {
18    pub smpl_type: u8,
19    pub gender: u8,
20    pub enable_pose_corrective: bool,
21}
22impl ToSerializable<SerializableSmplParams> for SmplParams {
23    fn to_serializable(&self) -> SerializableSmplParams {
24        SerializableSmplParams {
25            smpl_type: self.smpl_type as u8,
26            gender: self.gender as u8,
27            enable_pose_corrective: self.enable_pose_corrective,
28        }
29    }
30}
31impl FromSerializable<SerializableSmplParams> for SmplParams {
32    fn from_serializable(s: &SerializableSmplParams) -> SmplParams {
33        SmplParams {
34            smpl_type: SmplType::from_u8(s.smpl_type).unwrap(),
35            gender: Gender::from_u8(s.gender).unwrap(),
36            enable_pose_corrective: s.enable_pose_corrective,
37        }
38    }
39}
40/// Serializable version of Betas component
41#[derive(Clone, Debug, Serialize, Deserialize)]
42pub struct SerializableBetas {
43    pub betas_data: Vec<f32>,
44}
45impl ToSerializable<SerializableBetas> for Betas {
46    fn to_serializable(&self) -> SerializableBetas {
47        let betas_ndarray = self.betas.to_ndarray();
48        SerializableBetas {
49            betas_data: betas_ndarray.to_vec(),
50        }
51    }
52}
53impl FromSerializable<SerializableBetas> for Betas {
54    fn from_serializable(s: &SerializableBetas) -> Betas {
55        Betas::new_from_ndarray(ndarray::Array1::from(s.betas_data.clone()))
56    }
57}
58/// Serializable version of Animation component
59#[derive(Clone, Debug, Serialize, Deserialize)]
60pub struct SerializableAnimation {
61    pub per_frame_joint_poses_shape: (usize, usize, usize),
62    pub per_frame_joint_poses_data: Vec<f32>,
63    pub per_frame_root_trans_shape: (usize, usize),
64    pub per_frame_root_trans_data: Vec<f32>,
65    pub per_frame_expression_coeffs_shape: Option<(usize, usize)>,
66    pub per_frame_expression_coeffs_data: Option<Vec<f32>>,
67    pub start_offset: usize,
68    pub anim_current_time_nanos: u64,
69    pub anim_reversed: bool,
70    pub nr_repetitions: u32,
71    pub paused: bool,
72    pub temporary_pause: bool,
73    pub fps: f32,
74    pub wrap_behaviour: u8,
75    pub angle_type: u8,
76    pub up_axis: u8,
77    pub smpl_type: u8,
78    pub face_type: u8,
79}
80#[allow(clippy::cast_possible_truncation)]
81impl ToSerializable<SerializableAnimation> for Animation {
82    fn to_serializable(&self) -> SerializableAnimation {
83        let expr_shape_data = if let Some(ref expr) = self.per_frame_expression_coeffs {
84            (Some(expr.dim()), Some(expr.as_slice().unwrap().to_vec()))
85        } else {
86            (None, None)
87        };
88        SerializableAnimation {
89            per_frame_joint_poses_shape: self.per_frame_joint_poses.dim(),
90            per_frame_joint_poses_data: self.per_frame_joint_poses.as_slice().unwrap().to_vec(),
91            per_frame_root_trans_shape: self.per_frame_root_trans.dim(),
92            per_frame_root_trans_data: self.per_frame_root_trans.as_slice().unwrap().to_vec(),
93            per_frame_expression_coeffs_shape: expr_shape_data.0,
94            per_frame_expression_coeffs_data: expr_shape_data.1,
95            start_offset: self.start_offset,
96            anim_current_time_nanos: self.runner.anim_current_time.as_nanos() as u64,
97            anim_reversed: self.runner.anim_reversed,
98            nr_repetitions: self.runner.nr_repetitions,
99            paused: self.runner.paused,
100            temporary_pause: self.runner.temporary_pause,
101            fps: self.config.fps,
102            wrap_behaviour: match self.config.wrap_behaviour {
103                AnimWrap::Clamp => 0,
104                AnimWrap::Loop => 1,
105                AnimWrap::Reverse => 2,
106            },
107            angle_type: match self.config.angle_type {
108                AngleType::AxisAngle => 0,
109                AngleType::Euler => 1,
110            },
111            up_axis: match self.config.up_axis {
112                UpAxis::Y => 0,
113                UpAxis::Z => 1,
114            },
115            smpl_type: self.config.smpl_type as u8,
116            face_type: self.config.face_type as u8,
117        }
118    }
119}
120impl FromSerializable<SerializableAnimation> for Animation {
121    fn from_serializable(s: &SerializableAnimation) -> Animation {
122        use ndarray::Array2;
123        let per_frame_joint_poses = ndarray::Array3::from_shape_vec(s.per_frame_joint_poses_shape, s.per_frame_joint_poses_data.clone()).unwrap();
124        let per_frame_root_trans = Array2::from_shape_vec(s.per_frame_root_trans_shape, s.per_frame_root_trans_data.clone()).unwrap();
125        let per_frame_expression_coeffs =
126            if let (Some(shape), Some(data)) = (&s.per_frame_expression_coeffs_shape, &s.per_frame_expression_coeffs_data) {
127                Some(Array2::from_shape_vec(*shape, data.clone()).unwrap())
128            } else {
129                None
130            };
131        #[allow(clippy::match_same_arms)]
132        let wrap_behaviour = match s.wrap_behaviour {
133            0 => AnimWrap::Clamp,
134            1 => AnimWrap::Loop,
135            2 => AnimWrap::Reverse,
136            _ => AnimWrap::Loop,
137        };
138        #[allow(clippy::match_same_arms)]
139        let angle_type = match s.angle_type {
140            0 => AngleType::AxisAngle,
141            1 => AngleType::Euler,
142            _ => AngleType::AxisAngle,
143        };
144        #[allow(clippy::match_same_arms)]
145        let up_axis = match s.up_axis {
146            0 => UpAxis::Y,
147            1 => UpAxis::Z,
148            _ => UpAxis::Y,
149        };
150        Animation {
151            per_frame_joint_poses,
152            per_frame_root_trans,
153            per_frame_expression_coeffs,
154            start_offset: s.start_offset,
155            runner: AnimationRunner {
156                anim_current_time: Duration::from_nanos(s.anim_current_time_nanos),
157                anim_reversed: s.anim_reversed,
158                nr_repetitions: s.nr_repetitions,
159                paused: s.paused,
160                temporary_pause: s.temporary_pause,
161            },
162            config: AnimationConfig {
163                fps: s.fps,
164                wrap_behaviour,
165                angle_type,
166                up_axis,
167                smpl_type: SmplType::from_u8(s.smpl_type).unwrap_or(SmplType::SmplX),
168                face_type: FaceType::from_u8(s.face_type).unwrap_or(FaceType::SmplX),
169            },
170        }
171    }
172}
173/// Serializable version of `GlossInterop` component
174#[derive(Clone, Debug, Serialize, Deserialize)]
175pub struct SerializableGlossInterop {
176    pub with_uv: bool,
177}
178impl ToSerializable<SerializableGlossInterop> for GlossInterop {
179    fn to_serializable(&self) -> SerializableGlossInterop {
180        SerializableGlossInterop { with_uv: self.with_uv }
181    }
182}
183impl FromSerializable<SerializableGlossInterop> for GlossInterop {
184    fn from_serializable(s: &SerializableGlossInterop) -> GlossInterop {
185        GlossInterop { with_uv: s.with_uv }
186    }
187}
188/// Serializable version of `SceneAnimation` component
189#[derive(Clone, Debug, Serialize, Deserialize)]
190pub struct SerializableSceneAnimation {
191    pub num_frames: usize,
192    pub anim_current_time_nanos: u64,
193    pub anim_reversed: bool,
194    pub nr_repetitions: u32,
195    pub paused: bool,
196    pub temporary_pause: bool,
197    pub fps: f32,
198    pub wrap_behaviour: u8,
199    pub angle_type: u8,
200    pub up_axis: u8,
201    pub smpl_type: u8,
202    pub face_type: u8,
203}
204impl ToSerializable<SerializableSceneAnimation> for SceneAnimation {
205    fn to_serializable(&self) -> SerializableSceneAnimation {
206        #[allow(clippy::cast_possible_truncation)]
207        SerializableSceneAnimation {
208            num_frames: self.num_frames,
209            anim_current_time_nanos: self.runner.anim_current_time.as_nanos() as u64,
210            anim_reversed: self.runner.anim_reversed,
211            nr_repetitions: self.runner.nr_repetitions,
212            paused: self.runner.paused,
213            temporary_pause: self.runner.temporary_pause,
214            fps: self.config.fps,
215            wrap_behaviour: match self.config.wrap_behaviour {
216                AnimWrap::Clamp => 0,
217                AnimWrap::Loop => 1,
218                AnimWrap::Reverse => 2,
219            },
220            angle_type: match self.config.angle_type {
221                AngleType::AxisAngle => 0,
222                AngleType::Euler => 1,
223            },
224            up_axis: match self.config.up_axis {
225                UpAxis::Y => 0,
226                UpAxis::Z => 1,
227            },
228            smpl_type: self.config.smpl_type as u8,
229            face_type: self.config.face_type as u8,
230        }
231    }
232}
233impl FromSerializable<SerializableSceneAnimation> for SceneAnimation {
234    fn from_serializable(s: &SerializableSceneAnimation) -> SceneAnimation {
235        #[allow(clippy::match_same_arms)]
236        let wrap_behaviour = match s.wrap_behaviour {
237            0 => AnimWrap::Clamp,
238            1 => AnimWrap::Loop,
239            2 => AnimWrap::Reverse,
240            _ => AnimWrap::Loop,
241        };
242        #[allow(clippy::match_same_arms)]
243        let angle_type = match s.angle_type {
244            0 => AngleType::AxisAngle,
245            1 => AngleType::Euler,
246            _ => AngleType::AxisAngle,
247        };
248        #[allow(clippy::match_same_arms)]
249        let up_axis = match s.up_axis {
250            0 => UpAxis::Y,
251            1 => UpAxis::Z,
252            _ => UpAxis::Y,
253        };
254        SceneAnimation {
255            num_frames: s.num_frames,
256            runner: AnimationRunner {
257                anim_current_time: std::time::Duration::from_nanos(s.anim_current_time_nanos),
258                anim_reversed: s.anim_reversed,
259                nr_repetitions: s.nr_repetitions,
260                paused: s.paused,
261                temporary_pause: s.temporary_pause,
262            },
263            config: AnimationConfig {
264                fps: s.fps,
265                wrap_behaviour,
266                angle_type,
267                up_axis,
268                smpl_type: SmplType::from_u8(s.smpl_type).unwrap_or(SmplType::SmplX),
269                face_type: FaceType::from_u8(s.face_type).unwrap_or(FaceType::SmplX),
270            },
271        }
272    }
273}
274/// Serializable version of `TransformSequence` component
275#[derive(Clone, Debug, Serialize, Deserialize)]
276pub struct SerializableTransformSequence {
277    pub translations_shape: (usize, usize),
278    pub translations_data: Vec<f32>,
279    pub rotations_shape: (usize, usize),
280    pub rotations_data: Vec<f32>,
281    pub scales_shape: usize,
282    pub scales_data: Vec<f32>,
283}
284impl ToSerializable<SerializableTransformSequence> for TransformSequence {
285    fn to_serializable(&self) -> SerializableTransformSequence {
286        SerializableTransformSequence {
287            translations_shape: self.translations.dim(),
288            translations_data: self.translations.as_slice().unwrap().to_vec(),
289            rotations_shape: self.rotations.dim(),
290            rotations_data: self.rotations.as_slice().unwrap().to_vec(),
291            scales_shape: self.scales.len(),
292            scales_data: self.scales.as_slice().unwrap().to_vec(),
293        }
294    }
295}
296impl FromSerializable<SerializableTransformSequence> for TransformSequence {
297    fn from_serializable(s: &SerializableTransformSequence) -> TransformSequence {
298        TransformSequence {
299            translations: ndarray::Array2::from_shape_vec(s.translations_shape, s.translations_data.clone()).unwrap(),
300            rotations: ndarray::Array2::from_shape_vec(s.rotations_shape, s.rotations_data.clone()).unwrap(),
301            scales: ndarray::Array1::from(s.scales_data.clone()),
302        }
303    }
304}
305gloss_renderer::impl_network_sendable_and_receivable!(
306    SerializableSmplParams,
307    SerializableBetas,
308    SerializableAnimation,
309    SerializableGlossInterop,
310    SerializableSceneAnimation,
311    SerializableTransformSequence,
312);