From 8f0a7d0cfd5a12139641272152186620071b890e Mon Sep 17 00:00:00 2001 From: Matthew Gordon Date: Fri, 14 Aug 2020 22:32:35 -0400 Subject: [PATCH] Add Vec2, Vec3 and Vec4 structs --- src/lib.rs | 2 +- src/math/mod.rs | 8 ++ src/math/vec2.rs | 165 ++++++++++++++++++++++++++++++++++++++++ src/math/vec3.rs | 190 +++++++++++++++++++++++++++++++++++++++++++++++ src/math/vec4.rs | 187 ++++++++++++++++++++++++++++++++++++++++++++++ src/matrix.rs | 154 -------------------------------------- 6 files changed, 551 insertions(+), 155 deletions(-) create mode 100644 src/math/mod.rs create mode 100644 src/math/vec2.rs create mode 100644 src/math/vec3.rs create mode 100644 src/math/vec4.rs delete mode 100644 src/matrix.rs diff --git a/src/lib.rs b/src/lib.rs index a2030ec..3bfd442 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,7 +6,7 @@ pub mod colour; pub mod image; pub mod integrators; pub mod materials; -pub mod matrix; +pub mod math; pub mod mesh; pub mod raycasting; pub mod realtype; diff --git a/src/math/mod.rs b/src/math/mod.rs new file mode 100644 index 0000000..8b1ad9d --- /dev/null +++ b/src/math/mod.rs @@ -0,0 +1,8 @@ +mod vec2; +pub use vec2::*; + +mod vec3; +pub use vec3::*; + +mod vec4; +pub use vec4::*; diff --git a/src/math/vec2.rs b/src/math/vec2.rs new file mode 100644 index 0000000..4861e7c --- /dev/null +++ b/src/math/vec2.rs @@ -0,0 +1,165 @@ +use itertools::izip; + +use std::ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign}; + +#[derive(PartialEq, Debug)] +pub struct Vec2 { + coords: [f64; 2], +} + +impl Vec2 { + pub fn new(x: f64, y: f64) -> Self { + Vec2 { coords: [x, y] } + } + + pub fn x(&self) -> f64 { + self.coords[0] + } + + pub fn y(&self) -> f64 { + self.coords[1] + } + + pub fn dot(&self, rhs: &Vec2) -> f64 { + self.coords + .iter() + .zip(rhs.coords.iter()) + .map(|(a_elem, b_elem)| a_elem * b_elem) + .sum() + } +} + +impl Add for Vec2 { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + let mut coords = [0.0; 2]; + for (r, a, b) in izip!(coords.iter_mut(), self.coords.iter(), rhs.coords.iter()) { + *r = a + b; + } + Vec2 { coords } + } +} + +impl AddAssign for Vec2 { + fn add_assign(&mut self, rhs: Self) { + for (a, b) in self.coords.iter_mut().zip(rhs.coords.iter()) { + *a += b; + } + } +} + +impl Sub for Vec2 { + type Output = Self; + + fn sub(self, rhs: Self) -> Self { + let mut coords = [0.0; 2]; + for (r, a, b) in izip!(coords.iter_mut(), self.coords.iter(), rhs.coords.iter()) { + *r = a - b; + } + Vec2 { coords } + } +} + +impl SubAssign for Vec2 { + fn sub_assign(&mut self, rhs: Self) { + for (a, b) in self.coords.iter_mut().zip(rhs.coords.iter()) { + *a -= b; + } + } +} + +impl Mul for Vec2 { + type Output = Self; + + fn mul(self, rhs: f64) -> Vec2 { + let mut coords = [0.0; 2]; + for (r, a) in coords.iter_mut().zip(self.coords.iter()) { + *r = a * rhs; + } + Vec2 { coords } + } +} + +impl MulAssign for Vec2 { + fn mul_assign(&mut self, rhs: f64) { + for a in self.coords.iter_mut() { + *a *= rhs; + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn x_returns_first_element() { + let target = Vec2::new(1.0, 2.0); + assert!(target.x() == 1.0); + } + + #[test] + fn y_returns_second_element() { + let target = Vec2::new(1.0, 2.0); + assert!(target.y() == 2.0); + } + + #[test] + fn dot_product_returns_correct_result() { + let a = Vec2::new(1.0, 2.0); + let b = Vec2::new(4.0, 5.0); + assert!(a.dot(&b) == 14.0); + } + + #[test] + fn add_returns_correct_result() { + let a = Vec2::new(1.0, 2.0); + let b = Vec2::new(4.0, 5.0); + let c = Vec2::new(5.0, 7.0); + assert!(a + b == c); + } + + #[test] + fn add_assign_returns_correct_result() { + let mut a = Vec2::new(1.0, 2.0); + let b = Vec2::new(4.0, 5.0); + let c = Vec2::new(5.0, 7.0); + a += b; + assert!(a == c); + } + + #[test] + fn sub_returns_correct_result() { + let a = Vec2::new(1.0, 2.0); + let b = Vec2::new(4.0, 6.0); + let c = Vec2::new(-3.0, -4.0); + assert!(a - b == c); + } + + #[test] + fn sub_assign_returns_correct_result() { + let mut a = Vec2::new(1.0, 2.0); + let b = Vec2::new(4.0, 6.0); + let c = Vec2::new(-3.0, -4.0); + a -= b; + assert!(a == c); + } + + #[test] + fn mul_by_scalar_returns_correct_result() { + let a = Vec2::new(1.0, 2.0); + let b = 0.5; + let c = Vec2::new(0.5, 1.0); + assert!(a * b == c); + } + + #[test] + fn mul_assign_by_scalar_returns_correct_result() { + let mut a = Vec2::new(1.0, 2.0); + let b = 0.5; + let c = Vec2::new(0.5, 1.0); + a *= b; + assert!(a == c); + } +} diff --git a/src/math/vec3.rs b/src/math/vec3.rs new file mode 100644 index 0000000..11c0831 --- /dev/null +++ b/src/math/vec3.rs @@ -0,0 +1,190 @@ +use itertools::izip; + +use std::ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign}; + +#[derive(PartialEq, Debug)] +pub struct Vec3 { + coords: [f64; 3], +} + +impl Vec3 { + pub fn new(x: f64, y: f64, z: f64) -> Self { + Vec3 { coords: [x, y, z] } + } + + pub fn x(&self) -> f64 { + self.coords[0] + } + + pub fn y(&self) -> f64 { + self.coords[1] + } + + pub fn z(&self) -> f64 { + self.coords[2] + } + + pub fn dot(&self, rhs: &Vec3) -> f64 { + self.coords + .iter() + .zip(rhs.coords.iter()) + .map(|(a_elem, b_elem)| a_elem * b_elem) + .sum() + } + + pub fn cross(&self, rhs: &Vec3) -> Vec3 { + let x = self.y() * rhs.z() - self.z() * rhs.y(); + let y = self.z() * rhs.x() - self.x() * rhs.z(); + let z = self.x() * rhs.y() - self.y() * rhs.x(); + Vec3 { coords: [x, y, z] } + } +} + +impl Add for Vec3 { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + let mut coords = [0.0; 3]; + for (r, a, b) in izip!(coords.iter_mut(), self.coords.iter(), rhs.coords.iter()) { + *r = a + b; + } + Vec3 { coords } + } +} + +impl AddAssign for Vec3 { + fn add_assign(&mut self, rhs: Self) { + for (a, b) in self.coords.iter_mut().zip(rhs.coords.iter()) { + *a += b; + } + } +} + +impl Sub for Vec3 { + type Output = Self; + + fn sub(self, rhs: Self) -> Self { + let mut coords = [0.0; 3]; + for (r, a, b) in izip!(coords.iter_mut(), self.coords.iter(), rhs.coords.iter()) { + *r = a - b; + } + Vec3 { coords } + } +} + +impl SubAssign for Vec3 { + fn sub_assign(&mut self, rhs: Self) { + for (a, b) in self.coords.iter_mut().zip(rhs.coords.iter()) { + *a -= b; + } + } +} + +impl Mul for Vec3 { + type Output = Self; + + fn mul(self, rhs: f64) -> Vec3 { + let mut coords = [0.0; 3]; + for (r, a) in coords.iter_mut().zip(self.coords.iter()) { + *r = a * rhs; + } + Vec3 { coords } + } +} + +impl MulAssign for Vec3 { + fn mul_assign(&mut self, rhs: f64) { + for a in self.coords.iter_mut() { + *a *= rhs; + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn x_returns_first_element() { + let target = Vec3::new(1.0, 2.0, 3.0); + assert!(target.x() == 1.0); + } + + #[test] + fn y_returns_second_element() { + let target = Vec3::new(1.0, 2.0, 3.0); + assert!(target.y() == 2.0); + } + + #[test] + fn z_returns_third_element() { + let target = Vec3::new(1.0, 2.0, 3.0); + assert!(target.z() == 3.0); + } + + #[test] + fn dot_product_returns_correct_result() { + let a = Vec3::new(1.0, 2.0, 3.0); + let b = Vec3::new(4.0, 5.0, 6.0); + assert!(a.dot(&b) == 32.0); + } + + #[test] + fn cross_product_returns_correct_result() { + let a = Vec3::new(1.0, 2.0, 3.0); + let b = Vec3::new(4.0, 5.0, 6.0); + let c = Vec3::new(-3.0, 6.0, -3.0); + assert!(a.cross(&b) == c); + } + + #[test] + fn add_returns_correct_result() { + let a = Vec3::new(1.0, 2.0, 3.0); + let b = Vec3::new(4.0, 5.0, 6.0); + let c = Vec3::new(5.0, 7.0, 9.0); + assert!(a + b == c); + } + + #[test] + fn add_assign_returns_correct_result() { + let mut a = Vec3::new(1.0, 2.0, 3.0); + let b = Vec3::new(4.0, 5.0, 6.0); + let c = Vec3::new(5.0, 7.0, 9.0); + a += b; + assert!(a == c); + } + + #[test] + fn sub_returns_correct_result() { + let a = Vec3::new(1.0, 2.0, 3.0); + let b = Vec3::new(4.0, 6.0, 8.0); + let c = Vec3::new(-3.0, -4.0, -5.0); + assert!(a - b == c); + } + + #[test] + fn sub_assign_returns_correct_result() { + let mut a = Vec3::new(1.0, 2.0, 3.0); + let b = Vec3::new(4.0, 6.0, 8.0); + let c = Vec3::new(-3.0, -4.0, -5.0); + a -= b; + assert!(a == c); + } + + #[test] + fn mul_by_scalar_returns_correct_result() { + let a = Vec3::new(1.0, 2.0, 3.0); + let b = 0.5; + let c = Vec3::new(0.5, 1.0, 1.5); + assert!(a * b == c); + } + + #[test] + fn mul_assign_by_scalar_returns_correct_result() { + let mut a = Vec3::new(1.0, 2.0, 3.0); + let b = 0.5; + let c = Vec3::new(0.5, 1.0, 1.5); + a *= b; + assert!(a == c); + } +} diff --git a/src/math/vec4.rs b/src/math/vec4.rs new file mode 100644 index 0000000..2951ec7 --- /dev/null +++ b/src/math/vec4.rs @@ -0,0 +1,187 @@ +use itertools::izip; + +use std::ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign}; + +#[derive(PartialEq, Debug)] +pub struct Vec4 { + coords: [f64; 4], +} + +impl Vec4 { + pub fn new(x: f64, y: f64, z: f64, w: f64) -> Self { + Vec4 { + coords: [x, y, z, w], + } + } + + pub fn x(&self) -> f64 { + self.coords[0] + } + + pub fn y(&self) -> f64 { + self.coords[1] + } + + pub fn z(&self) -> f64 { + self.coords[2] + } + + pub fn w(&self) -> f64 { + self.coords[3] + } + + pub fn dot(&self, rhs: &Vec4) -> f64 { + self.coords + .iter() + .zip(rhs.coords.iter()) + .map(|(a_elem, b_elem)| a_elem * b_elem) + .sum() + } +} + +impl Add for Vec4 { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + let mut coords = [0.0; 4]; + for (r, a, b) in izip!(coords.iter_mut(), self.coords.iter(), rhs.coords.iter()) { + *r = a + b; + } + Vec4 { coords } + } +} + +impl AddAssign for Vec4 { + fn add_assign(&mut self, rhs: Self) { + for (a, b) in self.coords.iter_mut().zip(rhs.coords.iter()) { + *a += b; + } + } +} + +impl Sub for Vec4 { + type Output = Self; + + fn sub(self, rhs: Self) -> Self { + let mut coords = [0.0; 4]; + for (r, a, b) in izip!(coords.iter_mut(), self.coords.iter(), rhs.coords.iter()) { + *r = a - b; + } + Vec4 { coords } + } +} + +impl SubAssign for Vec4 { + fn sub_assign(&mut self, rhs: Self) { + for (a, b) in self.coords.iter_mut().zip(rhs.coords.iter()) { + *a -= b; + } + } +} + +impl Mul for Vec4 { + type Output = Self; + + fn mul(self, rhs: f64) -> Vec4 { + let mut coords = [0.0; 4]; + for (r, a) in coords.iter_mut().zip(self.coords.iter()) { + *r = a * rhs; + } + Vec4 { coords } + } +} + +impl MulAssign for Vec4 { + fn mul_assign(&mut self, rhs: f64) { + for a in self.coords.iter_mut() { + *a *= rhs; + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn x_returns_first_element() { + let target = Vec4::new(1.0, 2.0, 3.0, 4.0); + assert!(target.x() == 1.0); + } + + #[test] + fn y_returns_second_element() { + let target = Vec4::new(1.0, 2.0, 3.0, 4.0); + assert!(target.y() == 2.0); + } + + #[test] + fn z_returns_third_element() { + let target = Vec4::new(1.0, 2.0, 3.0, 4.0); + assert!(target.z() == 3.0); + } + + #[test] + fn w_returns_third_element() { + let target = Vec4::new(1.0, 2.0, 3.0, 4.0); + assert!(target.w() == 4.0); + } + + #[test] + fn dot_product_returns_correct_result() { + let a = Vec4::new(1.0, 2.0, 3.0, 4.0); + let b = Vec4::new(4.0, 5.0, 6.0, 7.0); + assert!(a.dot(&b) == 60.0); + } + + #[test] + fn add_returns_correct_result() { + let a = Vec4::new(1.0, 2.0, 3.0, 4.0); + let b = Vec4::new(4.0, 5.0, 6.0, 7.0); + let c = Vec4::new(5.0, 7.0, 9.0, 11.0); + assert!(a + b == c); + } + + #[test] + fn add_assign_returns_correct_result() { + let mut a = Vec4::new(1.0, 2.0, 3.0, 4.0); + let b = Vec4::new(4.0, 5.0, 6.0, 7.0); + let c = Vec4::new(5.0, 7.0, 9.0, 11.0); + a += b; + assert!(a == c); + } + + #[test] + fn sub_returns_correct_result() { + let a = Vec4::new(1.0, 2.0, 3.0, 4.0); + let b = Vec4::new(4.0, 6.0, 8.0, 10.0); + let c = Vec4::new(-3.0, -4.0, -5.0, -6.0); + assert!(a - b == c); + } + + #[test] + fn sub_assign_returns_correct_result() { + let mut a = Vec4::new(1.0, 2.0, 3.0, 4.0); + let b = Vec4::new(4.0, 6.0, 8.0, 10.0); + let c = Vec4::new(-3.0, -4.0, -5.0, -6.0); + a -= b; + assert!(a == c); + } + + #[test] + fn mul_by_scalar_returns_correct_result() { + let a = Vec4::new(1.0, 2.0, 3.0, 4.0); + let b = 0.5; + let c = Vec4::new(0.5, 1.0, 1.5, 2.0); + assert!(a * b == c); + } + + #[test] + fn mul_assign_by_scalar_returns_correct_result() { + let mut a = Vec4::new(1.0, 2.0, 3.0, 4.0); + let b = 0.5; + let c = Vec4::new(0.5, 1.0, 1.5, 2.0); + a *= b; + assert!(a == c); + } +} diff --git a/src/matrix.rs b/src/matrix.rs deleted file mode 100644 index b97a27c..0000000 --- a/src/matrix.rs +++ /dev/null @@ -1,154 +0,0 @@ -use std::ops::{Add, AddAssign, Sub, SubAssign}; - -#[derive(PartialEq, Debug)] -pub struct Vec3 { - coords: [f64; 3], -} - -impl Vec3 { - pub fn new(x: f64, y: f64, z: f64) -> Self { - Vec3 { coords: [x, y, z] } - } - - pub fn x(&self) -> f64 { - self.coords[0] - } - - pub fn y(&self) -> f64 { - self.coords[1] - } - - pub fn z(&self) -> f64 { - self.coords[2] - } - - pub fn dot(&self, rhs: &Vec3) -> f64 { - self.coords - .iter() - .zip(rhs.coords.iter()) - .map(|(a_elem, b_elem)| a_elem * b_elem) - .sum() - } - - pub fn cross(&self, rhs: &Vec3) -> Vec3 { - let x = self.y() * rhs.z() - self.z() * rhs.y(); - let y = self.z() * rhs.x() - self.x() * rhs.z(); - let z = self.x() * rhs.y() - self.y() * rhs.x(); - Vec3 { coords: [x, y, z] } - } -} - -impl Add for Vec3 { - type Output = Self; - - fn add(self, other: Self) -> Self { - let x = self.x() + other.x(); - let y = self.y() + other.y(); - let z = self.z() + other.z(); - Vec3 { coords: [x, y, z] } - } -} - -impl AddAssign for Vec3 { - fn add_assign(&mut self, other: Self) { - for (a, b) in self.coords.iter_mut().zip(other.coords.iter()) { - *a += b; - } - } -} - -impl Sub for Vec3 { - type Output = Self; - - fn sub(self, other: Self) -> Self { - let x = self.x() - other.x(); - let y = self.y() - other.y(); - let z = self.z() - other.z(); - Vec3 { coords: [x, y, z] } - } -} - -impl SubAssign for Vec3 { - fn sub_assign(&mut self, other: Self) { - for (a, b) in self.coords.iter_mut().zip(other.coords.iter()) { - *a -= b; - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[cfg(test)] - mod vec3 { - use super::*; - - #[test] - fn x_returns_first_element() { - let target = Vec3::new(1.0, 2.0, 3.0); - assert!(target.x() == 1.0); - } - - #[test] - fn y_returns_second_element() { - let target = Vec3::new(1.0, 2.0, 3.0); - assert!(target.y() == 2.0); - } - - #[test] - fn z_returns_third_element() { - let target = Vec3::new(1.0, 2.0, 3.0); - assert!(target.z() == 3.0); - } - - #[test] - fn dot_product_returns_correct_result() { - let a = Vec3::new(1.0, 2.0, 3.0); - let b = Vec3::new(4.0, 5.0, 6.0); - assert!(a.dot(&b) == 32.0); - } - - #[test] - fn cross_product_returns_correct_result() { - let a = Vec3::new(1.0, 2.0, 3.0); - let b = Vec3::new(4.0, 5.0, 6.0); - let c = Vec3::new(-3.0, 6.0, -3.0); - assert!(a.cross(&b) == c); - } - - #[test] - fn add_returns_correct_result() { - let a = Vec3::new(1.0, 2.0, 3.0); - let b = Vec3::new(4.0, 5.0, 6.0); - let c = Vec3::new(5.0, 7.0, 9.0); - assert!(a + b == c); - } - - #[test] - fn add_assign_returns_correct_result() { - let mut a = Vec3::new(1.0, 2.0, 3.0); - let b = Vec3::new(4.0, 5.0, 6.0); - let c = Vec3::new(5.0, 7.0, 9.0); - a += b; - assert!(a == c); - } - - #[test] - fn sub_returns_correct_result() { - let a = Vec3::new(1.0, 2.0, 3.0); - let b = Vec3::new(4.0, 6.0, 8.0); - let c = Vec3::new(-3.0, -4.0, -5.0); - assert!(a - b == c); - } - - #[test] - fn sub_assign_returns_correct_result() { - let mut a = Vec3::new(1.0, 2.0, 3.0); - let b = Vec3::new(4.0, 6.0, 8.0); - let c = Vec3::new(-3.0, -4.0, -5.0); - a -= b; - assert!(a == c); - } - } -}