Skip to content

Instantly share code, notes, and snippets.

@masonicboom
Created January 11, 2011 07:03
Show Gist options
  • Select an option

  • Save masonicboom/774140 to your computer and use it in GitHub Desktop.

Select an option

Save masonicboom/774140 to your computer and use it in GitHub Desktop.
// 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