raytracers/rtchallenge/src/patterns.rs

68 lines
1.9 KiB
Rust

use crate::tuples::{Color, Tuple};
#[derive(Debug, PartialEq, Clone)]
pub struct StripePattern {
pub a: Color,
pub b: Color,
}
/// Create a material pattern that alternates between the given colors along each unit of the
/// X-axis. The strip extends infinitely in the positive and negative Y and Z axes.
///
/// # Examples
/// ```
/// use rtchallenge::{patterns::stripe_pattern, BLACK, WHITE};
///
/// let pattern = stripe_pattern(BLACK, WHITE);
/// assert_eq!(pattern.a, BLACK);
/// assert_eq!(pattern.b, WHITE);
/// ```
pub fn stripe_pattern(a: Color, b: Color) -> StripePattern {
StripePattern { a, b }
}
impl StripePattern {
/// Sample the color at the given point.
///
/// # Examples
/// ```
/// use rtchallenge::{patterns::stripe_pattern, tuples::point, BLACK, WHITE};
///
/// let pattern = stripe_pattern(WHITE, BLACK);
///
/// for (p, want) in &[
/// // A stripe pattern is constant in y.
/// (point(0., 0., 0.), WHITE),
/// (point(0., 1., 0.), WHITE),
/// (point(0., 2., 0.), WHITE),
/// // A stripe pattern is constant in z.
/// (point(0., 0., 0.), WHITE),
/// (point(0., 0., 1.), WHITE),
/// (point(0., 0., 2.), WHITE),
/// // A stripe pattern alternates in z.
/// (point(0., 0., 0.), WHITE),
/// (point(0.9, 0., 0.), WHITE),
/// (point(1., 0., 0.), BLACK),
/// (point(-0.1, 0., 0.), BLACK),
/// (point(-1., 0., 0.), BLACK),
/// (point(-1.1, 0., 0.), WHITE),
/// ] {
/// assert_eq!(pattern.stripe_at(*p), *want, "{:?}", p);
/// }
/// ```
pub fn stripe_at(&self, point: Tuple) -> Color {
let x = point.x.floor() as i64;
// Shift negative valued to get correct striping.
if x < 0 {
x - 1
} else {
x
};
if x % 2 == 0 {
self.a
} else {
self.b
}
}
}