optic_render/util/transform/
trans2d.rs1use cgmath::*;
2
3#[derive(Clone, Debug)]
34pub struct Transform2D {
35 matrix: Matrix4<f32>,
36 pos: Vector2<f32>,
37 rot: f32,
38 layer: u8,
39 aspect: f32,
40 scale: Vector2<f32>,
41}
42
43impl Default for Transform2D {
44 fn default() -> Self {
45 Self {
46 matrix: Matrix4::identity(),
47 pos: Vector2::new(0.0, 0.0),
48 rot: 0.0,
49 layer: 0,
50 aspect: 1.0,
51 scale: Vector2::new(1.0, 1.0),
52 }
53 }
54}
55
56impl Transform2D {
57 fn calc_pos_matrix(&self) -> Matrix4<f32> {
58 let p = self.pos * 2.0;
59 let v = vec3((p.x - 1.0) * self.aspect, p.y - 1.0, 0.0);
60 Matrix4::from_translation(v)
61 }
62
63 fn calc_rot_matrix(&self) -> Matrix4<f32> {
64 Matrix4::from_angle_z(Rad::from(Deg(self.rot)))
65 }
66
67 fn calc_scale_matrix(&self) -> Matrix4<f32> {
68 Matrix4::from_nonuniform_scale(self.scale.x, self.scale.y, 1.0)
69 }
70
71 pub fn calc_matrix(&mut self) {
73 self.matrix = self.calc_pos_matrix() * self.calc_rot_matrix() * self.calc_scale_matrix();
74 }
75
76 pub fn aspect(&self) -> f32 { self.aspect }
78 pub fn set_aspect(&mut self, aspect: f32) { self.aspect = aspect; }
80 pub fn pos(&self) -> Vector2<f32> { self.pos }
82 pub fn rot(&self) -> f32 { self.rot }
84 pub fn layer(&self) -> u8 { self.layer }
86 pub fn scale(&self) -> Vector2<f32> { self.scale }
88 pub fn matrix(&self) -> Matrix4<f32> { self.matrix }
90
91 pub fn move_all(&mut self, x: f32, y: f32) { self.pos += vec2(x, y); }
93 pub fn move_x(&mut self, x: f32) { self.pos.x += x; }
95 pub fn move_y(&mut self, y: f32) { self.pos.y += y; }
97 pub fn set_pos_all(&mut self, x: f32, y: f32) { self.pos = vec2(x, y); }
99 pub fn set_pos_x(&mut self, x: f32) { self.pos.x = x; }
101 pub fn set_pos_y(&mut self, y: f32) { self.pos.y = y; }
103
104 pub fn rotate(&mut self, rot: f32) { self.rot += rot; }
106 pub fn set_rot(&mut self, rot: f32) { self.rot = rot; }
108 pub fn set_layer(&mut self, layer: u8) { self.layer = layer; }
110
111 pub fn scale_all(&mut self, x: f32, y: f32) { self.scale += vec2(x, y); }
113 pub fn scale_same(&mut self, xy: f32) { self.scale_all(xy, xy); }
115 pub fn scale_x(&mut self, x: f32) { self.scale.x += x; }
117 pub fn scale_y(&mut self, y: f32) { self.scale.y += y; }
119 pub fn set_scale_all(&mut self, x: f32, y: f32) { self.scale = vec2(x, y); }
121 pub fn set_scale_same(&mut self, xy: f32) { self.set_scale_all(xy, xy); }
123 pub fn set_scale_x(&mut self, x: f32) { self.scale.x = x; }
125 pub fn set_scale_y(&mut self, y: f32) { self.scale.y = y; }
127}
128
129#[cfg(test)]
130mod tests {
131 use super::*;
132
133 fn approx_eq(a: f32, b: f32) -> bool {
134 (a - b).abs() < 1e-5
135 }
136
137 #[test]
138 fn transform2d_default() {
139 let t = Transform2D::default();
140 assert_eq!(t.pos(), vec2(0.0, 0.0));
141 assert_eq!(t.rot(), 0.0);
142 assert_eq!(t.scale(), vec2(1.0, 1.0));
143 }
144
145 #[test]
146 fn transform2d_set_pos() {
147 let mut t = Transform2D::default();
148 t.set_pos_all(100.0, 200.0);
149 assert_eq!(t.pos(), vec2(100.0, 200.0));
150 t.set_pos_x(50.0);
151 t.set_pos_y(150.0);
152 assert_eq!(t.pos(), vec2(50.0, 150.0));
153 }
154
155 #[test]
156 fn transform2d_move() {
157 let mut t = Transform2D::default();
158 t.move_all(10.0, 20.0);
159 assert_eq!(t.pos(), vec2(10.0, 20.0));
160 t.move_x(5.0);
161 t.move_y(3.0);
162 assert_eq!(t.pos(), vec2(15.0, 23.0));
163 }
164
165 #[test]
166 fn transform2d_rotate() {
167 let mut t = Transform2D::default();
168 t.rotate(90.0);
169 assert!(approx_eq(t.rot(), 90.0));
170 t.set_rot(45.0);
171 assert!(approx_eq(t.rot(), 45.0));
172 }
173
174 #[test]
175 fn transform2d_scale() {
176 let mut t = Transform2D::default();
177 t.set_scale_all(2.0, 3.0);
178 assert_eq!(t.scale(), vec2(2.0, 3.0));
179 t.set_scale_x(5.0);
180 t.set_scale_y(6.0);
181 assert_eq!(t.scale(), vec2(5.0, 6.0));
182 }
183
184 #[test]
185 fn transform2d_scale_operations() {
186 let mut t = Transform2D::default();
187 t.scale_all(1.0, 2.0);
188 assert_eq!(t.scale(), vec2(2.0, 3.0));
189 t.scale_same(3.0);
190 assert_eq!(t.scale(), vec2(5.0, 6.0));
191 t.scale_x(1.0);
192 t.scale_y(1.0);
193 assert_eq!(t.scale(), vec2(6.0, 7.0));
194 }
195
196 #[test]
197 fn transform2d_layer() {
198 let mut t = Transform2D::default();
199 assert_eq!(t.layer(), 0);
200 t.set_layer(5);
201 assert_eq!(t.layer(), 5);
202 }
203
204 #[test]
205 fn transform2d_matrix() {
206 let mut t = Transform2D::default();
207 t.calc_matrix();
208 let m = t.matrix();
209 assert!(approx_eq(m[0][0], 1.0));
210 assert!(approx_eq(m[1][1], 1.0));
211 assert!(approx_eq(m[2][2], 1.0));
212 }
213
214 #[test]
215 fn transform2d_matrix_translation() {
216 let mut t = Transform2D::default();
217 t.set_pos_all(0.5, 0.0);
218 t.calc_matrix();
219 let m = t.matrix();
220 assert!(approx_eq(m[3][0], (0.5 * 2.0 - 1.0) * 1.0));
221 assert!(approx_eq(m[3][1], 0.0 * 2.0 - 1.0));
222 }
223
224 #[test]
225 fn transform2d_aspect() {
226 let mut t = Transform2D::default();
227 assert!(approx_eq(t.aspect(), 1.0));
228 t.set_aspect(1.5);
229 assert!(approx_eq(t.aspect(), 1.5));
230 }
231}