truster/
ray.rs

1//! Holds the [Ray] struct.
2
3use crate::matrix::Matrix;
4use crate::tuple::Tuple;
5
6/// A ray which can be used for calculating intersections with shapes to render 3D scenes.
7#[derive(Debug, PartialEq, Clone)]
8pub struct Ray {
9    origin: Tuple,
10    direction: Tuple,
11}
12
13impl Ray {
14    /// Returns a new [Ray] with the given origin and direction.
15    pub fn new(origin: Tuple, direction: Tuple) -> Self {
16        Self { origin, direction }
17    }
18
19    /// Returns `self`'s origin.
20    pub fn origin(&self) -> Tuple {
21        self.origin
22    }
23
24    /// Returns `self`'s direction.
25    pub fn direction(&self) -> Tuple {
26        self.direction
27    }
28
29    /// Returns the point at the given distance t along `self`.
30    ///
31    /// # Examples
32    ///
33    /// ```
34    /// # use truster::ray::Ray;
35    /// use truster::tuple::Tuple;
36    ///
37    /// let ray = Ray::new(Tuple::point(2.0, 3.0, 4.0), Tuple::vector(1.0, 0.0, 0.0));
38    /// assert_eq!(ray.at(0.0), Tuple::point(2.0, 3.0, 4.0));
39    /// assert_eq!(ray.at(1.0), Tuple::point(3.0, 3.0, 4.0));
40    /// assert_eq!(ray.at(-1.0), Tuple::point(1.0, 3.0, 4.0));
41    /// assert_eq!(ray.at(2.5), Tuple::point(4.5, 3.0, 4.0));
42    /// ```
43    pub fn at(&self, t: f64) -> Tuple {
44        self.origin + self.direction() * t
45    }
46
47    /// Returns a new ray where both origin and direction are `self`'s origin and direction
48    /// transformed by `transform`.
49    ///
50    /// # Examples
51    ///
52    /// Translating a ray:
53    /// ```
54    /// # use truster::ray::Ray;
55    /// use truster::tuple::Tuple;
56    /// use truster::matrix::Matrix;
57    ///
58    ///	let ray = Ray::new(Tuple::point(1.0, 2.0, 3.0), Tuple::vector(0.0, 1.0, 0.0));
59    /// let transform = Matrix::translation(3.0, 4.0, 5.0);
60    /// let ray = ray.transform(&transform);
61    ///
62    /// assert_eq!(ray, Ray::new(Tuple::point(4.0, 6.0, 8.0), Tuple::vector(0.0, 1.0, 0.0)));
63    /// ```
64    ///
65    /// Scaling a ray:
66    /// ```
67    /// # use truster::ray::Ray;
68    /// use truster::tuple::Tuple;
69    /// use truster::matrix::Matrix;
70    ///
71    ///	let ray = Ray::new(Tuple::point(1.0, 2.0, 3.0), Tuple::vector(0.0, 1.0, 0.0));
72    /// let transform = Matrix::scaling(2.0, 3.0, 4.0);
73    /// let ray = ray.transform(&transform);
74    ///
75    /// assert_eq!(ray, Ray::new(Tuple::point(2.0, 6.0, 12.0), Tuple::vector(0.0, 3.0, 0.0)));
76    /// ```
77    pub fn transform(&self, transform: &Matrix) -> Self {
78        Self {
79            origin: transform * self.origin,
80            direction: transform * self.direction,
81        }
82    }
83}