#[allow(unused)] pub mod calculus { use rand::Rng; #[derive(Copy, Clone, Debug)] pub struct Vec3 { pub x: f32, pub y: f32, pub z: f32, // cached: Vec3Cache, } pub type Point3 = Vec3; impl Vec3 { pub fn new(x: f32, y: f32, z: f32) -> Self { Self { x, y, z } } fn random() -> Self { let mut rng = rand::rng(); Self::new( rng.random(), rng.random(), rng.random(), ) } fn random_range(min: f32, max: f32) -> Self { let mut rng = rand::rng(); Self::new( rng.random_range(min..max), rng.random_range(min..max), rng.random_range(min..max), ) } pub fn random_unit() -> Vec3 { loop { let p = Self::random_range(-1.0, 1.0); let lensq = p.mag_sqr(); if f32::EPSILON < lensq && lensq <= 1.0 { return p.scalar_mul(1.0 / lensq.sqrt()) } } } pub fn random_on_hemisphere(normal: &Vec3) -> Vec3 { let on_unit_sphere = Self::random_unit(); if on_unit_sphere.dot_prod(normal) > 0.0 { on_unit_sphere } else { on_unit_sphere.scalar_mul(-1.0) } } pub fn add(&self, other: &Self) -> Self { Self { x: self.x + other.x, y: self.y + other.y, z: self.z + other.z } } pub fn sub(&self, other: &Self) -> Self { Self { x: self.x - other.x, y: self.y - other.y, z: self.z - other.z } } pub fn scalar_mul(&self, multiplier: f32) -> Self { Self { x: self.x * multiplier, y: self.y * multiplier, z: self.z * multiplier, } } pub fn mag_sqr(&self) -> f32 { self.x * self.x + self.y * self.y + self.z * self.z } pub fn mag(&self) -> f32 { self.mag_sqr().sqrt() } pub fn dot_prod(&self, other: &Self) -> f32 { self.x * other.x + self.y * other.y + self.z * other.z } pub fn cross_prod(&self, other: &Self) -> Self { Self { 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(&self) -> Self { let mag = self.mag(); Self { x: self.x / mag, y: self.y / mag, z: self.z / mag, } } pub fn is_near_zero(&self) -> bool { self.x.abs() < f32::EPSILON && self.y.abs() < f32::EPSILON && self.z.abs() < f32::EPSILON } pub fn reflect(&self, normal: &Self) -> Self { self.sub( &normal.scalar_mul( 2.0 * self.dot_prod(&normal) ) ) } pub fn refract(&self, normal: &Self, etai_over_etat: f32) -> Self { let cos_theta = f32::min( 1.0, self.scalar_mul(-1.0).dot_prod(&normal) ); let r_out_perp = self .add(&normal.scalar_mul(cos_theta)) .scalar_mul(etai_over_etat); let f = (1.0 - r_out_perp.mag_sqr()).abs().sqrt(); let r_out_parallel = normal.scalar_mul(-1.0 * f); r_out_perp.add(&r_out_parallel) } pub fn random_in_unit_disk() -> Self { let mut rng = rand::rng(); loop { let p = Vec3::new( rng.random_range(-1.0..1.0), rng.random_range(-1.0..1.0), 0.0 ); if p.mag_sqr() < 1.0 { return p; } } } } pub struct Ray { pub origin: Point3, pub direction: Vec3, } impl Ray { pub fn at(&self, t: f32) -> Point3 { // Get parametric location self.origin.add(&self.direction.scalar_mul(t)) } pub fn reflect(&self, normal: &Vec3) -> Vec3 { // return unit direction vector self.direction.reflect(&normal).unit() } pub fn refract(&self, normal: &Vec3, etai_over_etat: f32) -> Vec3 { // return unit direction vector self.direction.unit().refract(&normal, etai_over_etat) } } pub fn deg2rad(deg: f32) -> f32 { deg * std::f32::consts::PI / 180.0 } pub fn sample_square() -> Vec3 { // Returns the vector to a random point in the [-.5,-.5]-[+.5,+.5] unit square. let mut rng = rand::rng(); Vec3::new( rng.random_range(0.0..1.0) - 0.5, rng.random_range(0.0..1.0) - 0.5, 0.0) } }