smpl_gloss_integration/
scene.rs1use 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;
15pub trait McsCodecGloss {
18 fn to_entity_builders(&mut self) -> Vec<EntityBuilder>;
19}
20impl 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 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}