For my animation, I created an example of a Moiré pattern, which is an optical illusion caused by overlaying similar patterns. Lines seem to appear and move based on the relationship of the layers. I have seen examples of one bulls-eye pattern overlaying another bulls-eye pattern, so I decided to layer three of them and see how it looked. Here is the result:
(The 500×500 version, which was too large to be uploaded and looked gross when compressed, can be seen here)
Before I began, I doodled some ideas in my sketchbook, and finally decided on three bullseye layers:
Then, I made this gif. I got feedback that a looping design would be nicer (thanks, Austin!), and I also felt that the illusion wasn’t as strong after a given point, so I then created the looping version at the top.
Below is the code for my final animation, which builds upon the started code that Golan gave us. I reduced the size of the images after they were exported.
// Emily Danchik
// IACD Spring 2014
// Project 1-1 Lenticular Animation
//
// From Golan:
// When you press a key, this program will export a series of images
// into an "output" directory located in its sketch folder.
// These can then be combined into an animated GIF.
// Prof. Golan Levin, January 2014 - CMU IACD
//===================================================
// Global variables.
int nFramesInLoop = 30; // for lenticular export, change this to 10!
int nElapsedFrames;
boolean bRecording;
String myName = "emily"; // for file names
//===================================================
void setup() {
size (1500, 1500);
bRecording = false;
nElapsedFrames = 0;
frameRate (nFramesInLoop);
}
//===================================================
void keyPressed() {
// Press a key to export frames to the output folder
bRecording = true;
nElapsedFrames = 0;
}
//===================================================
void draw() {
// Compute a percentage (0...1) representing where we are in the loop.
float percentCompleteFraction = 0;
if (bRecording) {
percentCompleteFraction = (float) nElapsedFrames / (float)nFramesInLoop;
}
else {
float modFrame = (float) (frameCount % nFramesInLoop);
percentCompleteFraction = modFrame / (float)nFramesInLoop;
}
// Render the design, based on that percentage.
renderMyDesign (percentCompleteFraction);
// If we're recording the output, save the frame to a file.
if (bRecording) {
saveFrame("output/"+ myName + "-loop-" + nf(nElapsedFrames, 4) + ".png");
nElapsedFrames++;
if (nElapsedFrames == nFramesInLoop) {
bRecording = false;
}
}
}
//===================================================
void renderMyDesign (float percent) {
// From Golan:
// This is an example of a function that renders a temporally looping design.
// It takes a "percent", between 0 and 1, indicating where we are in the loop.
//----------------------
// Setting up the constants
background (255);
float speed = .2;
int spacing = 30;
int numberOfCircles = 40;
noFill();
strokeWeight(7);
// Let's loop through and make three bulls eye patterns
for(int i = 1 ; i <= numberOfCircles ; i++){
// centered circles
stroke(0,0,255,80);
ellipse(750, 750, spacing*i, spacing*i);
// For the first half of the animation, go out!
if(percent <=0.5){
// circles that move left
stroke(0,255,0,80);
ellipse(-750*percent*speed+750,750,spacing*i,spacing*i);
// circles that move right
stroke(255,0,0,80);
ellipse(750*percent*speed+750,750,spacing*i,spacing*i);
}
// For the second half of the animation, come in!
else{
// circles that moved left will now move right
stroke(0,255,0,80);
ellipse(-750*(1-percent)*speed+750,750,spacing*i,spacing*i);
// circles that moved right will now move left
stroke(255,0,0,80);
ellipse(750*(1-percent)*speed+750,750,spacing*i,spacing*i);
}
}
}
This was my first time creating an animation in Processing, and I think it went pretty well. The final result is simple, but effective in showing the illusion: