Fix a vector negation bug.

This commit is contained in:
Savanni D'Gerinel 2024-07-21 20:59:28 -04:00
parent f347e2e47d
commit 4d67ea4af2
3 changed files with 71 additions and 16 deletions

View File

@ -6,7 +6,14 @@ use std::{
sync::{Arc, RwLock}, sync::{Arc, RwLock},
}; };
const SIZE: usize = 100; const SIZE: usize = 1000;
const EPSILON: f64 = 0.00001;
fn eq_f64(l: f64, r: f64) -> bool {
(l - r).abs() < EPSILON
}
fn render( fn render(
camera: &Point, camera: &Point,
@ -23,6 +30,7 @@ fn render(
let ray = Ray::new(camera.clone(), (Point::new(0., 0., wall_z) - camera).normalize()); let ray = Ray::new(camera.clone(), (Point::new(0., 0., wall_z) - camera).normalize());
let xs = ray.intersect(sphere); let xs = ray.intersect(sphere);
/*
match xs.hit() { match xs.hit() {
Some(hit) => { Some(hit) => {
let point = ray.position(hit.t); let point = ray.position(hit.t);
@ -33,6 +41,7 @@ fn render(
} }
None => {} None => {}
} }
*/
(0..SIZE).into_par_iter().for_each(|x| { (0..SIZE).into_par_iter().for_each(|x| {
(0..SIZE).into_par_iter().for_each(|y| { (0..SIZE).into_par_iter().for_each(|y| {
@ -47,6 +56,7 @@ fn render(
let point = ray.position(hit.t); let point = ray.position(hit.t);
let normal = hit.object.normal_at(&point); let normal = hit.object.normal_at(&point);
let eye = -ray.direction; let eye = -ray.direction;
let color = hit let color = hit
.object .object
.material() .material()
@ -73,29 +83,43 @@ fn main() {
let camera = Point::new(0., 0., -5.); let camera = Point::new(0., 0., -5.);
let wall_z = 10.; let wall_z = 10.;
let wall_size = 7.; let wall_size = 7.;
let light = PointLight::new(Point::new(-5., 5., -10.), Color::new(1., 1., 1.));
render(&camera, &light, &sphere, wall_z, wall_size, "sphere_1.ppm");
/*
{ {
let light = PointLight::new(Point::new(0., 0., -10.), Color::new(1., 1., 1.)); let light = PointLight::new(Point::new(0., 0., -10.), Color::new(1., 1., 1.));
println!("Light at {:0.2} {:0.2} {:0.2}", light.position.x(), light.position.y(), light.position.z());
render(&camera, &light, &sphere, wall_z, wall_size, "sphere_1.ppm"); render(&camera, &light, &sphere, wall_z, wall_size, "sphere_1.ppm");
println!();
} }
{ {
let light = PointLight::new(Point::new(-1., 0., -10.), Color::new(1., 1., 1.)); let light = PointLight::new(Point::new(-2., 0., -10.), Color::new(1., 1., 1.));
println!("Light at {:0.2} {:0.2} {:0.2}", light.position.x(), light.position.y(), light.position.z());
render(&camera, &light, &sphere, wall_z, wall_size, "sphere_2.ppm"); render(&camera, &light, &sphere, wall_z, wall_size, "sphere_2.ppm");
println!();
} }
{ {
let light = PointLight::new(Point::new(1., 0., -10.), Color::new(1., 1., 1.)); let light = PointLight::new(Point::new(2., 0., -10.), Color::new(1., 1., 1.));
println!("Light at {:0.2} {:0.2} {:0.2}", light.position.x(), light.position.y(), light.position.z());
render(&camera, &light, &sphere, wall_z, wall_size, "sphere_3.ppm"); render(&camera, &light, &sphere, wall_z, wall_size, "sphere_3.ppm");
println!();
} }
{ {
let light = PointLight::new(Point::new(0., -1., -10.), Color::new(1., 1., 1.)); let light = PointLight::new(Point::new(0., -2., -10.), Color::new(1., 1., 1.));
println!("Light at {:0.2} {:0.2} {:0.2}", light.position.x(), light.position.y(), light.position.z());
render(&camera, &light, &sphere, wall_z, wall_size, "sphere_4.ppm"); render(&camera, &light, &sphere, wall_z, wall_size, "sphere_4.ppm");
println!();
} }
{ {
let light = PointLight::new(Point::new(0., 1., -10.), Color::new(1., 1., 1.)); let light = PointLight::new(Point::new(0., 2., -10.), Color::new(1., 1., 1.));
println!("Light at {:0.2} {:0.2} {:0.2}", light.position.x(), light.position.y(), light.position.z());
render(&camera, &light, &sphere, wall_z, wall_size, "sphere_5.ppm"); render(&camera, &light, &sphere, wall_z, wall_size, "sphere_5.ppm");
println!();
} }
*/
} }

View File

@ -1,4 +1,4 @@
use super::{Color, Point, PointLight, Vector}; use super::{eq_f64, Color, Point, PointLight, Vector};
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub struct Material { pub struct Material {
@ -22,7 +22,25 @@ impl Default for Material {
} }
impl Material { impl Material {
pub fn lighting(&self, light: &PointLight, position: &Point, eye: &Vector, normal_v: &Vector) -> Color { pub fn lighting(
&self,
light: &PointLight,
position: &Point,
eye: &Vector,
normal_v: &Vector,
) -> Color {
// let debug = eq_f64(position.x(), -0.09344)
// || eq_f64(position.x(), 0.09344) && eq_f64(position.y(), 0.)
// || eq_f64(position.y(), -0.09344)
// || eq_f64(position.y(), 0.09344) && eq_f64(position.x(), 0.);
// if debug {
// println!(
// "Debugging {:0.5} {:0.5} {:0.5}",
// position.x(),
// position.y(),
// position.z()
// );
// }
let effective_color = self.color * light.intensity; let effective_color = self.color * light.intensity;
let light_v = (light.position - position).normalize(); let light_v = (light.position - position).normalize();
@ -53,8 +71,8 @@ impl Material {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::types::{Color, Point, PointLight, Vector};
use super::*; use super::*;
use crate::types::{Color, Point, PointLight, Vector};
#[test] #[test]
fn lighting_with_eye_between_light_and_surface() { fn lighting_with_eye_between_light_and_surface() {
@ -65,7 +83,10 @@ mod tests {
let normalv = Vector::new(0., 0., -1.); let normalv = Vector::new(0., 0., -1.);
let light = PointLight::new(Point::new(0., 0., -10.), Color::new(1., 1., 1.)); let light = PointLight::new(Point::new(0., 0., -10.), Color::new(1., 1., 1.));
assert_eq!(m.lighting(&light, &position, &eyev, &normalv), Color::new(1.9, 1.9, 1.9)); assert_eq!(
m.lighting(&light, &position, &eyev, &normalv),
Color::new(1.9, 1.9, 1.9)
);
} }
#[test] #[test]
@ -77,7 +98,10 @@ mod tests {
let normalv = Vector::new(0., 0., -1.); let normalv = Vector::new(0., 0., -1.);
let light = PointLight::new(Point::new(0., 0., -10.), Color::new(1., 1., 1.)); let light = PointLight::new(Point::new(0., 0., -10.), Color::new(1., 1., 1.));
assert_eq!(m.lighting(&light, &position, &eyev, &normalv), Color::new(1., 1., 1.)); assert_eq!(
m.lighting(&light, &position, &eyev, &normalv),
Color::new(1., 1., 1.)
);
} }
#[test] #[test]
@ -89,7 +113,10 @@ mod tests {
let normalv = Vector::new(0., 0., -1.); let normalv = Vector::new(0., 0., -1.);
let light = PointLight::new(Point::new(0., 10., -10.), Color::new(1., 1., 1.)); let light = PointLight::new(Point::new(0., 10., -10.), Color::new(1., 1., 1.));
assert_eq!(m.lighting(&light, &position, &eyev, &normalv), Color::new(0.7364, 0.7364, 0.7364)); assert_eq!(
m.lighting(&light, &position, &eyev, &normalv),
Color::new(0.7364, 0.7364, 0.7364)
);
} }
#[test] #[test]
@ -102,7 +129,10 @@ mod tests {
let normalv = Vector::new(0., 0., -1.); let normalv = Vector::new(0., 0., -1.);
let light = PointLight::new(Point::new(0., 10., -10.), Color::new(1., 1., 1.)); let light = PointLight::new(Point::new(0., 10., -10.), Color::new(1., 1., 1.));
assert_eq!(m.lighting(&light, &position, &eyev, &normalv), Color::new(1.6364, 1.6364, 1.6364)); assert_eq!(
m.lighting(&light, &position, &eyev, &normalv),
Color::new(1.6364, 1.6364, 1.6364)
);
} }
#[test] #[test]
@ -114,6 +144,9 @@ mod tests {
let normalv = Vector::new(0., 0., -1.); let normalv = Vector::new(0., 0., -1.);
let light = PointLight::new(Point::new(0., 0., 10.), Color::new(1., 1., 1.)); let light = PointLight::new(Point::new(0., 0., 10.), Color::new(1., 1., 1.));
assert_eq!(m.lighting(&light, &position, &eyev, &normalv), Color::new(0.1, 0.1, 0.1)); assert_eq!(
m.lighting(&light, &position, &eyev, &normalv),
Color::new(0.1, 0.1, 0.1)
);
} }
} }

View File

@ -106,9 +106,7 @@ impl std::ops::Sub for Vector {
impl std::ops::Neg for Vector { impl std::ops::Neg for Vector {
type Output = Vector; type Output = Vector;
fn neg(self) -> Self::Output { fn neg(self) -> Self::Output {
let mut t = -self.0; Vector::from(-self.0)
t.0 = 0.;
Vector::from(t)
} }
} }