patterns: implement ring pattern
This commit is contained in:
parent
74fe69188a
commit
77215193fa
@ -45,7 +45,7 @@ pub mod prelude {
|
|||||||
lights::{PointLight, PointLightBuilder},
|
lights::{PointLight, PointLightBuilder},
|
||||||
materials::{Material, MaterialBuilder},
|
materials::{Material, MaterialBuilder},
|
||||||
matrices::{identity, rotation_x, rotation_y, rotation_z, scaling, shearing, translation},
|
matrices::{identity, rotation_x, rotation_y, rotation_z, scaling, shearing, translation},
|
||||||
patterns::{gradient_pattern, stripe_pattern},
|
patterns::{gradient_pattern, ring_pattern, stripe_pattern},
|
||||||
shapes::{plane, sphere, test_shape},
|
shapes::{plane, sphere, test_shape},
|
||||||
transformations::view_transform,
|
transformations::view_transform,
|
||||||
tuples::{point, vector, Color},
|
tuples::{point, vector, Color},
|
||||||
|
|||||||
@ -18,6 +18,8 @@ pub enum ColorMapper {
|
|||||||
Stripe { a: Color, b: Color },
|
Stripe { a: Color, b: Color },
|
||||||
/// Linear blend between `a` and `b` along the X-axis.
|
/// Linear blend between `a` and `b` along the X-axis.
|
||||||
Gradient { a: Color, b: Color },
|
Gradient { a: Color, b: Color },
|
||||||
|
/// Bullseye pattern in the XZ plane.
|
||||||
|
Ring { a: Color, b: Color },
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Builder, Debug, PartialEq, Clone)]
|
#[derive(Builder, Debug, PartialEq, Clone)]
|
||||||
@ -126,6 +128,28 @@ 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
|
||||||
|
/// 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 {
|
||||||
|
PatternBuilder::default().color(ColorMapper::Ring { a, b })
|
||||||
|
}
|
||||||
|
|
||||||
/// Generic implementation for mapping points to colors according to the given [ColorMapper].
|
/// Generic implementation for mapping points to colors according to the given [ColorMapper].
|
||||||
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
|
||||||
@ -174,8 +198,7 @@ impl Pattern {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a pattern that alternates between the given colors along each unit of the
|
/// Create a pattern that gradually blends between the given colors along the X-axis.
|
||||||
/// X-axis. The strip extends infinitely in the positive and negative Y and Z axes.
|
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
/// ```
|
/// ```
|
||||||
@ -194,6 +217,25 @@ impl Pattern {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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 {
|
||||||
|
Pattern {
|
||||||
|
color: ColorMapper::Ring { a, b },
|
||||||
|
..Pattern::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Sample the color at the given point in untranslated object space.
|
/// Sample the color at the given point in untranslated object space.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
@ -242,22 +284,22 @@ impl Pattern {
|
|||||||
/// pattern.pattern_at(point(0.75, 0., 0.)),
|
/// pattern.pattern_at(point(0.75, 0., 0.)),
|
||||||
/// [0.25, 0.25, 0.25].into()
|
/// [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);
|
||||||
/// ```
|
/// ```
|
||||||
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(),
|
||||||
ColorMapper::Constant(c) => c,
|
ColorMapper::Constant(c) => c,
|
||||||
ColorMapper::Stripe { a, b } => {
|
ColorMapper::Stripe { a, b } => {
|
||||||
let x = point.x.floor() as i64;
|
let x = point.x.floor();
|
||||||
/*
|
if x % 2. == 0. {
|
||||||
// Shift negative valued to get correct striping.
|
|
||||||
if x < 0 {
|
|
||||||
x - 1
|
|
||||||
} else {
|
|
||||||
x
|
|
||||||
};
|
|
||||||
*/
|
|
||||||
if x % 2 == 0 {
|
|
||||||
a
|
a
|
||||||
} else {
|
} else {
|
||||||
b
|
b
|
||||||
@ -268,6 +310,15 @@ impl Pattern {
|
|||||||
let fraction = point.x - point.x.floor();
|
let fraction = point.x - point.x.floor();
|
||||||
a + distance * fraction
|
a + distance * fraction
|
||||||
}
|
}
|
||||||
|
ColorMapper::Ring { a, b } => {
|
||||||
|
let px = point.x;
|
||||||
|
let pz = point.z;
|
||||||
|
if (px * px + pz * pz).sqrt().floor() % 2. == 0. {
|
||||||
|
a
|
||||||
|
} else {
|
||||||
|
b
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Sample the color at the given world point on the given object.
|
/// Sample the color at the given world point on the given object.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user