The animation of my GIF is a visualization of the process of tension and decompression that occurs in a sigh of relief. The look is inspired by classic film with its variable framerate and shaky images as well as the kind of chromatic aberration you might experience with the use of old monitors or television sets. Overall, I am pleased with the animation. I think it conveys the physiological process that I intended. There are issues when converting it to the GIF format. There are some artifacts in the colors of the triangles when it is converted into a GIF but I accept them as quirks of the medium. However, I am skeptical that I will be pleased with the lenticular print.
Code:
// This is a looping animation created from the template by Prof. Golan Levin
// When you press a key, this program will export a series of images
// into a directory located in its sketch folder.
// These can then be combined into an animated GIF.
// Collin Burger for IACD aka Freestyle Computing 2014
// Global variables.
int nFramesInLoop = 10; // for lenticular export, change this to 10!
int nElapsedFrames;
boolean bRecording;
int frameNum;
String myName = "collinburger";
//===================================================
void setup() {
size (1500, 1500);
bRecording = false;
nElapsedFrames = 0;
frameNum = 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("shakePrintTest/"+ myName + "-loop-" + nf(nElapsedFrames, 4) + "(100ms)" + ".png");
nElapsedFrames++;
if (nElapsedFrames == nFramesInLoop) {
bRecording = false;
}
}
frameNum ++;
}
//===================================================
void renderMyDesign (float percent) {
// 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.
// This example uses two different graphical techniques.
// Use or delete whatever you prefer from this example.
// Remember to SKETCH FIRST!
//----------------------
// here, I set the background and some other graphical properties
background (0);
//I change the blend mode to add so that the colors in my shapes add up
blendMode(ADD);
smooth();
//----------------------
//I change the percent so that the atan returns to the center to create a loop
if(percent >= 0.5)
{
percent = 1.0 - percent;
}
float armAngle = (percent) * (PI);
float px = (height/20)*atan(armAngle);
float py = px;
float theta = 0;
float thetaMagenta = 0;
//these change the rotation so that the shapes shake
//I dont want any to shake in phase the same amount so the magenta triangle shakes more
if(frameNum%2 == 0)
{
thetaMagenta = -percent*PI/32;
theta = thetaMagenta + percent*PI/64;
}
else
{
thetaMagenta = percent*PI/32;
theta = thetaMagenta - percent*PI/64;
}
//i define the bounds and size of the triangles
float triTopVertX = width/2;
float triTopVertY = height/2;
float triLeftVertX = width/2;
float triLeftVertY = 2*height/2;
float triRightVertX = 2*width/2;
float triRightVertY = 2*height/2;
float triSideLength = sqrt(sq(triTopVertX-triLeftVertX) + sq(triTopVertY-triLeftVertY));
float triHeight = sqrt(3)*triSideLength/2;
float triRadVert = 2*triHeight/3;
float triRadSide = triSideLength/3;
translate(random(-10,10),random(-10,10));
//these draw the triangles and rotate them from their centers
pushMatrix();
fill(200,0,200);
translate(width/2, height/2 + py);
rotate(thetaMagenta);
triangle(-triSideLength/2, triRadSide, 0, -triRadVert, triSideLength/2, triRadSide);
popMatrix();
//draw half of the colors of the blue triangle before drawing the green one to even out the artifacts of the blending
pushMatrix();
translate(width/2 - px, height/2 -py);
fill(0,50,128);
rotate(-theta);
triangle(-triSideLength/2, triRadSide, 0, -triRadVert, triSideLength/2, triRadSide);
popMatrix();
pushMatrix();
translate(width/2 + px,height/2 - py);
fill(50,200,0);
rotate(theta);
triangle(-triSideLength/2, triRadSide, 0, -triRadVert, triSideLength/2, triRadSide);
popMatrix();
//draw the rest of the colors of the blue triangle
pushMatrix();
translate(width/2 - px, height/2 -py);
fill(0,100,100);
rotate(-theta);
triangle(-triSideLength/2, triRadSide, 0, -triRadVert, triSideLength/2, triRadSide);
popMatrix();
//define the blurring parameters
int radius = 1;
int passes = (int)(percent*60);
for(int i = 0; i < passes; i++)
{
filter(BLUR,radius);
}
}