Difficulty |
3 |
We consider two kinds of patterns: 2D and 3D patterns. Let’s start with 2D patterns, because those are the easiest to reason about.
1. 2D Patterns
A 2D pattern can be seen as a black-and-white image.
With black and white, we mean literally black and white, not grayscale.
In code, a 2D pattern is represented as an object that takes 2D coordinates \((x, y)\) and returns the corresponding color, i.e., black or white.
In code, we’ll represent these two colors as true
and false
.
Note
|
Which boolean value corresponds to which color does not really matter.
In a later step, we will make this configurable: For now though, we limit ourselves to simply |
1.1. Examples
Below are a few examples of patterns:
Horizontal lines |
![]() |
Vertical lines |
![]() |
Checkered |
![]() |
1.2. Target Syntax
How would we model a 2D pattern in code? As explained above, there really is just one operation: we can ask a 2D pattern what color appears at a certain position.
// Possible implementation
Pattern2D some_pattern;
Point2D p(x, y);
bool color = some_pattern.get_color_at(p);
However, we’d rather see patterns as functions, so instead of calling a get_color_at
method, we’d rather write
// Function syntax
Pattern2D some_pattern;
Point2D p(x, y);
bool color = some_pattern(p);
This function-like syntax will be achieved by defining a class Pattern2D
and overloading the operator ()
on it.
1.3. Value Semantics
We would like Pattern2D
objects to be easily usable, i.e., we would prefer having to think about references and pointers and such.
Ideally, we would use Pattern2D
s as if they were int
s, bool
s or any other simple value type.
In fact, this kind of types have already been implemented: Primitive
is an example of this.
Take a good at the types
|
1.4. Implementation
1.4.1. Setting Things Up
|
1.4.2. Pattern2DImplementation
This class will be fully abstract. It acts as a base class for all 2D patterns and therefore will define all functionality common to 2D patterns.
Inside
If you’re wondering about the |
1.4.3. Pattern2D
If client code were to have to use Pattern2DImplementation
directly, it would have to keep track of these objects using pointers, as the object is involved in an object hierarchy.
To simplify usage, we also provide a wrapper class named Pattern2D
which will allow client code to manipulate pattern objects as if they were values, i.e., pass them by value.
In
|
2. 3D Patterns
3D patterns are identical to 2D pattern, except that they take a 3D point instead of a 2D point.
Pattern3D some_pattern;
Point3D p(x, y, z);
bool color = some_pattern(p);
2.1. Implementation
Still in |
To the same file, define the class |
3. Bindings
As a last step, we need to set up the necessary foundations to expose pattern-related functionality to the scripting language.
We would like all such functionality to be hosted in a separate module named Patterns
, just like there is are Animations
, Samplers
and Raytracers
modules.
Create files
|
4. Evaluation
Create two patterns (2D and 3D) that (rather boringly) always returns the same value.
Place the code in files named
For example, |
Write tests to ensure that both |