Cross product

This commit is contained in:
Michael Zhang 2023-01-31 01:38:03 -06:00
parent 85316dd934
commit b6c6ac9e35
7 changed files with 204 additions and 45 deletions

View file

@ -14,8 +14,15 @@ version = "0.1.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"clap", "clap",
"num",
] ]
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "1.3.2" version = "1.3.2"
@ -135,6 +142,85 @@ version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" 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]] [[package]]
name = "once_cell" name = "once_cell"
version = "1.17.0" version = "1.17.0"
@ -203,6 +289,12 @@ dependencies = [
"windows-sys", "windows-sys",
] ]
[[package]]
name = "serde"
version = "1.0.152"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
[[package]] [[package]]
name = "strsim" name = "strsim"
version = "0.10.0" version = "0.10.0"

View file

@ -8,3 +8,4 @@ edition = "2021"
[dependencies] [dependencies]
anyhow = "1.0.68" anyhow = "1.0.68"
clap = { version = "4.1.4", features = ["derive"] } clap = { version = "4.1.4", features = ["derive"] }
num = { version = "0.4.0", features = ["serde"] }

View file

@ -1,6 +1,8 @@
mod input_file; mod input_file;
mod ray; mod ray;
mod scene_data; mod scene_data;
mod view;
mod vec3;
use std::path::PathBuf; use std::path::PathBuf;

View file

@ -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 { pub struct Ray {
origin: Vec3, origin: Vec3,
direction: Vec3, direction: Vec3,
} }
impl Ray { impl Ray {
/// Evaluate the ray at a certain point in time, yielding a point
pub fn eval(&self, time: f64) -> Vec3 { pub fn eval(&self, time: f64) -> Vec3 {
self.origin + self.direction * time 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. /// If there is no intersection point, returns None.
pub fn ray_intersection_time(ray: &Ray, sphere: &Sphere) -> Option<f64> { pub fn ray_intersection_time(ray: &Ray, sphere: &Sphere) -> Option<f64> {
@ -43,13 +48,16 @@ pub fn ray_intersection_time(ray: &Ray, sphere: &Sphere) -> Option<f64> {
return Some(solution_1.min(solution_2)); return Some(solution_1.min(solution_2));
} }
// Probably hit some NaN or Infinity value due to faulty inputs...
_ => unreachable!("Invalid determinant value: {discriminant}"), _ => unreachable!("Invalid determinant value: {discriminant}"),
} }
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::scene_data::{Sphere, Vec3}; use crate::scene_data::Sphere;
use crate::vec3::Vec3;
use super::{ray_intersection_time, Ray}; use super::{ray_intersection_time, Ray};
@ -64,7 +72,24 @@ mod tests {
radius: 4.0, radius: 4.0,
}; };
let t = ray_intersection_time(&ray, &sphere).unwrap(); let point = ray_intersection_time(&ray, &sphere).map(|t| ray.eval(t));
assert_eq!(ray.eval(t), Vec3::new(0.0, 0.0, -6.0));
// 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);
} }
} }

View file

@ -1,42 +1,4 @@
use std::ops::{Add, Mul}; use crate::vec3::Vec3;
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct Vec3<T = f64> {
pub x: T,
pub y: T,
pub z: T,
}
impl<T> Vec3<T> {
pub fn new(x: T, y: T, z: T) -> Self {
Vec3 { x, y, z }
}
}
/// Vector addition
impl<T> Add<Vec3<T>> for Vec3<T>
where
T: Add<T>,
{
type Output = Vec3<T::Output>;
fn add(self, rhs: Vec3<T>) -> Self::Output {
Vec3::new(self.x + rhs.x, self.y + rhs.y, self.z + rhs.z)
}
}
/// Scalar multiplication
impl<T, U> Mul<U> for Vec3<T>
where
T: Mul<U, Output = U>,
U: Copy,
{
type Output = Vec3<U>;
fn mul(self, rhs: U) -> Self::Output {
Vec3::new(self.x * rhs, self.y * rhs, self.z * rhs)
}
}
pub struct Sphere { pub struct Sphere {
pub center: Vec3, pub center: Vec3,

65
assignment-1/src/vec3.rs Normal file
View file

@ -0,0 +1,65 @@
use std::ops::{Add, Mul};
use num::Float;
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct Vec3<T = f64> {
pub x: T,
pub y: T,
pub z: T,
}
impl<T> Vec3<T> {
pub fn new(x: T, y: T, z: T) -> Self {
Vec3 { x, y, z }
}
}
impl<T: Float> Vec3<T> {
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<T> Add<Vec3<T>> for Vec3<T>
where
T: Add<T>,
{
type Output = Vec3<T::Output>;
fn add(self, rhs: Vec3<T>) -> Self::Output {
Vec3::new(self.x + rhs.x, self.y + rhs.y, self.z + rhs.z)
}
}
/// Scalar multiplication
impl<T, U> Mul<U> for Vec3<T>
where
T: Mul<U, Output = U>,
U: Copy,
{
type Output = Vec3<U>;
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));
}
}

12
assignment-1/src/view.rs Normal file
View file

@ -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() {
}