diff --git a/ray-tracer/src/bin/projectile.rs b/ray-tracer/src/bin/projectile.rs index 895be40..46711a1 100644 --- a/ray-tracer/src/bin/projectile.rs +++ b/ray-tracer/src/bin/projectile.rs @@ -29,15 +29,15 @@ fn main() { }; let mut p = start; - while p.position.y > 0. { + while p.position.y() > 0. { p = tick(&e, &p); } println!( "distance travelled: [{}] {} {} {}", (p.position - start.position).magnitude(), - p.position.x, - p.position.y, - p.position.z + p.position.x(), + p.position.y(), + p.position.z(), ); } diff --git a/ray-tracer/src/types/mod.rs b/ray-tracer/src/types/mod.rs index a89d667..e501927 100644 --- a/ray-tracer/src/types/mod.rs +++ b/ray-tracer/src/types/mod.rs @@ -26,52 +26,16 @@ mod tests { #[test] fn add_two_tuples() { - let a = Tuple { - x: 3., - y: -2., - z: 5., - w: 1., - }; - let b = Tuple { - x: -2., - y: 3., - z: 1., - w: 0., - }; - assert_eq!( - a + b, - Tuple { - x: 1., - y: 1., - z: 6., - w: 1. - } - ); + let a = Tuple(3., -2., 5., 1.); + let b = Tuple(-2., 3., 1., 0.); + assert_eq!(a + b, Tuple(1., 1., 6., 1.)); } #[test] fn subtracts_two_tuples() { - let a = Tuple { - x: 3., - y: 2., - z: 1., - w: 1., - }; - let b = Tuple { - x: 5., - y: 6., - z: 7., - w: 1., - }; - assert_eq!( - a - b, - Tuple { - x: -2., - y: -4., - z: -6., - w: 0. - } - ); + let a = Tuple(3., 2., 1., 1.); + let b = Tuple(5., 6., 7., 1.); + assert_eq!(a - b, Tuple(-2., -4., -6., 0.)); } #[test] @@ -104,56 +68,17 @@ mod tests { #[test] fn it_negates_primitives() { - assert_eq!( - -Tuple { - x: 1., - y: 2., - z: 3., - w: 4. - }, - Tuple { - x: -1., - y: -2., - z: -3., - w: -4. - }, - ); + assert_eq!(-Tuple(1., 2., 3., 4.), Tuple(-1., -2., -3., -4.),); } #[test] fn multiply_tuple_by_scalar() { - assert_eq!( - Tuple { - x: 1., - y: -2., - z: 3., - w: -4. - } * 3.5, - Tuple { - x: 3.5, - y: -7., - z: 10.5, - w: -14. - } - ); + assert_eq!(Tuple(1., -2., 3., -4.) * 3.5, Tuple(3.5, -7., 10.5, -14.)); } #[test] fn divide_tuple_by_scalar() { - assert_eq!( - Tuple { - x: 1., - y: -2., - z: 3., - w: -4. - } / 2., - Tuple { - x: 0.5, - y: -1., - z: 1.5, - w: -2. - } - ); + assert_eq!(Tuple(1., -2., 3., -4.) / 2., Tuple(0.5, -1., 1.5, -2.)); } #[test] diff --git a/ray-tracer/src/types/point.rs b/ray-tracer/src/types/point.rs index 7c0c141..c8a0d98 100644 --- a/ray-tracer/src/types/point.rs +++ b/ray-tracer/src/types/point.rs @@ -5,7 +5,22 @@ pub struct Point(Tuple); impl Point { pub fn new(x: f64, y: f64, z: f64) -> Self { - Self(Tuple { x, y, z, w: 1.0 }) + Self(Tuple(x, y, z, 1.0)) + } + + #[inline] + pub fn x(&self) -> f64 { + self.0.0 + } + + #[inline] + pub fn y(&self) -> f64 { + self.0.1 + } + + #[inline] + pub fn z(&self) -> f64 { + self.0.2 } } @@ -17,7 +32,7 @@ impl Default for Point { impl From for Point { fn from(tuple: Tuple) -> Self { - assert_eq!(tuple.w, 1.0); + assert_eq!(tuple.3, 1.0); Self(tuple) } } @@ -54,7 +69,7 @@ impl std::ops::Neg for Point { type Output = Point; fn neg(self) -> Self::Output { let mut t = -self.0; - t.w = 1.; + t.3 = 1.; Point::from(t) } } diff --git a/ray-tracer/src/types/tuple.rs b/ray-tracer/src/types/tuple.rs index 7ea6d6b..62250e0 100644 --- a/ray-tracer/src/types/tuple.rs +++ b/ray-tracer/src/types/tuple.rs @@ -1,48 +1,37 @@ use crate::types::eq_f64; #[derive(Debug, Clone, Copy)] -pub struct Tuple { - pub x: f64, - pub y: f64, - pub z: f64, - pub w: f64, // Used for very low-level math. w = 1.0 indicates a point, w = 0.0 indicates a vector. - // Theoretically the type system should make this redundant, so operations on points - // and vectors can always assert the correct value. -} +pub struct Tuple( + pub f64, // x or red + pub f64, // y or green + pub f64, // z or blue + pub f64, // w, the flag which + // indicates point vs vec, or alpha +); impl Tuple { pub fn dot(&self, r: &Tuple) -> f64 { - self.x * r.x + self.y * r.y + self.z * r.z + self.w * r.w + self.0 * r.0 + self.1 * r.1 + self.2 * r.2 + self.3 * r.3 } } impl PartialEq for Tuple { fn eq(&self, r: &Tuple) -> bool { - eq_f64(self.x, r.x) && eq_f64(self.y, r.y) && eq_f64(self.z, r.z) && eq_f64(self.w, r.w) + eq_f64(self.0, r.0) && eq_f64(self.1, r.1) && eq_f64(self.2, r.2) && eq_f64(self.3, r.3) } } impl std::ops::Add for Tuple { type Output = Tuple; fn add(self, r: Tuple) -> Self::Output { - return Self::Output { - x: self.x + r.x, - y: self.y + r.y, - z: self.z + r.z, - w: self.w + r.w, - }; + Tuple(self.0 + r.0, self.1 + r.1, self.2 + r.2, self.3 + r.3) } } impl std::ops::Sub for Tuple { type Output = Tuple; fn sub(self, r: Tuple) -> Self::Output { - return Self::Output { - x: self.x - r.x, - y: self.y - r.y, - z: self.z - r.z, - w: self.w - r.w, - }; + Tuple(self.0 - r.0, self.1 - r.1, self.2 - r.2, self.3 - r.3) } } @@ -50,10 +39,10 @@ impl std::ops::Neg for Tuple { type Output = Tuple; fn neg(self) -> Self::Output { return Self::Output { - x: -self.x, - y: -self.y, - z: -self.z, - w: -self.w, + 0: -self.0, + 1: -self.1, + 2: -self.2, + 3: -self.3, }; } } @@ -61,23 +50,23 @@ impl std::ops::Neg for Tuple { impl std::ops::Mul for Tuple { type Output = Tuple; fn mul(self, scalar: f64) -> Self::Output { - return Self::Output { - x: self.x * scalar, - y: self.y * scalar, - z: self.z * scalar, - w: self.w * scalar, - }; + Tuple( + self.0 * scalar, + self.1 * scalar, + self.2 * scalar, + self.3 * scalar, + ) } } impl std::ops::Div for Tuple { type Output = Tuple; fn div(self, scalar: f64) -> Self::Output { - return Self::Output { - x: self.x / scalar, - y: self.y / scalar, - z: self.z / scalar, - w: self.w / scalar, - }; + Tuple( + self.0 / scalar, + self.1 / scalar, + self.2 / scalar, + self.3 / scalar, + ) } } diff --git a/ray-tracer/src/types/vector.rs b/ray-tracer/src/types/vector.rs index f2aa4c8..eb0f8bb 100644 --- a/ray-tracer/src/types/vector.rs +++ b/ray-tracer/src/types/vector.rs @@ -5,16 +5,31 @@ pub struct Vector(Tuple); impl Vector { pub fn new(x: f64, y: f64, z: f64) -> Self { - Self(Tuple { x, y, z, w: 0.0 }) + Self(Tuple(x, y, z, 0.0)) + } + + #[inline] + pub fn x(&self) -> f64 { + self.0.0 + } + + #[inline] + pub fn y(&self) -> f64 { + self.0.1 + } + + #[inline] + pub fn z(&self) -> f64 { + self.0.2 } pub fn magnitude(&self) -> f64 { - (self.x * self.x + self.y * self.y + self.z * self.z).sqrt() + (self.x() * self.x() + self.y() * self.y() + self.z() * self.z()).sqrt() } pub fn normalize(&self) -> Self { let mag = self.magnitude(); - Self::new(self.x / mag, self.y / mag, self.z / mag) + Self::new(self.x() / mag, self.y() / mag, self.z() / mag) } pub fn dot(&self, r: &Vector) -> f64 { @@ -22,9 +37,9 @@ impl Vector { } pub fn cross(&self, r: &Vector) -> Self { - let x = self.y * r.z - self.z * r.y; - let y = self.z * r.x - self.x * r.z; - let z = self.x * r.y - self.y * r.x; + let x = self.y() * r.z() - self.z() * r.y(); + let y = self.z() * r.x() - self.x() * r.z(); + let z = self.x() * r.y() - self.y() * r.x(); Self::new(x, y, z) } } @@ -37,7 +52,7 @@ impl Default for Vector { impl From for Vector { fn from(tuple: Tuple) -> Self { - assert_eq!(tuple.w, 0.0); + assert_eq!(tuple.3, 0.0); Self(tuple) } } @@ -67,7 +82,7 @@ impl std::ops::Neg for Vector { type Output = Vector; fn neg(self) -> Self::Output { let mut t = -self.0; - t.w = 0.; + t.0 = 0.; Vector::from(t) } }