Skip to main content

ass_renderer/utils/
math.rs

1//! Math utilities for transformations and interpolation
2
3/// 3x3 transformation matrix
4#[derive(Debug, Clone, Copy)]
5pub struct Matrix3x3 {
6    /// Matrix elements in row-major order
7    pub m: [[f32; 3]; 3],
8}
9
10impl Matrix3x3 {
11    /// Create identity matrix
12    pub fn identity() -> Self {
13        Self {
14            m: [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]],
15        }
16    }
17
18    /// Create translation matrix
19    pub fn translate(x: f32, y: f32) -> Self {
20        Self {
21            m: [[1.0, 0.0, x], [0.0, 1.0, y], [0.0, 0.0, 1.0]],
22        }
23    }
24
25    /// Create scale matrix
26    pub fn scale(sx: f32, sy: f32) -> Self {
27        Self {
28            m: [[sx, 0.0, 0.0], [0.0, sy, 0.0], [0.0, 0.0, 1.0]],
29        }
30    }
31
32    /// Create rotation matrix (angle in radians)
33    pub fn rotate(angle: f32) -> Self {
34        let cos = angle.cos();
35        let sin = angle.sin();
36        Self {
37            m: [[cos, -sin, 0.0], [sin, cos, 0.0], [0.0, 0.0, 1.0]],
38        }
39    }
40
41    /// Multiply two matrices
42    pub fn multiply(&self, other: &Self) -> Self {
43        let mut result = Self::identity();
44        for i in 0..3 {
45            for j in 0..3 {
46                result.m[i][j] = 0.0;
47                for k in 0..3 {
48                    result.m[i][j] += self.m[i][k] * other.m[k][j];
49                }
50            }
51        }
52        result
53    }
54
55    /// Transform a point
56    pub fn transform_point(&self, x: f32, y: f32) -> (f32, f32) {
57        let tx = self.m[0][0] * x + self.m[0][1] * y + self.m[0][2];
58        let ty = self.m[1][0] * x + self.m[1][1] * y + self.m[1][2];
59        (tx, ty)
60    }
61}
62
63impl Default for Matrix3x3 {
64    fn default() -> Self {
65        Self::identity()
66    }
67}
68
69/// 2D transformation
70#[derive(Debug, Clone, Copy)]
71pub struct Transform2D {
72    /// Translation X
73    pub tx: f32,
74    /// Translation Y
75    pub ty: f32,
76    /// Scale X
77    pub sx: f32,
78    /// Scale Y
79    pub sy: f32,
80    /// Rotation angle in radians
81    pub rotation: f32,
82    /// Shear X
83    pub shear_x: f32,
84    /// Shear Y
85    pub shear_y: f32,
86}
87
88impl Transform2D {
89    /// Create identity transform
90    pub fn identity() -> Self {
91        Self {
92            tx: 0.0,
93            ty: 0.0,
94            sx: 1.0,
95            sy: 1.0,
96            rotation: 0.0,
97            shear_x: 0.0,
98            shear_y: 0.0,
99        }
100    }
101
102    /// Convert to matrix
103    pub fn to_matrix(&self) -> Matrix3x3 {
104        let translate = Matrix3x3::translate(self.tx, self.ty);
105        let scale = Matrix3x3::scale(self.sx, self.sy);
106        let rotate = Matrix3x3::rotate(self.rotation);
107
108        translate.multiply(&rotate).multiply(&scale)
109    }
110
111    /// Interpolate between two transforms
112    pub fn lerp(&self, other: &Self, t: f32) -> Self {
113        Self {
114            tx: lerp(self.tx, other.tx, t),
115            ty: lerp(self.ty, other.ty, t),
116            sx: lerp(self.sx, other.sx, t),
117            sy: lerp(self.sy, other.sy, t),
118            rotation: lerp(self.rotation, other.rotation, t),
119            shear_x: lerp(self.shear_x, other.shear_x, t),
120            shear_y: lerp(self.shear_y, other.shear_y, t),
121        }
122    }
123}
124
125impl Default for Transform2D {
126    fn default() -> Self {
127        Self::identity()
128    }
129}
130
131/// Linear interpolation
132pub fn lerp(a: f32, b: f32, t: f32) -> f32 {
133    a + (b - a) * t
134}
135
136/// Cubic bezier interpolation (for animation curves)
137pub fn cubic_bezier(t: f32, p1: f32, p2: f32) -> f32 {
138    // Using ass-core's eval_cubic_bezier would be better here
139    // This is a simplified version
140    let t2 = t * t;
141    let t3 = t2 * t;
142    let mt = 1.0 - t;
143    let mt2 = mt * mt;
144    let mt3 = mt2 * mt;
145
146    mt3 * 0.0 + 3.0 * mt2 * t * p1 + 3.0 * mt * t2 * p2 + t3 * 1.0
147}