1#[derive(Debug, Clone, Copy)]
8pub struct Keyframe<'a> {
9 pub vertices: &'a [[f32; 3]],
10 pub time: f32,
11}
12
13#[derive(Debug)]
15pub struct VertexAnimation<'a> {
16 keyframes: &'a [Keyframe<'a>],
17 looping: bool,
18}
19
20impl<'a> VertexAnimation<'a> {
21 pub fn new(keyframes: &'a [Keyframe<'a>], looping: bool) -> Self {
30 assert!(!keyframes.is_empty(), "Keyframes array cannot be empty");
31
32 let vertex_count = keyframes[0].vertices.len();
34 for kf in keyframes.iter() {
35 assert_eq!(
36 kf.vertices.len(),
37 vertex_count,
38 "All keyframes must have the same number of vertices"
39 );
40 }
41
42 Self { keyframes, looping }
43 }
44
45 pub fn sample(&self, time: f32, output: &mut [[f32; 3]]) {
54 assert_eq!(
55 output.len(),
56 self.keyframes[0].vertices.len(),
57 "Output buffer size must match keyframe vertex count"
58 );
59
60 if self.keyframes.len() == 1 {
62 output.copy_from_slice(self.keyframes[0].vertices);
63 return;
64 }
65
66 let duration = self.keyframes.last().unwrap().time;
68
69 let t = if self.looping {
71 if duration > 0.0 { time % duration } else { 0.0 }
72 } else {
73 time.clamp(0.0, duration)
74 };
75
76 let mut kf1_idx = 0;
78 let mut kf2_idx = 0;
79
80 for (i, kf) in self.keyframes.iter().enumerate() {
81 if kf.time <= t {
82 kf1_idx = i;
83 }
84 if kf.time >= t {
85 kf2_idx = i;
86 break;
87 }
88 }
89
90 if kf1_idx == self.keyframes.len() - 1 {
92 output.copy_from_slice(self.keyframes[kf1_idx].vertices);
93 return;
94 }
95
96 let kf1 = &self.keyframes[kf1_idx];
97 let kf2 = &self.keyframes[kf2_idx];
98
99 let alpha = if kf2.time > kf1.time {
101 (t - kf1.time) / (kf2.time - kf1.time)
102 } else {
103 0.0
104 };
105
106 for (i, out_vertex) in output.iter_mut().enumerate() {
108 let v1 = &kf1.vertices[i];
109 let v2 = &kf2.vertices[i];
110
111 out_vertex[0] = v1[0] + alpha * (v2[0] - v1[0]);
112 out_vertex[1] = v1[1] + alpha * (v2[1] - v1[1]);
113 out_vertex[2] = v1[2] + alpha * (v2[2] - v1[2]);
114 }
115 }
116
117 pub fn duration(&self) -> f32 {
119 self.keyframes.last().map(|kf| kf.time).unwrap_or(0.0)
120 }
121
122 pub fn keyframe_count(&self) -> usize {
124 self.keyframes.len()
125 }
126}
127
128#[cfg(test)]
129mod tests {
130 extern crate std;
131 use super::*;
132
133 #[test]
134 fn test_single_keyframe() {
135 let vertices = [[0.0, 0.0, 0.0], [1.0, 0.0, 0.0]];
136 let kf = Keyframe {
137 vertices: &vertices,
138 time: 0.0,
139 };
140 let keyframes = [kf];
141 let anim = VertexAnimation::new(&keyframes, false);
142
143 let mut output = [[0.0, 0.0, 0.0]; 2];
144 anim.sample(0.5, &mut output);
145
146 assert_eq!(output[0], [0.0, 0.0, 0.0]);
147 assert_eq!(output[1], [1.0, 0.0, 0.0]);
148 }
149
150 #[test]
151 fn test_two_keyframe_interpolation() {
152 let vertices1 = [[0.0, 0.0, 0.0], [1.0, 0.0, 0.0]];
153 let vertices2 = [[0.0, 2.0, 0.0], [1.0, 2.0, 0.0]];
154
155 let kf1 = Keyframe {
156 vertices: &vertices1,
157 time: 0.0,
158 };
159 let kf2 = Keyframe {
160 vertices: &vertices2,
161 time: 1.0,
162 };
163
164 let keyframes = [kf1, kf2];
165 let anim = VertexAnimation::new(&keyframes, false);
166
167 let mut output = [[0.0, 0.0, 0.0]; 2];
169 anim.sample(0.5, &mut output);
170
171 assert_eq!(output[0], [0.0, 1.0, 0.0]);
172 assert_eq!(output[1], [1.0, 1.0, 0.0]);
173 }
174
175 #[test]
176 fn test_looping_animation() {
177 let vertices1 = [[0.0, 0.0, 0.0]];
178 let vertices2 = [[1.0, 0.0, 0.0]];
179
180 let kf1 = Keyframe {
181 vertices: &vertices1,
182 time: 0.0,
183 };
184 let kf2 = Keyframe {
185 vertices: &vertices2,
186 time: 1.0,
187 };
188
189 let keyframes = [kf1, kf2];
190 let anim = VertexAnimation::new(&keyframes, true);
191
192 let mut output = [[0.0, 0.0, 0.0]; 1];
194 anim.sample(1.5, &mut output);
195
196 assert_eq!(output[0], [0.5, 0.0, 0.0]);
198 }
199
200 #[test]
201 fn test_clamping_non_looping() {
202 let vertices1 = [[0.0, 0.0, 0.0]];
203 let vertices2 = [[1.0, 0.0, 0.0]];
204
205 let kf1 = Keyframe {
206 vertices: &vertices1,
207 time: 0.0,
208 };
209 let kf2 = Keyframe {
210 vertices: &vertices2,
211 time: 1.0,
212 };
213
214 let keyframes = [kf1, kf2];
215 let anim = VertexAnimation::new(&keyframes, false);
216
217 let mut output = [[0.0, 0.0, 0.0]; 1];
219 anim.sample(2.0, &mut output);
220
221 assert_eq!(output[0], [1.0, 0.0, 0.0]);
222 }
223
224 #[test]
225 fn test_duration() {
226 let vertices1 = [[0.0, 0.0, 0.0]];
227 let vertices2 = [[1.0, 0.0, 0.0]];
228
229 let kf1 = Keyframe {
230 vertices: &vertices1,
231 time: 0.0,
232 };
233 let kf2 = Keyframe {
234 vertices: &vertices2,
235 time: 2.5,
236 };
237
238 let keyframes = [kf1, kf2];
239 let anim = VertexAnimation::new(&keyframes, false);
240 assert_eq!(anim.duration(), 2.5);
241 assert_eq!(anim.keyframe_count(), 2);
242 }
243
244 #[test]
245 #[should_panic(expected = "Keyframes array cannot be empty")]
246 fn test_empty_keyframes_panics() {
247 let keyframes: &[Keyframe] = &[];
248 let _anim = VertexAnimation::new(keyframes, false);
249 }
250
251 #[test]
252 #[should_panic(expected = "All keyframes must have the same number of vertices")]
253 fn test_inconsistent_vertex_count_panics() {
254 let vertices1 = [[0.0, 0.0, 0.0]];
255 let vertices2 = [[1.0, 0.0, 0.0], [2.0, 0.0, 0.0]];
256
257 let kf1 = Keyframe {
258 vertices: &vertices1,
259 time: 0.0,
260 };
261 let kf2 = Keyframe {
262 vertices: &vertices2,
263 time: 1.0,
264 };
265
266 let keyframes = [kf1, kf2];
267 let _anim = VertexAnimation::new(&keyframes, false);
268 }
269}