use super::utility; use std::ops::*; #[derive(Clone, Copy, Debug)] pub struct Vec3 { pub e: [f64; 3], } pub type Color = Vec3; pub type Point3 = Vec3; impl Vec3 { pub fn new(x: f64, y: f64, z: f64) -> Self { Vec3 { e: [x, y, z] } } pub fn length(&self) -> f64 { self.length_squared().sqrt() } pub fn length_squared(&self) -> f64 { self.e[0] * self.e[0] + self.e[1] * self.e[1] + self.e[2] * self.e[2] } pub fn cross(a: Vec3, b: Vec3) -> Vec3 { Vec3::new( a.y() * b.z() - a.z() * b.y(), a.z() * b.x() - a.x() * b.z(), a.x() * b.y() - a.y() * b.x(), ) } pub fn dot(a: Vec3, b: Vec3) -> f64 { a.x() * b.x() + a.y() * b.y() + a.z() * b.z() } pub fn unit_vector(a: Vec3) -> Vec3 { a / a.length() } pub fn random_f64() -> Vec3 { Vec3::new( utility::random_f64(), utility::random_f64(), utility::random_f64(), ) } pub fn random_rng(min: f64, max: f64) -> Self { Self::new( utility::random_rng(min, max), utility::random_rng(min, max), utility::random_rng(min, max), ) } pub fn random_in_unit_sphere() -> Self { loop { let p = Vec3::random_rng(-1.0, 1.0); if p.length_squared() >= 1.0 { continue; }; return p; } } pub fn random_unit_vector() -> Self { Self::unit_vector(Self::random_in_unit_sphere()) } pub fn random_in_hemisphere(&self) -> Self { let in_unit_sphere = Self::random_in_unit_sphere(); if Self::dot(in_unit_sphere, *self) > 0.0 { return in_unit_sphere; } else { return -1.0 * in_unit_sphere; } } pub fn x(&self) -> f64 { self.e[0] } pub fn y(&self) -> f64 { self.e[1] } pub fn z(&self) -> f64 { self.e[2] } } impl Add for Vec3 { type Output = Vec3; fn add(self, rhs: Self) -> Vec3 { Vec3::new(self.x() + rhs.x(), self.y() + rhs.y(), self.z() + rhs.z()) } } impl AddAssign for Vec3 { fn add_assign(&mut self, rhs: Self) { self.e[0] += rhs.x(); self.e[1] += rhs.y(); self.e[2] += rhs.z(); } } impl Sub for Vec3 { type Output = Vec3; fn sub(self, rhs: Self) -> Vec3 { Vec3::new(self.x() - rhs.x(), self.y() - rhs.y(), self.z() - rhs.z()) } } impl SubAssign for Vec3 { fn sub_assign(&mut self, rhs: Self) { self.e[0] -= rhs.x(); self.e[1] -= rhs.y(); self.e[2] -= rhs.z(); } } impl Mul for f64 { type Output = Vec3; fn mul(self, rhs: Vec3) -> Vec3 { Vec3::new(self * rhs.x(), self * rhs.y(), self * rhs.z()) } } impl MulAssign for Vec3 { fn mul_assign(&mut self, rhs: f64) { self.e[0] *= rhs; self.e[1] *= rhs; self.e[2] *= rhs; } } impl DivAssign for Vec3 { fn div_assign(&mut self, rhs: f64) { self.e[0] /= rhs; self.e[1] /= rhs; self.e[2] /= rhs; } } impl Div for Vec3 { type Output = Vec3; fn div(self, rhs: f64) -> Vec3 { Vec3::new(self.x() / rhs, self.y() / rhs, self.z() / rhs) } }