Category Archives: 22-animatedgif

ST

08 Feb 2015

GIF_For_Website

 

When I was brainstorming for this GIF, my main goal was to create some infinite action that would look good in two directions. The lenticular print will need to be animating in both forward and reverse.  I was inspired by a basic principle of color theory, that warmer colors appear closer to the viewer.  This GIF was an experiment, to see if the effect could be exaggerated by form and motion.

 

Sketch

 

I think that the GIF will work well in two directions and make a vibrant lenticular print.

Overall, the design is less interesting than I was hoping it would be. This idea seemed much more exciting in my mind.

Code:

ArrayList bottomSlices = new ArrayList();
ArrayList middleSlices = new ArrayList();
ArrayList topSlices = new ArrayList();

Slice slice0, slice1, slice2, slice3, slice4, slice5, slice6,
slice7, slice8, slice9, slice10, slice11, slice12, slice13;


class Slice{
 
 int Y;
 int hue;
 
 int position; 
 
 Slice(int Y){
   this.Y = Y;
 }  
  
 void drawSelf(){
    int y = this.Y;
    int hue =  this.hue;
    noStroke();
    smooth();
    
    fill(hue, 280, 355);
    beginShape();
    vertex(width/3, y);
    vertex(width/3, y+(height/18));
    vertex(width/2, y+(height/9));
    vertex(width/2, y+(height/18));
    endShape();
    
    fill(hue, 280, 260);
    beginShape();
    vertex(2*width/3, y);
    vertex(2*width/3, y+(height/18));
    vertex(width/2, y+(height/9));
    vertex(width/2, y+(height/18));
    endShape();
    
    fill(hue, 280, 310);
    beginShape();
    vertex(width/3, y);
    vertex(width/2, y+(height/18));
    vertex(2*width/3, y);
    vertex(width/2, y-(height/18));
    endShape();
  }
  
  void bottomReset(){
    this.Y = (19*height/18);
  }
  
  void topReset(){
    this.Y = (8*height/18);
  }
  
  void move(){
    this.Y--;
  }
}


void setup(){
  frameRate(60);
  size(500, 500);
  colorMode(HSB, 360);
  
  // Bottom Slices
  slice0 = new Slice(19*height/18);
  slice1 = new Slice(17*height/18);
  slice2 = new Slice(15*height/18);
  slice3 = new Slice(13*height/18);
  slice4 = new Slice(11*height/18);
  
  bottomSlices.add(slice0);
  bottomSlices.add(slice1);
  bottomSlices.add(slice2);
  bottomSlices.add(slice3);
  bottomSlices.add(slice4);
  
  // Middle Slices
  slice5 = new Slice(11*height/18);
  slice6 = new Slice(10*height/18);
  slice7 = new Slice(9*height/18);
  slice8 = new Slice(8*height/18);
  
  middleSlices.add(slice5);
  middleSlices.add(slice6);
  middleSlices.add(slice7);
  middleSlices.add(slice8);
  
  // Top Slices
  slice9 = new Slice(7*height/18);
  slice10 = new Slice(5*height/18);
  slice11 = new Slice(3*height/18);
  slice12 = new Slice(1*height/18);
  slice13 = new Slice(-height/18);
  
  topSlices.add(slice9);
  topSlices.add(slice10);
  topSlices.add(slice11);
  topSlices.add(slice12);
  topSlices.add(slice13);
}

void draw(){
  background(229, 220, 70);
  drawBottom();  
  drawMiddle();
  drawTop(); 
}

void drawBottom(){
  int toRemove = -1;
  for (int i=0; i < bottomSlices.size(); i++){
    Slice thisSlice = bottomSlices.get(i);
    thisSlice.move(); 
    int hue = int(map(thisSlice.Y, height, height/2, 240, 70));   
    thisSlice.hue = hue;
    thisSlice.drawSelf();
    if (thisSlice.Y < 11*height/18){
      thisSlice.bottomReset();
      toRemove = i;
    }
  }
  if (toRemove != -1){
    bottomSlices.remove(toRemove);
    Slice newSlice = new Slice(19*height/18);
    ArrayList temp = new ArrayList();
    temp.add(newSlice);
    for (int i = 0; i < bottomSlices.size(); i++){
      temp.add(bottomSlices.get(i));
    }
    bottomSlices = temp;
  }
}

void drawMiddle(){

  for (int i=0; i < middleSlices.size(); i++){
    Slice thisSlice = middleSlices.get(i);
    thisSlice.hue = 110;
    thisSlice.drawSelf();
  }
  fill(110, 280, 355);
  beginShape();
  vertex(width/3, 8*height/18);
  vertex(width/2, 9*height/18);
  vertex(width/2,12*height/18);
  vertex(width/3, 12*height/18);
  endShape();
  
  fill(110, 280, 260);
  beginShape();
  vertex(width/2, 9*height/18);
  vertex(2*width/3, 8*height/18);
  vertex(2*width/3,12*height/18);
  vertex(width/2, 12*height/18);
  endShape();
}

void drawTop(){
  int toRemove = -1;
  for (int i=0; i < topSlices.size(); i++){
    Slice thisSlice = topSlices.get(i);
    thisSlice.move();    
    int hue = int(map(thisSlice.Y, 0, height/2, 30, 120));
    thisSlice.hue = hue;
    thisSlice.drawSelf();
    if (thisSlice.Y < -(2*height/18)){
      thisSlice.topReset();
      toRemove = i;
    }
   
  }
  if (toRemove != -1){
    topSlices.remove(toRemove);
    Slice newSlice = new Slice(8*height/18);
    ArrayList temp = new ArrayList();
    temp.add(newSlice);
    for (int i = 0; i < topSlices.size(); i++){
      temp.add(topSlices.get(i));
    }
    topSlices = temp;
  }
}

Bryce Summers

08 Feb 2015

Assignment 22: Lenticular

In this post, I will outline my journey towards making my final lenticular animation.

Bryce's Sketches for designing a looping animation.

Bryce’s Sketches for designing a looping animation.

I was originally thinking about telling the story of some worker going around, climbing ladders, etc, but thought that would be too complicated. I then thought I would give my personal ray tracer a spin and make an animation with some nifty spheres traveling around on top of a plane.

Raytraced Balls GIF

I decided that this was not very suitable for the 10-frame format of the lenticular print, because although I liked it and it was simple enough, it did not have enough temporal coherence. I then envisioned a discrete path in space. I tried to envision how to define the path, but the best I did was create a spiral pattern as follows:

Bryce's Web Lenticular

Bryce’s Spiral Based Lenticular.

I decided that this animation required too many frames to realize my creative vision, but my friend reminded me that the path that I envisioned was called Hilbert’s Curve. From this I was able to solve and implement an animation along the path of this fractal curve.

Hilbert1

Hilbert1

I then decided to try out moving spheres instead.

Hilbert4

Hilbert4


It still needed a bit of work and after several iterations, I finally produced one that I am reasonably happy with.

A looping gif related to the path of a Hilbert Space filling curve.

A looping gif related to the path of a Hilbert Space filling curve. (Final)

I believe that I achieved everything that I wanted to with this design. I was able to visualize a mathematical path in a concise way and was able to make a movement that is at first glance repetitious, but after further viewing displays quite a bit of unique character.

More Information.

Please see https://en.wikipedia.org/wiki/Hilbert_curve. Also note that I have donated a copy of this animation to the creative commons and it should be visible on the Wikipedia page.

Code

You can view the code for my Assignment here:
https://github.com/Bryce-Summers/IACD_Lenticular/

Alex Sciuto

08 Feb 2015

Screen Shot 2015-02-08 at 12.40.38 PM

Piet Mondrian is a modern artist best known for his grid-based abstract art. The artworks, all composed of a plane of blue, black, white, yellow, and/or red rectangles. They are well known because Mondrian was able to elicit so much visual dynamism and drama within such limiting rules. For my gif, I decided to take a Mondrian-like grid and use the looping gif to explode the grid then bring it back together.

piet

What works? I think the concept is kind of fun, I like how Mondrian’s state is serious but then the explosion adds some whimsy. I think that I could spend more time playing with the easing to give each color additional character. I wanted to use the motion to emphasize how the white tiles were the ubiquitous background and the colored tiles were the main actors. I did this by having the whites move quickly and freeze while the colored ones smoothly animate. I’m not sure my intention is well conveyed by this combination of movement.

Sketches:

IMG_3870

Code:

//Time variables
int fullTime;
int pause = 0;
float timeProportion;
float currentTime;

//Arrays to store the squares
Yellow[] yellowSquares;
Blue[] blueSquares;
White[] whiteSquares;
Red[] redSquares;
Black[] blackSquares;

//Constants for the easing functions
float a = .467;
float b = .660;
float c = .0;

//variable for the PatternMaster. Not actually used in this script
String functionName;

//Debug Boolean to turn on and off recording and to turn on and off animation
boolean recording = true;
boolean animation = true;


void setup() {
 frameRate(3);
 size(1500,938);
 fullTime = 10;
 currentTime = 0;
 yellowSquares = new Yellow[8];
 blueSquares = new Blue[3];
 whiteSquares = new White[24];
 redSquares = new Red[3];
 blackSquares = new Black[6];
 createShapes();
 
}

//Where all the shapes are created.
void createShapes() {
 yellowSquares[0] = new Yellow(.02,25,568,112,236);
 yellowSquares[1] = new Yellow(.02,512,22,235,82);
 yellowSquares[2] = new Yellow(.02,512,114,235,171);
 yellowSquares[3] = new Yellow(.02,330,751,74,174);
 yellowSquares[4] = new Yellow(.02,758,657,231,169);
 yellowSquares[5] = new Yellow(.02,1003,22,78,78);
 yellowSquares[6] = new Yellow(.02,1003,114,170,76);
 yellowSquares[7] = new Yellow(.02,1367,114,111,262); 

 blueSquares[0] = new Blue(.02,760,27,232,169);
 blueSquares[1] = new Blue(.02,1005,477,350,350);
 blueSquares[2] = new Blue(.02,512,568,237,174);
 
 redSquares[0] = new Red(.02,148,112,345,347);
 redSquares[1] = new Red(.02,756,206,231,165);
 redSquares[2] = new Red(.02,510,749,230,168);

 blackSquares[0] = new Black(.02,147,476,170,170);
 blackSquares[1] = new Black(.02,329,659,172,80);
 blackSquares[2] = new Black(.02,881,840,109,79);
 blackSquares[3] = new Black(.02,1185,296,171,169);
 blackSquares[4] = new Black(.02,1004,205,167,81);
 blackSquares[5] = new Black(.02,1094,23,81,78);
 
 whiteSquares[0] = new White(.02,23,22,169,76);
 whiteSquares[1] = new White(.02,207,23,290,75);
 whiteSquares[2] = new White(.02,1187,23,291,78);
 whiteSquares[3] = new White(.02,25,113,110,168);
 whiteSquares[4] = new White(.02,1186,112,166,168);
 whiteSquares[5] = new White(.02,24,293,109,260);
 whiteSquares[6] = new White(.02,512,294,108,170);
 whiteSquares[7] = new White(.02,633,294,108,170); 
 whiteSquares[8] = new White(.02,511,478,233,76);
 whiteSquares[9] = new White(.02,1004,297,164,74);
 whiteSquares[10] = new White(.02,1002,386,172,75);
 whiteSquares[11] = new White(.02,1368,386,107,259);
 whiteSquares[12] = new White(.02,1365,659,113,170);
 whiteSquares[13] = new White(.02,1309,843,166,75);
 whiteSquares[14] = new White(.02,1005,839,289,78); 
 whiteSquares[15] = new White(.02,420,749,75,168);
 whiteSquares[16] = new White(.02,330,568,169,76);
 whiteSquares[17] = new White(.02,148,656,165,171);
 whiteSquares[18] = new White(.02,331,477,166,76);
 whiteSquares[19] = new White(.02,880,477,111,169);
 whiteSquares[20] = new White(.02,757,476,111,169);
 whiteSquares[21] = new White(.02,757,386,233,79);
 whiteSquares[22] = new White(.02,24,840,291,78);
 whiteSquares[23] = new White(.02,757,840,110,77);
}



void draw() {
 if(animation) {
 updateTime();
 } else {
 currentTime = 1; 
 }
 drawBackground(); 
 
 drawShapes();
 if(recording) {
 saveFrame();
 }
}


//function to control the time. I've inserted a pause after each transition
void updateTime() {
 currentTime++;
 if(currentTime > (fullTime+pause)) {
 recording = false;
 currentTime = 0;
 } else if (currentTime == (fullTime)) {
 currentTime = fullTime;
 }
 
 timeProportion = currentTime/fullTime;
 
 if(timeProportion > 1) { timeProportion = 1; }
}

void drawBackground() {
 background(40); 
}

void drawShapes() {
 for(int i = 0; i < whiteSquares.length; i++) {
 whiteSquares[i].update();
 }
 
 for(int i = 0; i < yellowSquares.length; i++) {
 yellowSquares[i].update();
 }
 
 for(int i = 0; i < blueSquares.length; i++) {
 blueSquares[i].update();
 }
 
 for(int i = 0; i < redSquares.length; i++) {
 redSquares[i].update();
 }
 
 for(int i = 0; i < blackSquares.length; i++) {
 blackSquares[i].update();
 }
}

//An example of the Yellow class. I'm excluding the other classes to save space. 
//They all function similarly.

class Yellow {
 int x;
 int y;
 int w;
 int h;

 int direction;
 int leftRight;
 float comeIn = random(1);
 int magnitude = 0;
 float shadowDepth = 5;
 
 
 Yellow (float _wait, int _x, int _y, int _w, int _h) {
 x = _x;
 y = _y;
 h = _h;
 w = _w;
 direction = (int) random(2);
 leftRight = 0;
 if (random(1) > .5) {
 leftRight = -1;
 } else {
 leftRight = 1;
 }
 shadowDepth += random(10);
 magnitude = (int) random(10) + 12; 
 } 
 

 
 void update() {
 pushMatrix();
 noStroke();
 
 float easePoint = ease(timeProportion, a, b) ;
 float newX = x;
 float newY = y;
 
 if(direction == 1) {
 newX = x + leftRight*magnitude*easePoint;
 newY = y + leftRight*magnitude*easePoint;
 } else {
 newX = x - leftRight*magnitude*easePoint;
 newY = y - leftRight*magnitude*easePoint;
 
 }
 
 translate(newX, newY);
 
 fill(250,223,23,40);
 float shadowOffset = easePoint*shadowDepth;
 rect(shadowOffset,shadowOffset,w,h); 
 
 fill(250,223,23);
 rect(0,0,w,h); 
 
 popMatrix(); 
 }
}

pedro

06 Feb 2015

My concept for this assignment had to be abstract and at the same time hypnotic. I began with a neutral grid of squares and I tried to manage some kind of disruption that should initiate a loop. At first, I tried some complex experiments such as a discharge that would spread all over the grid destabilizing its regularity, but it ended being too much for a 10 frames gif. Then I adopted the idea of hinged tesselation, where a move of one square would unfold a serie of transformations in all the grid.

sketch1

After defining and simulating the transformations I defined two colours: yellow and black. The squares are yellow and the background black, in order to provide a strong contrast and emphasize the negative forms between the square, that change radically along the transformations. This contrast worked better than expected and the grid started to walk on the plane while in-between diamond shapes blink and move.

The idea that the squares would bounce after the movement was also too much for the 10 frames, so I decided to adopt the exponential easing in and out function with some custom adjustments in the frames. In the end, it reinforced the cyclic aspect of the movement. A clue to understand the transformations:, try to look at the square that is starting the movement… it is in one corner and it moves much slower than the others.

expanding_grid_500

revised version:

pedro_hypnotic_grid500

Where do you feel you succeeded?
The colours and the pattern of movement worked better than expected, so it end up being a very mysterious grid.

Where do you feel you fell short of what you’d hoped to achieve?
Once the transformation is incremental, in some areas the animation is not smooth at all. Update: In the revised version these problems were solved (see above).

//HINGED TESSELATION for animation
//by pedro veloso
int counter = 0;
int time, initial;
int wid = 500;
int hei = 500;
int num = 8;
float mod = float(wid) / num;
float ang = radians(0);
float rot, nextx, nexty;
float cycle = 2000;
void setup(){
  frameRate (10); 
  size (wid, hei);
  background(0, 0, 0);
  noStroke();
  initial = millis();
  counter = 0;
}
void draw(){
  ang = function_PennerEaseInOutExpo((millis() % cycle) / cycle) * (PI / 2); 
  fill(0, 0, 0);
  rect(0, 0, wid, hei);
  fill(250, 250, 0);
  nexty = 0;
  for (int i = 0; i < num + 1; i ++){
    pushMatrix();
    if (i == 0){ 
      rot = - ang;
    }
    else if (i % 2 == 1){ 
      nexty += 2 * cos(ang) * mod;
      rot = ang;
    }
    else if (i % 2 == 0){ 
      nexty += 2 * sin(ang) * mod;
      rot = -ang;
    }    
    translate(0, nexty);
    rotate(rot);
    int test = i % 2;
    for(int j = 0; j < num + 1 ; j ++){
      if (j % 2 == test){
        rect(0, 0, mod, mod);
        translate(mod, mod);
        rotate(2 * ang);
      }
      else{
        rect(0, 0, mod, -mod);
        translate(mod, -mod);
        rotate(-2 * ang);
      }
    }
    popMatrix();
  }
  counter += 1;
}
float function_PennerEaseInOutExpo(float t) {
  if (t==0) return 0.0;
  if (t==1) return 1.0;
  if ((t/=1.f/2) < 1) return 1.0f/2 * pow(2, 10 * (t - 1));
return 1.f/2 * (-pow(2, -10 * --t) + 2);
}

dantasse

05 Feb 2015

Here’s geotagged tweets in Pittsburgh in 2014, by the hour.

dantasse_500px

Data: all* geotagged tweets in Pittsburgh in 2014, sorted by lat/lon bins and by hour. Stored in a MongoDB on an EC2 instance, then scrobbled together with a bunch of python scripts.

How it’s made: A small web app using the Google Maps API and their heatmap layer. Max set at 600 tweets – I chose to keep it linearly scaled instead of log or anything, but we don’t know which of the red spots are 600 and which are 6000. GIF created using this photoshop tutorial and gifmaker.me. Screenshots taken with the mac “screencapture” tool so they all line up.

Why it’s cool: Okay, people wake up and go to sleep, and downtown and Oakland are busy all the time. Fine. South side gets busy at night. Shadyside and Lawrenceville do a little bit too. Sure. But check out the south hills at night: what’s going on there? And what’s happening over in Lincoln/Larimer? How about Highland park at 8pm?

What I wish I’d done better: Curated it at all. This tells stories, but they’re the most interesting or meaningful stories. My sketches (below) were a little primitive; I thought I’d turn this data more into a 3d shape, so maybe you’ll see it more in that project. This is more “computational” than “art and design”. Still, this is way more interesting to me than a coffee cup filling up or a little doodle or something.

* I don’t really know if it’s “all”. We’re just using the public API. Still, you can get something like 1% of all tweets from their public API, and geotagged tweets in Pittsburgh is way less than 1% of all tweets, so we have reason to believe it’s all the Pittsburgh tweets.

Code: on github. (not embedded because there’s rather a bit of it)

Sketches:
IMG_20150205_112227IMG_20150205_112239IMG_20150205_112248