From 0000029064c43059853ee6850b9e522ca50dc705 Mon Sep 17 00:00:00 2001 From: Michael Zhang Date: Thu, 2 Feb 2023 19:06:04 -0600 Subject: [PATCH] Filter out t < 0 --- assignment-1a/src/main.rs | 2 +- assignment-1a/src/scene/cylinder.rs | 16 +++++++++------- assignment-1a/src/scene/sphere.rs | 11 +++++++++-- assignment-1a/src/{math.rs => utils.rs} | 11 +++++++++++ 4 files changed, 30 insertions(+), 10 deletions(-) rename assignment-1a/src/{math.rs => utils.rs} (72%) diff --git a/assignment-1a/src/main.rs b/assignment-1a/src/main.rs index 588a297..08fcbe1 100644 --- a/assignment-1a/src/main.rs +++ b/assignment-1a/src/main.rs @@ -3,7 +3,7 @@ extern crate anyhow; mod image; mod input_file; -mod math; +mod utils; mod ray; mod scene; diff --git a/assignment-1a/src/scene/cylinder.rs b/assignment-1a/src/scene/cylinder.rs index 87b552a..90faac4 100644 --- a/assignment-1a/src/scene/cylinder.rs +++ b/assignment-1a/src/scene/cylinder.rs @@ -1,7 +1,7 @@ use nalgebra::Vector3; -use ordered_float::NotNan; -use crate::{math::compute_rotation_matrix, ray::Ray}; +use crate::ray::Ray; +use crate::utils::{compute_rotation_matrix, min_f64}; use super::data::ObjectKind; @@ -113,12 +113,14 @@ impl ObjectKind for Cylinder { ray_point.x.powi(2) + ray_point.y.powi(2) <= self.radius.powi(2) }); - let solutions = side_solutions.into_iter().chain(end_solutions.into_iter()); + let solutions = side_solutions + .into_iter() + .chain(end_solutions.into_iter()) + // Remove any t < 0, since that means it's behind the viewer and we + // can't see it. + .filter(|t| *t >= 0.0); // Return the minimum solution - solutions - .filter_map(|t| NotNan::new(t).ok()) - .min() - .map(|t| t.into_inner()) + min_f64(solutions) } } diff --git a/assignment-1a/src/scene/sphere.rs b/assignment-1a/src/scene/sphere.rs index 0acd760..4e51043 100644 --- a/assignment-1a/src/scene/sphere.rs +++ b/assignment-1a/src/scene/sphere.rs @@ -1,6 +1,6 @@ use nalgebra::Vector3; -use crate::ray::Ray; +use crate::{ray::Ray, utils::min_f64}; use super::data::ObjectKind; @@ -40,7 +40,14 @@ impl ObjectKind for Sphere { let solution_1 = (-b + discriminant.sqrt()) / (2.0 * a); let solution_2 = (-b - discriminant.sqrt()) / (2.0 * a); - Some(solution_1.min(solution_2)) + let solutions = [solution_1, solution_2] + .into_iter() + // Remove any t < 0, since that means it's behind the viewer and we + // can't see it. + .filter(|t| *t >= 0.0); + + // Return the minimum solution + min_f64(solutions) } // Probably hit some NaN or Infinity value due to faulty inputs... diff --git a/assignment-1a/src/math.rs b/assignment-1a/src/utils.rs similarity index 72% rename from assignment-1a/src/math.rs rename to assignment-1a/src/utils.rs index e04f80b..73fe3db 100644 --- a/assignment-1a/src/math.rs +++ b/assignment-1a/src/utils.rs @@ -1,4 +1,15 @@ use nalgebra::{Matrix3, Vector3}; +use ordered_float::NotNan; + +/// Finds the minimum of an iterator of f64s, ignoring any NaN values +pub fn min_f64(i: I) -> Option +where + I: Iterator, +{ + i.filter_map(|i| NotNan::new(i).ok()) + .min() + .map(|i| i.into_inner()) +} /// Calculate the rotation matrix between the 2 given vectors /// Based on the method here: https://math.stackexchange.com/a/897677