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
140
use crate::{Matrix, Point, Vector};

impl std::ops::Neg for Vector {
    type Output = Self;

    fn neg(self) -> Self {
        Self {
            x: -self.x,
            y: -self.y,
            z: -self.z,
        }
    }
}

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

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

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

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

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

        result
    }
}

impl std::ops::Mul<Point> for Matrix {
    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<Vector> for Matrix {
    type Output = Vector;

    fn mul(self, rhs: Vector) -> Vector {
        Vector::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,
        )
    }
}

macro_rules! scalar_op {
    ($trait: ident, $op_fn: ident, $type: ty, $other_type: ty, $result_type: ty, $op: tt) => {
        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.x $op rhs, self.y $op rhs, self.z $op rhs)
            }
        }
    };
}

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

macro_rules! vector_op {
    ($trait: ident, $op_fn: ident, $type: ty, $other_type: ty, $result_type: ty, $op: tt) => {
        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.x $op rhs.x, self.y $op rhs.y, self.z $op rhs.z)
            }
        }
    };
}

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

scalar_op!(Add, add, Point, f32, Point, +);
scalar_op!(Sub, sub, Point, f32, Point, -);
scalar_op!(Mul, mul, Point, f32, Point, *);
scalar_op!(Div, div, Point, f32, Point, /);
scalar_assign_op!(AddAssign, add_assign, Point, f32, +=);
scalar_assign_op!(SubAssign, sub_assign, Point, f32, -=);
scalar_assign_op!(MulAssign, mul_assign, Point, f32, *=);
scalar_assign_op!(DivAssign, div_assign, Point, f32, /=);

scalar_op!(Add, add, Vector, f32, Vector, +);
scalar_op!(Sub, sub, Vector, f32, Vector, -);
scalar_op!(Mul, mul, Vector, f32, Vector, *);
scalar_op!(Div, div, Vector, f32, Vector, /);
scalar_assign_op!(AddAssign, add_assign, Vector, f32, +=);
scalar_assign_op!(SubAssign, sub_assign, Vector, f32, -=);
scalar_assign_op!(MulAssign, mul_assign, Vector, f32, *=);
scalar_assign_op!(DivAssign, div_assign, Vector, f32, /=);

vector_op!(Add, add, Vector, Vector, Vector, +);
vector_op!(Sub, sub, Vector, Vector, Vector, -);
vector_assign_op!(AddAssign, add_assign, Vector, Vector, +=);
vector_assign_op!(SubAssign, sub_assign, Vector, Vector, -=);

vector_op!(Add, add, Point, Vector, Point, +);
vector_op!(Sub, sub, Point, Vector, Point, -);
vector_op!(Sub, sub, Point, Point, Vector, -);
vector_assign_op!(AddAssign, add_assign, Point, Vector, +=);
vector_assign_op!(SubAssign, sub_assign, Point, Vector, -=);