crystal_ball 0.3.0

A path tracing library written in Rust.
Documentation
use crate::math::{Point3, Vec3};

/// A ray in 3D space.
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Ray {
    /// The ray's origin.
    pub origin: Point3,
    /// The ray's direction.
    pub direction: Vec3,
    /// The index of refraction of the ray's last medium.
    pub last_ior: f64,
}

impl Ray {
    /// Create a new [`Ray`].
    /// 
    /// This slightly shifts `origin` in the positive `direction` (by a factor of 1e-9)
    /// to avoid problems with floating point precision.
    pub fn new(origin: Point3, direction: Vec3, last_ior: f64) -> Self {
        let direction = direction.normalize();
        Ray {
            // Shift the intersection point slightly outwards in order to avoid problems due to finite floating point precision.
            origin: origin + direction * 1e-9,
            direction,
            last_ior,
        }
    }

    /// Return the [`Point3`] on the [`Ray`] at the given distance.
    pub fn get(&self, distance: f64) -> Point3 {
        self.origin + self.direction * distance
    }
}

#[cfg(test)]
mod tests {
    use assert_approx_eq::assert_approx_eq;

    use crate::math::Point3;
    use crate::util::EPSILON_F64;

    use super::{Ray, Vec3};

    #[test]
    fn ray_get_point() {
        assert_approx_eq!(
            Ray::new(Point3::new(0.0, 0.0, 0.0), Vec3::new(1.0, 0.0, 0.0), 1.0).get(2.0),
            Point3::new(2.0, 0.0, 0.0),
            EPSILON_F64 + 1e-9
        );
        assert_approx_eq!(
            Ray::new(
                Point3::new(5.72, 2.5, 8.824),
                Vec3::new(8.7, 5.987, 0.12),
                1.0
            )
            .get(2.5),
            Point3::new(7.779336228, 3.917154712, 8.852404638),
            EPSILON_F64 + 1e-9
        );
    }
}