raytracer 0.2.2

Toy raytracer in Rust
Documentation
use crate::{
    Vec3
};



/// This struct represents a mathematical ray.
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct Ray {
    /// Starting point of a ray.
    pub origin: Vec3,
    /// Direction of a ray.
    ///
    /// In mathematics, ray does not have a length, but this vector isn't guaranteed
    /// to be an unit vector. It is useful when distance between origin and point that
    /// ray intersects is needed.
    pub direction: Vec3
}

impl Ray {
    /// Ray constructor.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use raytracer::{Ray, vec3};
    /// let r = Ray::new(vec3!(0.0), vec3!(5.0));
    ///
    /// assert_eq!(r.origin, vec3!(0.0));
    /// assert_eq!(r.direction, vec3!(5.0));
    /// ```
    pub fn new(origin: Vec3, direction: Vec3) -> Ray {
        Ray {origin, direction}
    }

    /// Returns a point between origin and direction.
    ///
    /// When t = 0, returns [`Ray.origin`], when t = 1, returns [`Ray.direction`].
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use raytracer::{ray, vec3};
    /// let origin = vec3!(0.0);
    /// let direction = vec3!(10.0);
    ///
    /// let r = ray!(origin, direction);
    ///
    /// assert_eq!(r.at(0.0), origin);
    /// assert_eq!(r.at(0.75), vec3!(7.5));
    /// assert_eq!(r.at(1.0), direction);
    /// ```
    ///
    /// [`Ray.origin`]: struct.Ray.html#structfield.origin
    /// [`Ray.direction`]: struct.Ray.html#structfield.direction
    pub fn at(self, t: f32) -> Vec3 {
        self.origin + t * self.direction
    }
}



/// Shorthand for [`Ray::new`].
///
/// # Examples
///
/// ```rust
/// # use raytracer::{Ray, ray, vec3};
/// let r = ray!(vec3!(0.0), vec3!(1.0));
///
/// assert_eq!(r, Ray::new(vec3!(0.0), vec3!(1.0)));
/// ```
///
/// [`Ray::new`]: ray/struct.Ray.html#method.new
#[macro_export]
macro_rules! ray {
    ($origin:expr, $direction:expr) => { $crate::Ray::new($origin, $direction) };
}



#[cfg(test)]
mod tests {
    use crate::vec3;
    use super::*;

    #[test]
    fn macro_ray() {
        let ra = ray!(vec3!(0.0), vec3!(1.0));
        let rb = Ray::new(vec3!(0.0), vec3!(1.0));

        assert_eq!(ra, rb);
    }

    #[test]
    fn ray_new() {
        let o = vec3!(1.0, 2.0, 3.0);
        let d = vec3!(4.0, 5.0, 6.0);
        let r = Ray::new(o, d);

        assert_eq!(r.origin.x, 1.0);
        assert_eq!(r.origin.y, 2.0);
        assert_eq!(r.origin.z, 3.0);
        assert_eq!(r.direction.x, 4.0);
        assert_eq!(r.direction.y, 5.0);
        assert_eq!(r.direction.z, 6.0);
    }

    #[test]
    fn ray_at() {
        let r = ray!(vec3!(0.0), vec3!(10.0));

        assert_eq!(r.at(0.0), vec3!(0.0));
        assert_eq!(r.at(0.25), vec3!(2.5));
        assert_eq!(r.at(0.5), vec3!(5.0));
        assert_eq!(r.at(0.75), vec3!(7.5));
    }
}