patterns: move tests from doctest to unit.
This commit is contained in:
parent
3aea76b35c
commit
5d6b3e6d57
@ -64,112 +64,30 @@ where
|
|||||||
|
|
||||||
/// Builder for creating a material pattern used for testing. The color returned is the pattern space point
|
/// Builder for creating a material pattern used for testing. The color returned is the pattern space point
|
||||||
/// after going through world->object and object->pattern space translation.
|
/// after going through world->object and object->pattern space translation.
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
/// ```
|
|
||||||
/// use rtchallenge::{
|
|
||||||
/// matrices::Matrix4x4,
|
|
||||||
/// patterns::{test_pattern, ColorMapper},
|
|
||||||
/// BLACK, WHITE,
|
|
||||||
/// };
|
|
||||||
///
|
|
||||||
/// # fn main() -> Result<(), Box<std::error::Error>> {
|
|
||||||
///
|
|
||||||
/// let pattern = test_pattern().build()?;
|
|
||||||
/// assert_eq!(pattern.transform(), Matrix4x4::identity());
|
|
||||||
///
|
|
||||||
/// # Ok(())
|
|
||||||
/// # }
|
|
||||||
/// ```
|
|
||||||
pub fn test_pattern() -> PatternBuilder {
|
pub fn test_pattern() -> PatternBuilder {
|
||||||
PatternBuilder::default().color(ColorMapper::TestPattern)
|
PatternBuilder::default().color(ColorMapper::TestPattern)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builder for creating a material pattern that alternates between the given colors along each unit of the
|
/// Builder for creating 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.
|
/// X-axis. The strip extends infinitely in the positive and negative Y and Z axes.
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
/// ```
|
|
||||||
/// use rtchallenge::{
|
|
||||||
/// patterns::{stripe_pattern, ColorMapper},
|
|
||||||
/// BLACK, WHITE,
|
|
||||||
/// };
|
|
||||||
///
|
|
||||||
/// # fn main() -> Result<(), Box<std::error::Error>> {
|
|
||||||
///
|
|
||||||
/// let pattern = stripe_pattern(BLACK, WHITE).build()?;
|
|
||||||
/// assert_eq!(pattern.color, ColorMapper::Stripe { a: BLACK, b: WHITE });
|
|
||||||
///
|
|
||||||
/// # Ok(())
|
|
||||||
/// # }
|
|
||||||
/// ```
|
|
||||||
pub fn stripe_pattern(a: Color, b: Color) -> PatternBuilder {
|
pub fn stripe_pattern(a: Color, b: Color) -> PatternBuilder {
|
||||||
PatternBuilder::default().color(ColorMapper::Stripe { a, b })
|
PatternBuilder::default().color(ColorMapper::Stripe { a, b })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builder for creating a material pattern that gradually blends between the given colors along
|
/// Builder for creating a material pattern that gradually blends between the given colors along
|
||||||
/// the X-axis.
|
/// the X-axis.
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
/// ```
|
|
||||||
/// use rtchallenge::{
|
|
||||||
/// matrices::Matrix4x4,
|
|
||||||
/// patterns::{gradient_pattern, ColorMapper},
|
|
||||||
/// BLACK, WHITE,
|
|
||||||
/// };
|
|
||||||
///
|
|
||||||
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
||||||
///
|
|
||||||
/// let pattern = gradient_pattern(WHITE, BLACK).build()?;
|
|
||||||
/// assert_eq!(pattern.color, ColorMapper::Gradient { a: WHITE, b: BLACK });
|
|
||||||
///
|
|
||||||
/// # Ok(())
|
|
||||||
/// # }
|
|
||||||
/// ```
|
|
||||||
pub fn gradient_pattern(a: Color, b: Color) -> PatternBuilder {
|
pub fn gradient_pattern(a: Color, b: Color) -> PatternBuilder {
|
||||||
PatternBuilder::default().color(ColorMapper::Gradient { a, b })
|
PatternBuilder::default().color(ColorMapper::Gradient { a, b })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builder for creating a material pattern that alternates between the given colors in a ring
|
/// Builder for creating a material pattern that alternates between the given colors in a ring
|
||||||
/// shape in the XZ plane.
|
/// shape in the XZ plane.
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
/// ```
|
|
||||||
/// use rtchallenge::{
|
|
||||||
/// patterns::{ring_pattern, ColorMapper},
|
|
||||||
/// BLACK, WHITE,
|
|
||||||
/// };
|
|
||||||
///
|
|
||||||
/// # fn main() -> Result<(), Box<std::error::Error>> {
|
|
||||||
///
|
|
||||||
/// let pattern = ring_pattern(BLACK, WHITE).build()?;
|
|
||||||
/// assert_eq!(pattern.color, ColorMapper::Ring { a: BLACK, b: WHITE });
|
|
||||||
///
|
|
||||||
/// # Ok(())
|
|
||||||
/// # }
|
|
||||||
/// ```
|
|
||||||
pub fn ring_pattern(a: Color, b: Color) -> PatternBuilder {
|
pub fn ring_pattern(a: Color, b: Color) -> PatternBuilder {
|
||||||
PatternBuilder::default().color(ColorMapper::Ring { a, b })
|
PatternBuilder::default().color(ColorMapper::Ring { a, b })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builder for creating a material pattern that alternates between the given colors along the X, Y
|
/// Builder for creating a material pattern that alternates between the given colors along the X, Y
|
||||||
/// and Z pattern. Creates traditional ray tracer tile floor pattern.
|
/// and Z pattern. Creates traditional ray tracer tile floor pattern.
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
/// ```
|
|
||||||
/// use rtchallenge::{
|
|
||||||
/// patterns::{checkers_pattern, ColorMapper},
|
|
||||||
/// BLACK, WHITE,
|
|
||||||
/// };
|
|
||||||
///
|
|
||||||
/// # fn main() -> Result<(), Box<std::error::Error>> {
|
|
||||||
///
|
|
||||||
/// let pattern = checkers_pattern(BLACK, WHITE).build()?;
|
|
||||||
/// assert_eq!(pattern.color, ColorMapper::Checkers { a: BLACK, b: WHITE });
|
|
||||||
///
|
|
||||||
/// # Ok(())
|
|
||||||
/// # }
|
|
||||||
/// ```
|
|
||||||
pub fn checkers_pattern(a: Color, b: Color) -> PatternBuilder {
|
pub fn checkers_pattern(a: Color, b: Color) -> PatternBuilder {
|
||||||
PatternBuilder::default().color(ColorMapper::Checkers { a, b })
|
PatternBuilder::default().color(ColorMapper::Checkers { a, b })
|
||||||
}
|
}
|
||||||
@ -178,23 +96,6 @@ pub fn checkers_pattern(a: Color, b: Color) -> PatternBuilder {
|
|||||||
impl Pattern {
|
impl Pattern {
|
||||||
/// Create a pattern used for testing. The color returned is the pattern space point
|
/// Create a pattern used for testing. The color returned is the pattern space point
|
||||||
/// after going through world->object and object->pattern space translation.
|
/// after going through world->object and object->pattern space translation.
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
/// ```
|
|
||||||
/// use rtchallenge::{
|
|
||||||
/// matrices::Matrix4x4,
|
|
||||||
/// patterns::{ColorMapper, Pattern},
|
|
||||||
/// BLACK, WHITE,
|
|
||||||
/// };
|
|
||||||
///
|
|
||||||
/// # fn main() -> Result<(), Box<std::error::Error>> {
|
|
||||||
///
|
|
||||||
/// let pattern = Pattern::test();
|
|
||||||
/// assert_eq!(pattern.transform(), Matrix4x4::identity());
|
|
||||||
///
|
|
||||||
/// # Ok(())
|
|
||||||
/// # }
|
|
||||||
/// ```
|
|
||||||
pub fn test() -> Pattern {
|
pub fn test() -> Pattern {
|
||||||
Pattern {
|
Pattern {
|
||||||
color: ColorMapper::TestPattern,
|
color: ColorMapper::TestPattern,
|
||||||
@ -204,17 +105,6 @@ impl Pattern {
|
|||||||
|
|
||||||
/// Create a pattern that alternates between the given colors along each unit of the
|
/// Create a 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.
|
/// X-axis. The strip extends infinitely in the positive and negative Y and Z axes.
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
/// ```
|
|
||||||
/// use rtchallenge::{
|
|
||||||
/// patterns::{ColorMapper, Pattern},
|
|
||||||
/// BLACK, WHITE,
|
|
||||||
/// };
|
|
||||||
///
|
|
||||||
/// let pattern = Pattern::stripe(BLACK, WHITE);
|
|
||||||
/// assert_eq!(pattern.color, ColorMapper::Stripe { a: BLACK, b: WHITE });
|
|
||||||
/// ```
|
|
||||||
pub fn stripe(a: Color, b: Color) -> Pattern {
|
pub fn stripe(a: Color, b: Color) -> Pattern {
|
||||||
Pattern {
|
Pattern {
|
||||||
color: ColorMapper::Stripe { a, b },
|
color: ColorMapper::Stripe { a, b },
|
||||||
@ -223,17 +113,6 @@ impl Pattern {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Create a pattern that gradually blends between the given colors along the X-axis.
|
/// Create a pattern that gradually blends between the given colors along the X-axis.
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
/// ```
|
|
||||||
/// use rtchallenge::{
|
|
||||||
/// patterns::{ColorMapper, Pattern},
|
|
||||||
/// BLACK, WHITE,
|
|
||||||
/// };
|
|
||||||
///
|
|
||||||
/// let pattern = Pattern::gradient(BLACK, WHITE);
|
|
||||||
/// assert_eq!(pattern.color, ColorMapper::Gradient { a: BLACK, b: WHITE });
|
|
||||||
/// ```
|
|
||||||
pub fn gradient(a: Color, b: Color) -> Pattern {
|
pub fn gradient(a: Color, b: Color) -> Pattern {
|
||||||
Pattern {
|
Pattern {
|
||||||
color: ColorMapper::Gradient { a, b },
|
color: ColorMapper::Gradient { a, b },
|
||||||
@ -242,17 +121,6 @@ impl Pattern {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Create a pattern that alternates between the given colors in a ring in the XZ plane.
|
/// Create a pattern that alternates between the given colors in a ring in the XZ plane.
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
/// ```
|
|
||||||
/// use rtchallenge::{
|
|
||||||
/// patterns::{ColorMapper, Pattern},
|
|
||||||
/// BLACK, WHITE,
|
|
||||||
/// };
|
|
||||||
///
|
|
||||||
/// let pattern = Pattern::ring(BLACK, WHITE);
|
|
||||||
/// assert_eq!(pattern.color, ColorMapper::Ring { a: BLACK, b: WHITE });
|
|
||||||
/// ```
|
|
||||||
pub fn ring(a: Color, b: Color) -> Pattern {
|
pub fn ring(a: Color, b: Color) -> Pattern {
|
||||||
Pattern {
|
Pattern {
|
||||||
color: ColorMapper::Ring { a, b },
|
color: ColorMapper::Ring { a, b },
|
||||||
@ -261,17 +129,6 @@ impl Pattern {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Create a pattern that alternates between the given colors along the X, Y and Z axis.
|
/// Create a pattern that alternates between the given colors along the X, Y and Z axis.
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
/// ```
|
|
||||||
/// use rtchallenge::{
|
|
||||||
/// patterns::{ColorMapper, Pattern},
|
|
||||||
/// BLACK, WHITE,
|
|
||||||
/// };
|
|
||||||
///
|
|
||||||
/// let pattern = Pattern::checkers(BLACK, WHITE);
|
|
||||||
/// assert_eq!(pattern.color, ColorMapper::Checkers { a: BLACK, b: WHITE });
|
|
||||||
/// ```
|
|
||||||
pub fn checkers(a: Color, b: Color) -> Pattern {
|
pub fn checkers(a: Color, b: Color) -> Pattern {
|
||||||
Pattern {
|
Pattern {
|
||||||
color: ColorMapper::Checkers { a, b },
|
color: ColorMapper::Checkers { a, b },
|
||||||
@ -280,80 +137,6 @@ impl Pattern {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Sample the color at the given point in untranslated object space.
|
/// Sample the color at the given point in untranslated object space.
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
/// ```
|
|
||||||
/// use rtchallenge::{patterns::Pattern, tuples::point, BLACK, WHITE};
|
|
||||||
///
|
|
||||||
/// // A test returns the pattern space coordinates of the point.
|
|
||||||
/// let pattern = Pattern::test();
|
|
||||||
/// let p = point(1., 2., 3.);
|
|
||||||
/// assert_eq!(pattern.pattern_at(p), [p.x, p.y, p.z].into());
|
|
||||||
///
|
|
||||||
/// // A stripe alternates between two colors.
|
|
||||||
/// let pattern = Pattern::stripe(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.pattern_at(*p), *want, "{:?}", p);
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// // A gradient linearly interpolates between two colors.
|
|
||||||
/// let pattern = Pattern::gradient(WHITE, BLACK);
|
|
||||||
/// assert_eq!(pattern.pattern_at(point(0., 0., 0.)), WHITE);
|
|
||||||
/// assert_eq!(
|
|
||||||
/// pattern.pattern_at(point(0.25, 0., 0.)),
|
|
||||||
/// [0.75, 0.75, 0.75].into()
|
|
||||||
/// );
|
|
||||||
/// assert_eq!(
|
|
||||||
/// pattern.pattern_at(point(0.5, 0., 0.)),
|
|
||||||
/// [0.5, 0.5, 0.5].into()
|
|
||||||
/// );
|
|
||||||
/// assert_eq!(
|
|
||||||
/// pattern.pattern_at(point(0.75, 0., 0.)),
|
|
||||||
/// [0.25, 0.25, 0.25].into()
|
|
||||||
/// );
|
|
||||||
///
|
|
||||||
/// // A ring should extend both in x and z.
|
|
||||||
/// let pattern = Pattern::ring(WHITE, BLACK);
|
|
||||||
/// assert_eq!(pattern.pattern_at(point(0., 0., 0.)), WHITE);
|
|
||||||
/// assert_eq!(pattern.pattern_at(point(1., 0., 0.)), BLACK);
|
|
||||||
/// assert_eq!(pattern.pattern_at(point(0., 0., 1.)), BLACK);
|
|
||||||
/// // 0.708 is slight more than 2.sqrt()/2.
|
|
||||||
/// assert_eq!(pattern.pattern_at(point(0.708, 0., 0.708)), BLACK);
|
|
||||||
///
|
|
||||||
/// // Checkers should repeat along X-axis.
|
|
||||||
/// let pattern = Pattern::checkers(WHITE, BLACK);
|
|
||||||
/// assert_eq!(pattern.pattern_at(point(0., 0., 0.)), WHITE);
|
|
||||||
/// assert_eq!(pattern.pattern_at(point(0.99, 0., 0.)), WHITE);
|
|
||||||
/// assert_eq!(pattern.pattern_at(point(1.01, 0., 0.)), BLACK);
|
|
||||||
///
|
|
||||||
/// // Checkers should repeat along Y-axis.
|
|
||||||
/// let pattern = Pattern::checkers(WHITE, BLACK);
|
|
||||||
/// assert_eq!(pattern.pattern_at(point(0., 0., 0.)), WHITE);
|
|
||||||
/// assert_eq!(pattern.pattern_at(point(0., 0.99, 0.)), WHITE);
|
|
||||||
/// assert_eq!(pattern.pattern_at(point(0., 1.01, 0.)), BLACK);
|
|
||||||
///
|
|
||||||
/// // Checkers should repeat along Z-axis.
|
|
||||||
/// let pattern = Pattern::checkers(WHITE, BLACK);
|
|
||||||
/// assert_eq!(pattern.pattern_at(point(0., 0., 0.)), WHITE);
|
|
||||||
/// assert_eq!(pattern.pattern_at(point(0., 0., 0.99)), WHITE);
|
|
||||||
/// assert_eq!(pattern.pattern_at(point(0., 0., 1.01)), BLACK);
|
|
||||||
/// ```
|
|
||||||
pub fn pattern_at(&self, point: Tuple) -> Color {
|
pub fn pattern_at(&self, point: Tuple) -> Color {
|
||||||
match self.color {
|
match self.color {
|
||||||
ColorMapper::TestPattern => [point.x, point.y, point.z].into(),
|
ColorMapper::TestPattern => [point.x, point.y, point.z].into(),
|
||||||
@ -392,37 +175,6 @@ impl Pattern {
|
|||||||
}
|
}
|
||||||
/// Sample the color at the given world point on the given object.
|
/// Sample the color at the given world point on the given object.
|
||||||
/// This function respects the object and the pattern's transform matrix.
|
/// This function respects the object and the pattern's transform matrix.
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
/// ```
|
|
||||||
/// use rtchallenge::{
|
|
||||||
/// matrices::scaling,
|
|
||||||
/// patterns::stripe_pattern,
|
|
||||||
/// shapes::{Shape, ShapeBuilder},
|
|
||||||
/// tuples::point,
|
|
||||||
/// BLACK, WHITE,
|
|
||||||
/// };
|
|
||||||
///
|
|
||||||
/// # fn main() -> Result<(), Box<std::error::Error>> {
|
|
||||||
///
|
|
||||||
/// // Stripes with an object transformation.
|
|
||||||
/// let object = ShapeBuilder::sphere()
|
|
||||||
/// .transform(scaling(2., 2., 2.))
|
|
||||||
/// .build()?;
|
|
||||||
/// let pattern = stripe_pattern(WHITE, BLACK).build()?;
|
|
||||||
/// let c = pattern.pattern_at_object(&object, point(1.5, 0., 0.));
|
|
||||||
/// assert_eq!(c, WHITE);
|
|
||||||
///
|
|
||||||
/// // Stripes with an pattern transformation.
|
|
||||||
/// let object = Shape::sphere();
|
|
||||||
/// let mut pattern = stripe_pattern(WHITE, BLACK).build()?;
|
|
||||||
/// pattern.set_transform(scaling(2., 2., 2.));
|
|
||||||
/// let c = pattern.pattern_at_object(&object, point(1.5, 0., 0.));
|
|
||||||
/// assert_eq!(c, WHITE);
|
|
||||||
///
|
|
||||||
/// # Ok(())
|
|
||||||
/// # }
|
|
||||||
/// ```
|
|
||||||
pub fn pattern_at_object(&self, object: &Shape, world_point: Tuple) -> Color {
|
pub fn pattern_at_object(&self, object: &Shape, world_point: Tuple) -> Color {
|
||||||
let object_point = object.inverse_transform() * world_point;
|
let object_point = object.inverse_transform() * world_point;
|
||||||
let pattern_point = self.inverse_transform * object_point;
|
let pattern_point = self.inverse_transform * object_point;
|
||||||
@ -441,3 +193,169 @@ impl Pattern {
|
|||||||
self.inverse_transform = t.inverse();
|
self.inverse_transform = t.inverse();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use crate::{
|
||||||
|
matrices::identity,
|
||||||
|
patterns::{ColorMapper, Pattern},
|
||||||
|
BLACK, WHITE,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_create() {
|
||||||
|
let pattern = Pattern::test();
|
||||||
|
assert_eq!(pattern.transform(), identity());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn stripe_create() {
|
||||||
|
let pattern = Pattern::stripe(BLACK, WHITE);
|
||||||
|
assert_eq!(pattern.color, ColorMapper::Stripe { a: BLACK, b: WHITE });
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn gradient_create() {
|
||||||
|
let pattern = Pattern::gradient(BLACK, WHITE);
|
||||||
|
assert_eq!(pattern.color, ColorMapper::Gradient { a: BLACK, b: WHITE });
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn ring_create() {
|
||||||
|
let pattern = Pattern::ring(BLACK, WHITE);
|
||||||
|
assert_eq!(pattern.color, ColorMapper::Ring { a: BLACK, b: WHITE });
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn checkers_create() {
|
||||||
|
let pattern = Pattern::checkers(BLACK, WHITE);
|
||||||
|
assert_eq!(pattern.color, ColorMapper::Checkers { a: BLACK, b: WHITE });
|
||||||
|
}
|
||||||
|
|
||||||
|
mod pattern_at {
|
||||||
|
use super::*;
|
||||||
|
use crate::tuples::point;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_returns_coordinates() {
|
||||||
|
// A test returns the pattern space coordinates of the point.
|
||||||
|
let pattern = Pattern::test();
|
||||||
|
let p = point(1., 2., 3.);
|
||||||
|
assert_eq!(pattern.pattern_at(p), [p.x, p.y, p.z].into());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn stripe_alternates_between_two_colors() {
|
||||||
|
// A stripe alternates between two colors.
|
||||||
|
let pattern = Pattern::stripe(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.pattern_at(*p), *want, "{:?}", p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn gradient_linearly_interpolates_between_colors() {
|
||||||
|
// A gradient linearly interpolates between two colors.
|
||||||
|
let pattern = Pattern::gradient(WHITE, BLACK);
|
||||||
|
assert_eq!(pattern.pattern_at(point(0., 0., 0.)), WHITE);
|
||||||
|
assert_eq!(
|
||||||
|
pattern.pattern_at(point(0.25, 0., 0.)),
|
||||||
|
[0.75, 0.75, 0.75].into()
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
pattern.pattern_at(point(0.5, 0., 0.)),
|
||||||
|
[0.5, 0.5, 0.5].into()
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
pattern.pattern_at(point(0.75, 0., 0.)),
|
||||||
|
[0.25, 0.25, 0.25].into()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn ring_extend_in_x_and_z() {
|
||||||
|
// A ring should extend both in x and z.
|
||||||
|
let pattern = Pattern::ring(WHITE, BLACK);
|
||||||
|
assert_eq!(pattern.pattern_at(point(0., 0., 0.)), WHITE);
|
||||||
|
assert_eq!(pattern.pattern_at(point(1., 0., 0.)), BLACK);
|
||||||
|
assert_eq!(pattern.pattern_at(point(0., 0., 1.)), BLACK);
|
||||||
|
// 0.708 is slight more than 2.sqrt()/2.
|
||||||
|
assert_eq!(pattern.pattern_at(point(0.708, 0., 0.708)), BLACK);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn checkers_repeat_along_x_axis() {
|
||||||
|
// Checkers should repeat along X-axis.
|
||||||
|
let pattern = Pattern::checkers(WHITE, BLACK);
|
||||||
|
assert_eq!(pattern.pattern_at(point(0., 0., 0.)), WHITE);
|
||||||
|
assert_eq!(pattern.pattern_at(point(0.99, 0., 0.)), WHITE);
|
||||||
|
assert_eq!(pattern.pattern_at(point(1.01, 0., 0.)), BLACK);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn checkers_repeat_along_y_axis() {
|
||||||
|
// Checkers should repeat along Y-axis.
|
||||||
|
let pattern = Pattern::checkers(WHITE, BLACK);
|
||||||
|
assert_eq!(pattern.pattern_at(point(0., 0., 0.)), WHITE);
|
||||||
|
assert_eq!(pattern.pattern_at(point(0., 0.99, 0.)), WHITE);
|
||||||
|
assert_eq!(pattern.pattern_at(point(0., 1.01, 0.)), BLACK);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn checkers_repeat_along_z_axis() {
|
||||||
|
// Checkers should repeat along Z-axis.
|
||||||
|
let pattern = Pattern::checkers(WHITE, BLACK);
|
||||||
|
assert_eq!(pattern.pattern_at(point(0., 0., 0.)), WHITE);
|
||||||
|
assert_eq!(pattern.pattern_at(point(0., 0., 0.99)), WHITE);
|
||||||
|
assert_eq!(pattern.pattern_at(point(0., 0., 1.01)), BLACK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod pattern_at_object {
|
||||||
|
use std::error::Error;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
matrices::scaling,
|
||||||
|
patterns::stripe_pattern,
|
||||||
|
shapes::{Shape, ShapeBuilder},
|
||||||
|
tuples::point,
|
||||||
|
BLACK, WHITE,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn stripes_with_an_object_transformation() -> Result<(), Box<dyn Error>> {
|
||||||
|
// Stripes with an object transformation.
|
||||||
|
let object = ShapeBuilder::sphere()
|
||||||
|
.transform(scaling(2., 2., 2.))
|
||||||
|
.build()?;
|
||||||
|
let pattern = stripe_pattern(WHITE, BLACK).build()?;
|
||||||
|
let c = pattern.pattern_at_object(&object, point(1.5, 0., 0.));
|
||||||
|
assert_eq!(c, WHITE);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn stripes_with_a_pattern_transformation() -> Result<(), Box<dyn Error>> {
|
||||||
|
// Stripes with a pattern transformation.
|
||||||
|
let object = Shape::sphere();
|
||||||
|
let mut pattern = stripe_pattern(WHITE, BLACK).build()?;
|
||||||
|
pattern.set_transform(scaling(2., 2., 2.));
|
||||||
|
let c = pattern.pattern_at_object(&object, point(1.5, 0., 0.));
|
||||||
|
assert_eq!(c, WHITE);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user