vec3.rs (5044B)
1 use std::{ 2 fmt::{Debug, Display}, 3 ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub}, 4 }; 5 6 use crate::random::RandomNumberGenerator; 7 8 #[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd)] 9 pub struct Vec3 { 10 x: f64, 11 y: f64, 12 z: f64, 13 } 14 15 impl Vec3 { 16 pub const fn new(x: f64, y: f64, z: f64) -> Self { 17 Vec3 { x, y, z } 18 } 19 20 pub fn random(rng: &mut RandomNumberGenerator, min: f64, max: f64) -> Self { 21 Vec3::new( 22 rng.next_f64_in_range(min, max), 23 rng.next_f64_in_range(min, max), 24 rng.next_f64_in_range(min, max), 25 ) 26 } 27 28 pub fn random_unit(rng: &mut RandomNumberGenerator) -> Self { 29 loop { 30 let p = Vec3::random(rng, -1., 1.); 31 let length_squared = p.length_squared(); 32 if 1e-160 < length_squared && length_squared <= 1. { 33 return p / length_squared.sqrt(); 34 } 35 } 36 } 37 38 pub fn random_on_hemisphere(rng: &mut RandomNumberGenerator, normal: &Vec3) -> Self { 39 let on_unit_sphere = Vec3::random_unit(rng); 40 if on_unit_sphere.dot(normal) > 0. { 41 on_unit_sphere 42 } else { 43 -on_unit_sphere 44 } 45 } 46 47 pub fn random_in_unit_disk(rng: &mut RandomNumberGenerator) -> Self { 48 loop { 49 let p = Vec3::new( 50 rng.next_f64_in_range(-1., 1.), 51 rng.next_f64_in_range(-1., 1.), 52 0., 53 ); 54 if p.length_squared() < 1. { 55 return p; 56 } 57 } 58 } 59 60 pub const fn x(&self) -> f64 { 61 self.x 62 } 63 64 pub const fn y(&self) -> f64 { 65 self.y 66 } 67 68 pub const fn z(&self) -> f64 { 69 self.z 70 } 71 72 pub const fn cross(&self, other: &Vec3) -> Vec3 { 73 Vec3 { 74 x: self.y * other.z - self.z * other.y, 75 y: self.z * other.x - self.x * other.z, 76 z: self.x * other.y - self.y * other.x, 77 } 78 } 79 80 pub const fn dot(&self, other: &Vec3) -> f64 { 81 self.x * other.x + self.y * other.y + self.z * other.z 82 } 83 84 pub fn length(&self) -> f64 { 85 self.length_squared().sqrt() 86 } 87 88 pub fn length_squared(&self) -> f64 { 89 self.x.powi(2) + self.y.powi(2) + self.z.powi(2) 90 } 91 92 pub fn unit(&self) -> Vec3 { 93 *self / self.length() 94 } 95 96 pub fn near_zero(&self) -> bool { 97 const THRESHOLD: f64 = 1e-8; 98 self.x().abs() < THRESHOLD && self.y().abs() < THRESHOLD && self.z().abs() < THRESHOLD 99 } 100 101 pub fn reflect(&self, normal: &Vec3) -> Vec3 { 102 *self - 2. * self.dot(normal) * *normal 103 } 104 105 pub fn refract(&self, normal: &Vec3, refractive_index_ratio: f64) -> Vec3 { 106 let cosine_theta = (-*self).dot(normal).min(1.); 107 let r_out_perpendicular = refractive_index_ratio * (*self + cosine_theta * *normal); 108 let r_out_parallel = -(1. - r_out_perpendicular.length_squared()).abs().sqrt() * *normal; 109 r_out_perpendicular + r_out_parallel 110 } 111 } 112 113 impl Add for Vec3 { 114 type Output = Self; 115 116 fn add(self, rhs: Self) -> Self::Output { 117 Vec3 { 118 x: self.x + rhs.x, 119 y: self.y + rhs.y, 120 z: self.z + rhs.z, 121 } 122 } 123 } 124 125 impl AddAssign for Vec3 { 126 fn add_assign(&mut self, rhs: Self) { 127 self.x += rhs.x; 128 self.y += rhs.y; 129 self.z += rhs.z; 130 } 131 } 132 133 impl Display for Vec3 { 134 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 135 write!(f, "{} {} {}", self.x, self.y, self.z) 136 } 137 } 138 139 impl DivAssign<f64> for Vec3 { 140 fn div_assign(&mut self, rhs: f64) { 141 self.x /= rhs; 142 self.y /= rhs; 143 self.z /= rhs; 144 } 145 } 146 147 impl Div<f64> for Vec3 { 148 type Output = Vec3; 149 150 fn div(self, rhs: f64) -> Self::Output { 151 Vec3 { 152 x: self.x / rhs, 153 y: self.y / rhs, 154 z: self.z / rhs, 155 } 156 } 157 } 158 159 impl MulAssign<f64> for Vec3 { 160 fn mul_assign(&mut self, rhs: f64) { 161 self.x *= rhs; 162 self.y *= rhs; 163 self.z *= rhs; 164 } 165 } 166 167 impl Mul<f64> for Vec3 { 168 type Output = Vec3; 169 170 fn mul(self, rhs: f64) -> Self::Output { 171 Vec3 { 172 x: self.x * rhs, 173 y: self.y * rhs, 174 z: self.z * rhs, 175 } 176 } 177 } 178 179 impl Mul<Vec3> for f64 { 180 type Output = Vec3; 181 182 fn mul(self, rhs: Vec3) -> Self::Output { 183 rhs * self 184 } 185 } 186 187 impl Mul<Vec3> for Vec3 { 188 type Output = Vec3; 189 190 fn mul(self, rhs: Vec3) -> Self::Output { 191 Vec3 { 192 x: self.x * rhs.x, 193 y: self.y * rhs.y, 194 z: self.z * rhs.z, 195 } 196 } 197 } 198 199 impl Neg for Vec3 { 200 type Output = Self; 201 202 fn neg(self) -> Self::Output { 203 Vec3 { 204 x: -self.x, 205 y: -self.y, 206 z: -self.z, 207 } 208 } 209 } 210 211 impl Sub for Vec3 { 212 type Output = Vec3; 213 214 fn sub(self, rhs: Self) -> Self::Output { 215 Vec3 { 216 x: self.x - rhs.x, 217 y: self.y - rhs.y, 218 z: self.z - rhs.z, 219 } 220 } 221 }