smpl_gloss_integration/
scene.rs1use crate::components::GlossInterop;
2use gloss_hecs::EntityBuilder;
3use gloss_renderer::components::{Name, VisMesh};
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 smpl_utils::numerical::hex_to_rgb_f32;
16use std::time::Duration;
17const COLOR_CODES: [&str; 4] = ["#63D4BF", "#BAC2F7", "#FFEF9E", "#72B0C5"];
18pub trait McsCodecGloss {
20 fn to_entity_builders(&mut self) -> Vec<EntityBuilder>;
21}
22impl McsCodecGloss for McsCodec {
24 #[allow(clippy::cast_precision_loss)]
25 fn to_entity_builders(&mut self) -> Vec<EntityBuilder> {
26 let mut builders: Vec<EntityBuilder> = Vec::new();
27 if let Some(camera_track) = &self.camera_track {
28 let mut camera_builder = EntityBuilder::new();
29 camera_builder.add(Name("TrackedCamera".to_string()));
30 camera_builder.add(camera_track.clone());
31 builders.push(camera_builder);
32 }
33 for (i, smpl_body) in self.smpl_bodies.iter().enumerate() {
34 let start_offset = smpl_body.frame_presence[0];
35 let fps = smpl_body.codec.frame_rate.unwrap();
36 self.frame_rate = fps;
37 let color = hex_to_rgb_f32(COLOR_CODES[i % COLOR_CODES.len()]);
38 let mut builder = EntityBuilder::new();
39 let smpl_params = SmplParams::new_from_smpl_codec(&smpl_body.codec);
40 info!("Found smpl_params in the .smpl file");
41 builder.add(smpl_params);
42 if let Some(mut betas) = Betas::new_from_smpl_codec(&smpl_body.codec) {
43 info!("Found betas in the .smpl file");
44 let trimmed_betas = betas.betas.slice(s![..10]).to_owned();
45 betas.betas = trimmed_betas;
46 builder.add(betas);
47 }
48 if let Some(mut anim) = Animation::new_from_smpl_codec(&smpl_body.codec, AnimWrap::Clamp) {
49 anim.start_offset = start_offset;
50 builder.add(anim);
51 }
52 let pose_override = PoseOverride::allow_all();
53 builder.add(pose_override);
54 builder.add(GlossInterop { with_uv: true });
55 builder.add(VisMesh {
56 solid_color: nalgebra::Vector4::<f32>::new(color.0, color.1, color.2, 1.0),
57 ..Default::default()
58 });
59 builders.push(builder);
60 }
61 builders
62 }
63}
64#[derive(Default)]
65pub struct SceneAnimation {
66 pub num_frames: usize,
67 pub runner: AnimationRunner,
68 pub config: AnimationConfig,
69}
70impl SceneAnimation {
71 pub fn new(num_frames: usize) -> Self {
72 Self {
73 num_frames,
74 runner: AnimationRunner::default(),
75 config: AnimationConfig::default(),
76 }
77 }
78 pub fn new_with_fps(num_frames: usize, fps: f32) -> Self {
79 Self {
80 num_frames,
81 runner: AnimationRunner::default(),
82 config: AnimationConfig { fps, ..Default::default() },
83 }
84 }
85 pub fn new_with_config(num_frames: usize, config: AnimationConfig) -> Self {
86 Self {
87 num_frames,
88 runner: AnimationRunner::default(),
89 config,
90 }
91 }
92 #[allow(clippy::cast_precision_loss)]
93 pub fn duration(&self) -> Duration {
94 Duration::from_secs_f32(self.num_frames as f32 / self.config.fps)
95 }
96 pub fn get_cur_time(&self) -> Duration {
97 self.runner.anim_current_time
98 }
99 pub fn set_cur_time_as_sec(&mut self, time_sec: f32) {
100 self.runner.anim_current_time = Duration::from_secs_f32(time_sec);
101 }
102 pub fn is_finished(&self) -> bool {
103 self.config.wrap_behaviour == AnimWrap::Clamp && self.runner.anim_current_time >= self.duration()
104 }
105 pub fn advance(&mut self, dt_raw: Duration, first_time: bool) {
108 let duration = self.duration();
109 let runner = &mut self.runner;
110 let config = &self.config;
111 let mut dt = dt_raw;
112 if first_time {
113 dt = Duration::ZERO;
114 }
115 let will_overflow = runner.anim_current_time + dt > duration;
116 let will_underflow = runner.anim_current_time < dt && runner.anim_reversed;
117 if will_overflow || will_underflow {
118 if will_overflow {
119 match config.wrap_behaviour {
120 AnimWrap::Clamp => {
121 dt = Duration::ZERO;
122 runner.anim_current_time = duration;
123 }
124 AnimWrap::Loop => {
125 dt = Duration::from_secs_f64(dt.as_secs_f64() % duration.as_secs_f64());
126 runner.anim_current_time = Duration::ZERO;
127 runner.nr_repetitions += 1;
128 }
129 AnimWrap::Reverse => {
130 dt = Duration::from_secs_f64(dt.as_secs_f64() % duration.as_secs_f64());
131 runner.anim_current_time = duration;
132 runner.anim_reversed = !runner.anim_reversed;
133 runner.nr_repetitions += 1;
134 }
135 }
136 } else {
137 match config.wrap_behaviour {
138 AnimWrap::Clamp => {
139 dt = Duration::ZERO;
140 runner.anim_current_time = Duration::ZERO;
141 }
142 AnimWrap::Loop => {
143 dt = Duration::from_secs_f64(dt.as_secs_f64() % duration.as_secs_f64());
144 runner.anim_current_time = duration;
145 runner.nr_repetitions += 1;
146 }
147 AnimWrap::Reverse => {
148 dt = Duration::from_secs_f64(dt.as_secs_f64() % duration.as_secs_f64());
149 runner.anim_reversed = !runner.anim_reversed;
150 runner.nr_repetitions += 1;
151 }
152 }
153 }
154 }
155 if runner.anim_reversed {
156 runner.anim_current_time = runner.anim_current_time.saturating_sub(dt);
157 } else {
158 runner.anim_current_time = runner.anim_current_time.saturating_add(dt);
159 }
160 }
161}