-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
142 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
use crate::tuple::*; | ||
|
||
#[derive(Debug, Clone, Copy)] | ||
pub struct Ray { | ||
pub origin: Tuple, | ||
pub direction: Tuple, | ||
} | ||
|
||
impl Ray { | ||
pub fn new(origin: Tuple, direction: Tuple) -> Ray { | ||
Ray { | ||
origin, | ||
direction, | ||
} | ||
} | ||
|
||
pub fn position(&self, t: f32) -> Tuple { | ||
self.origin + self.direction * t | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
use wasm_bindgen_test::*; | ||
|
||
#[wasm_bindgen_test] | ||
pub fn creating_and_querying_a_ray() { | ||
let origin = Tuple::point(1.0, 2.0, 3.0); | ||
let direction = Tuple::vector(4.0, 5.0, 6.0); | ||
let r = Ray::new(origin, direction); | ||
|
||
assert_eq!(r.origin, origin); | ||
assert_eq!(r.direction, direction); | ||
} | ||
|
||
#[wasm_bindgen_test] | ||
pub fn computing_a_point_from_a_distance() { | ||
let r = Ray::new(Tuple::point(2.0, 3.0, 4.0), Tuple::vector(1.0, 0.0, 0.0)); | ||
|
||
assert_eq!(r.position(0.0), Tuple::point(2.0, 3.0, 4.0)); | ||
assert_eq!(r.position(1.0), Tuple::point(3.0, 3.0, 4.0)); | ||
assert_eq!(r.position(-1.0), Tuple::point(1.0, 3.0, 4.0)); | ||
assert_eq!(r.position(2.5), Tuple::point(4.5, 3.0, 4.0)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
use crate::ray::*; | ||
use crate::tuple::*; | ||
|
||
#[derive(Debug, Clone, Copy)] | ||
pub struct Sphere {} | ||
|
||
impl Sphere { | ||
pub fn new() -> Sphere { | ||
Sphere {} | ||
} | ||
|
||
pub fn intersect(&self, ray: &Ray) -> Vec<f32> { | ||
let sphere_to_ray = ray.origin - Tuple::point(0.0, 0.0, 0.0); | ||
|
||
// Determine the discriminant. | ||
let a = ray.direction.dot(ray.direction); | ||
let b = 2.0 * ray.direction.dot(sphere_to_ray); | ||
let c = sphere_to_ray.dot(sphere_to_ray) - 1.0; | ||
let discriminant = b * b - 4.0 * a * c; | ||
|
||
if discriminant < 0.0 { | ||
vec![] | ||
} else { | ||
vec![ | ||
(-b - discriminant.sqrt()) / (2.0 * a), | ||
(-b + discriminant.sqrt()) / (2.0 * a), | ||
] | ||
} | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
use wasm_bindgen_test::*; | ||
|
||
#[wasm_bindgen_test] | ||
pub fn a_ray_intersects_a_sphere_at_two_points() { | ||
let r = Ray::new(Tuple::point(0.0, 0.0, -5.0), Tuple::vector(0.0, 0.0, 1.0)); | ||
let s = Sphere::new(); | ||
|
||
let xs = s.intersect(&r); | ||
|
||
assert_eq!(xs.len(), 2); | ||
assert_eq!(xs[0], 4.0); | ||
assert_eq!(xs[1], 6.0); | ||
} | ||
|
||
#[wasm_bindgen_test] | ||
pub fn a_ray_intersects_a_sphere_at_a_tangent() { | ||
let r = Ray::new(Tuple::point(0.0, 1.0, -5.0), Tuple::vector(0.0, 0.0, 1.0)); | ||
let s = Sphere::new(); | ||
|
||
let xs = s.intersect(&r); | ||
|
||
assert_eq!(xs.len(), 2); | ||
assert_eq!(xs[0], 5.0); | ||
assert_eq!(xs[1], 5.0); | ||
} | ||
|
||
#[wasm_bindgen_test] | ||
pub fn a_ray_misses_a_sphere() { | ||
let r = Ray::new(Tuple::point(0.0, 2.0, -5.0), Tuple::vector(0.0, 0.0, 1.0)); | ||
let s = Sphere::new(); | ||
|
||
let xs = s.intersect(&r); | ||
|
||
assert_eq!(xs.len(), 0); | ||
} | ||
|
||
#[wasm_bindgen_test] | ||
pub fn a_ray_originates_inside_a_sphere() { | ||
let r = Ray::new(Tuple::point(0.0, 0.0, 0.0), Tuple::vector(0.0, 0.0, 1.0)); | ||
let s = Sphere::new(); | ||
|
||
let xs = s.intersect(&r); | ||
|
||
assert_eq!(xs.len(), 2); | ||
assert_eq!(xs[0], -1.0); | ||
assert_eq!(xs[1], 1.0); | ||
} | ||
|
||
#[wasm_bindgen_test] | ||
pub fn a_sphere_is_behind_a_ray() { | ||
let r = Ray::new(Tuple::point(0.0, 0.0, 5.0), Tuple::vector(0.0, 0.0, 1.0)); | ||
let s = Sphere::new(); | ||
|
||
let xs = s.intersect(&r); | ||
|
||
assert_eq!(xs.len(), 2); | ||
assert_eq!(xs[0], -6.0); | ||
assert_eq!(xs[1], -4.0); | ||
} | ||
} |