flow_ngin/resources/
animation.rs1use std::ops::BitAnd;
2
3use gltf::animation;
4use instant::{Duration, Instant};
5
6use cgmath::{AbsDiffEq, num_traits::Float};
7
8use crate::data_structures::{instance::Instance, scene_graph::SceneNode};
9
10const EPSILON: f32 = 1e-2;
11
12#[derive(Clone, Debug)]
13pub enum Keyframes {
14 Translation(Vec<cgmath::Vector3<f32>>),
15 Rotation(Vec<cgmath::Quaternion<f32>>),
16 Scale(Vec<cgmath::Vector3<f32>>),
17 Other,
18}
19
20pub struct Animation {
21 speed: f32,
22 rep_after_sec: f32,
23 time: Instant,
24}
25
26impl<'a> Animation {
27 pub fn new(speed: f32, rep_after_sec: f32) -> Self {
28 let time = Instant::now();
29 Self {
30 speed,
31 time,
32 rep_after_sec,
33 }
34 }
35
36 pub fn set_rep_time(&mut self, new_time: f32) {
37 self.rep_after_sec = new_time;
38 }
39
40 pub fn animate(
49 &mut self,
50 graph: &'a mut Box<dyn SceneNode>,
51 anim_idx: usize,
52 instance_idx: usize,
53 ) {
54 let current_time = &mut self.time;
55 let duration = animate_graph(graph, instance_idx, anim_idx, current_time, self.speed);
56 self.set_rep_time(duration);
57
58 if self.time.elapsed().as_secs_f32() > self.rep_after_sec {
59 self.time = Instant::now();
60 }
61 }
62
63 pub fn animate_with(
74 &mut self,
75 graph: &'a mut Box<dyn SceneNode>,
76 current: &[&[usize]],
77 reference: &[&Instance],
78 idx: usize,
79 dt: Duration,
80 ) -> bool {
81 let mut all_lts = Vec::new();
82 let speed = self.speed.clone();
83
84 for (curr, ref_pos) in current.iter().zip(reference) {
85 let scene_node = curr
86 .into_iter()
87 .fold(&mut *graph, |g, &i| &mut g.get_children_mut()[i]);
88
89 if let Some(local_transform) = scene_node.get_local_transform(idx) {
90 let lt_epsilon = diff_lt_epsilon(&local_transform, ref_pos);
91 all_lts.push(lt_epsilon);
92 if !lt_epsilon {
93 let new_transform: Instance =
94 step(&local_transform, ref_pos, dt.as_secs_f32(), speed);
95 scene_node.set_local_transform(idx, new_transform);
96 }
97 } else {
98 log::warn!("Warning, animation with index {} not found.", idx)
99 }
100 }
101 all_lts.into_iter().fold(true, BitAnd::bitand)
102 }
103}
104
105fn animate_graph(
107 graph: &mut Box<dyn SceneNode>,
108 instance_idx: usize,
109 anim_idx: usize,
110 time: &mut Instant,
111 speed: f32,
112) -> f32 {
113 let current_time = time.elapsed().as_secs_f32();
114 let animations = graph.get_animation();
115 let mut longest_anim_duration = 0.0;
116 let mut current_keyframe_index = 0;
117 if let Some(animation) = &animations.get(anim_idx) {
119 if let Some(timestamp) = animation.timestamps.last() {
120 longest_anim_duration = longest_anim_duration.max(*timestamp)
121 }
122 for timestamp in &animation.timestamps {
124 if timestamp > ¤t_time {
126 break;
127 }
128 if ¤t_keyframe_index < &(&animation.timestamps.len() - 1) {
129 current_keyframe_index += 1;
130 }
131 }
132
133 let ref_pos = &animation.instances[current_keyframe_index];
135 graph.set_local_transform(instance_idx, ref_pos.clone());
136 }
137
138 for child in graph.get_children_mut() {
139 let duration = animate_graph(child, instance_idx, anim_idx, time, speed);
140 longest_anim_duration = longest_anim_duration.max(duration);
141 }
142 longest_anim_duration
143}
144
145fn step(fst: &Instance, snd: &Instance, dt: f32, speed: f32) -> Instance {
147 let position = fst.position + (snd.position - fst.position) * dt * speed;
148 let rotation = fst.rotation.nlerp(snd.rotation, dt * speed);
149 let scale = fst.scale + (snd.scale - fst.scale) * dt * speed;
150
151 Instance {
152 position,
153 rotation,
154 scale,
155 }
156}
157
158fn diff_lt_epsilon(fst: &Instance, snd: &Instance) -> bool {
159 let pos_diff = fst.position.abs_diff_eq(&snd.position, EPSILON);
160 let rot_diff = fst.rotation.abs_diff_eq(&snd.rotation, EPSILON);
161 let scale_diff = fst.scale.abs_diff_eq(&snd.scale, EPSILON);
162 pos_diff && rot_diff && scale_diff
163}