comparison 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
comparison
equal deleted inserted replaced
786:7e940ebeb5fd 787:7f9b3f5001c2
15 Formula::InvertPower2 => 2. * x - x * x, 15 Formula::InvertPower2 => 2. * x - x * x,
16 } 16 }
17 } 17 }
18 } 18 }
19 19
20 macro_rules! generate_interpolator { 20 #[derive(Debug, Clone)]
21 ($name:ident, $n:tt) => { 21 pub(crate) struct Interpolator<T, const N: usize> {
22 #[derive(Debug, Clone)] 22 start_values: [T; N],
23 pub(crate) struct $name<T> { 23 end_values: [T; N],
24 start_values: [T; $n], 24 start_frame: u32,
25 end_values: [T; $n], 25 end_frame: u32,
26 start_frame: u32, 26 formula: Formula,
27 end_frame: u32,
28 formula: Formula,
29 }
30
31 impl<T> $name<T>
32 where f32: From<T>,
33 T: From<f32>,
34 T: std::ops::Sub<Output = T>,
35 T: std::ops::Add<Output = T>,
36 T: Copy,
37 T: Default,
38 {
39 pub fn new(start_values: [T; $n], start_frame: u32, end_values: [T; $n], end_frame: u32, formula: Formula) -> $name<T> {
40 $name {
41 start_values,
42 end_values,
43 start_frame,
44 end_frame,
45 formula,
46 }
47 }
48
49 pub fn set_start(&mut self, frame: u32, values: [T; $n]) {
50 self.start_values = values;
51 self.start_frame = frame;
52 }
53
54 pub fn set_end(&mut self, frame: u32, values: [T; $n]) {
55 self.end_values = values;
56 self.end_frame = frame;
57 }
58
59 pub fn set_end_values(&mut self, values: [T; $n]) {
60 self.end_values = values;
61 }
62
63 pub fn set_end_frame(&mut self, frame: u32) {
64 self.end_frame = frame;
65 }
66
67 // XXX: Make it return [T; $n] instead, we don’t want to only do f32 here.
68 pub fn values(&self, frame: u32) -> [f32; $n] {
69 if frame + 1 >= self.end_frame {
70 // XXX: skip the last interpolation step.
71 // This bug is replicated from the original game.
72 //self.start_frame = self.end_frame;
73 //self.end_values
74 let mut values: [f32; $n] = [Default::default(); $n];
75 for (i, value) in self.end_values.iter().enumerate() {
76 values[i] = f32::from(*value);
77 }
78 values
79 } else {
80 let mut coeff = (frame - self.start_frame) as f32 / (self.end_frame - self.start_frame) as f32;
81 coeff = self.formula.apply(coeff);
82 let mut values: [f32; $n] = [Default::default(); $n];
83 for (i, (start, end)) in self.start_values.iter().zip(&self.end_values).enumerate() {
84 values[i] = f32::from(*start + T::from(coeff * f32::from(*end - *start)));
85 }
86 values
87 }
88 }
89 }
90 };
91 } 27 }
92 28
93 generate_interpolator!(Interpolator1, 1); 29 impl<T, const N: usize> Interpolator<T, N>
94 generate_interpolator!(Interpolator2, 2); 30 where f32: From<T>,
95 generate_interpolator!(Interpolator3, 3); 31 T: From<f32>,
96 //generate_interpolator!(Interpolator4, 4); 32 T: std::ops::Sub<Output = T>,
33 T: std::ops::Add<Output = T>,
34 T: Copy,
35 T: Default,
36 {
37 pub fn new(start_values: [T; N], start_frame: u32, end_values: [T; N], end_frame: u32, formula: Formula) -> Interpolator<T, N> {
38 Interpolator {
39 start_values,
40 end_values,
41 start_frame,
42 end_frame,
43 formula,
44 }
45 }
46
47 pub fn set_start(&mut self, frame: u32, values: [T; N]) {
48 self.start_values = values;
49 self.start_frame = frame;
50 }
51
52 pub fn set_end(&mut self, frame: u32, values: [T; N]) {
53 self.end_values = values;
54 self.end_frame = frame;
55 }
56
57 pub fn set_end_values(&mut self, values: [T; N]) {
58 self.end_values = values;
59 }
60
61 pub fn set_end_frame(&mut self, frame: u32) {
62 self.end_frame = frame;
63 }
64
65 // XXX: Make it return [T; N] instead, we don’t want to only do f32 here.
66 pub fn values(&self, frame: u32) -> [f32; N] {
67 if frame + 1 >= self.end_frame {
68 // XXX: skip the last interpolation step.
69 // This bug is replicated from the original game.
70 //self.start_frame = self.end_frame;
71 //self.end_values
72 let mut values: [f32; N] = [Default::default(); N];
73 for (i, value) in self.end_values.iter().enumerate() {
74 values[i] = f32::from(*value);
75 }
76 values
77 } else {
78 let mut coeff = (frame - self.start_frame) as f32 / (self.end_frame - self.start_frame) as f32;
79 coeff = self.formula.apply(coeff);
80 let mut values: [f32; N] = [Default::default(); N];
81 for (i, (start, end)) in self.start_values.iter().zip(&self.end_values).enumerate() {
82 values[i] = f32::from(*start + T::from(coeff * f32::from(*end - *start)));
83 }
84 values
85 }
86 }
87 }