1use std::ops;
2
3#[derive(Debug, Copy, Clone, PartialEq)]
4pub struct Vector3(pub f64, pub f64, pub f64);
5
6impl Vector3 {
7 pub fn new(x: f64, y: f64, z: f64) -> Vector3 {
8 Vector3(x, y, z)
9 }
10
11 pub fn x(&self) -> f64 {
12 self.0
13 }
14 pub fn y(&self) -> f64 {
15 self.1
16 }
17 pub fn z(&self) -> f64 {
18 self.2
19 }
20
21 pub fn length_squared(&self) -> f64 {
22 self.0 * self.0 + self.1 * self.1 + self.2 * self.2
23 }
24
25 pub fn length(&self) -> f64 {
26 self.length_squared().sqrt()
27 }
28
29 pub fn dot(&self, other: &Self) -> f64 {
30 self.0 * other.0 + self.1 * other.1 + self.2 * other.2
31 }
32
33 pub fn cross(&self, other: &Self) -> Self {
34 Vector3(
35 self.1 * other.2 - self.2 * other.1,
36 self.2 * other.0 - self.0 * other.2,
37 self.0 * other.1 - self.1 * other.0,
38 )
39 }
40
41 pub fn unit_vector(&self) -> Self {
42 *self / self.length()
43 }
44
45 pub fn near_zero(&self) -> bool {
46 let small = 1e-8;
47
48 (self.0.abs() < small) && (self.1.abs() < small) && (self.2.abs() < small)
49 }
50}
51
52impl ops::Add for Vector3 {
53 type Output = Vector3;
54
55 fn add(self, rhs: Self) -> Self::Output {
56 Vector3(self.0 + rhs.0, self.1 + rhs.1, self.2 + rhs.2)
57 }
58}
59
60impl ops::AddAssign for Vector3 {
61 fn add_assign(&mut self, rhs: Self) {
62 self.0 += rhs.0;
63 self.1 += rhs.1;
64 self.2 += rhs.2;
65 }
66}
67
68impl ops::Sub for Vector3 {
69 type Output = Vector3;
70
71 fn sub(self, rhs: Self) -> Self::Output {
72 Vector3(self.0 - rhs.0, self.1 - rhs.1, self.2 - rhs.2)
73 }
74}
75
76impl ops::SubAssign for Vector3 {
77 fn sub_assign(&mut self, rhs: Self) {
78 self.0 -= rhs.0;
79 self.1 -= rhs.1;
80 self.2 -= rhs.2;
81 }
82}
83
84impl ops::Div<f64> for Vector3 {
85 type Output = Vector3;
86
87 fn div(self, rhs: f64) -> Self::Output {
88 Vector3(self.0 / rhs, self.1 / rhs, self.2 / rhs)
89 }
90}
91
92impl ops::DivAssign<f64> for Vector3 {
93 fn div_assign(&mut self, rhs: f64) {
94 self.0 /= rhs;
95 self.1 /= rhs;
96 self.2 /= rhs;
97 }
98}
99
100impl ops::Mul<f64> for Vector3 {
101 type Output = Vector3;
102
103 fn mul(self, rhs: f64) -> Self::Output {
104 Vector3(self.0 * rhs, self.1 * rhs, self.2 * rhs)
105 }
106}
107
108impl ops::Mul<Vector3> for f64 {
109 type Output = Vector3;
110
111 fn mul(self, rhs: Vector3) -> Self::Output {
112 Vector3(self * rhs.0, self * rhs.1, self * rhs.2)
113 }
114}
115
116impl ops::MulAssign<f64> for Vector3 {
117 fn mul_assign(&mut self, rhs: f64) {
118 self.0 *= rhs;
119 self.1 *= rhs;
120 self.2 *= rhs;
121 }
122}
123
124impl ops::Neg for Vector3 {
125 type Output = Vector3;
126
127 fn neg(self) -> Self::Output {
128 Vector3(-self.0, -self.1, -self.2)
129 }
130}
131
132impl ops::Mul<Vector3> for Vector3 {
133 type Output = Vector3;
134
135 fn mul(self, rhs: Vector3) -> Self::Output {
136 Vector3(self.0 * rhs.0, self.1 * rhs.1, self.2 * rhs.2)
137 }
138}
139
140pub type Point3 = Vector3;
141pub type Color = Vector3;
142
143#[cfg(test)]
144mod tests {
145 use crate::math::*;
146
147 #[test]
148 fn vector_eq() {
149 assert_eq!(Vector3(1.0, 2.0, 3.0), Vector3(1.0, 2.0, 3.0));
150 }
151
152 #[test]
153 fn vector_add() {
154 assert_eq!(
155 Vector3(1.0, 2.0, 3.0) + Vector3(4.0, 5.0, 6.0),
156 Vector3(5.0, 7.0, 9.0)
157 );
158 }
159
160 #[test]
161 fn vector_add_assign() {
162 let mut v = Vector3(1.0, 2.0, 3.0);
163 v += Vector3(4.0, 5.0, 6.0);
164
165 assert_eq!(v, Vector3(5.0, 7.0, 9.0));
166 }
167
168 #[test]
169 fn vector_sub() {
170 assert_eq!(
171 Vector3(1.0, 2.0, 3.0) - Vector3(4.0, 5.0, 6.0),
172 Vector3(-3.0, -3.0, -3.0)
173 );
174 }
175
176 #[test]
177 fn vector_sub_assign() {
178 let mut v = Vector3(1.0, 2.0, 3.0);
179 v -= Vector3(4.0, 5.0, 6.0);
180
181 assert_eq!(v, Vector3(-3.0, -3.0, -3.0));
182 }
183
184 #[test]
185 fn vector_div() {
186 assert_eq!(Vector3(1.0, 2.0, 3.0) / 2.0, Vector3(0.5, 1.0, 1.5));
187 }
188
189 #[test]
190 fn vector_div_assign() {
191 let mut v = Vector3(1.0, 2.0, 3.0);
192 v /= 2.0;
193
194 assert_eq!(v, Vector3(0.5, 1.0, 1.5));
195 }
196
197 #[test]
198 fn vector_mul() {
199 assert_eq!(Vector3(1.0, 2.0, 3.0) * 2.0, Vector3(2.0, 4.0, 6.0));
200 }
201
202 #[test]
203 fn vector_mul_assign() {
204 let mut v = Vector3(1.0, 2.0, 3.0);
205 v *= 2.0;
206
207 assert_eq!(v, Vector3(2.0, 4.0, 6.0));
208 }
209
210 #[test]
211 fn vector_neg() {
212 assert_eq!(-Vector3(1.0, 2.0, 3.0), Vector3(-1.0, -2.0, -3.0));
213 }
214}
215
216#[derive(Debug, Copy, Clone, PartialEq)]
217pub struct Ray {
218 pub origin: Point3,
219 pub direction: Vector3,
220}
221
222impl Ray {
223 pub fn new(origin: Point3, direction: Vector3) -> Self {
224 Ray { origin, direction }
225 }
226
227 pub fn at(&self, t: f64) -> Point3 {
228 self.origin + self.direction * t
229 }
230}