Created
January 11, 2011 07:03
-
-
Save masonicboom/774140 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // spring pixels, by mason simon, 1-10-2010 | |
| import processing.video.*; | |
| float BASE_INTENSITY = 0.3; // this is the steady-state intensity of each Spring | |
| float t = 0; | |
| float dt = 1; | |
| Spring[][] intensities; | |
| DifferenceImage di = new DifferenceImage(); | |
| Capture video; | |
| MovieMaker mm; | |
| boolean SAVE_VIDEO = false; | |
| float radius; | |
| float space; | |
| void setup() { | |
| int FPS = 24; | |
| size(800, 600); | |
| video = new Capture(this, width, height, FPS); | |
| if (SAVE_VIDEO) { | |
| // I think dividing FPS by 3 made the resulting videos look better. Didn't dig too deep into why... | |
| mm = new MovieMaker(this, width, height, "screencap.mov", FPS/3, MovieMaker.RAW, MovieMaker.LOSSLESS); | |
| } | |
| frameRate(FPS); | |
| // rendering parameters | |
| radius = 10; | |
| space = 3; | |
| // spring parameters | |
| float range = 1.0; | |
| float hz = 1.0/30; | |
| float damping = 0.4; | |
| intensities = new Spring[(int)(width/radius)][(int)(height/radius)]; | |
| for (int x = 0; x < width/radius; x++) { | |
| for (int y = 0; y < height/radius; y++) { | |
| intensities[x][y] = new Spring(0, damping, hz, random(0, TWO_PI), 0.5*range); | |
| } | |
| } | |
| noStroke(); | |
| } | |
| void draw() { | |
| if (video.available() == false) return; | |
| background(0); | |
| video.read(); | |
| draw_frame(video, t); | |
| if (SAVE_VIDEO) | |
| mm.addFrame(); | |
| t += dt; | |
| } | |
| void draw_frame(PImage input, float t) { | |
| di.update(video); | |
| for (int x = 0, i = 0; x < width; x += radius + space, i++) { | |
| for (int y = 0, j = 0; y < height; y += radius + space, j++) { | |
| // if there's been a significant difference at this pixel, hit it! | |
| float diff = di.get(round(x), round(y)); | |
| float ad = abs(diff); | |
| if ( ad > 0.05 && ad <= 1.0 ) intensities[i][j].strike( t, ad/2.0 ); | |
| // draw the pixel | |
| color c = video.get(round(x), round(y)); | |
| float r = red(c); | |
| float g = green(c); | |
| float b = blue(c); | |
| float l = intensities[i][j].eval(t); | |
| fill(color(r*l, g*l, b*l) ); // I know. This isn't the perceptually correct way to scale luminance. | |
| ellipse(x, y, radius, radius); | |
| } | |
| } | |
| } | |
| // this function saves the video when you hit spacebar | |
| void keyPressed() { | |
| if (key == ' ' && SAVE_VIDEO) { | |
| mm.finish(); | |
| } | |
| } | |
| // This class models a damped, harmonically oscillating particle. | |
| class Spring { | |
| float ma, ad, hz, pl; | |
| float x0; | |
| float t0; // time offset | |
| Spring(float max_amplitude, | |
| float amplitude_decay, | |
| float hz, | |
| float phase_lag, | |
| float initial) { | |
| this.ma = max_amplitude; | |
| this.ad = amplitude_decay; | |
| this.hz = hz; | |
| this.pl = phase_lag; | |
| this.x0 = initial; | |
| this.t0 = 0; | |
| } | |
| float eval(float t) { | |
| return ma * exp(-1*ad*(t-t0)) * cos(hz*TWO_PI*t + pl) + x0; | |
| } | |
| // reset max amplitude based on the amplitude of the strike | |
| void strike(float t, float amplitude) { | |
| this.t0 = t; | |
| this.x0 = BASE_INTENSITY; | |
| this.ma = amplitude; | |
| } | |
| } | |
| // This class represents the intensity difference between two images. | |
| class DifferenceImage { | |
| PImage prev, cur; | |
| DifferenceImage() { | |
| this.prev = null; | |
| this.cur = null; | |
| } | |
| // set a new image as the current one | |
| void update(PImage new_cur) { | |
| prev = cur; | |
| int w = new_cur.width; | |
| int h = new_cur.height; | |
| cur = new PImage(w, h); | |
| cur.copy(new_cur, 0, 0, w, h, 0, 0, w, h); | |
| cur.filter(GRAY); | |
| } | |
| // get the intensity difference at the point (x, y) | |
| float get(int x, int y) { | |
| if (prev == null) return cur.get(x, y); | |
| float i1 = brightness(cur.get(x, y)); | |
| float i0 = brightness(prev.get(x, y)); | |
| return (i1 - i0)/255.0; | |
| } | |
| } | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment