Archive by Author

Googly Eyes

6 Nov

Today’s script is a shameless ripoff heartfelt homage to Sean Bogg’s wonderful 2009 artwork, Blue Monster. I thought this would be a great way to demonstrate how to use the transformation matrix in Processing.

I cranked this one out pretty quickly, by building up on previous work. I started with a copy of the final script from my circles and spirals tutorial. Then I ripped out the code that cycled the colors, and just made it white circles on a blue background, stealing the blue color from my French Flag.

Then instead of calculating the positions of the circles in a loop, I moved that code into a new subroutine, called setup_eyes(). This routine does exactly the same calculations, but creates individual eye objects in an array. Each eye knows its center coordinates and its diameter. I did this because I knew each eye would have to keep track of its rotation so the pupils can randomly drop, the way googly eyes do.

The drawing loop is now greatly simpler.

  pushMatrix();
    translate(width/2,height/2);
    rotate(gRotate);
    for (int i = 0; i < eyes.length; ++i) {
      eyes[i].draw();
    }
    popMatrix();

pushMatrix() and popMatrix() allow me to use the awesome translate and rotate functions, which transform the drawing space. I translate the center of the coordinate space to the center of the canvas, and then I rotate a little bit. This is what causes the overall spinning effect.

The rate of spin is controlled by the global variable orbit, which says how long it takes to do a full rotation. This in turn is used to figure out how much I need to currently spin, based on the clock.

float orbit = 6*60*1000;    // 6 minute orbit (in milliseconds)
gRotate = millis()*TWO_PI/orbit;

The value gRotate is recomputed each frame of animation, using the current value of millis(), which measures how long the sketch has been running, in milliseconds.

Finally, the draw() method of the Eye class is used to draw each eye. The basic eye shape is drawn with a white ellipse, a black ellipse, and a little white arc which makes the pupil look shiny.

        noStroke();
        fill(255);
        ellipse(0,0,diam,diam);
        fill(0);
        ellipse(0,diam*(1-phi)*.9/2,diam*phi,diam*phi);
        stroke(255);
        noFill();
        arc(0,diam*(1-phi)/2*.9,diam*phi*.9,diam*phi*.9,TWO_PI-PI/2,TWO_PI);

This code is bookended by some code that provides the jerky eyeball rotation that appears to be controlled by gravity, just like a real set of googly eyes. Each Googly Eye keeps track of how much adjustment it needs to make to compensate for the spin. As the necessary adjustment grows larger, the likelihood that the eye will shift it's position (back to the bottom) increases.
Here's what it looks like:

      if (random(180) < degrees(gRotate-adj)*gStickiness) {
        adj = gRotate;
      }

The global variable gStickiness controls how sticky the eyes are. I currently have it set to .5. Lower values will make the eyes travel even further before they adjust.

Then, the adj value is used to rotate the individual eye when it is drawn.

     pushMatrix();
        translate(x,y);
        rotate(-adj); // compensate for overall spin so pupil appears on or near bottom
        // draw eye here
     popMatrix();

That's it! 'Til next time, here's looking at you, kids.