1use std::ops::Deref;2use std::ops::Neg;34use crate::math::Interval;56#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Default)]7pub struct Vec3 {8 pub x: f64,9 pub y: f64,10 pub z: f64,11}1213impl Vec3 {14 pub fn length(&self) -> f64 {15 self.length_squared().sqrt()16 }1718 pub fn length_squared(&self) -> f64 {19 self.x * self.x + self.y * self.y + self.z * self.z20 }2122 pub fn dot(self, rhs: &Self) -> f64 {23 self.x * rhs.x + self.y * rhs.y + self.z * rhs.z24 }2526 pub fn cross(self, rhs: &Self) -> Vec3 {27 Vec3 {28 x: self.y * rhs.z - self.z * rhs.y,29 y: self.z * rhs.x - self.x * rhs.z,30 z: self.x * rhs.y - self.y * rhs.x,31 }32 }3334 pub fn normalize(self) -> NormalizedVec3 {35 let length = self.length();36 NormalizedVec3(self / length)37 }3839 pub fn random<R: rand::Rng>(rng: &mut R, range: &Interval) -> Vec3 {40 Vec3 {41 x: rng.random_range(range.min..=range.max),42 y: rng.random_range(range.min..=range.max),43 z: rng.random_range(range.min..=range.max),44 }45 }4647 pub fn random_on_unit_sphere<R: rand::Rng>(rng: &mut R) -> NormalizedVec3 {48 loop {49 let v = Self::random(rng, &Interval::new(-1., 1.).unwrap());50 let lensq = v.length_squared();51 if lensq > 1e-160 && lensq <= 1. {52 return v.normalize();53 }54 }55 }5657 pub fn random_on_unit_hemisphere<R: rand::Rng>(58 rng: &mut R,59 normal: &NormalizedVec3,60 ) -> NormalizedVec3 {61 let on_unit_sphere = Self::random_on_unit_sphere(rng);62 if on_unit_sphere.dot(normal) > 0. {63 on_unit_sphere64 } else {65 -on_unit_sphere66 }67 }68}6970#[derive(Debug, Copy, Clone)]71pub struct NormalizedVec3(Vec3);7273impl NormalizedVec3 {74 pub fn get(self) -> Vec3 {75 self.076 }7778 pub fn x(&self) -> f64 {79 self.0.x80 }8182 pub fn y(&self) -> f64 {83 self.0.y84 }8586 pub fn z(&self) -> f64 {87 self.0.z88 }89}9091impl Deref for NormalizedVec3 {92 type Target = Vec3;9394 fn deref(&self) -> &Self::Target {95 &self.096 }97}9899impl Neg for NormalizedVec3 {100 type Output = Self;101102 fn neg(self) -> Self::Output {103 Self(self.0.neg())104 }105}106107impl std::ops::Add for Vec3 {108 type Output = Vec3;109110 fn add(self, rhs: Self) -> Self::Output {111 Vec3 {112 x: self.x + rhs.x,113 y: self.y + rhs.y,114 z: self.z + rhs.z,115 }116 }117}118119impl std::ops::AddAssign for Vec3 {120 fn add_assign(&mut self, rhs: Self) {121 self.x += rhs.x;122 self.y += rhs.y;123 self.z += rhs.z;124 }125}126127impl std::ops::Add<f64> for Vec3 {128 type Output = Vec3;129130 fn add(self, rhs: f64) -> Self::Output {131 Vec3 {132 x: self.x + rhs,133 y: self.y + rhs,134 z: self.z + rhs,135 }136 }137}138139impl std::ops::AddAssign<f64> for Vec3 {140 fn add_assign(&mut self, rhs: f64) {141 self.x += rhs;142 self.y += rhs;143 self.z += rhs;144 }145}146147impl std::ops::Sub for Vec3 {148 type Output = Vec3;149150 fn sub(self, rhs: Self) -> Self::Output {151 Vec3 {152 x: self.x - rhs.x,153 y: self.y - rhs.y,154 z: self.z - rhs.z,155 }156 }157}158159impl std::ops::SubAssign for Vec3 {160 fn sub_assign(&mut self, rhs: Self) {161 self.x -= rhs.x;162 self.y -= rhs.y;163 self.z -= rhs.z;164 }165}166167impl std::ops::Sub<f64> for Vec3 {168 type Output = Vec3;169170 fn sub(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}178179impl std::ops::SubAssign<f64> for Vec3 {180 fn sub_assign(&mut self, rhs: f64) {181 self.x -= rhs;182 self.y -= rhs;183 self.z -= rhs;184 }185}186187impl std::ops::Mul<f64> for Vec3 {188 type Output = Vec3;189190 fn mul(self, rhs: f64) -> Self::Output {191 Vec3 {192 x: self.x * rhs,193 y: self.y * rhs,194 z: self.z * rhs,195 }196 }197}198199impl std::ops::MulAssign<f64> for Vec3 {200 fn mul_assign(&mut self, rhs: f64) {201 self.x *= rhs;202 self.y *= rhs;203 self.z *= rhs;204 }205}206207impl std::ops::Div<f64> for Vec3 {208 type Output = Vec3;209210 fn div(self, rhs: f64) -> Self::Output {211 Vec3 {212 x: self.x / rhs,213 y: self.y / rhs,214 z: self.z / rhs,215 }216 }217}218219impl std::ops::DivAssign<f64> for Vec3 {220 fn div_assign(&mut self, rhs: f64) {221 self.x /= rhs;222 self.y /= rhs;223 self.z /= rhs;224 }225}226227impl std::ops::Neg for Vec3 {228 type Output = Vec3;229230 fn neg(self) -> Self::Output {231 Vec3 {232 x: -self.x,233 y: -self.y,234 z: -self.z,235 }236 }237}238239pub type Color = Vec3;240pub type Point = Vec3;241242impl Color {243 pub fn bytes(&self) -> [u8; 6] {244 let r = (self.x * 65535.).round() as u16;245 let g = (self.y * 65535.).round() as u16;246 let b = (self.z * 65535.).round() as u16;247248 [249 (r >> 8) as u8,250 (r & 0xFF) as u8,251 (g >> 8) as u8,252 (g & 0xFF) as u8,253 (b >> 8) as u8,254 (b & 0xFF) as u8,255 ]256 }257}258259#[cfg(test)]260mod tests {261 use super::Vec3;262263 #[test]264 fn vec3_add() {265 let l = Vec3 {266 x: 1.,267 y: 2.,268 z: 3.,269 };270 let r = Vec3 {271 x: 30.,272 y: 20.,273 z: 10.,274 };275276 let sum = l + r;277 assert_eq!(278 sum,279 Vec3 {280 x: 31.,281 y: 22.,282 z: 13.,283 }284 );285 }286287 #[test]288 fn vec3_add_assign() {289 let mut l = Vec3 {290 x: 1.,291 y: 2.,292 z: 3.,293 };294 let r = Vec3 {295 x: 30.,296 y: 20.,297 z: 10.,298 };299300 l += r;301 assert_eq!(302 l,303 Vec3 {304 x: 31.,305 y: 22.,306 z: 13.,307 }308 );309 }310311 #[test]312 fn vec3_sub() {313 let l = Vec3 {314 x: 30.,315 y: 20.,316 z: 10.,317 };318 let r = Vec3 {319 x: 1.,320 y: 2.,321 z: 3.,322 };323324 let dif = l - r;325 assert_eq!(326 dif,327 Vec3 {328 x: 29.,329 y: 18.,330 z: 7.,331 }332 );333 }334335 #[test]336 fn vec3_sub_assign() {337 let mut l = Vec3 {338 x: 30.,339 y: 20.,340 z: 10.,341 };342 let r = Vec3 {343 x: 1.,344 y: 2.,345 z: 3.,346 };347348 l -= r;349 assert_eq!(350 l,351 Vec3 {352 x: 29.,353 y: 18.,354 z: 7.,355 }356 );357 }358359 #[test]360 fn vec3_mul_vec3() {361 let l = Vec3 {362 x: 2.,363 y: 3.,364 z: 4.,365 };366367 let prod = l * 10.;368 assert_eq!(369 prod,370 Vec3 {371 x: 20.,372 y: 30.,373 z: 40.,374 }375 );376 }377378 #[test]379 fn vec3_mul_assign() {380 let mut l = Vec3 {381 x: 2.,382 y: 3.,383 z: 4.,384 };385386 l *= 10.;387 assert_eq!(388 l,389 Vec3 {390 x: 20.,391 y: 30.,392 z: 40.,393 }394 );395 }396397 #[test]398 fn vec3_div() {399 let l = Vec3 {400 x: 20.,401 y: 30.,402 z: 40.,403 };404405 let div = l / 10.;406 assert_eq!(407 div,408 Vec3 {409 x: 2.,410 y: 3.,411 z: 4.,412 }413 );414 }415416 #[test]417 fn vec3_div_assign() {418 let mut l = Vec3 {419 x: 20.,420 y: 30.,421 z: 40.,422 };423424 l /= 10.;425 assert_eq!(426 l,427 Vec3 {428 x: 2.,429 y: 3.,430 z: 4.,431 }432 );433 }434}