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