Added Unit wrapper for normals

A
This commit is contained in:
STP
2023-11-17 14:02:18 -05:00
parent 9383ef5bbf
commit cf56edace6

View File

@@ -1,6 +1,6 @@
use crate::ray::Ray; use crate::ray::Ray;
use crate::{EPSILON, INFINITY}; use crate::{EPSILON, EPSILON_VECTOR, INFINITY};
use nalgebra::{distance, Matrix4, Point3, Vector3}; use nalgebra::{distance, Matrix4, Point3, Unit, Vector3};
use roots::{find_roots_quadratic, Roots}; use roots::{find_roots_quadratic, Roots};
use std::fs::File; use std::fs::File;
use std::io::{BufRead, BufReader}; use std::io::{BufRead, BufReader};
@@ -19,7 +19,31 @@ impl Material {
} }
pub fn magenta() -> Self { pub fn magenta() -> Self {
let kd = Vector3::new(1.0, 0.0, 1.0); let kd = Vector3::new(1.0, 0.0, 1.0);
let ks = Vector3::new(0.0, 1.0, 1.0); let ks = Vector3::new(1.0, 0.0, 1.0);
let shininess = 0.5;
Material { kd, ks, shininess }
}
pub fn turquoise() -> Self {
let kd = Vector3::new(0.25, 1.0, 0.7);
let ks = Vector3::new(0.25, 1.0, 0.7);
let shininess = 0.5;
Material { kd, ks, shininess }
}
pub fn red() -> Self {
let kd = Vector3::new(1.0, 0.0, 0.0);
let ks = Vector3::new(1.0, 0.0, 0.0);
let shininess = 0.5;
Material { kd, ks, shininess }
}
pub fn blue() -> Self {
let kd = Vector3::new(0.0, 0.0, 1.0);
let ks = Vector3::new(0.0, 0.0, 1.0);
let shininess = 0.5;
Material { kd, ks, shininess }
}
pub fn green() -> Self {
let kd = Vector3::new(0.0, 1.0, 0.0);
let ks = Vector3::new(0.0, 1.0, 0.0);
let shininess = 0.5; let shininess = 0.5;
Material { kd, ks, shininess } Material { kd, ks, shininess }
} }
@@ -28,16 +52,16 @@ impl Material {
pub struct Intersection { pub struct Intersection {
// Information about an intersection // Information about an intersection
pub point: Point3<f32>, pub point: Point3<f32>,
pub normal: Vector3<f32>, pub normal: Unit<Vector3<f32>>,
pub incidence: Vector3<f32>, pub incidence: Unit<Vector3<f32>>,
pub material: Arc<Material>, pub material: Arc<Material>,
pub distance: f32, pub distance: f32,
} }
impl Intersection { impl Intersection {
pub fn new( pub fn new(
point: Point3<f32>, point: Point3<f32>,
normal: Vector3<f32>, normal: Unit<Vector3<f32>>,
incidence: Vector3<f32>, incidence: Unit<Vector3<f32>>,
material: Arc<Material>, material: Arc<Material>,
t: f32, t: f32,
) -> Self { ) -> Self {
@@ -58,6 +82,8 @@ struct BoundingBox {
impl BoundingBox { impl BoundingBox {
fn new(bln: Point3<f32>, trf: Point3<f32>) -> Self { fn new(bln: Point3<f32>, trf: Point3<f32>) -> Self {
let bln = bln - EPSILON_VECTOR;
let trf = trf + EPSILON_VECTOR;
BoundingBox { bln, trf } BoundingBox { bln, trf }
} }
fn intersect_bounding_box(&self, ray: &Ray) -> Option<Point3<f32>> { fn intersect_bounding_box(&self, ray: &Ray) -> Option<Point3<f32>> {
@@ -73,6 +99,9 @@ impl BoundingBox {
None None
} }
} }
fn get_centroid(&self) -> Point3<f32> {
self.bln + (self.trf - self.bln) / 2.0
}
} }
// PRIMITIVE TRAIT ----------------------------------------------------------------- // PRIMITIVE TRAIT -----------------------------------------------------------------
pub trait Primitive { pub trait Primitive {
@@ -137,7 +166,7 @@ impl Primitive for Sphere {
}; };
let intersect = ray.at_t(t); let intersect = ray.at_t(t);
let normal = (intersect - self.position).normalize(); let normal = Unit::new_normalize(intersect - self.position);
Some(Intersection { Some(Intersection {
point: intersect, point: intersect,
normal, normal,
@@ -220,7 +249,7 @@ impl Primitive for Circle {
false => { false => {
return Some(Intersection { return Some(Intersection {
point: intersect, point: intersect,
normal: self.normal, normal: Unit::new_normalize(self.normal),
incidence: ray.b, incidence: ray.b,
material: Arc::clone(&self.material), material: Arc::clone(&self.material),
distance: t, distance: t,
@@ -342,7 +371,7 @@ impl Primitive for Cone {
match intersect.y >= self.base && intersect.y <= self.height { match intersect.y >= self.base && intersect.y <= self.height {
true => Some(Intersection { true => Some(Intersection {
point: intersect, point: intersect,
normal: self.get_normal(intersect), normal: Unit::new_normalize(self.get_normal(intersect)),
material: Arc::clone(&self.material), material: Arc::clone(&self.material),
incidence: ray.b, incidence: ray.b,
distance: t, distance: t,
@@ -447,7 +476,7 @@ impl Primitive for Rectangle {
if pi_dot_r1 >= -w2 && pi_dot_r1 <= w2 && pi_dot_r2 >= -h2 && pi_dot_r2 <= h2 { if pi_dot_r1 >= -w2 && pi_dot_r1 <= w2 && pi_dot_r2 >= -h2 && pi_dot_r2 <= h2 {
return Some(Intersection { return Some(Intersection {
point: intersect, point: intersect,
normal: self.normal, normal: Unit::new_normalize(self.normal),
incidence: ray.b, incidence: ray.b,
material: Arc::clone(&self.material), material: Arc::clone(&self.material),
distance: t, distance: t,
@@ -534,7 +563,7 @@ impl Primitive for Box {
Some(Intersection { Some(Intersection {
point: intersect, point: intersect,
normal, normal: Unit::new_normalize(normal),
incidence: ray.b, incidence: ray.b,
material: Arc::clone(&self.material), material: Arc::clone(&self.material),
distance: tmin, distance: tmin,
@@ -619,7 +648,7 @@ impl Primitive for Triangle {
{ {
Some(Intersection { Some(Intersection {
point: intersect, point: intersect,
normal, normal: Unit::new_normalize(normal),
incidence: ray.b, incidence: ray.b,
material: Arc::clone(&self.material), material: Arc::clone(&self.material),
distance: t, distance: t,