diff options
author | lamp | 2023-03-05 21:45:56 +0000 |
---|---|---|
committer | lamp | 2023-03-05 21:45:56 +0000 |
commit | 78ddaff5855bf8446adef9e18eb0d7b7ddcee52a (patch) | |
tree | 0d0e93cfa28751a2f96518eeb231cf715958e1fa /src/vec3.rs |
init
Diffstat (limited to 'src/vec3.rs')
-rw-r--r-- | src/vec3.rs | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/src/vec3.rs b/src/vec3.rs new file mode 100644 index 0000000..8525fdd --- /dev/null +++ b/src/vec3.rs @@ -0,0 +1,201 @@ +use auto_ops::{impl_op_ex, impl_op_ex_commutative}; +use std::fmt; + +pub type Point3 = Vec3; +pub type Color = Vec3; + +#[derive(Clone, Default)] +pub struct Vec3 { + pub x: f64, + pub y: f64, + pub z: f64, +} + +impl Vec3 { + pub fn new() -> Vec3 { + Vec3 { + x: 0.0, + y: 0.0, + z: 0.0, + } + } + + pub fn get(&self, index: usize) -> Option<&f64> { + match index { + 0 => Some(&self.x), + 1 => Some(&self.y), + 2 => Some(&self.z), + _ => None, + } + } + + pub fn get_mut(&mut self, index: usize) -> Option<&mut f64> { + match index { + 0 => Some(&mut self.x), + 1 => Some(&mut self.y), + 2 => Some(&mut self.z), + _ => None, + } + } + + pub fn length(&self) -> f64 { + self.length_squared().sqrt() + } + + pub fn length_squared(&self) -> f64 { + self.x * self.x + self.y * self.y + self.z * self.z + } + + pub fn dot(&self, other: &Vec3) -> f64 { + self.x * other.x + self.y * other.y + self.z * other.z + } + + pub fn cross(&self, other: &Vec3) -> Vec3 { + Vec3 { + x: self.y * other.z - self.z * other.y, + y: self.z * other.x - self.x * other.z, + z: self.x * other.y - self.y * other.x, + } + } + + pub fn unit_vector(&self) -> Vec3 { + self / self.length() + } + + pub fn random() -> Vec3 { + Vec3 { + x: rand::random::<f64>(), + y: rand::random::<f64>(), + z: rand::random::<f64>(), + } + } + + pub fn random_in_range(min: f64, max: f64) -> Vec3 { + Vec3 { + x: min + (max - min) * rand::random::<f64>(), + y: min + (max - min) * rand::random::<f64>(), + z: min + (max - min) * rand::random::<f64>(), + } + } + + pub fn random_in_unit_sphere() -> Vec3 { + loop { + let p = Vec3 { + x: 2.0 * rand::random::<f64>() - 1.0, + y: 2.0 * rand::random::<f64>() - 1.0, + z: 2.0 * rand::random::<f64>() - 1.0, + }; + if p.length_squared() < 1.0 { + return p; + } + }; + } + + pub fn random_unit_vector() -> Vec3 { + Self::random_in_unit_sphere().unit_vector() + } + + pub fn random_in_unit_disk() -> Vec3 { + loop { + let p = Vec3 { + x: 2.0 * rand::random::<f64>() -1.0, + y: 2.0 * rand::random::<f64>() -1.0, + z: 0.0, + }; + if p.length_squared() < 1.0 { + return p; + } + } + } + + pub fn near_zero(&self) -> bool { + const S: f64 = 1e-8; + self.x.abs() < S && self.y.abs() < S && self.z.abs() < S + } + + pub fn reflect(&self, normal: &Vec3) -> Vec3 { + self - 2.0 * self.dot(normal) * normal + } + + pub fn refract(&self, normal: &Vec3, etai_over_etat: f64) -> Vec3 { + let cos_theta = normal.dot(&-self).min(1.0); + let r_out_perp = etai_over_etat * (self + cos_theta * normal); + let r_out_parallel = -((1.0 - r_out_perp.length_squared()).abs().sqrt()) * normal; + r_out_perp + r_out_parallel + } + + pub fn has_infinite_member(&self) -> bool { + self.x.is_infinite() || self.y.is_infinite() || self.z.is_infinite() + } +} + +impl fmt::Display for Vec3 { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{} {} {}", self.x, self.y, self.z) + } +} + +impl<'a> IntoIterator for &'a Vec3 { + type Item = f64; + type IntoIter = Vec3Iterator<'a>; + + fn into_iter(self) -> Self::IntoIter { + Vec3Iterator { + vec3: self, + index: 0, + } + } +} + +pub struct Vec3Iterator<'a> { + vec3: &'a Vec3, + index: usize, +} + +impl<'a> Iterator for Vec3Iterator<'a> { + type Item = f64; + fn next(&mut self) -> Option<f64> { + let result = match self.index { + 0 => self.vec3.x, + 1 => self.vec3.y, + 2 => self.vec3.z, + _ => return None, + }; + self.index += 1; + Some(result) + } +} + +impl_op_ex!(- |a: &Vec3| -> Vec3 { + Vec3 { + x: -a.x, + y: -a.y, + z: -a.z, + } +}); +impl_op_ex!(+= |lhs: &mut Vec3, rhs: Vec3| { *lhs = Vec3 { x: lhs.x + rhs.x, y: lhs.y + rhs.y, z: lhs.z + rhs.z } }); +impl_op_ex!(*= |lhs: &mut Vec3, rhs: &f64| { *lhs = Vec3 { x: lhs.x * rhs, y: lhs.y * rhs, z: lhs.z * rhs } }); +impl_op_ex!(/= |lhs: &mut Vec3, rhs: &f64| { *lhs *= 1.0 / rhs }); +impl_op_ex!(+ |lhs: &Vec3, rhs: &Vec3| -> Vec3 { Vec3 { x: lhs.x + rhs.x, y: lhs.y + rhs.y, z: lhs.z + rhs.z } }); +impl_op_ex!(-|lhs: &Vec3, rhs: &Vec3| -> Vec3 { + Vec3 { + x: lhs.x - rhs.x, + y: lhs.y - rhs.y, + z: lhs.z - rhs.z, + } +}); +impl_op_ex!(*|lhs: &Vec3, rhs: &Vec3| -> Vec3 { + Vec3 { + x: lhs.x * rhs.x, + y: lhs.y * rhs.y, + z: lhs.z * rhs.z, + } +}); +impl_op_ex_commutative!(*|lhs: &Vec3, rhs: &f64| -> Vec3 { + Vec3 { + x: lhs.x * rhs, + y: lhs.y * rhs, + z: lhs.z * rhs, + } +}); +impl_op_ex!(/ |lhs: &Vec3, rhs: &f64| -> Vec3 { lhs * (1.0/rhs) }); |