Scope GIF:
Description:
My praxinoscope is a very simple design, centered around rotating circles. Initially, I was really inspired by planets and was thinking about maybe having a planet with a single asteroid. However, I thought that looked boring and decided to play around with rotation patterns and spirals. There is not much conceptually behind the design, instead it was mainly an experimentation with rotation patterns and how to make a trippy image that hurts your eyes.
Scope PDF:
Scope Code:
import processing.pdf.*; boolean bRecordingPDF = false; float inch = 72; float diamArtInner = inch * 1.50; float diamArtOuter = inch * 4.80; float diamCutInner = inch * 1.41; float diamCutOuter = inch * 4.875; float holeDy = inch * 0.23; float holeDx = inch * 0.20; float holeD = inch * 0.1; final int nFrames = 10; int myFrameCount = 0; int exportFrameCount = 0; boolean bAnimate = true; boolean bExportFrameImages = false; //------------------------------------------------------- void setup() { size(792, 612); // 11x8.5" at 72DPI frameRate(15); smooth(); } //------------------------------------------------------- void draw() { background(240); if (bRecordingPDF) { beginRecord(PDF, "praxinoscope-output.pdf"); } // Do all the drawing. pushMatrix(); translate(width/2, height/2); drawCutLines(); drawGuides(); drawAllFrames(); popMatrix(); if (bExportFrameImages) { // If activated, export .PNG frames if (exportFrameCount < nFrames) { String filename = "frame_" + nf((exportFrameCount%nFrames), 3) + ".png"; saveFrame("frames/" + filename); println("Saved: " + filename); exportFrameCount++; if (exportFrameCount >= nFrames) { bExportFrameImages = false; exportFrameCount = 0; } } } if (bRecordingPDF) { endRecord(); bRecordingPDF = false; } } //------------------------------------------------------- void keyPressed() { switch (key) { case ' ': // Press spacebar to pause/unpause the animation. bAnimate = !bAnimate; break; case 'p': case 'P': // Press 'p' to export a PDF for the Praxinoscope. bRecordingPDF = true; break; case 'f': case 'F': // Press 'f' to export .png Frames (to make an animated .GIF) myFrameCount = 0; exportFrameCount = 0; bExportFrameImages = true; bAnimate = true; break; } } //------------------------------------------------------- void drawCutLines() { fill(0); textAlign(CENTER, BOTTOM); text("Praxinoscope Template", 0, 0-diamCutOuter/2-6); stroke(0); strokeWeight(1.0); noFill(); if (!bRecordingPDF) { fill(255); } ellipse(0, 0, diamCutOuter, diamCutOuter); noFill(); if (!bRecordingPDF) { fill(240); } ellipse(0, 0, diamCutInner, diamCutInner); noFill(); ellipse(diamCutOuter/2 - holeDx, 0-holeDy, holeD, holeD); line (diamCutInner/2, 0, diamCutOuter/2, 0); } //------------------------------------------------------- void drawGuides() { // This function draws the guidelines. // Don't draw these when we're exporting the PDF. if (!bRecordingPDF) { noFill(); stroke(128); strokeWeight(0.2); ellipse(0, 0, diamArtInner, diamArtInner); ellipse(0, 0, diamArtOuter, diamArtOuter); for (int i=0; i<nFrames; i++) { float angle = map(i, 0, nFrames, 0, TWO_PI); float pxi = diamArtInner/2 * cos(angle); float pyi = diamArtInner/2 * sin(angle); float pxo = diamArtOuter/2 * cos(angle); float pyo = diamArtOuter/2 * sin(angle); stroke(128); strokeWeight(0.2); line (pxi, pyi, pxo, pyo); } // Draw the red wedge outline, highlighting the main view. int redWedge = 7; // assuming nFrames = 10 for (int i=redWedge; i<=(redWedge+1); i++) { float angle = map(i, 0, nFrames, 0, TWO_PI); float pxi = diamArtInner/2 * cos(angle); float pyi = diamArtInner/2 * sin(angle); float pxo = diamArtOuter/2 * cos(angle); float pyo = diamArtOuter/2 * sin(angle); stroke(255, 0, 0); strokeWeight(2.0); line (pxi, pyi, pxo, pyo); } noFill(); stroke(255, 0, 0); strokeWeight(2.0); float startAngle = redWedge*TWO_PI/nFrames; float endAngle = (redWedge+1)*TWO_PI/nFrames; arc(0, 0, diamArtInner, diamArtInner, startAngle, endAngle); arc(0, 0, diamArtOuter, diamArtOuter, startAngle, endAngle); for (int i=0; i<nFrames; i++) { float angle = map(i, 0, nFrames, 0, TWO_PI); pushMatrix(); rotate(angle); float originY = ((diamArtOuter + diamArtInner)/2)/2; translate(0, 0-originY); noFill(); stroke(128); strokeWeight(0.2); line (-inch/2, 0, inch/2, 0); line (0, -inch/2, 0, inch/2); popMatrix(); } } } //------------------------------------------------------- void drawAllFrames() { for (int i=0; i<nFrames; i++) { float angle = map(i, 0, nFrames, 0, TWO_PI); float originY = ((diamArtOuter + diamArtInner)/2)/2; pushMatrix(); rotate(angle); translate(0, 0-originY); scale(0.8, 0.8); // feel free to ditch this int whichFrame = i; if (bAnimate) { whichFrame = (i+myFrameCount)%nFrames; } drawArtFrame (whichFrame); // drawArtFrameAlternate (whichFrame); popMatrix(); } myFrameCount++; } //------------------------------------------------------- void drawArtFrame (int whichFrame) { // Draw the artwork for a generic frame of the Praxinoscope, // given the framenumber (whichFrame) out of nFrames. // NOTE #1: The "origin" for the frame is in the center of the wedge. // NOTE #2: Remember that everything will appear upside-down! // Draw the frame number fill(0); noStroke(); // Draw a pulsating ellipse noFill(); stroke(0); strokeWeight(1); float t = map(whichFrame, 0, nFrames, 0, 1); float diam = map(cos(t*TWO_PI), -1, 1, 25, 50); ellipse(0, 0, diam, diam); //rotating circle float radius = diam/2; float rotatingArmAngle = (whichFrame*.1) * TWO_PI; float px = 0 + radius*cos(rotatingArmAngle); float py = 0 + radius*sin(rotatingArmAngle); fill (0); stroke(51); ellipse(px, py, 8, 8); //rotating circle float rotatingArmAngle2 = (whichFrame*.1) * TWO_PI; float px2 = 15 + radius*cos(rotatingArmAngle2); float py2 = 15 + radius*sin(rotatingArmAngle2); fill (0); stroke(51); ellipse(-px2, -py2, 8, 8); float px3 = -12 + radius*cos(rotatingArmAngle2); float py3 = -20 + radius*sin(rotatingArmAngle2); fill (0); stroke(51); ellipse(-px3, -py3, 8, 8); //rect figure float amplitude=100; float f=.1; float xR=160; float yR=(160)+amplitude*sin(f*whichFrame); rect(xR,yR,10,10); } //------------------------------------------------------- void drawArtFrameAlternate(int whichFrame) { // An alternate drawing test. // Draw a falling object. // Draw a little splat on the frame when it hits the ground. if (whichFrame == (nFrames-1)) { stroke(0, 0, 0); strokeWeight(0.5); int nL = 10; for (int i=0; i<nL; i++) { float a = HALF_PI + map(i, 0, nL-1, 0, TWO_PI); float cx = 12 * cos(a); float cy = 10 * sin(a); float dx = 16 * cos(a); float dy = 13 * sin(a); line (cx, 45+cy, dx, 45+dy); } } // Draw a little box frame fill(255); stroke(0, 0, 0); strokeWeight(1); rect(-5, -50, 10, 100); // Make the puck accelerate downward float t = map(whichFrame, 0, nFrames-1, 0, 1); float t2 = pow(t, 2.0); float rh = 8 + whichFrame * 0.5; // wee stretch float ry = map(t2, 0, 1, 0, 100-rh) - 50; noStroke(); fill(0, 0, 0); rect(-5, ry, 10, rh); } |