Mercurial > touhou
annotate interpreters/src/th06/interpolator.rs @ 787:7f9b3f5001c2
interpreters: Make Interpolator generic over N
This was a workaround for Rust < 1.51 which didn’t support const generics yet,
but we’ve had tat for close to five years now!
| author | Link Mauve <linkmauve@linkmauve.fr> |
|---|---|
| date | Mon, 15 Dec 2025 11:34:58 +0100 |
| parents | 21b186be2590 |
| children |
| rev | line source |
|---|---|
|
642
9e40bd5cc26d
Move interpolators in another module.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
1 //! Animation runner. |
|
9e40bd5cc26d
Move interpolators in another module.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
2 |
|
9e40bd5cc26d
Move interpolators in another module.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
3 #[derive(Debug, Clone, Copy, PartialEq)] |
|
9e40bd5cc26d
Move interpolators in another module.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
4 pub(crate) enum Formula { |
|
9e40bd5cc26d
Move interpolators in another module.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
5 Linear, |
|
9e40bd5cc26d
Move interpolators in another module.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
6 Power2, |
|
9e40bd5cc26d
Move interpolators in another module.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
7 InvertPower2, |
|
9e40bd5cc26d
Move interpolators in another module.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
8 } |
|
9e40bd5cc26d
Move interpolators in another module.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
9 |
|
9e40bd5cc26d
Move interpolators in another module.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
10 impl Formula { |
|
9e40bd5cc26d
Move interpolators in another module.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
11 fn apply(&self, x: f32) -> f32 { |
|
9e40bd5cc26d
Move interpolators in another module.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
12 match self { |
|
9e40bd5cc26d
Move interpolators in another module.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
13 Formula::Linear => x, |
|
9e40bd5cc26d
Move interpolators in another module.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
14 Formula::Power2 => x * x, |
|
9e40bd5cc26d
Move interpolators in another module.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
15 Formula::InvertPower2 => 2. * x - x * x, |
|
9e40bd5cc26d
Move interpolators in another module.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
16 } |
|
9e40bd5cc26d
Move interpolators in another module.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
17 } |
|
9e40bd5cc26d
Move interpolators in another module.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
18 } |
|
9e40bd5cc26d
Move interpolators in another module.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
19 |
|
787
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
20 #[derive(Debug, Clone)] |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
21 pub(crate) struct Interpolator<T, const N: usize> { |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
22 start_values: [T; N], |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
23 end_values: [T; N], |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
24 start_frame: u32, |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
25 end_frame: u32, |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
26 formula: Formula, |
|
642
9e40bd5cc26d
Move interpolators in another module.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
27 } |
|
9e40bd5cc26d
Move interpolators in another module.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
28 |
|
787
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
29 impl<T, const N: usize> Interpolator<T, N> |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
30 where f32: From<T>, |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
31 T: From<f32>, |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
32 T: std::ops::Sub<Output = T>, |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
33 T: std::ops::Add<Output = T>, |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
34 T: Copy, |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
35 T: Default, |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
36 { |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
37 pub fn new(start_values: [T; N], start_frame: u32, end_values: [T; N], end_frame: u32, formula: Formula) -> Interpolator<T, N> { |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
38 Interpolator { |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
39 start_values, |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
40 end_values, |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
41 start_frame, |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
42 end_frame, |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
43 formula, |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
44 } |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
45 } |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
46 |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
47 pub fn set_start(&mut self, frame: u32, values: [T; N]) { |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
48 self.start_values = values; |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
49 self.start_frame = frame; |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
50 } |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
51 |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
52 pub fn set_end(&mut self, frame: u32, values: [T; N]) { |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
53 self.end_values = values; |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
54 self.end_frame = frame; |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
55 } |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
56 |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
57 pub fn set_end_values(&mut self, values: [T; N]) { |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
58 self.end_values = values; |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
59 } |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
60 |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
61 pub fn set_end_frame(&mut self, frame: u32) { |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
62 self.end_frame = frame; |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
63 } |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
64 |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
65 // XXX: Make it return [T; N] instead, we don’t want to only do f32 here. |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
66 pub fn values(&self, frame: u32) -> [f32; N] { |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
67 if frame + 1 >= self.end_frame { |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
68 // XXX: skip the last interpolation step. |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
69 // This bug is replicated from the original game. |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
70 //self.start_frame = self.end_frame; |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
71 //self.end_values |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
72 let mut values: [f32; N] = [Default::default(); N]; |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
73 for (i, value) in self.end_values.iter().enumerate() { |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
74 values[i] = f32::from(*value); |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
75 } |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
76 values |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
77 } else { |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
78 let mut coeff = (frame - self.start_frame) as f32 / (self.end_frame - self.start_frame) as f32; |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
79 coeff = self.formula.apply(coeff); |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
80 let mut values: [f32; N] = [Default::default(); N]; |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
81 for (i, (start, end)) in self.start_values.iter().zip(&self.end_values).enumerate() { |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
82 values[i] = f32::from(*start + T::from(coeff * f32::from(*end - *start))); |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
83 } |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
84 values |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
85 } |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
86 } |
|
7f9b3f5001c2
interpreters: Make Interpolator generic over N
Link Mauve <linkmauve@linkmauve.fr>
parents:
757
diff
changeset
|
87 } |
