This lenticular animation was inspired by the oscillation of the balance wheel found within mechanical timepieces. My initial plan was to do a very literal modeling of this mechanic in processing and my initial results were promising. Using a YouTube video that had a slow motion view of the wheel I was able to extract a lot of good detail about the movement, for example, the wheel rotated about 495 degrees before switching directions, and the spring expanded as the wheel moved counter-clockwise and contracted during clockwise movement.
Once I had the simple harmonic motion working I realized that with the 10 frame limit for Gifpop, there was no way to make a very literal animation of the balance wheel look acceptable. So I went more abstract using what I had as a base for expansion. The animation isn’t very visually complex or compelling so I chose a pop art color palette to make the piece more visually engaging.
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 | // 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 // Author: Jeff Crossman //=================================================== // Global variables. int nFramesInLoop = 30; // for lenticular export, change this to 10! int nScreenResolution = 500; // n X n pixels int nElapsedFrames; boolean bRecording; String myName = "jeffcrossman"; //=================================================== void setup() { size (nScreenResolution, nScreenResolution); bRecording = false; nElapsedFrames = 0; frameRate (nFramesInLoop); rectMode(CENTER); } //=================================================== 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 (0, 153, 255); stroke (229, 6, 123); fill(0, 0, 0); strokeWeight (42); smooth(); //---------------------- // Here, I assign some handy variables. float amplitude = radians(55); float period = 240; float x = amplitude * cos(TWO_PI * percent); if (x > radians(45)) x = radians(45); else if ( x < -radians(45)) x = -radians(45); //text (x, 200, 20); scale(nScreenResolution / 500); // Scale drawing to screen size translate(250, 250); rotate(-radians(percent*90)); translate(-250, -250); pushMatrix(); translate(250, 250); rotate(x); rect(0, 0, 100, 100); popMatrix(); pushMatrix(); translate(151, 151); rotate(-x); rect(0, 0, 100, 100); popMatrix(); pushMatrix(); translate(349, 151); rotate(-x); rect(0, 0, 100, 100); popMatrix(); pushMatrix(); translate(349, 349); rotate(-x); rect(0, 0, 100, 100); popMatrix(); pushMatrix(); translate(151, 349); rotate(-x); rect(0, 0, 100, 100); popMatrix(); } |