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
130
131
132
133
134
135
136
137
138
139
use crate::{Matrix4, Point, Vector3, Vector4};

impl std::ops::Mul<&Matrix4> for Matrix4 {
    type Output = Self;

    fn mul(self, rhs: &Matrix4) -> Self {
        self * *rhs
    }
}

impl std::ops::Mul for Matrix4 {
    type Output = Self;

    fn mul(self, rhs: Self) -> Self {
        let mut result = Self::zero();

        for i in 0..4 {
            for j in 0..4 {
                result.0[i][j] = rhs.0[i][0] * self.0[0][j]
                    + rhs.0[i][1] * self.0[1][j]
                    + rhs.0[i][2] * self.0[2][j]
                    + rhs.0[i][3] * self.0[3][j];
            }
        }

        result
    }
}

impl std::ops::Mul<Point> for Matrix4 {
    type Output = Point;

    fn mul(self, rhs: Point) -> Point {
        Point::new(
            self.0[0][0] * rhs.x + self.0[1][0] * rhs.y + self.0[2][0] * rhs.z + self.0[3][0],
            self.0[0][1] * rhs.x + self.0[1][1] * rhs.y + self.0[2][1] * rhs.z + self.0[3][1],
            self.0[0][2] * rhs.x + self.0[1][2] * rhs.y + self.0[2][2] * rhs.z + self.0[3][2],
        )
    }
}

impl std::ops::Mul<Vector3> for Matrix4 {
    type Output = Vector3;

    fn mul(self, rhs: Vector3) -> Vector3 {
        Vector3::new(
            self.0[0][0] * rhs.x + self.0[1][0] * rhs.y + self.0[2][0] * rhs.z,
            self.0[0][1] * rhs.x + self.0[1][1] * rhs.y + self.0[2][1] * rhs.z,
            self.0[0][2] * rhs.x + self.0[1][2] * rhs.y + self.0[2][2] * rhs.z,
        )
    }
}

impl std::ops::Mul<Vector4> for Matrix4 {
    type Output = Vector4;

    fn mul(self, rhs: Vector4) -> Vector4 {
        Vector4::new(
            self.row(0).dot(rhs),
            self.row(1).dot(rhs),
            self.row(2).dot(rhs),
            self.row(3).dot(rhs),
        )
    }
}

impl std::ops::Mul<Matrix4> for Point {
    type Output = Point;

    fn mul(self, rhs: Matrix4) -> Point {
        Point::new(
            Vector3::from_scalar(self.x).dot(Vector3::from(rhs.column(0))),
            Vector3::from_scalar(self.y).dot(Vector3::from(rhs.column(1))),
            Vector3::from_scalar(self.z).dot(Vector3::from(rhs.column(2))),
        )
    }
}

impl std::ops::Mul<Matrix4> for Vector3 {
    type Output = Vector3;

    fn mul(self, rhs: Matrix4) -> Vector3 {
        Vector3::new(
            Vector3::from_scalar(self.x).dot(Vector3::from(rhs.column(0))),
            Vector3::from_scalar(self.y).dot(Vector3::from(rhs.column(1))),
            Vector3::from_scalar(self.z).dot(Vector3::from(rhs.column(2))),
        )
    }
}

impl std::ops::Mul<Matrix4> for Vector4 {
    type Output = Vector4;

    fn mul(self, rhs: Matrix4) -> Vector4 {
        Vector4::new(
            Vector4::from_scalar(self.x).dot(rhs.column(0)),
            Vector4::from_scalar(self.y).dot(rhs.column(1)),
            Vector4::from_scalar(self.z).dot(rhs.column(2)),
            Vector4::from_scalar(self.w).dot(rhs.column(3)),
        )
    }
}

macro_rules! vector_op {
    (impl $trait:ident<$other_type: ty> for $type:ty {
        fn $op_fn:ident -> $result_type:ty, $op:tt { $($field:ident),+ }
    }) => {
        impl std::ops::$trait<$other_type> for $type {
            type Output = $result_type;

            fn $op_fn(self, rhs: $other_type) -> $result_type {
                <$result_type>::new($(self.$field $op rhs.$field),+)
            }
        }
    };
}

macro_rules! vector_assign_op {
    (impl $trait:ident<$other_type: ty> for $type:ty {
        fn $op_fn:ident, $op:tt { $($field:ident),+ }
    }) => {
        impl std::ops::$trait<$other_type> for $type {
            fn $op_fn(&mut self, rhs: $other_type) {
                $(self.$field $op rhs.$field);+
            }
        }
    };
}

vector_op!(impl Add<Vector3> for Vector3 { fn add -> Vector3, + {x, y, z} });
vector_op!(impl Sub<Vector3> for Vector3 { fn sub -> Vector3, - {x, y, z} });
vector_assign_op!(impl AddAssign<Vector3> for Vector3 { fn add_assign, += {x, y, z} });
vector_assign_op!(impl SubAssign<Vector3> for Vector3 { fn sub_assign, -= {x, y, z} });

vector_op!(impl Add<Vector3> for Point { fn add -> Point, + {x, y, z} });
vector_op!(impl Sub<Vector3> for Point { fn sub -> Point, - {x, y, z} });
vector_op!(impl Sub<Point> for Point { fn sub -> Vector3, - {x, y, z} });
vector_assign_op!(impl AddAssign<Vector3> for Point { fn add_assign, += {x, y, z} });
vector_assign_op!(impl SubAssign<Vector3> for Point { fn sub_assign, -= {x, y, z} });