Cross product
This commit is contained in:
parent
85316dd934
commit
b6c6ac9e35
7 changed files with 204 additions and 45 deletions
92
assignment-1/Cargo.lock
generated
92
assignment-1/Cargo.lock
generated
|
@ -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"
|
||||||
|
|
|
@ -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"] }
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
65
assignment-1/src/vec3.rs
Normal 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
12
assignment-1/src/view.rs
Normal 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() {
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue