Files
raytracers/rtchallenge/src/rays.rs

75 lines
2.3 KiB
Rust

use crate::{matrices::Matrix4x4, tuples::Tuple, Float};
/// Rays have an origin and a direction. This datatype is the 'ray' in 'raytracer'.
#[derive(Debug, Default, Clone, PartialEq)]
pub struct Ray {
pub origin: Tuple,
pub direction: Tuple,
}
impl Ray {
/// Create a ray with the given origin point and direction vector.
/// Will panic if origin not a point or direction not a vector.
pub fn new(origin: Tuple, direction: Tuple) -> Ray {
assert!(origin.is_point(), "Ray origin must be a point");
assert!(direction.is_vector(), "Ray direction must be a vector");
Ray { origin, direction }
}
/// Compute a point from the given distance along the `Ray`.
pub fn position(&self, t: Float) -> Tuple {
self.origin + self.direction * t
}
/// Apply Matrix4x4 transforms to Ray.
pub fn transform(&self, m: Matrix4x4) -> Ray {
Ray {
origin: m * self.origin,
direction: m * self.direction,
}
}
}
#[cfg(test)]
mod tests {
use crate::{
matrices::Matrix4x4,
rays::Ray,
tuples::{point, vector},
};
#[test]
fn create() {
let origin = point(1., 2., 3.);
let direction = vector(4., 5., 6.);
let r = Ray::new(origin, direction);
assert_eq!(r.origin, origin);
assert_eq!(r.direction, direction);
}
#[test]
fn position() {
let r = Ray::new(point(2., 3., 4.), vector(1., 0., 0.));
assert_eq!(r.position(0.), point(2., 3., 4.));
assert_eq!(r.position(1.), point(3., 3., 4.));
assert_eq!(r.position(-1.), point(1., 3., 4.));
assert_eq!(r.position(2.5), point(4.5, 3., 4.));
}
#[test]
fn transform_translating_ray() {
// Translating a ray
let r = Ray::new(point(1., 2., 3.), vector(0., 1., 0.));
let m = Matrix4x4::translation(3., 4., 5.);
let r2 = r.transform(m);
assert_eq!(r2.origin, point(4., 6., 8.));
assert_eq!(r2.direction, vector(0., 1., 0.));
}
#[test]
fn transform_scaling_ray() {
// Scaling a ray
let r = Ray::new(point(1., 2., 3.), vector(0., 1., 0.));
let m = Matrix4x4::scaling(2., 3., 4.);
let r2 = r.transform(m);
assert_eq!(r2.origin, point(2., 6., 12.));
assert_eq!(r2.direction, vector(0., 3., 0.));
}
}