CS 106 Winter 2018
Lab 07: Randomness and Noise
Question 1 Gravel Stones
In the slides for this module, have another look at Gravel Stones by Georg Nees. We discussed it as a canonical example of generative art: using the computer to inject a design with an "exactly calculated dose of randomness". You will use Processing to recreate this artwork.
In the starter code, open the sketch GravelStones. Most of the coding is already done for you. You will find global variables to control the width and height of the grid of random squares, and the size of each square. There is also a ControlP5 interface consisting of a single slider to control the amount of randomness used in the sketch. Beginning there, proceed as follows:
Draw a grid of plain squares with no randomness. The grid should be cols cells wide and rows cells tall, and each grid cell should be a square of side length dim. Centre the grid so that there is a uniform margin of width margin on all four sides. You should get a sketch that looks like this:
Next, give every cell a random rotation between -45 degrees and 45 degrees. The result should look something like this:
This step should require a single new line of code.
Now for the trickiest step. Change the sketch so that the amount of random rotation is controlled by the cell's vertical position in the sketch window. Cells in the top row should not rotate at all, and cells in the bottom row should rotate by a random amount in the full range from -45 degrees to 45 degrees.
To make this step work, let's assume you have a for loop that counts which row of the grid you're drawing; the loop counter starts at 0 and goes up to rows-1. Define a float (inside the loop) that maps the loop counter into a number between 0 and 1. When you generate each random angle, multiply it by this new variable, so that cells higher in the sketch window can't rotate as much. The result will look like this:
This step shouldn't require a big change to the code; you'll need a single new line of code to define the variable described above, and a modification to the line from the previous step that does the rotation.
-
Repeat Steps 2 and 3 to control the translation of each grid cell. Add different random amounts in x and y to the translation of every cell, ranging from -5 to 5. Now use the same variable you created in Step 3 to vary the extent of the translation across the sketch window, so that squares at the top don't move at all and squares at the bottom can move by the maximum possible distance. You'll end up with a design like this:
Make sure that your squares can move in any direction (i.e., that the amount of random translation can be positive or negative.)
-
Finally, modify the code so that the slider (which we haven't used yet) acts as a global "volume knob" on the total amount of randomness. When the slider is turned down to zero, all randomness disappears and we get back the drawing in Step 1. When the slider is set to one (the default), we get drawings like the one in the previous step.
This step can be completed in as little as a single change to one line of code: simply multiply the variable you defined in Step 3 by the current value of the slider.
Note: to make later steps easier, draw each grid square by translating it in a geometric context. That is, use the call rect( 0, 0, dim, dim ) to draw a square, and pushMatrix(), translate() and popMatrix() to wrap a suitable context around the draw call. Note that because of the use of rectMode( CENTER ) in this sketch, you'll need to translate by an additional half the side length of the square in x and y to get the grid to be centred. The starter code contains an example of drawing one of the squares.
This entire step should require 8–10 lines of code.
This sketch sets the random seed at the start of every frame. Therefore, the random gravel stones drawing should stay still on the screen, and not flicker or change. If you want to see a new version, press the space bar to change the random seed.
Note that you'll be making three separate calls to random() when drawing every grid cell: two for the translation and one for the rotation. Don't re-use the same random number more than once in a given frame!
Save your sketch under the name GravelStones.
Question 2 Lava Lamp
The Noise2DDirectManip sample sketch offers a direct visualization of the noise() function, together with the ability to explore the function's behaviour across the entire plane via direct manipulation. In this exercise, you will add a few simple features to this sketch to turn it into an animated visualization sort of like a lava lamp.
In the starter code, open the LavaLamp sketch.
As provided, the sketch is nothing more than a clone of Noise2DDirectManip. We'll use it as a starting point for adding new features.Choose a colour scheme. Your colour scheme must consist of at least three, and not more than six, distinct colours. You might enjoy browsing repositories of popular colour schemes, such as Adobe Color CC. Store your colours in an array declared as a global variable.
Currently, the sketch turns the noise function directly into a greyscale colour (by multiplying by 256). Instead, let's divide the range of noise values into narrow "bands" and assign each band a colour from your array.
There's a nice mathematical trick to doing this. Choose the number of bands you want, an integer between 20 and 150. Multiply the value of the noise() function by the number of bands, and round the result to an integer. Now compute the remainder when that integer is divided by the number of colours in your array (using the % operation). That remainder can be used as an index into the array of colours; set each pixel to the colour taken from the array for the pixel's corresponding noise value. You should now have something that looks like a frame in the video above, though it won't warp over time.
Experiment with the global variable sc and the number of bands you chose in the previous step until you have a density of bands and visual complexity that you're happy with.
To add the slow animated warping, simply add a third parameter to the call to noise() (i.e., use the 3D noise() function instead of the 2D one). This third parameter should be something that changes slowly from frame to frame; the effect is to move gradually through 2D "slices" out of the 3D noise function, allowing us to visualize the change in noise over time. A simple choice is something like frameCount * temp_scale, where temp_scale is a variable that controls how fast the pattern changes. Choose a small number (say, 0.001) to start and then experiment from there.
That's all you need to do for this sketch. The total sketch will be 30–35 lines, and you need to write only about 5 of them. You are welcome to experiment with other visual effects or changes, and we may award bonus marks to especially attractive results.
Save your sketch under the name LavaLamp.
Submission
When you are ready to submit, please follow these steps.
If necessary, review the Code Style Guide and use Processing's built-in auto format tool. You do not need to use the precise coding style outlined in the guide, but whatever style you use, your code must be clear, concise, consistent, and commented.
If necessary, review the How To Submit document for a reminder on how to submit to LEARN.
Make sure to include a comment at the top of all source files containing your name and student ID number.
Create a zip file called L07.zip containing the entire L07 folder and its subfolders GravelStones and LavaLamp.
Upload L06.zip to LEARN. Remember that you can (and should!) submit as many times as you like. That way, if there's a catastrophe, you and the course staff will still have access to a recent version of your code.
If LEARN isn't working, and only if LEARN isn't working, please email your ZIP file to the course account (see the course home page for the address). In this case, you must mail your ZIP file before the deadline. Please use this only for emergencies, not "just in case". Submissions received after the deadline may receive feedback, but their marks will not count.