Compare commits
No commits in common. "0e8a0e4163b8eef431ad23b67faee07e6fafcca3" and "c0e422a7ebabf181ef8f851772a14484ebe6e9a0" have entirely different histories.
0e8a0e4163
...
c0e422a7eb
@ -1,7 +1,6 @@
|
||||
use crate::{matrices::Matrix4x4, tuples::Tuple, Float};
|
||||
|
||||
/// Rays have an origin and a direction. This datatype is the 'ray' in 'raytracer'.
|
||||
#[derive(Debug)]
|
||||
pub struct Ray {
|
||||
pub origin: Tuple,
|
||||
pub direction: Tuple,
|
||||
|
||||
@ -4,15 +4,12 @@ use crate::{
|
||||
matrices::Matrix4x4,
|
||||
rays::Ray,
|
||||
tuples::{dot, Tuple},
|
||||
EPSILON,
|
||||
};
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
enum Geometry {
|
||||
/// Sphere represents the unit-sphere (radius of unit 1.) at the origin 0., 0., 0.
|
||||
Sphere,
|
||||
/// Flat surface that extends infinitely in the XZ axes.
|
||||
Plane,
|
||||
}
|
||||
|
||||
/// Shape represents visible objects. A signal instance of Shape can generically represent one of
|
||||
@ -58,14 +55,6 @@ impl Shape {
|
||||
geometry: Geometry::Sphere,
|
||||
}
|
||||
}
|
||||
pub fn plane() -> Shape {
|
||||
Shape {
|
||||
transform: Matrix4x4::identity(),
|
||||
inverse_transform: Matrix4x4::identity(),
|
||||
material: Material::default(),
|
||||
geometry: Geometry::Plane,
|
||||
}
|
||||
}
|
||||
/// Find the normal at the point on the sphere.
|
||||
///
|
||||
/// # Examples
|
||||
@ -129,28 +118,12 @@ impl Shape {
|
||||
/// -(2. as Float).sqrt() / 2.,
|
||||
/// ));
|
||||
/// assert_eq!(n, Tuple::vector(0., 0.97014, -0.24254));
|
||||
///
|
||||
/// // Normal of a plane is constant everywhere.
|
||||
/// let p = Shape::plane();
|
||||
/// assert_eq!(
|
||||
/// p.normal_at(Tuple::point(0., 0., 0.)),
|
||||
/// Tuple::vector(0., 1., 0.)
|
||||
/// );
|
||||
/// assert_eq!(
|
||||
/// p.normal_at(Tuple::point(10., 0., -10.)),
|
||||
/// Tuple::vector(0., 1., 0.)
|
||||
/// );
|
||||
/// assert_eq!(
|
||||
/// p.normal_at(Tuple::point(-5., 0., 150.)),
|
||||
/// Tuple::vector(0., 1., 0.)
|
||||
/// );
|
||||
/// ```
|
||||
#[cfg(not(feature = "disable-inverse-cache"))]
|
||||
pub fn normal_at(&self, world_point: Tuple) -> Tuple {
|
||||
let object_point = self.inverse_transform * world_point;
|
||||
let object_normal = match self.geometry {
|
||||
Geometry::Sphere => object_point - Tuple::point(0., 0., 0.),
|
||||
Geometry::Plane => Tuple::vector(0., 1., 0.),
|
||||
};
|
||||
let mut world_normal = self.inverse_transform.transpose() * object_normal;
|
||||
world_normal.w = 0.;
|
||||
@ -161,7 +134,6 @@ impl Shape {
|
||||
let object_point = self.transform.inverse() * world_point;
|
||||
let object_normal = match self.geometry {
|
||||
Geometry::Sphere => object_point - Tuple::point(0., 0., 0.),
|
||||
Geometry::Plane => Tuple::vector(0., 1., 0.),
|
||||
};
|
||||
let mut world_normal = self.transform.inverse().transpose() * object_normal;
|
||||
world_normal.w = 0.;
|
||||
@ -238,40 +210,14 @@ impl Shape {
|
||||
/// s.set_transform(Matrix4x4::translation(5., 0., 0.));
|
||||
/// let xs = intersect(&s, &r);
|
||||
/// assert_eq!(xs.len(), 0);
|
||||
///
|
||||
/// // Intersect with a ray parallel to the plane.
|
||||
/// let p = Shape::plane();
|
||||
/// let r = Ray::new(Tuple::point(0., 10., 0.), Tuple::vector(0., 0., 1.));
|
||||
/// let xs = intersect(&p, &r);
|
||||
/// assert_eq!(xs.len(), 0);
|
||||
///
|
||||
/// // Intersect with a coplanar.
|
||||
/// let r = Ray::new(Tuple::point(0., 0., 0.), Tuple::vector(0., 0., 1.));
|
||||
/// let xs = intersect(&p, &r);
|
||||
/// assert_eq!(xs.len(), 0);
|
||||
///
|
||||
/// // A ray intersecting a plane from above.
|
||||
/// let r = Ray::new(Tuple::point(0., 1., 0.), Tuple::vector(0., -1., 0.));
|
||||
/// let xs = intersect(&p, &r);
|
||||
/// assert_eq!(xs.len(), 1);
|
||||
/// assert_eq!(xs[0].t, 1.);
|
||||
/// assert_eq!(xs[0].object, &p);
|
||||
///
|
||||
/// // A ray intersecting a plane from below.
|
||||
/// let r = Ray::new(Tuple::point(0., -1., 0.), Tuple::vector(0., 1., 0.));
|
||||
/// let xs = intersect(&p, &r);
|
||||
/// assert_eq!(xs.len(), 1);
|
||||
/// assert_eq!(xs[0].t, 1.);
|
||||
/// assert_eq!(xs[0].object, &p);
|
||||
/// ```
|
||||
pub fn intersect<'s>(shape: &'s Shape, ray: &Ray) -> Intersections<'s> {
|
||||
match shape.geometry {
|
||||
Geometry::Sphere => intersect_sphere(shape, ray),
|
||||
Geometry::Plane => intersect_plane(shape, ray),
|
||||
Geometry::Sphere => intersect_rtc(shape, ray),
|
||||
}
|
||||
}
|
||||
|
||||
fn intersect_sphere<'s>(shape: &'s Shape, ray: &Ray) -> Intersections<'s> {
|
||||
fn intersect_rtc<'s>(shape: &'s Shape, ray: &Ray) -> Intersections<'s> {
|
||||
let ray = ray.transform(shape.inverse_transform);
|
||||
let sphere_to_ray = ray.origin - Tuple::point(0., 0., 0.);
|
||||
let a = dot(ray.direction, ray.direction);
|
||||
@ -286,12 +232,18 @@ fn intersect_sphere<'s>(shape: &'s Shape, ray: &Ray) -> Intersections<'s> {
|
||||
Intersection::new((-b + discriminant.sqrt()) / (2. * a), &shape),
|
||||
])
|
||||
}
|
||||
fn intersect_plane<'s>(shape: &'s Shape, ray: &Ray) -> Intersections<'s> {
|
||||
if (ray.direction.y).abs() < EPSILON {
|
||||
fn intersect_rtiow<'s>(shape: &'s Shape, ray: &Ray) -> Intersections<'s> {
|
||||
let ray = ray.transform(shape.inverse_transform);
|
||||
let oc = ray.origin - Tuple::point(0., 0., 0.);
|
||||
let a = dot(ray.direction, ray.direction);
|
||||
let b = dot(oc, ray.direction);
|
||||
let c = dot(oc, oc) - 1.;
|
||||
let discriminant = b * b - a * c;
|
||||
if discriminant < 0. {
|
||||
return Intersections::default();
|
||||
}
|
||||
Intersections::new(vec![Intersection::new(
|
||||
-ray.origin.y / ray.direction.y,
|
||||
&shape,
|
||||
)])
|
||||
Intersections::new(vec![
|
||||
Intersection::new((-b - discriminant.sqrt()) / a, &shape),
|
||||
Intersection::new((-b + discriminant.sqrt()) / a, &shape),
|
||||
])
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user