From 0000006041d29b101cf6c323f7d6c33e5640a599 Mon Sep 17 00:00:00 2001 From: Michael Zhang Date: Tue, 31 Jan 2023 01:38:03 -0600 Subject: [PATCH] Cross product --- assignment-1/Cargo.lock | 92 ++++++++++++++++++++++++++++++++++ assignment-1/Cargo.toml | 1 + assignment-1/src/main.rs | 2 + assignment-1/src/ray.rs | 37 +++++++++++--- assignment-1/src/scene_data.rs | 40 +-------------- assignment-1/src/vec3.rs | 65 ++++++++++++++++++++++++ assignment-1/src/view.rs | 12 +++++ 7 files changed, 204 insertions(+), 45 deletions(-) create mode 100644 assignment-1/src/vec3.rs create mode 100644 assignment-1/src/view.rs diff --git a/assignment-1/Cargo.lock b/assignment-1/Cargo.lock index b05f05b..15567d1 100644 --- a/assignment-1/Cargo.lock +++ b/assignment-1/Cargo.lock @@ -14,8 +14,15 @@ version = "0.1.0" dependencies = [ "anyhow", "clap", + "num", ] +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + [[package]] name = "bitflags" version = "1.3.2" @@ -135,6 +142,85 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" +[[package]] +name = "num" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43db66d1170d347f9a065114077f7dccb00c1b9478c89384490a3425279a4606" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", + "serde", +] + +[[package]] +name = "num-complex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02e0d21255c828d6f128a1e41534206671e8c3ea0c62f32291e808dc82cff17d" +dependencies = [ + "num-traits", + "serde", +] + +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +dependencies = [ + "autocfg", + "num-bigint", + "num-integer", + "num-traits", + "serde", +] + +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", +] + [[package]] name = "once_cell" version = "1.17.0" @@ -203,6 +289,12 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "serde" +version = "1.0.152" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" + [[package]] name = "strsim" version = "0.10.0" diff --git a/assignment-1/Cargo.toml b/assignment-1/Cargo.toml index 1b68709..eb235bb 100644 --- a/assignment-1/Cargo.toml +++ b/assignment-1/Cargo.toml @@ -8,3 +8,4 @@ edition = "2021" [dependencies] anyhow = "1.0.68" clap = { version = "4.1.4", features = ["derive"] } +num = { version = "0.4.0", features = ["serde"] } diff --git a/assignment-1/src/main.rs b/assignment-1/src/main.rs index 5a722b9..dc1df78 100644 --- a/assignment-1/src/main.rs +++ b/assignment-1/src/main.rs @@ -1,6 +1,8 @@ mod input_file; mod ray; mod scene_data; +mod view; +mod vec3; use std::path::PathBuf; diff --git a/assignment-1/src/ray.rs b/assignment-1/src/ray.rs index c963fbf..c010cd8 100644 --- a/assignment-1/src/ray.rs +++ b/assignment-1/src/ray.rs @@ -1,18 +1,23 @@ -use crate::scene_data::{Sphere, Vec3}; +use crate::scene_data::Sphere; +use crate::vec3::Vec3; -/// A normalized Ray +/// A normalized parametric Ray of the form (origin + direction * time) +/// +/// That means at any time t: f64, the point represented by origin + direction * time occurs on the +/// ray. pub struct Ray { origin: Vec3, direction: Vec3, } impl Ray { + /// Evaluate the ray at a certain point in time, yielding a point pub fn eval(&self, time: f64) -> Vec3 { self.origin + self.direction * time } } -/// Given a ray and a sphere, returns the first point at which this ray intersects the sphere. +/// Given a ray and a sphere, returns the first time at which this ray intersects the sphere. /// /// If there is no intersection point, returns None. pub fn ray_intersection_time(ray: &Ray, sphere: &Sphere) -> Option { @@ -43,13 +48,16 @@ pub fn ray_intersection_time(ray: &Ray, sphere: &Sphere) -> Option { return Some(solution_1.min(solution_2)); } + + // Probably hit some NaN or Infinity value due to faulty inputs... _ => unreachable!("Invalid determinant value: {discriminant}"), } } #[cfg(test)] mod tests { - use crate::scene_data::{Sphere, Vec3}; + use crate::scene_data::Sphere; + use crate::vec3::Vec3; use super::{ray_intersection_time, Ray}; @@ -64,7 +72,24 @@ mod tests { radius: 4.0, }; - let t = ray_intersection_time(&ray, &sphere).unwrap(); - assert_eq!(ray.eval(t), Vec3::new(0.0, 0.0, -6.0)); + let point = ray_intersection_time(&ray, &sphere).map(|t| ray.eval(t)); + + // the intersection point in this case is (0, 0, –6) + assert_eq!(point, Some(Vec3::new(0.0, 0.0, -6.0))); + } + + #[test] + fn practice_problem_slide_158() { + let ray = Ray { + origin: Vec3::new(0.0, 0.0, 0.0), + direction: Vec3::new(0.0, 0.5, -1.0), + }; + let sphere = Sphere { + center: Vec3::new(0.0, 0.0, -10.0), + radius: 4.0, + }; + + // oops! In this case, the ray does not intersect the sphere. + assert_eq!(ray_intersection_time(&ray, &sphere), None); } } diff --git a/assignment-1/src/scene_data.rs b/assignment-1/src/scene_data.rs index 99ae346..cf2b8e2 100644 --- a/assignment-1/src/scene_data.rs +++ b/assignment-1/src/scene_data.rs @@ -1,42 +1,4 @@ -use std::ops::{Add, Mul}; - -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -pub struct Vec3 { - pub x: T, - pub y: T, - pub z: T, -} - -impl Vec3 { - pub fn new(x: T, y: T, z: T) -> Self { - Vec3 { x, y, z } - } -} - -/// Vector addition -impl Add> for Vec3 -where - T: Add, -{ - type Output = Vec3; - - fn add(self, rhs: Vec3) -> Self::Output { - Vec3::new(self.x + rhs.x, self.y + rhs.y, self.z + rhs.z) - } -} - -/// Scalar multiplication -impl Mul for Vec3 -where - T: Mul, - U: Copy, -{ - type Output = Vec3; - - fn mul(self, rhs: U) -> Self::Output { - Vec3::new(self.x * rhs, self.y * rhs, self.z * rhs) - } -} +use crate::vec3::Vec3; pub struct Sphere { pub center: Vec3, diff --git a/assignment-1/src/vec3.rs b/assignment-1/src/vec3.rs new file mode 100644 index 000000000..77495da --- /dev/null +++ b/assignment-1/src/vec3.rs @@ -0,0 +1,65 @@ +use std::ops::{Add, Mul}; + +use num::Float; + +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub struct Vec3 { + pub x: T, + pub y: T, + pub z: T, +} + +impl Vec3 { + pub fn new(x: T, y: T, z: T) -> Self { + Vec3 { x, y, z } + } +} + +impl Vec3 { + pub fn cross(u: Self, v: Self) -> Self { + Vec3::new( + u.y * v.z - u.z * v.y, + u.z * v.x - u.x * v.z, + u.x * v.y - u.y * v.x, + ) + } +} + +/// Vector addition +impl Add> for Vec3 +where + T: Add, +{ + type Output = Vec3; + + fn add(self, rhs: Vec3) -> Self::Output { + Vec3::new(self.x + rhs.x, self.y + rhs.y, self.z + rhs.z) + } +} + +/// Scalar multiplication +impl Mul for Vec3 +where + T: Mul, + U: Copy, +{ + type Output = Vec3; + + fn mul(self, rhs: U) -> Self::Output { + Vec3::new(self.x * rhs, self.y * rhs, self.z * rhs) + } +} + +#[cfg(test)] +mod tests { + use super::Vec3; + + #[test] + fn test_cross() { + let u = Vec3::new(1.0, 0.0, 0.0); + let v = Vec3::new(0.0, 1.0, 0.0); + + assert_eq!(Vec3::cross(u, v), Vec3::new(0.0, 0.0, 1.0)); + assert_eq!(Vec3::cross(v, u), Vec3::new(0.0, 0.0, -1.0)); + } +} diff --git a/assignment-1/src/view.rs b/assignment-1/src/view.rs new file mode 100644 index 000000000..da5e522 --- /dev/null +++ b/assignment-1/src/view.rs @@ -0,0 +1,12 @@ +use crate::vec3::Vec3; + +pub struct Rect { + pub upper_left: Vec3, + pub upper_right: Vec3, + pub lower_left: Vec3, + pub lower_right: Vec3, +} + +pub fn compute_viewing_rect() { + +}