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}