patterns: add builder pattern for creating Patterns.
This commit is contained in:
parent
2e4e8b3dcd
commit
bdcee49d5a
@ -56,7 +56,7 @@ impl Default for Material {
|
|||||||
/// use rtchallenge::{
|
/// use rtchallenge::{
|
||||||
/// lights::PointLight,
|
/// lights::PointLight,
|
||||||
/// materials::{lighting, Material},
|
/// materials::{lighting, Material},
|
||||||
/// patterns::stripe_pattern,
|
/// patterns::Pattern,
|
||||||
/// shapes::Shape,
|
/// shapes::Shape,
|
||||||
/// tuples::{point, vector, Color},
|
/// tuples::{point, vector, Color},
|
||||||
/// Float, BLACK, WHITE,
|
/// Float, BLACK, WHITE,
|
||||||
@ -113,7 +113,7 @@ impl Default for Material {
|
|||||||
/// // Lighting with a pattern applied.
|
/// // Lighting with a pattern applied.
|
||||||
///
|
///
|
||||||
/// let m = Material {
|
/// let m = Material {
|
||||||
/// color: stripe_pattern(WHITE, BLACK).into(),
|
/// color: Pattern::stripe(WHITE, BLACK),
|
||||||
/// ambient: 1.,
|
/// ambient: 1.,
|
||||||
/// diffuse: 0.,
|
/// diffuse: 0.,
|
||||||
/// specular: 0.,
|
/// specular: 0.,
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
use derive_builder::Builder;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
matrices::Matrix4x4,
|
matrices::Matrix4x4,
|
||||||
shapes::Shape,
|
shapes::Shape,
|
||||||
@ -5,7 +7,7 @@ use crate::{
|
|||||||
WHITE,
|
WHITE,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Copy, Clone)]
|
||||||
pub enum ColorMapper {
|
pub enum ColorMapper {
|
||||||
/// TestPattern the color returned is the pattern space point after going through world->object and object->pattern space translation.
|
/// TestPattern the color returned is the pattern space point after going through world->object and object->pattern space translation.
|
||||||
TestPattern,
|
TestPattern,
|
||||||
@ -16,13 +18,21 @@ pub enum ColorMapper {
|
|||||||
Stripe { a: Color, b: Color },
|
Stripe { a: Color, b: Color },
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Builder, Debug, PartialEq, Clone)]
|
||||||
|
#[builder(default, pattern = "owned")]
|
||||||
pub struct Pattern {
|
pub struct Pattern {
|
||||||
pub color: ColorMapper,
|
pub color: ColorMapper,
|
||||||
transform: Matrix4x4,
|
transform: Matrix4x4,
|
||||||
|
#[builder(private, default = "self.default_inverse_transform()?")]
|
||||||
inverse_transform: Matrix4x4,
|
inverse_transform: Matrix4x4,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl PatternBuilder {
|
||||||
|
fn default_inverse_transform(&self) -> Result<Matrix4x4, String> {
|
||||||
|
Ok(self.transform.unwrap_or(Matrix4x4::identity()).inverse())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Default for Pattern {
|
impl Default for Pattern {
|
||||||
fn default() -> Pattern {
|
fn default() -> Pattern {
|
||||||
Pattern {
|
Pattern {
|
||||||
@ -46,7 +56,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create 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
|
/// # Examples
|
||||||
@ -56,17 +66,19 @@ where
|
|||||||
/// BLACK, WHITE,
|
/// BLACK, WHITE,
|
||||||
/// };
|
/// };
|
||||||
///
|
///
|
||||||
/// let pattern = stripe_pattern(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 });
|
/// assert_eq!(pattern.color, ColorMapper::Stripe { a: BLACK, b: WHITE });
|
||||||
|
///
|
||||||
|
/// # Ok(())
|
||||||
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn stripe_pattern(a: Color, b: Color) -> Pattern {
|
pub fn stripe_pattern(a: Color, b: Color) -> PatternBuilder {
|
||||||
Pattern {
|
PatternBuilder::default().color(ColorMapper::Stripe { a, b })
|
||||||
color: ColorMapper::Stripe { a, b },
|
|
||||||
..Pattern::default()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create 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
|
/// # Examples
|
||||||
@ -77,25 +89,74 @@ pub fn stripe_pattern(a: Color, b: Color) -> Pattern {
|
|||||||
/// BLACK, WHITE,
|
/// BLACK, WHITE,
|
||||||
/// };
|
/// };
|
||||||
///
|
///
|
||||||
/// let pattern = test_pattern();
|
/// # fn main() -> Result<(), Box<std::error::Error>> {
|
||||||
|
///
|
||||||
|
/// let pattern = test_pattern().build()?;
|
||||||
/// assert_eq!(pattern.transform(), Matrix4x4::identity());
|
/// assert_eq!(pattern.transform(), Matrix4x4::identity());
|
||||||
|
///
|
||||||
|
/// # Ok(())
|
||||||
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn test_pattern() -> Pattern {
|
pub fn test_pattern() -> PatternBuilder {
|
||||||
|
PatternBuilder::default().color(ColorMapper::TestPattern)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generic implementation for mapping points to colors according to the given [ColorMapper].
|
||||||
|
impl Pattern {
|
||||||
|
/// 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.
|
||||||
|
///
|
||||||
|
/// # 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 {
|
||||||
|
Pattern {
|
||||||
|
color: ColorMapper::Stripe { a, b },
|
||||||
|
..Pattern::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a pattern used for testing. The color returned is the pattern space point
|
||||||
|
/// 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 {
|
||||||
Pattern {
|
Pattern {
|
||||||
color: ColorMapper::TestPattern,
|
color: ColorMapper::TestPattern,
|
||||||
..Pattern::default()
|
..Pattern::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generic implementation for mapping points to colors according to the given [ColorMapper].
|
|
||||||
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
|
/// # Examples
|
||||||
/// ```
|
/// ```
|
||||||
/// use rtchallenge::{patterns::stripe_pattern, tuples::point, BLACK, WHITE};
|
/// use rtchallenge::{patterns::stripe_pattern, tuples::point, BLACK, WHITE};
|
||||||
///
|
///
|
||||||
/// let pattern = stripe_pattern(WHITE, BLACK);
|
/// # fn main() -> Result<(), Box<std::error::Error>> {
|
||||||
|
///
|
||||||
|
/// let pattern = stripe_pattern(WHITE, BLACK).build()?;
|
||||||
///
|
///
|
||||||
/// for (p, want) in &[
|
/// for (p, want) in &[
|
||||||
/// // A stripe pattern is constant in y.
|
/// // A stripe pattern is constant in y.
|
||||||
@ -116,6 +177,9 @@ impl Pattern {
|
|||||||
/// ] {
|
/// ] {
|
||||||
/// assert_eq!(pattern.pattern_at(*p), *want, "{:?}", p);
|
/// assert_eq!(pattern.pattern_at(*p), *want, "{:?}", p);
|
||||||
/// }
|
/// }
|
||||||
|
///
|
||||||
|
/// # Ok(())
|
||||||
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn pattern_at(&self, point: Tuple) -> Color {
|
pub fn pattern_at(&self, point: Tuple) -> Color {
|
||||||
match self.color {
|
match self.color {
|
||||||
@ -158,13 +222,13 @@ impl Pattern {
|
|||||||
/// let object = ShapeBuilder::sphere()
|
/// let object = ShapeBuilder::sphere()
|
||||||
/// .transform(scaling(2., 2., 2.))
|
/// .transform(scaling(2., 2., 2.))
|
||||||
/// .build()?;
|
/// .build()?;
|
||||||
/// let pattern = stripe_pattern(WHITE, BLACK);
|
/// let pattern = stripe_pattern(WHITE, BLACK).build()?;
|
||||||
/// let c = pattern.pattern_at_object(&object, point(1.5, 0., 0.));
|
/// let c = pattern.pattern_at_object(&object, point(1.5, 0., 0.));
|
||||||
/// assert_eq!(c, WHITE);
|
/// assert_eq!(c, WHITE);
|
||||||
///
|
///
|
||||||
/// // Stripes with an pattern transformation.
|
/// // Stripes with an pattern transformation.
|
||||||
/// let object = Shape::sphere();
|
/// let object = Shape::sphere();
|
||||||
/// let mut pattern = stripe_pattern(WHITE, BLACK);
|
/// let mut pattern = stripe_pattern(WHITE, BLACK).build()?;
|
||||||
/// pattern.set_transform(scaling(2., 2., 2.));
|
/// pattern.set_transform(scaling(2., 2., 2.));
|
||||||
/// let c = pattern.pattern_at_object(&object, point(1.5, 0., 0.));
|
/// let c = pattern.pattern_at_object(&object, point(1.5, 0., 0.));
|
||||||
/// assert_eq!(c, WHITE);
|
/// assert_eq!(c, WHITE);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user