Mercurial > touhou
comparison interpreters/src/th06/interpolator.rs @ 757:21b186be2590
Split the Rust version into multiple crates.
author | Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> |
---|---|
date | Tue, 05 Jan 2021 02:16:32 +0100 |
parents | src/th06/interpolator.rs@5016c09e5d7c |
children |
comparison
equal
deleted
inserted
replaced
756:4d91790cf8ab | 757:21b186be2590 |
---|---|
1 //! Animation runner. | |
2 | |
3 #[derive(Debug, Clone, Copy, PartialEq)] | |
4 pub(crate) enum Formula { | |
5 Linear, | |
6 Power2, | |
7 InvertPower2, | |
8 } | |
9 | |
10 impl Formula { | |
11 fn apply(&self, x: f32) -> f32 { | |
12 match self { | |
13 Formula::Linear => x, | |
14 Formula::Power2 => x * x, | |
15 Formula::InvertPower2 => 2. * x - x * x, | |
16 } | |
17 } | |
18 } | |
19 | |
20 macro_rules! generate_interpolator { | |
21 ($name:ident, $n:tt) => { | |
22 #[derive(Debug, Clone)] | |
23 pub(crate) struct $name<T> { | |
24 start_values: [T; $n], | |
25 end_values: [T; $n], | |
26 start_frame: u32, | |
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 } | |
92 | |
93 generate_interpolator!(Interpolator1, 1); | |
94 generate_interpolator!(Interpolator2, 2); | |
95 generate_interpolator!(Interpolator3, 3); | |
96 //generate_interpolator!(Interpolator4, 4); |