Category Archives: 11-Lenticular-GIF

Andre Le

21 Jan 2014

andrele_lenticular

 

The above gif is actually the second animation I completed for this project. I originally wanted to create a black hole that continuously swallowed itself up. I played with lines, circles, and spirals to convey the illusion of the outer mass sucking in towards the center, but after doing a few tests, I realized that the amount of motion wouldn’t lend well to a lenticular print.

andrele_blackhole_lenticular

What I really wanted was to play with seamless eternity. Something that you would fixate upon without realizing it. I took inspiration from a spinning umbrella and Pittsburgh’s endless downpour of rain and snow.

In order to play with animation curves, I imported a library called Ani to help with timing the animations and working with animation curves. It proved to be a very useful library for prototyping, but I felt that the preset animation curves could be limiting.

Overall, this was a great experience that I feel I could apply to loading animations, video loops, etc.

Sketches of process:

IMG_1023 blackHole-Process IMG_1024

 

Code for Refill Animation:

import de.looksgood.ani.*;
 
String   myName = "andrele";
int      SKETCH_SIZE = 1500;
int      nFramesInLoop = 10;
int      nElapsedFrames;
float    EDGE = SKETCH_SIZE/2*.75;
int      sides = 6;
float    angleIncrement = 360/sides;
float    overlap = .7;
boolean  bRecording;
color    fillColor = color(0,146,252);
Ani      rotationAni, insertAni;
float    rotation = -60;
float    insertPos = -EDGE;
Segment  insert;
Segment[] segments;
 
void setup() {
  size (SKETCH_SIZE,SKETCH_SIZE);
  frameRate(nFramesInLoop);
  noStroke();
  smooth();
 
  nElapsedFrames = 0;
 
  Ani.init(this);
  Ani.setDefaultTimeMode(Ani.FRAMES);
 
  segments = new Segment[sides];
  for (int i = 0; i < sides; i++) {
    segments[i] = new Segment(angleIncrement*i, EDGE, fillColor, (float)(255/(float)sides*((float)i+1)));
    segments[i].opacityAnimation = new Ani(segments[i], nFramesInLoop*.5, "opacity", segments[i].opacity - (float)(255/(float)sides), Ani.SINE_IN_OUT);
  }
  rotationAni = new Ani(this, nFramesInLoop*.5, "rotation", rotation-60, Ani.SINE_IN_OUT); 
 
  // Draw segment off-screen
  insert = new Segment(-120, 0, fillColor, 255);
  insertAni = new Ani(insert, nFramesInLoop*.5, nFramesInLoop*.5, "size", EDGE, Ani.SINE_IN_OUT);
}
 
void keyPressed() { 
  // Press a key to export frames to the output folder
  bRecording = true;
  nElapsedFrames = 0;
}
 
void draw() {
  background(0);
  translate(SKETCH_SIZE/2, SKETCH_SIZE/2);
  pushMatrix();
  rotate(radians(rotation));
 
  // If we've received the frames in the loop, reset the animation
  if (frameCount%nFramesInLoop == 0) {
    for (Segment segment:segments){
      segment.opacityAnimation.start();
    }
    insertAni.start();
    rotationAni.start();
  }
 
//  float percentage = (frameCount%nFramesInLoop)/(float)nFramesInLoop;
  for (int i = 0; i < sides; i++) {
    segments[i].draw();
  } 
 
  pushStyle();
  popStyle();
  popMatrix();
  insert.draw();
 
  if (bRecording) {
    saveFrame("output/"+ myName + "-loop-" + nf(nElapsedFrames, 4) + ".png");
    nElapsedFrames++; 
    if (nElapsedFrames == nFramesInLoop) {
      bRecording = false;
    }
  }
 
}
 
class Segment {
 
  float angle, size, opacity;
  color fill;
  Ani opacityAnimation;
 
  Segment(float angle, float size, color fill, float opacity) {
    this.angle = angle;
    this.size = size;
    this.fill = fill;
    this.opacity = opacity;
  }
 
  void draw() {
    pushStyle();
    color newColor = color(red(fillColor), green(fillColor), blue(fillColor), opacity);
    fill(newColor);
    triangle(0,0, size*cos(radians(angle)), size*sin(radians(angle)), size*cos(radians(angle+angleIncrement)), size*sin(radians(angle+angleIncrement)));
    popStyle();
  }
 
}

Code for “Black Hole” animation:

import de.looksgood.ani.*;
 
int     nElapsedFrames;
boolean bRecording;
String  myName = "andrele";
 
int MASTER_RADIUS = 200;
int MAX_FRAMES = 30;
int INNER_CIRCLES = 8;
float LINE_WEIGHT = 60;
Blob defaultBlob, whiteBlob, blackBlob;
Blob[] innerBlobs;
AniSequence innerSeq;
Ani whiteAnimation, blackAnimation, initialAnimation;
Line[] innerLines;
 
void setup() {
  size(500,500, P2D);
  frameRate(MAX_FRAMES);
  smooth();
  ellipseMode(RADIUS);
  noStroke();
  background(255);
  fill(0);
  defaultBlob = new Blob(0, 0, MASTER_RADIUS, color(0));
  blackBlob = new Blob(0, 0, MASTER_RADIUS/2, color(0));
  whiteBlob = new Blob(0, 0, 0, color(255));
 
  Ani.init(this);
  Ani.setDefaultTimeMode(Ani.FRAMES);
  whiteAnimation = new Ani(whiteBlob, MAX_FRAMES, "radius", MASTER_RADIUS, Ani.QUAD_OUT);
  blackAnimation = new Ani(blackBlob, MAX_FRAMES*.20, MAX_FRAMES*.80, "radius", MASTER_RADIUS, Ani.QUAD_IN_OUT, "onEnd:animationEnd");
  initialAnimation = new Ani(blackBlob, MAX_FRAMES*.7, "radius", 40, Ani.SINE_OUT, "onEnd:initialAniEnd");
  whiteAnimation.start();
  initialAnimation.start();
  blackAnimation.start();
 
  innerLines = new Line[INNER_CIRCLES];
  float angleIncrement = 360/INNER_CIRCLES;
  for (int i = 0; i < INNER_CIRCLES; i++) {
    innerLines[i] = new Line(0, MASTER_RADIUS-(LINE_WEIGHT/2), (i+1)*angleIncrement, LINE_WEIGHT, color(0));
  }
 
//  innerBlobs = new Blob[INNER_CIRCLES];
//  for (int i = 0; i < INNER_CIRCLES; i++) {
//    innerBlobs[i] = new Blob((MASTER_RADIUS-LINE_WEIGHT/2)*cos(radians(angleIncrement*i)), (MASTER_RADIUS-LINE_WEIGHT/2)*sin(radians(angleIncrement*i)), LINE_WEIGHT/2, color(0));
//    innerBlobs[i].moveAnimation = new Ani(innerBlobs[i], MAX_FRAMES/2, MAX_FRAMES/2, "rEnd", 0, Ani.SINE_IN_OUT);
//    innerBlobs[i].sizeAnimation = new Ani(innerBlobs[i], MAX_FRAMES-10, 10, "radius", 0, Ani.QUART_IN_OUT);
//  }
}
 
void keyPressed() { 
  // Press a key to export frames to the output folder
  bRecording = true;
  nElapsedFrames = 0;
}
 
void draw() {
  background(255);
  pushStyle();
  pushMatrix();
  translate(width/2, height/2);
 
  defaultBlob.draw();
  whiteBlob.draw();
 
  // Draw swirl inbetween
//  float swirlR;
//  if (whiteBlob.radius<MASTER_RADIUS) {
//    swirlR = (whiteBlob.radius + blackBlob.radius)/2;
//  } else {
//    swirlR = (whiteBlob.radius - blackBlob.radius)/2;
//  }
//  float swirlX = (swirlR-blackBlob.radius);
//  float swirlAngle = 360 * ( (float)frameCount%(float)MAX_FRAMES/(float)MAX_FRAMES );
////  float swirlAngle = 45;
//  float swirlOffset = 90;
//  println(swirlAngle);
//  fill(0);
//  ellipse(swirlX*cos(radians(swirlAngle)),swirlX*sin(radians(swirlAngle)),swirlR,swirlR);
//  arc(0,0,whiteBlob.radius < MASTER_RADIUS ? whiteBlob.radius : 0,whiteBlob.radius < MASTER_RADIUS ? whiteBlob.radius : 0, radians(swirlAngle-(swirlOffset*.6)-23), radians(swirlAngle+(swirlOffset*.6)-23));
//  fill(255);
//  ellipse(swirlX*cos(radians(swirlAngle-swirlOffset)),swirlX*sin(radians(swirlAngle-swirlOffset)), swirlR, swirlR);
 
  for (Line line:innerLines) {
    line.draw();
  }
 
//  for (Blob blob:innerBlobs) {
//    blob.draw();
//  }
//  
  blackBlob.draw();
 
//  for (int i = 0; i < innerBlobs.length; i++) {
//    innerBlobs[i].draw();
//  }
 
  popMatrix();
  popStyle();
 
    // 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 == MAX_FRAMES) {
      bRecording = false;
    }
  }
}
 
class Blob {
  float x, y, radius;
  color circleColor;
  Ani sizeAnimation, moveAnimation;
  Blob( float x, float y, float radius, color circleColor ) {
    this.x = x;
    this.y = y;
    this.radius = radius;
    this.circleColor = circleColor;
  }
 
  void draw() {
    pushStyle();
    fill(circleColor);
    ellipse(x,y,radius,radius);
    popStyle();
  }
 
  void animationEnd(Ani theAni) {
      println("Black animation end");
      whiteAnimation.start();
      initialAnimation.start();
      blackAnimation.start();
      for (Line line : innerLines) {
        line.lengthAnimation.start();
        line.weightAnimation.start();
      }
 
//      for (Blob blob : innerBlobs) {
//        blob.sizeAnimation.start();
//        blob.moveAnimation.start();
//      } 
  }
 
}
 
class Line {
  float rStart, rEnd, angle, weight;
  color lineColor;
  Ani lengthAnimation, weightAnimation;
 
  Line( float rStart, float rEnd, float angle, float weight, color lineColor ) {
    this.rStart = rStart;
    this.rEnd = rEnd;
    this.angle = angle;
    this.weight = weight;
    this.lineColor = lineColor;
    this.lengthAnimation = new Ani(this, MAX_FRAMES*.4, MAX_FRAMES*.6, "rEnd", 0, Ani.SINE_IN_OUT);
    this.weightAnimation = new Ani(this, MAX_FRAMES*.65, MAX_FRAMES*.03, "weight", 0, Ani.SINE_IN);
  }
 
  float getX(float radius){
    return radius * cos(radians(angle)); 
  }
 
  float getY(float radius){
    return radius * sin(radians(angle)); 
  }
 
  void draw(){
    this.rEnd = MASTER_RADIUS-(this.weight/2);
    pushStyle();
    strokeWeight(weight);
    stroke(lineColor);
    line(getX(rStart),getY(rStart),getX(rEnd),getY(rEnd));
    popStyle();
  }
}

Sama Kanbour

21 Jan 2014

For this assignment, I had the idea of creating an elegant design using recursion. Inspired by Diana Lange’s recursive flower, I played with the design to recreate the human pupil. In my opinion, playing with transparency added an effect of depth. I am not entirely satisfied with the rotating effect.

Lenticular-GIF-samak

photo

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
// Inspired by Diana Lange
 
String     myName = "samakanbour";
int        nFramesInLoop = 10;
int        size = 500;
int        nElapsedFrames;
Circles    c;
Flower     f;
float      iteration;
 
void setup () {
  size(size, size);
  nElapsedFrames = 0;
  frameRate (nFramesInLoop);
  smooth();
  iteration = 0;
}
 
void draw () {
  iteration ++;
  float modFrame = (float) (frameCount % nFramesInLoop);
  float p = modFrame / (float)nFramesInLoop;
  fill (10, 250, 200, 20);
  background (#D8DBFF);
  noStroke();
  ellipse (width/2, height/2, size*.9, size*.9);
  f = new Flower (200, width/2, height/2, size * 0.16, 0.1);
  c = new Circles (width/2, height/2, 6, p);
  fill (#000000);
  f.display();
  if (iteration < = nFramesInLoop){     saveFrame("output/"+ myName + "-loop-" + iteration + ".png");   } } class Circles {   private int cx, cy;   Circles (int x, int y, int n, float p) {     this.cx = x;     this.cy = y;     createCircles(n, p);   }   private void createCircles(int n, float p) {     float per = p;     if (p > 0.5) { per = 1 - p; }
    float radius = size * 0.08 * per + size/10;
    int nSpokes = 10; 
    if (n == 1){
      return;
    } else {
      for (int i=0; i < nSpokes; i++) {         float armAngle = (p + i) * (TWO_PI/nSpokes);          float px = cx + radius*cos(armAngle);          float py = cy + radius*sin(armAngle);          ellipse (px, py, size * 0.08 * n, size * 0.08 * n);       }       fill (10*n, 10*n, 20*n, 30*n/10);       createCircles(n-1, p);               }    } } class Anchor {   private float angle, minAngle, maxAngle, length;   private int centerX, centerY;   private ArrayList branches;   Anchor (float angle, float minAngle, float maxAngle, float length, int centerX, int centerY, float minNext ) {     this.angle = angle;     this.minAngle = minAngle;      this.maxAngle = maxAngle;     this.length = length;     this.centerX = centerX;     this.centerY = centerY;     branches = new ArrayList();     createBranches(angle, centerX, centerY, 0, random (length /15.0, length /2.0), 0, minNext);   }   public int getCenterX () {     return centerX;   }   public int getCenterY () {     return centerY;   }   private void createBranches (float fAngle, float startX, float startY, float totalLength, float flength, int count, float minNext) {     float mangle = minAngle / 4;     float weighing = 0.5;     float [] [] points = new float [5] [2];     if (flength>80) points = new float [6] [2];
    points [0] [0] = points [1] [0] = startX;                                                                                                                  // startpunkt x
    points [0] [1] = points [1] [1] = startY;                                                                                                                  // startpunkt y
    points [points.length-2] [0] = points [points.length-1] [0] = startX + cos (radians (fAngle)) * flength;                                                   // endpunkt x
    points [points.length-2] [1] = points [points.length-1] [1] = startY + sin (radians (fAngle)) * flength;                                                   // endpunkt y
    if (flength< =80) {
    points [2] [0] = startX + cos (radians (fAngle+mangle)) * dist (startX, startY, points [points.length-1] [0], points [points.length-1] [1]) * weighing;  // kontrollpunkt x
    points [2] [1] = startY + sin (radians (fAngle+mangle)) * dist (startX, startY, points [points.length-1] [0], points [points.length-1] [1]) * weighing;  // kontrolltpunkt y
    } else {
    weighing = 0.4;
    points [2] [0] = startX + cos (radians (fAngle+mangle)) * dist (startX, startY, points [points.length-1] [0], points [points.length-1] [1]) * weighing;  // kontrollpunkt x
    points [2] [1] = startY + sin (radians (fAngle+mangle)) * dist (startX, startY, points [points.length-1] [0], points [points.length-1] [1]) * weighing;  // kontrolltpunkt y
    weighing = 0.6;
    points [3] [0] = startX + cos (radians (fAngle+mangle)) * dist (startX, startY, points [points.length-1] [0], points [points.length-1] [1]) * weighing;  // kontrollpunkt x
    points [3] [1] = startY + sin (radians (fAngle+mangle)) * dist (startX, startY, points [points.length-1] [0], points [points.length-1] [1]) * weighing;  // kontrolltpunkt y
    }
    //----- add new branch
    branches.add (new Branch (points));
    //----- calculate current branch length
    totalLength += flength;
    //----- recursion
    if (count < 25 && flength > 1.5) {
      count++;
      int dir = (int) random(0, 3);
      //----- one or two anchors
      if (dir < = 1) {
      float nextflength = flength * random(0.75, 1.20);
      if ( totalLength+nextflength < length) createBranches (fAngle + random(minAngle*2, maxAngle*2), points [points.length-1] [0], points [points.length-1] [1], totalLength, nextflength, count, minNext);
      } else {
        float nextflength = flength * random(minNext, 1.05);
        if ( totalLength+nextflength < length) createBranches (fAngle + minAngle/2, points [points.length-1] [0], points [points.length-1] [1], totalLength, nextflength, count, minNext);
        nextflength = flength * random(minNext, 1.05);
        if ( totalLength+nextflength < length) createBranches (fAngle + maxAngle/2, points [points.length-1] [0], points [points.length-1] [1], totalLength, nextflength, count, minNext);
      }
    }
  }
 
  public void display () {
    Branch br;
    for (int i = 0; i < branches.size(); i++) {
      br = (Branch) branches.get (i);
      br.display();
    }
  }
}
 
class Branch {
  private float [] [] points;
  Branch (float [] [] points) {
  this.points = new float [points.length] [points[0].length];
  arrayCopy (points, this.points);
  }
  public void display () {
  noFill();
  stroke (0, 50);
  beginShape();
  for (int i = 0; i < points.length; i++) {
    curveVertex (points [i] [0], points [i] [1]);
  }
  endShape();
  }
}
 
class Flower {
  private Anchor [] anchor;
  private int num, centerX, centerY;
  private float minNext, d;
  private float [] angles, length;
 
  Flower (int num, int centerX, int centerY, float d, float minNext) {
    this.num = num;
    this.centerX = centerX;
    this.centerY = centerY;
    this.d = d;
    this.minNext = minNext;
    this.angles = new float [num];
    this.length = new float [num];
    createFlower();
  }
 
  private void createFlower() {
    anchor = new Anchor [num];
    for (int i = 0; i < num; i++) {
      angles [i] = random (360);
    }
    arrayCopy (sort (angles), angles);
    float minLength = d*10, maxLength = 0;
    for (int i = 0; i < length.length; i++) {
      length [i] = d;
      if (length [i] < minLength) minLength = length [i];       if (length [i] > maxLength) maxLength = length [i];
    }
  }
 
  public void display(){
    for (int i = 0; i < num; i++) {
      anchor[i] = new Anchor (angles [i], -20, 20, length [i], centerX, centerY, minNext);
      anchor[i].display();
    }
  }
}

Kevyn McPhail

21 Jan 2014

FinalGIF_500

 

As someone who has only touched processing here and there, this project was a tiny bit challenging at first. However as I formulated a more concrete Idea of the motions that I wanted to create, and peeked at a bit of inspiration, the juices began to flow. I had some early ideas, as shown in the sketches, of having the GIF have a focal point, with a static or dynamic background, that emphasized the focal point.

2014-01-21 00.41.12

So, the concept that I had for this project was inspired by the “All Seeing Eye”, as the title shows. I tried to replicate the feel of an ominous, omnipotent being, ever-fixated on you. I also set out to give the GIF a sort of hypnotic feel, which is achieved by the rotation and the pulsating ring. The most difficult part of this project for me was getting the timing right for the outer rings of circles so that they loop while each ring maintains its own varied speed.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
//Kevyn McPhail
//Interactive Art and Computational Design
//Lenticular Animation
 
int nFrames = 30;
int elapsedFrames; 
boolean isRecording;
 
void setup(){
size(500,500);
elapsedFrames = 0;
frameRate (nFrames); 
}
 
void keyPressed(){
isRecording = true;
elapsedFrames = 0;
}
 
void draw(){
float percentCompleted = 0;
if (isRecording){
percentCompleted = (float) elapsedFrames / (float) nFrames;
}
else{
float modFrame = (float) (frameCount % nFrames);
percentCompleted = modFrame / (float) nFrames;
}
 
renderGIF(percentCompleted); 
 
if(isRecording) {
saveFrame("output/" + "kmcphail" + "-loop" + nf(elapsedFrames, 4) + ".png");
elapsedFrames ++;
if (elapsedFrames == nFrames) {
isRecording = false;
}
}
}
 
// Redners Gif
void renderGIF(float percent){
 
//Fading Background
if (percent < 0.5){
background(percent*255);
}else{
background(255 - (percent*255));
}
//background(255);
smooth();
 
float cx = width/2; 
float cy = height/2;
 
int numSpokes = 20;
 
//Shooting Circles
for (int i=0; i<numSpokes; i++){
float armAngle = (percent + i) * (TWO_PI/numSpokes); 
float px = cx + (percent*width)*cos(armAngle); 
float py = cy + (percent*height)*sin(armAngle); 
fill(0,255-(255*percent*2));
noStroke();
ellipse(px,py,(percent*(width/5)),(percent*(height/5)));
}
 
//Orbiting Rings
int numRings = 20;
for (int i=0; i<numRings; i++){
for (int j=0; j<20; j++){
float armAngle = (percent + j) * (TWO_PI/(10*i));
float px = cx + ((width/2.5)+((width/17)*i))*cos(armAngle); 
float py = cy + ((height/2.5)+((height/17)*i))*sin(armAngle); 
if (percent > 0.5){
fill(percent*255);
}else{
fill(255 - (percent*255));
}
ellipse(px,py,width/25,height/25);
}
}
 
//Rotating Eye
pushMatrix();
fill(0);
translate(cx,cy);
rotate(radians(-12*(map(percent,0,1,1,30))));
float a = map(percent,0,1,1,30);
println(a);
ellipse(0,0,width/3,height/6);
popMatrix();
fill(255);
ellipse(cx,cy,width/6.5,height/6.5);
fill(0);
ellipse(cx,cy,width/12,height/12);
 
//Orbiting Eyes
for (int i=0; i<15; i++){
float armAngle = (percent + i) * (TWO_PI/(15));
float px = cx + (width/4)*cos(armAngle); 
float py = cy + (height/4)*sin(armAngle); 
float px_2 = cx + (width/17)*cos(armAngle); 
float py_2 = cy + (height/17)*sin(armAngle);
if (percent > 0.5){
stroke(percent*255);
}else{
stroke(255 - (percent*255));
} 
strokeWeight(width/200);
line(px,py,px_2,py_2);
}
 
//InnerArc
pushMatrix();
fill(0);
translate(cx,cy);
rotate(radians(-12*(map(percent,0,1,1,30))));
noFill();
strokeWeight(width/100);
arc(0,0,width/1.75,width/1.75,0,PI);
popMatrix();
 
//Outer Arc
pushMatrix();
fill(0);
translate(cx,cy);
rotate(radians(12*(map(percent,0,1,1,30))));
noFill();
strokeWeight(width/100);
arc(0,0,width/1.5,width/1.5,0,PI);
popMatrix();
}

 

 

MacKenzie Bates

21 Jan 2014

pigeon_gif_background_90_redp
Unsure which of these two I like more. The smoothness of the above one is nice, but so is the variation in the below one.
pigeon_gif_background_90_red2p

Of all the artist print on GifPop’s website Pixelfucks‘ smeared doe caught my eye.  I real liked the gif. I also thought it would print well since its composition stayed mostly the same and the doe was created in such a way that even if the colors weren’t right, it’d still stand out.

It took me a while to figure out what I wanted to make for my gif. I kept playing around in processing hoping something would pop out. I had created a series of photos (Walking in the Sky) in December that I wanted to animate in some way so I decided to try this, which lead me to create the shimmering diamond effect.

On my journey of tinkering I decided to incorporate a pigeon I made in Illustrator a while ago. And when I tried it out, I realized that I had created my own version of Pixelfuck’s doe.

Origins – Ze Pigeon (Made in Illustrator):

Pig2 [Converted]

 Origins – Background Pattern Source (Made in Photoshop/Illustrator):

background copy

Red Pigeon:

pigeon_gif_red_90

 Background Strobe:

pigeon_gif_background2

Alternative Version (Original Blue Background):

pigeon_gif_background_903

I was not sure about the shimmering diamond effect with this color choice or it could be that I have messed with it way too much that I have lost any sense of what it truly looks like.

Alternative Version (Pigeon Swarm):

pigeon_gif_swarm_90

 Sketch:

sketch_final

 Ze Code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
// This is a template for creating a looping animation in Processing. 
// 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 = 7; // for lenticular export, change this to 10!
int     nElapsedFrames;
boolean bRecording; 
PImage img, img2;
 
String  myName = "itbmac-902";
 
int offsetX = 45;
 
int arraySize = 33; // 8;
int[] xPoints = {
  234, 207, 236, 190, 237, 209, 237, 188, 234, 207, 236, 191, 236, 188, 237, 191, 236, 284, 237, 284, 234, 282, 236, 265, 234, 284, 236, 267, 236, 283, 236, 266, 234
};
 
int[] yPoints = {
  7, 58, 92, 125, 168, 212, 258, 302, 343, 383, 438, 494, 539, 584, 632, 679, 719, 679, 633, 586, 540, 492, 438, 381, 343, 303, 258, 212, 168, 127, 91, 58, 9
};
 
int arraySize2 = 35; 
int[] xPoints2 = {
  240, 268, 237, 284, 239, 269, 238, 285, 239, 269, 237, 284, 237, 267, 239, 285, 243, 321, 284, 331, 276, 332, 283, 329, 282, 331, 286, 327, 281, 334, 284, 331, 282, 324, 240
};
int[] yPoints2 = {
  9, 58, 93, 125, 169, 211, 258, 303, 342, 381, 440, 493, 540, 585, 632, 678, 719, 718, 677, 632, 586, 539, 496, 437, 381, 344, 307, 257, 212, 170, 126, 91, 55, 11, 10
};
 
//===================================================
void setup() {
  size (1500, 1500); 
  img = loadImage("pigeon.png");
  img2 = loadImage("pigeon_2.png");
  colorMode(HSB, 1500, 100, 100, 1.0);
  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) {
 
  // 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 (180);
  smooth(); 
  stroke (0, 0, 0, 0); 
  strokeWeight (0); 
 
  //----------------------
  // Here's a set of linearly-moving circles
  float ballSize = 80;
  float topY = 0 ;//- ballSize - 2;
  float botY = height+100;
  float spanY = botY - topY; 
 
  int nMovingBalls = 90; // 30; 
  for (int i=0; i &lt; = nMovingBalls; i++) {
    float ballSpacing = spanY / (float)nMovingBalls;
    float yBase = -100; // offset for radius of ball 
    float yPercent = map(percent, 0, 1, topY, topY+ballSpacing);
    float yPosition = yBase + (yPercent + (i*ballSpacing))%spanY; 
 
    // stroke (yPercent, 100, 100); //random(255), random(255), random(255), 0.8); 
 
    //float cPos = map(yPosition, -100, 1600, 600, 1200); // old
    //float cPos = map(yPosition, -100, 1600, 00, 300); //red
    float cPos = map(yPosition, -100, 1600, 780, 1120);
    fill (cPos+10, 75, 100, 0.8);
    rect (0, yPosition, 1500, 80);
  }
 
  //float yPerc = map(percent, 0, 1, 0, -500);
  float yPerc = map(percent, 0, 1, 0, -1500);
  float offsetY = yPerc; //-1 * (20 + percent*300)%500;//90;
 
  float offsetY2 = offsetY + 2100;
 
  float offsetXD = 3.0;
 
   float offsetC = 3.0;
  //float offsetC = 1.0; // red
 
  fill ((percent * 140 + 150) * offsetC, 75, 100);
  beginShape();
  for (int i = 0; i &lt; arraySize; i++)
  {
    vertex(xPoints[i] * offsetXD + offsetX, yPoints[i] * offsetXD + offsetY);
  }
  endShape();
 
  fill ((percent * 90 + 250) * offsetC, 75, 100);
  beginShape();
  for (int i = 0; i &lt; arraySize2; i++)
  {
    vertex(xPoints2[i] * offsetXD + 0 + offsetX, yPoints2[i] * offsetXD + offsetY);
  }
  endShape();
 
  fill ((percent * 140 + 175) * offsetC, 75, 100);
  beginShape();
  for (int i = 0; i &lt; arraySize; i++)
  {
    vertex(xPoints[i] * offsetXD + 300  + offsetX, yPoints[i] * offsetXD + offsetY);
  }
  endShape();
 
  fill ((percent * 90 + 275) * offsetC, 75, 100);
  beginShape();
  for (int i = 0; i &lt; arraySize2; i++)
  {
    vertex(xPoints2[i] * offsetXD + 300 + offsetX, yPoints2[i] * offsetXD + offsetY);
  }
  endShape();
 
  fill ((percent * 140 + 175) * offsetC, 75, 100);
  beginShape();
  for (int i = 0; i &lt; arraySize; i++)
  {
    vertex(xPoints[i] * offsetXD - 300 + offsetX, yPoints[i] * offsetXD + offsetY);
  }
  endShape();
 
  fill ((percent * 90 + 250) * offsetC, 75, 100);
  beginShape();
  for (int i = 0; i &lt; arraySize2; i++)
  {
    vertex(xPoints2[i] * offsetXD - 300 + offsetX, yPoints2[i] * offsetXD + offsetY);
  }
  endShape();
 
  fill ((percent * 90 + 275) * offsetC, 75, 100);
  beginShape();
  for (int i = 0; i &lt; arraySize2; i++)
  {
    vertex(xPoints2[i] * offsetXD - 600 + offsetX, yPoints2[i] * offsetXD + offsetY);
  }
  endShape();
 
  fill ((percent * 140 + 150) * offsetC, 75, 100);
  beginShape();
  for (int i = 0; i &lt; arraySize; i++)
  {
    vertex(xPoints[i] * offsetXD - 600 + offsetX, yPoints[i] * offsetXD + offsetY);
  }
  endShape();
 
  fill ((percent * 140 + 150) * offsetC, 75, 100);
  beginShape();
  for (int i = 0; i &lt; arraySize; i++)
  {
    vertex(xPoints[i] * offsetXD + 600 + offsetX, yPoints[i] * offsetXD + offsetY);
  }
  endShape();
 
  fill ((percent * 140 + 150) * offsetC, 75, 100);
  beginShape();
  for (int i = 0; i &lt; arraySize; i++)
  {
    vertex(xPoints[i] * offsetXD + offsetX, yPoints[i] * offsetXD + offsetY2);
  }
  endShape();
 
  fill ((percent * 90 + 250) * offsetC, 75, 100);
  beginShape();
  for (int i = 0; i &lt; arraySize2; i++)
  {
    vertex(xPoints2[i] * offsetXD + 0 + offsetX, yPoints2[i] * offsetXD + offsetY2);
  }
  endShape();
 
  fill ((percent * 140 + 175) * offsetC, 75, 100);
  beginShape();
  for (int i = 0; i &lt; arraySize; i++)
  {
    vertex(xPoints[i] * offsetXD + 300  + offsetX, yPoints[i] * offsetXD + offsetY2);
  }
  endShape();
 
  fill ((percent * 90 + 275) * offsetC, 75, 100);
  beginShape();
  for (int i = 0; i &lt; arraySize2; i++)
  {
    vertex(xPoints2[i] * offsetXD + 300 + offsetX, yPoints2[i] * offsetXD + offsetY2);
  }
  endShape();
 
  fill ((percent * 140 + 175) * offsetC, 75, 100);
  beginShape();
  for (int i = 0; i &lt; arraySize; i++)
  {
    vertex(xPoints[i] * offsetXD - 300 + offsetX, yPoints[i] * offsetXD + offsetY2);
  }
  endShape();
 
  fill ((percent * 90 + 250) * offsetC, 75, 100);
  beginShape();
  for (int i = 0; i &lt; arraySize2; i++)
  {
    vertex(xPoints2[i] * offsetXD - 300 + offsetX, yPoints2[i] * offsetXD + offsetY2);
  }
  endShape();
 
  fill ((percent * 90 + 275) * offsetC, 75, 100);
  beginShape();
  for (int i = 0; i &lt; arraySize2; i++)
  {
    vertex(xPoints2[i] * offsetXD - 600 + offsetX, yPoints2[i] * offsetXD + offsetY2);
  }
  endShape();
 
  fill ((percent * 140 + 150) * offsetC, 75, 100);
  beginShape();
  for (int i = 0; i &lt; arraySize; i++)
  {
    vertex(xPoints[i] * offsetXD - 600 + offsetX, yPoints[i] * offsetXD + offsetY2);
  }
  endShape();
 
  fill ((percent * 140 + 150) * offsetC, 75, 100);
  beginShape();
  for (int i = 0; i &lt; arraySize; i++)
  {
    vertex(xPoints[i] * offsetXD + 600 + offsetX, yPoints[i] * offsetXD + offsetY2);
  }
  endShape();
 
  for (int i=0; i &lt;= nMovingBalls; i++) {
    float ballSpacing = spanY / (float)nMovingBalls;
    float yBase = -100; // offset for radius of ball 
    float yPercent = map(percent, 0, 1, topY, topY+ballSpacing);
    float yPosition = yBase + (yPercent + (i*ballSpacing))%spanY; 
 
    float cPos = map(yPosition, -100, 1600, 780, 1120);
    //float cPos = map(yPosition, -100, 1600, 000, 300); //red
    //float cPos = map(yPosition, -100, 1600, 600, 1200); // old
    fill (cPos+10, 75, 100, 0.2); // non-swarm
    //fill (cPos+10, 75, 100, 0.30); // swarm
    rect (0, yPosition, 1500, 80);
 
    println(percent);
  }
 
  //image(img, 0, 0);
  //image(img2, 0, 0);
 
}

Paul Peng

21 Jan 2014

file-transfer

Peng, Paul. File Transfer (or: Vortex Virtual (or: No Escape))). 2014. Found images and Processing. golancourses.net/2014/, the Internet.

Born from a successful experiment in forming a large motion by intertwining two smaller motions, which itself was born from a failed experiment in making one movement look like another, File Transfer (or: Vortex Virtual (or: No Escape))) is another harrowing reminder of the imprisonment we face from the corporate-ized nature of modern technology, both hard and soft. In the center rests an emoji, an archetype of the basic expressions of the human condition as well as the perceived one-dimensionality of today’s mainstream emotional society, worn down into a close-eyed trance, finally given into the .NET neurosis obtained from the constant barrage of the 21st century virtual reality data flow. Around this figurehead of humanity is this data flow itself, moving in a hypnotic, entrancing, yet ultimately mechanical motion designed to keep our hapless emoji subdued and at bay, unable to breach the sinister and highly interwoven ring of corporate iconography and alienated data. Even if our protagonist were to break free of this ring, he/she/ze/e/it is faced with the barrier between the menacingly convenient iPad™ tablet computer and the physical realm, so corrupted by the vortex of virtual reality that our hero has been reduced to yet another byte of the transphysical system that haunts us all (which should be apparent as our hero is an emoji). Assuming our emoji is somehow able to transcend this barrier, we find our hero left adrift in the open sea to perish, just as those who break free of today’s virtual entrapments are left as well. Truly, there is no escape from this virtual vortex. File transfer.

Artistic bullshit aside, this piece, as mentioned earlier, was born from a desire to create a motion that seems like another, as seen in the work of those recommended on the assignment page (e.g., dvdp, Bees & Bombs). After several sketches, I somehow got sidetracked and became interested in cyclical motions and how they could possibly intertwine, leading me to create several plans consisting of one large motion isomorphic to a cyclic motion that is intertwined between many other cyclic motions that exist independently from one another. Only two of these plans actually worked. At some point in the aforementioned process I decided that the moving elements in the piece should be emojis. At some point earlier than the previous I had decided that I wanted it to be in a grid. This process is shown in the sketches below.

img001

my first sketches for the project: tried to make something not cyclical look cyclical, but ended up just sticking with cyclical. grid shapes are for some other idea that i forgot about but really shouldn’t have because it was also pretty good.

img002

starting to play with the idea of cycles passing off some of its elements to other cycles, which eventually grows into the idea of intertwined cycles. enter the emoji.

img003

Additional sketches pursuing the idea of intertwined cycles, including one where I realized that all of the intertwined sketches I came up with so far didn’t work. decided on which emoji was going to be in the center. thought about putting the cycles in 3d but decided against it. In the top-left corner: sketches for one of my anitype letters.

img005

should have used “giant emoji thing spinny grid” as my working title. oh well. came up with the final design for the motion at the bottom; looks like a swastika but hopefully that won’t be apparent when animated (it isn’t). also: hoping that there are tuples in java (there aren’t).

img006

upper-left corner: notes on jasper johns’ artistic theory and the realization that this assignment is due tomorrow (i made these sketches on 21 jan 2014). bottom-left corner: notes on what to include in the Emoji class for the implementation. right page: sketch for the placement of all of the emojis and some notes on how to mathematically derive the rate at which the emojis should move.

Considering the wide amount of time between finalizing my sketches and implementing the animation in Processing, I could have tried to come up with something a little more complicated than what I have. Nevertheless, I’m okay with it since it’s really just a warm-up and it’s pretty appealing as is, in my opinion. In case the background is too distracting with all of the posterization, I do have an alternate version with a blank white background.

/* 
 * This gif was made by Paul Peng!
 * some parts of the code were based off of a gif-making template
 * provided by Prof Golan Levin.
 */
 
/* ******* globals ******* */
 
/* you can change these ones for stuff */
String filename = "noescape";
int fps = 30;  // make 10 for GIFPOP, 30 for web
int side = 500;  // make 1500 for GIFPOP, 500 for web
boolean recording = false;  // make true when exporting as GIF
 
int framesElapsed;
 
Dir[][][] dirArray;
Emoji[] emojiArray;
float sizeOfEmoji;
float rateOfEmoji;
float emoji_offset;
 
PImage ipad;
PImage bg;
 
/* ******* classes and also classes pretending to be structs/tuples ******* */
 
class Dir {
  float dx;
  float dy;
 
  Dir(float i_dx, float i_dy) {
    dx = i_dx;
    dy = i_dy;
  }
}
 
class Emoji {
  float x;
  float y;
  int movetype;  /* 0 for circular, 1 for squiggly */
  PImage pic;
  Dir dir;
  int dirArrayX;
  int dirArrayY;
 
  Emoji(float ix, float iy, PImage ipic, int imovetype, int i_dirx, int i_diry) {
    x = ix;
    y = iy;
    movetype = imovetype;
    pic = ipic;
    dirArrayX = i_dirx;
    dirArrayY = i_diry;
  }
 
  void get_newDir() {
    dir = dirArray[dirArrayY][dirArrayX][movetype];
    dirArrayX += dir.dx;
    dirArrayY += dir.dy;
  }
 
  void update_pos() {
    x += dir.dx * rateOfEmoji;
    y += dir.dy * rateOfEmoji;
  }
 
  void draw_emoji() {
    image(pic, x, y);
  }
}
 
/* ******* setup ******* */
 
void setup() {
  emoji_offset = float(side) - float(side) / sqrt(2);
  sizeOfEmoji = (float(side) / sqrt(2) - emoji_offset) / 9;
  rateOfEmoji = 4*sizeOfEmoji / fps;
 
  dirArray = setup_dirArray();
  emojiArray = setup_emojiArray();
 
  if (side == 500) {
    ipad = loadImage("data/ipad-small.png");
    bg = loadImage("data/paradise-small.jpg");
  } else {
    ipad = loadImage("data/ipad.png");
    bg = loadImage("data/paradise.jpg");
  }
 
  size(side, side);  // make 1500x1500 for GIFPOP
  frameRate(fps);
  framesElapsed = 0;
}
 
Dir[][][] setup_dirArray() {
  Dir lf = new Dir(-1, 0);
  Dir rt = new Dir(1, 0);
  Dir up = new Dir(0, -1);
  Dir dn = new Dir(0, 1);
  Dir nn = new Dir(0, 0);
  Dir[][][] the_array = { { {rt,rt}, {rt,rt}, {rt,dn}, {rt,rt}, {dn,dn} },
                          { {up,up}, {rt,lf}, {rt,rt}, {dn,up}, {dn,dn} },
                          { {up,rt}, {up,up}, {nn,nn}, {dn,dn}, {dn,lf} },
                          { {up,up}, {up,dn}, {lf,lf}, {lf,rt}, {dn,dn} },
                          { {up,up}, {lf,lf}, {lf,up}, {lf,lf}, {lf,lf} }, };
  return the_array;
}                  
 
Emoji[] setup_emojiArray() {
  PImage move0_img;
    PImage move1_img;
    PImage center_img;
  if (side == 500) {
    move0_img = loadImage("data/floppy-small.png");
    move1_img = loadImage("data/folder-small.png");
    center_img = loadImage("data/face-small.png");
  } else {
    move0_img = loadImage("data/floppy.png");
    move1_img = loadImage("data/folder.png");
    center_img = loadImage("data/face.png");
  }
  boolean isMovetype0 = true;
 
  Emoji[] the_array = new Emoji[25];
  for (int row = 0; row &lt; 5; row++) {
    for (int col = 0; col &lt; 5; col++) {
      int i = 5*row + col;
      float ix = emoji_offset + 2*sizeOfEmoji*row;
      float iy = emoji_offset + 2*sizeOfEmoji*col;
      if (isMovetype0) {
        the_array[i] = new Emoji(ix, iy, move0_img, 0, row, col);
      } else {
        the_array[i] = new Emoji(ix, iy, move1_img, 1, row, col);
      }
      isMovetype0 = !isMovetype0;
    }
  }
  /* center emoji's pic is changed to centerpic */
  the_array[12].pic = center_img;
  return the_array;
}
 
/* ******* draw ******* */
 
void draw() {
 
  /* change direction when direction needs to be changed */
  if (framesElapsed % (fps/2) == 0) {
    for (int i = 0; i &lt; 25; i++) {
      emojiArray[i].get_newDir();
    }
  }
 
  /* update the position of each emoji */
  for (int i = 0; i &lt; 25; i++) {
    emojiArray[i].update_pos();
  }
 
  /* actually draw the thing */
  background(bg);
  imageMode(CENTER);
  image(ipad, side/2 - 5*(side/500), side/2);
  imageMode(CORNER);
  for (int i = 0; i &lt; 25; i++) {
    emojiArray[i].draw_emoji();
  }
 
  /* if recording output, save frame into file until done */
  if (recording) {
    saveFrame("output/"+ filename + "-loop-" + nf(framesElapsed, 4) + ".png");
    if (framesElapsed+1 == fps) recording = false;
  }
 
  framesElapsed++;
}

Emily Danchik

20 Jan 2014

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:
small
(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:
20140120_214957
20140120_224218

 

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.
small

 

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:
small

Wanfang Diao

20 Jan 2014

Low_IACD_1_1_Wanfang_Diao

My inspiration of this project is from my first time experience of using processing—to build an application for visualizing Smith chart to help myself learning electromagnetic theory. When I think of generative art or animation by code, I always think about math. Therefore, I draw  Cardioid learned in high school on paper and envision something like water wave or magnetic field… I try the equations on processing. And try to make some change of the equation. Finally I use this equation:

y=a*(3*cos(rad)-cos(3*rad));
x=a*(3*sin(rad)-sin(3*rad));

Next,  I make the curves move out to intimate magnetic field. Finally,  I tried 3D function to render the curves. After trials, I found white line reduce the sense of 3D but seems more harmony in the image.

 

 
int     nFramesInLoop = 10; 
int     nElapsedFrames;
boolean bRecording; 

String myName="wanfangdiao";
//===================================================
void setup() {
  size (1500, 1500,P3D); 

  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) {
 background(255);
 strokeWeight(2);
 //smooth();
 for(int i=0; i<= 200; i+=20)
 {
drawCardioid(percent*2, i);
 }

}

void drawCardioid (float change, int startpoint)
{
float a=startpoint+10*change;
int centerX=750;
int centerY=750;
//
//stroke(0,30);
//noFill();

stroke(255);
float x, y;
float lastx=-2999;
float lasty=-2999;
for(float t=0; t <= 360; t+=5){
  pushMatrix();
float rad=radians(t);

y=centerY-a*(3*cos(rad)-cos(3*rad));
x=centerX+a*(3*sin(rad)-sin(3*rad));
translate(x,y,0);
rotateZ(0.5);
fill(100,0,200,50);
box(40);
 popMatrix();

}

}

Andrew Sweet

20 Jan 2014

asweet Lenticular

 

I was looking for inspiration in other media I’ve consumed recently. I thought of rhythmic, trance-like repetition for a GIF, and ultimately went to Hotline Miami for inspiration. The image was inspired by the game’s rhythmic hot-neon colors and rotating text for it’s title screen: (Feel free to mute)

I started iteration by working toward an exact replica of the original title screen. I realized there wasn’t much value to direct imitation in this case, and tried to figure out where I could diverge and create something different. I decided on Hello World since this is the first homework assignment, and well anytime you’re starting something new in CS, you’ve got to make a Hello World.

When I’ve seen lenticular images in the past, I’ve noticed that the delta of any image is the most interesting part. Having something that kind of graphically comes out at you in 3D made more sense than a simple rotation. Stylistically, I also decided to layer multiple text images on top of each other to create the illusion of depth, rather than creating 3D protruding objects. I saw this as kind of a challenge to myself to try to create the illusion of depth mathematically, without relying on a 3D camera to create the sort of effect I was looking for. After trying out some tests on GIFPOP, I realized that I could have an image that appeared to have more depth to it if I had the image angle change with the angle of the Lenticular. The popping out illusion with added skew really works well on the digital lenticular preview, and I hope it works well in the real version as well.

Having never really worked with GIFs before, I didn’t realize that they were limited to a 256 color palette. I’m not upset with the result, but it was not planned to have color banding. Had I been aware, I might have avoided gradients… (especially after Golan stated he hated rainbows). I actually like seeing the artifact of my lack of knowledge in starting with a new tool. Overall, it was a nice re-introduction to the Processing tools which I haven’t used in over 2 years.

sketch

// This is based on a template for creating a looping animation 
// in Processing by Prof. Golan Levin:
 
// 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
 
// Andrew Sweet, January 2014
 
//===================================================
// Global variables. 
 
int     nFramesInLoop = 30; // for lenticular export, change this to 10!
int     nElapsedFrames;
boolean bRecording; 
int     Y_AXIS = 1;
int     X_AXIS = 2;
color   b1, b2, b3;
PFont   font;
float   theta;
float[] ringRadii;
int     numRings;
float   screenDiagonal;
 
String  myName = "andrewsweet";
 
void prepopulateRings(){
  // a^2 + b^2 = c^2
  screenDiagonal = sqrt(sq(width) + sq(height));
 
  for (int i = 0; i &lt; numRings; i++){
    ringRadii[i] = (i*screenDiagonal)/numRings;
  }
}
 
//===================================================
void setup() {
  size (500, 500); 
  bRecording = false;
  nElapsedFrames = 0;
  numRings = 6;
  ringRadii = new float[numRings];
 
  prepopulateRings();
 
  // Define colors
  b1 = color(254, 31, 146);
  b2 = color(48, 52, 210);
  b3 = color(43, 214, 184);
  font = createFont("Chicago",16,true); // STEP 3 Create Font
 
  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;
    }
  }
}
 
//Function from http://processing.org/examples/lineargradient.html
  void setGradient(int x, int y, float w, float h, color c1, color c2, int axis ) {
 
  noFill();
 
  if (axis == Y_AXIS) {  // Top to bottom gradient
    for (int i = y; i &lt;= y+h; i++) {
      float inter = map(i, y, y+h, 0, 1);
      color c = lerpColor(c1, c2, inter);
      stroke(c);
      line(x, i, x+w, i);
    }
  }  
  else if (axis == X_AXIS) {  // Left to right gradient
    for (int i = x; i &lt;= x+w; i++) {
      float inter = map(i, x, x+w, 0, 1);
      color c = lerpColor(c1, c2, inter);
      stroke(c);
      line(i, y, i, y+h);
    }
  }
}
 
//===================================================
void pulseText3D (String text, float x, float y, float percent){
  int numLayers = 20 + int((sin(percent * 2 * PI) * 17));
 
  translate(x, y);   // Translate to the center
  rotate(theta);     // Rotate by theta
  textAlign(CENTER);  
 
  for (int i = 0; i &lt; numLayers; i++){
    textFont(font, (width/10) + (i * (width/500.0)) + (sin(percent * 2 * PI) * (width/100)));
 
    float inter = map(i, 0, numLayers, 0, 1 - abs(sin(percent * 2 * PI)/8));
    color c = lerpColor(b2, b1, inter);
    fill(c);
    text(text, cos(percent * 2 * PI) * (numLayers/2 - i) * width/500.0, sin(percent * 2 * PI) * (numLayers/2 - i) * width/500.0);  // STEP 6 Display Text
  }
  rotate(-theta);
  theta += 0.01 * cos (percent * 2 * PI);                // Increase rotation
  translate(-x, -y);
}
 
void drawRings (float percent){
  float maxRadiusDelta = screenDiagonal/numRings;
  int maxStroke = width/50;
 
  for (int i = 0; i &lt; numRings; i++){
    float radius = ringRadii[i] + (percent * maxRadiusDelta);
 
    float weight = map(radius, 0, width, 0, maxStroke);
    float alpha = map(radius, 0, width/4 * 5, 255, 0);
 
    noFill();
 
    strokeWeight(weight);
    stroke(255, 255, 255, alpha);
 
    ellipse(width/2, height/2, radius, radius);
  }
}  
 
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!
 
  //----------------------
 
  int stretch = height/9;
 
  setGradient(0, - stretch - int((sin(percent * 2 * PI) * stretch)), 
              width, height + stretch + int(sin(percent * 2 * PI) * stretch), b1, b3, Y_AXIS);
 
  drawRings(percent);
 
  pulseText3D("Hello World", width/2, height/2, percent);
 
  smooth(); 
  stroke (0, 0, 0); 
  strokeWeight (2); 
}

Collin Burger

20 Jan 2014

Sigh

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);
}
}

Notes and Sketches:
CollinBurgerGifNotes

Spencer Barton

20 Jan 2014

Rush Hour

sebarton_blog

This design was inspired by the game Rush Hour which I recently played. In that game cars move back and forth until the exit is reached but continually block each other along the way.

I spent a lot of time attempting various fractal designs in a desire to create something complex. The rush hour idea pulled me away from my inclination towards mathematical complexity by keeping the structure simple. I believe the simpler form made a more interesting final piece.

Simplicity is also a downside to this piece. In particular I would like more emphasis on the collisions. This may be corrected by infusing color. This is also a two dimensional piece and it lacks an ability to pull the viewers focus in since the overall scrolling is towards the upper right. I find my eyes leave the picture fairly quickly.

Basic Movement and Starting Position

2014-01-20 14.11.41

End Position

2014-01-20 14.11.48

Code: GitHub

/* Spencer Barton
 * Interactive Art & Computational Design, Spring 2014
 * 1.1 Lenticular Animation
 * 
 * Boxes
 * Starter code from https://ems.andrew.cmu.edu/2014/assignments/project-1/lenticular-animation/
 *
 * Ideas
 * - Slow down collisions
 * - Collision color changes
 */
 
/*===================================================
  Global variables & constants
  =================================================== */
 
int FRAME_SIZE = 500; 
int NUM_FRAMES_IN_LOOP = 50; // for lenticular export, change this to 10!
color STROKE_CLR = 255;
int STROKE_WEIGHT = 0;
String IMG_NAME = "sebarton-blog";
float GRID_LENGTH = 30;
float BOX_WIDTH = GRID_LENGTH;
float BOX_HEIGHT = 2*GRID_LENGTH;
int NUM_BOX_TYPES = 4;
 
int nElapsedFrames;
boolean bRecording; 
Box[] boxes;
 
/*===================================================
  Setup
  =================================================== */
 
void setup() {
  size (FRAME_SIZE, FRAME_SIZE); 
  bRecording = false;
  nElapsedFrames = 0;
  frameRate (NUM_FRAMES_IN_LOOP);
 
  generateBoxes();
}
 
void generateBoxes() {
 
  int nBoxesSide = (int)round(FRAME_SIZE / BOX_HEIGHT);
  nBoxesSide = nBoxesSide + nBoxesSide % 2 + 2; // round up to nearest power of 2 and add 2 for good measure
  int nOneTypeBoxPerSide = nBoxesSide / 2;
 
  boxes = new Box[nBoxesSide * nBoxesSide];
 
  // generate individual boxes
  float startX, startY, endX, endY, boxHoriz, boxVert, difference;
  int index = 0;
  for( int t = 0; t < NUM_BOX_TYPES; t++ ) {
    for( int i = 0; i < nOneTypeBoxPerSide; i++) {
      for( int j = 0; j < nOneTypeBoxPerSide; j++) {
 
        startX = j*2*BOX_HEIGHT;
        startY = i*2*BOX_HEIGHT;
        endX = startX;
        endY = startY;
        difference = BOX_HEIGHT - BOX_WIDTH;
        boxHoriz = BOX_HEIGHT;
        boxVert = BOX_WIDTH;
        color clr = color(255,255,255);
 
        switch (t) {
          case(0):
            // horiz, left
            endX = startX - difference;
            break;
          case(1): 
            // horiz, right 
            startX += BOX_WIDTH;
            startY += BOX_HEIGHT;
            endX = startX + difference;
            endY = startY;
            break;
          case(2):
            startX += BOX_HEIGHT;
            endX = startX;
            endY = startY - difference;
            boxHoriz = BOX_WIDTH;
            boxVert = BOX_HEIGHT;
            break;
          case(3):
            startY += BOX_WIDTH;
            endY = startY +  difference;
            boxHoriz = BOX_WIDTH;
            boxVert = BOX_HEIGHT;
            break;
        }
 
        boxes[index] = new Box(startX, startY, endX, endY, boxVert, boxHoriz, clr);
        index++;
 
      }
    }
  }
}
 
/*===================================================
  Keyboard Interupt
  =================================================== */
 
void keyPressed() { 
  // Press a key to export frames to the output folder
  println("Recording");
  bRecording = true;
  nElapsedFrames = 0;
}
 
/*===================================================
  Draw
  =================================================== */
void draw() {
 
  // Compute a percentage (0...1) representing where we are in the loop.
  float percentCompleteFraction = 0; 
 
  if (bRecording) {
    percentCompleteFraction = (float) nElapsedFrames / (float)NUM_FRAMES_IN_LOOP;
  } else {
    float modFrame = (float) (frameCount % NUM_FRAMES_IN_LOOP);
    percentCompleteFraction = modFrame / (float)NUM_FRAMES_IN_LOOP;
  }
 
  // 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/"+ IMG_NAME + "-loop-" + nf(nElapsedFrames, 4) + ".png");
    nElapsedFrames++; 
    if (nElapsedFrames == NUM_FRAMES_IN_LOOP) {
      bRecording = false;
      println("Done Recording");
    }
  }
}
 
/*===================================================
  Render
  =================================================== */
 
void renderMyDesign (float percent) {
 
  background(0);
  smooth(); 
  stroke (STROKE_CLR); 
  strokeWeight (STROKE_WEIGHT);
 
  float transX = -BOX_HEIGHT * percent;
  float transY = -BOX_HEIGHT * percent;
  translate(transX, transY);
 
  for( Box box : boxes ) {
    box.drawBox(percent);
  }
 
}
/*===================================================
  Box
  =================================================== */
 
class Box {
 
  float startX, startY, endX, endY, boxHeight, boxWidth, cornerRadius;
  color clr;
 
  Box(float startX, float startY, float endX, float endY, float boxHeight, float boxWidth, color clr) {
 
    this.startX = startX;
    this.startY = startY;
    this.endX = endX;
    this.endY = endY;
    this.boxHeight = boxHeight;
    this.boxWidth = boxWidth;
 
    this.clr = clr;
    this.cornerRadius = 2;
  }
 
  void drawBox(float percent) {
    percent  = percentFunction(percent);
    float curX = map(percent, 0, 1, startX, endX);
    float curY = map(percent, 0, 1, startY, endY);
 
    fill(clr);
    rect(curX, curY, boxWidth, boxHeight, cornerRadius);
  }
 
  float percentFunction(float percent) {
    //return sqrt(percent);
    return .5*sin( PI * (percent + .5) ) + .5;
  }
 
}