summaryrefslogtreecommitdiffstats
path: root/graphics/src/transformation.rs
blob: 1aeb691eca8935aa8f8e7d6dba6c7b180d924bb7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
use crate::core::{Point, Rectangle, Size, Vector};

use glam::{Mat4, Vec3, Vec4};
use std::ops::Mul;

/// A 2D transformation matrix.
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Transformation(Mat4);

impl Transformation {
    /// A [`Transformation`] that preserves whatever is transformed.
    pub const IDENTITY: Self = Self(Mat4::IDENTITY);

    /// Creates an orthographic projection.
    #[rustfmt::skip]
    pub fn orthographic(width: u32, height: u32) -> Transformation {
        Transformation(Mat4::orthographic_rh_gl(
            0.0, width as f32,
            height as f32, 0.0,
            -1.0, 1.0
        ))
    }

    /// Creates a translate transformation.
    pub fn translate(x: f32, y: f32) -> Transformation {
        Transformation(Mat4::from_translation(Vec3::new(x, y, 0.0)))
    }

    /// Creates a scale transformation.
    pub fn scale(x: f32, y: f32) -> Transformation {
        Transformation(Mat4::from_scale(Vec3::new(x, y, 1.0)))
    }

    /// The scale factor on the X axis.
    pub fn scale_x(&self) -> f32 {
        self.0.x_axis.x
    }

    /// The scale factor on the Y axis.
    pub fn scale_y(&self) -> f32 {
        self.0.y_axis.y
    }

    /// The translation on the X axis.
    pub fn translation_x(&self) -> f32 {
        self.0.w_axis.x
    }

    /// The translation on the Y axis.
    pub fn translation_y(&self) -> f32 {
        self.0.w_axis.y
    }
}

impl Mul for Transformation {
    type Output = Self;

    fn mul(self, rhs: Self) -> Self {
        Transformation(self.0 * rhs.0)
    }
}

impl Mul<Transformation> for Point {
    type Output = Self;

    fn mul(self, transformation: Transformation) -> Self {
        let point = transformation
            .0
            .mul_vec4(Vec4::new(self.x, self.y, 1.0, 1.0));

        Point::new(point.x, point.y)
    }
}

impl Mul<Transformation> for Vector {
    type Output = Self;

    fn mul(self, transformation: Transformation) -> Self {
        let new_vector = transformation
            .0
            .mul_vec4(Vec4::new(self.x, self.y, 1.0, 0.0));

        Vector::new(new_vector.x, new_vector.y)
    }
}

impl Mul<Transformation> for Size {
    type Output = Self;

    fn mul(self, transformation: Transformation) -> Self {
        let new_size = transformation.0.mul_vec4(Vec4::new(
            self.width,
            self.height,
            1.0,
            0.0,
        ));

        Size::new(new_size.x, new_size.y)
    }
}

impl Mul<Transformation> for Rectangle {
    type Output = Self;

    fn mul(self, transformation: Transformation) -> Self {
        let position = self.position();
        let size = self.size();

        Self::new(position * transformation, size * transformation)
    }
}

impl AsRef<[f32; 16]> for Transformation {
    fn as_ref(&self) -> &[f32; 16] {
        self.0.as_ref()
    }
}

impl From<Transformation> for [f32; 16] {
    fn from(t: Transformation) -> [f32; 16] {
        *t.as_ref()
    }
}

impl From<Transformation> for Mat4 {
    fn from(transformation: Transformation) -> Self {
        transformation.0
    }
}