Mercurial > touhou
view 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 |
line wrap: on
line source
//! Animation runner. #[derive(Debug, Clone, Copy, PartialEq)] pub(crate) enum Formula { Linear, Power2, InvertPower2, } impl Formula { fn apply(&self, x: f32) -> f32 { match self { Formula::Linear => x, Formula::Power2 => x * x, Formula::InvertPower2 => 2. * x - x * x, } } } macro_rules! generate_interpolator { ($name:ident, $n:tt) => { #[derive(Debug, Clone)] pub(crate) struct $name<T> { start_values: [T; $n], end_values: [T; $n], start_frame: u32, end_frame: u32, formula: Formula, } impl<T> $name<T> where f32: From<T>, T: From<f32>, T: std::ops::Sub<Output = T>, T: std::ops::Add<Output = T>, T: Copy, T: Default, { pub fn new(start_values: [T; $n], start_frame: u32, end_values: [T; $n], end_frame: u32, formula: Formula) -> $name<T> { $name { start_values, end_values, start_frame, end_frame, formula, } } pub fn set_start(&mut self, frame: u32, values: [T; $n]) { self.start_values = values; self.start_frame = frame; } pub fn set_end(&mut self, frame: u32, values: [T; $n]) { self.end_values = values; self.end_frame = frame; } pub fn set_end_values(&mut self, values: [T; $n]) { self.end_values = values; } pub fn set_end_frame(&mut self, frame: u32) { self.end_frame = frame; } // XXX: Make it return [T; $n] instead, we don’t want to only do f32 here. pub fn values(&self, frame: u32) -> [f32; $n] { if frame + 1 >= self.end_frame { // XXX: skip the last interpolation step. // This bug is replicated from the original game. //self.start_frame = self.end_frame; //self.end_values let mut values: [f32; $n] = [Default::default(); $n]; for (i, value) in self.end_values.iter().enumerate() { values[i] = f32::from(*value); } values } else { let mut coeff = (frame - self.start_frame) as f32 / (self.end_frame - self.start_frame) as f32; coeff = self.formula.apply(coeff); let mut values: [f32; $n] = [Default::default(); $n]; for (i, (start, end)) in self.start_values.iter().zip(&self.end_values).enumerate() { values[i] = f32::from(*start + T::from(coeff * f32::from(*end - *start))); } values } } } }; } generate_interpolator!(Interpolator1, 1); generate_interpolator!(Interpolator2, 2); generate_interpolator!(Interpolator3, 3); //generate_interpolator!(Interpolator4, 4);