smpl_gloss_integration/
scene.rs

1use crate::components::GlossInterop;
2use gloss_hecs::EntityBuilder;
3use gloss_renderer::components::Name;
4use log::info;
5use ndarray::s;
6use smpl_rs::{
7    codec::scene::McsCodec,
8    common::{
9        animation::{AnimWrap, Animation, AnimationConfig, AnimationRunner},
10        betas::Betas,
11        smpl_params::SmplParams,
12    },
13};
14use std::time::Duration;
15/// creates a ``Vec<gloss_hecs::EntityBuilder>`` from the ``McsCodec``
16/// TODO: Treat Camera tracks like an entity and this should be in the Vec
17pub trait McsCodecGloss {
18    fn to_entity_builders(&mut self) -> Vec<EntityBuilder>;
19}
20/// Trait implementation for `McsCodec`
21impl McsCodecGloss for McsCodec {
22    #[allow(clippy::cast_precision_loss)]
23    fn to_entity_builders(&mut self) -> Vec<EntityBuilder> {
24        let mut builders: Vec<EntityBuilder> = Vec::new();
25        if let Some(camera_track) = &self.camera_track {
26            let mut camera_builder = EntityBuilder::new();
27            camera_builder.add(Name("TrackedCamera".to_string()));
28            camera_builder.add(camera_track.clone());
29            builders.push(camera_builder);
30        }
31        for smpl_body in self.smpl_bodies.iter() {
32            let start_offset = smpl_body.frame_presence[0];
33            let fps = smpl_body.codec.frame_rate.unwrap();
34            self.frame_rate = fps;
35            let mut builder = EntityBuilder::new();
36            let smpl_params = SmplParams::new_from_smpl_codec(&smpl_body.codec);
37            info!("Found smpl_params in the .smpl file");
38            builder.add(smpl_params);
39            if let Some(mut betas) = Betas::new_from_smpl_codec(&smpl_body.codec) {
40                info!("Found betas in the .smpl file");
41                let trimmed_betas = betas.betas.slice(s![..10]).to_owned();
42                betas.betas = trimmed_betas;
43                builder.add(betas);
44            }
45            if let Some(mut anim) = Animation::new_from_smpl_codec(&smpl_body.codec, AnimWrap::Clamp) {
46                anim.start_offset = start_offset;
47                builder.add(anim);
48            }
49            builder.add(GlossInterop { with_uv: true });
50            builders.push(builder);
51        }
52        builders
53    }
54}
55#[derive(Default)]
56pub struct SceneAnimation {
57    pub num_frames: usize,
58    pub runner: AnimationRunner,
59    pub config: AnimationConfig,
60}
61impl SceneAnimation {
62    pub fn new(num_frames: usize) -> Self {
63        Self {
64            num_frames,
65            runner: AnimationRunner::default(),
66            config: AnimationConfig::default(),
67        }
68    }
69    pub fn new_with_fps(num_frames: usize, fps: f32) -> Self {
70        Self {
71            num_frames,
72            runner: AnimationRunner::default(),
73            config: AnimationConfig { fps, ..Default::default() },
74        }
75    }
76    pub fn new_with_config(num_frames: usize, config: AnimationConfig) -> Self {
77        Self {
78            num_frames,
79            runner: AnimationRunner::default(),
80            config,
81        }
82    }
83    #[allow(clippy::cast_precision_loss)]
84    pub fn duration(&self) -> Duration {
85        Duration::from_secs_f32(self.num_frames as f32 / self.config.fps)
86    }
87    pub fn get_cur_time(&self) -> Duration {
88        self.runner.anim_current_time
89    }
90    pub fn set_cur_time_as_sec(&mut self, time_sec: f32) {
91        self.runner.anim_current_time = Duration::from_secs_f32(time_sec);
92    }
93    pub fn is_finished(&self) -> bool {
94        self.config.wrap_behaviour == AnimWrap::Clamp && self.runner.anim_current_time >= self.duration()
95    }
96    /// Advances the animation by the amount of time elapsed since last time we
97    /// got the current pose
98    pub fn advance(&mut self, dt_raw: Duration, first_time: bool) {
99        let duration = self.duration();
100        let runner = &mut self.runner;
101        let config = &self.config;
102        let mut dt = dt_raw;
103        if first_time {
104            dt = Duration::ZERO;
105        }
106        let will_overflow = runner.anim_current_time + dt > duration;
107        let will_underflow = runner.anim_current_time < dt && runner.anim_reversed;
108        if will_overflow || will_underflow {
109            if will_overflow {
110                match config.wrap_behaviour {
111                    AnimWrap::Clamp => {
112                        dt = Duration::ZERO;
113                        runner.anim_current_time = duration;
114                    }
115                    AnimWrap::Loop => {
116                        dt = Duration::from_secs_f64(dt.as_secs_f64() % duration.as_secs_f64());
117                        runner.anim_current_time = Duration::ZERO;
118                        runner.nr_repetitions += 1;
119                    }
120                    AnimWrap::Reverse => {
121                        dt = Duration::from_secs_f64(dt.as_secs_f64() % duration.as_secs_f64());
122                        runner.anim_current_time = duration;
123                        runner.anim_reversed = !runner.anim_reversed;
124                        runner.nr_repetitions += 1;
125                    }
126                }
127            } else {
128                match config.wrap_behaviour {
129                    AnimWrap::Clamp => {
130                        dt = Duration::ZERO;
131                        runner.anim_current_time = Duration::ZERO;
132                    }
133                    AnimWrap::Loop => {
134                        dt = Duration::from_secs_f64(dt.as_secs_f64() % duration.as_secs_f64());
135                        runner.anim_current_time = duration;
136                        runner.nr_repetitions += 1;
137                    }
138                    AnimWrap::Reverse => {
139                        dt = Duration::from_secs_f64(dt.as_secs_f64() % duration.as_secs_f64());
140                        runner.anim_reversed = !runner.anim_reversed;
141                        runner.nr_repetitions += 1;
142                    }
143                }
144            }
145        }
146        if runner.anim_reversed {
147            runner.anim_current_time = runner.anim_current_time.saturating_sub(dt);
148        } else {
149            runner.anim_current_time = runner.anim_current_time.saturating_add(dt);
150        }
151    }
152}