And I was lucky enough to find the source code from this website:
Here's the code:
// Star Nursery
// by Ryan Alexander at Motion Theory
//
// Press tilde (~) to show the bounding circles
// Press the mouse to hide the video
//
// Make sure to have your camera turned on before you run me!
//
// Deep currents
// Like the sky
// Use no pentameter
// Mike Stipe is just this guy
int maxStars = 10000;
int nStars = 0;
Star stars[] = new Star[maxStars];
BImage basicStar, vidThumb;
boolean newFrame;
float brightest = 255;
float darkest = 0;
float brightX[][] = new float[8][6];
float brightY[][] = new float[8][6];
float brightVelX[][] = new float[8][6];
float brightVelY[][] = new float[8][6];
boolean firstFrame = true;
void setup()
{
size(500, 375);
background(0);
basicStar = loadImage("pfx_star.gif");
brightToAlpha(basicStar);
beginVideo(width, height, 15);
framerate(30);
conceiveStars(300);
}
void loop()
{
// Calibrate the video for next frame
if(newFrame) {
calibrateVideo();
newFrame = false;
firstFrame = false;
}
if(mousePressed) {
background(0);
} else {
background(video);
}
noFill();
stroke(255,0,0,40);
for(int i=0; i < nStars; i++) {
stars[i].update();
}
stroke(128,128,128,40);
for(int i=0; i < nStars; i++) {
stars[i].display();
}
}
void mouseReleased()
{
background(0);
}
void videoEvent()
{
newFrame = true;
}
void conceiveStars(int n)
{
n += nStars;
for(int i=nStars; i < n; i++) {
stars[i] = new Star(i, random(width), random(height), random(-5, 5), random(-5, 5));
}
nStars += n;
}
void calibrateVideo()
{
vidThumb = video.copy(40, 30);
float tempb = brightness(vidThumb.pixels[0]);
brightest = tempb;
darkest = tempb;
for(int i=1; i < 1200; i++) {
tempb = brightness(vidThumb.pixels[i]);
if(tempb > brightest) {
brightest = tempb;
}
if(tempb < darkest) {
darkest = tempb;
}
}
// Make sure that lightest is > darkest
if(brightest <= darkest) brightest = darkest + 1;
// Calculate the changes in general brightness
float tempx, tempy, totalBright;
int pxx, pxy;
for(int j=0; j < 6; j++) {
for(int i=0; i < 8; i++) {
tempx = 0;
tempy = 0;
totalBright = 0;
for(int jj=0; jj < 5; jj++) {
for(int ii=0; ii < 5; ii++) {
pxx = i*5 + ii;
pxy = j*5 + jj;
tempb = brightness(vidThumb.pixels[pxx + pxy * 40]);
tempx += pxx * tempb;
tempy += pxy * tempb;
totalBright += tempb;
}
}
// Adjust the general velocity of the brightness
if(totalBright == 0) { // Avoid divide by 0
if(firstFrame) {
brightX[i][j] = i * (width/8) + (width/16);
brightY[i][j] = j * (height/6) + (height/12);
}
} else {
tempx = (tempx / totalBright + .5) * (width / 40.0);
tempy = (tempy / totalBright + .5) * (height / 30.0);
if(firstFrame) {
brightX[i][j] = tempx;
brightY[i][j] = tempy;
} else {
brightX[i][j] += brightVelX[i][j];
brightY[i][j] += brightVelY[i][j];
brightVelX[i][j] = ((tempx - brightX[i][j]) - brightVelX[i][j]) * .2;
brightVelY[i][j] = ((tempy - brightY[i][j]) - brightVelY[i][j]) * .2;
}
}
}
}
}
// //
// Star //
// //
class Star
{
float x, y, xv, yv;
float diameter, inside, minD, maxD;
int id, age;
boolean connected[] = new boolean[maxStars];
float red, green, blue;
Star(int iid, float ix, float iy, float ixv, float iyv)
{
x = ix; y = iy;
xv = ixv; yv = iyv;
id = iid;
age = (int)random(500);
minD = 20;
maxD = 60;
}
void update()
{
// Decay the inside diameter
if(inside > 0) inside -= 1;
// React to video input
if(x >= 0 && x < width && y >= 0 && y < height) {
color tempPixel = video.pixels[(int)x + (int)y*width];
// Diameter grows with brightness
float multiplier = 255.0 / (brightest - darkest);
float bright = constrain(((brightness(tempPixel) - darkest) * multiplier) / 255, 0, 1);
float sizeMult = sin(age * .05) * .4 + .6;
diameter += ( (((1 - bright) * (maxD - minD) + minD) * sizeMult) - diameter ) * .2;
// Influence by movement of general brightness
xv += brightVelX[(int)floor(x / (width/8.0))][(int)floor(y / (height/6.0))] * 1;
yv += brightVelY[(int)floor(x / (width/8.0))][(int)floor(y / (height/6.0))] * 1;
}
// Check for new connections
for(int i=0; i < nStars; i++) {
if(i != id) {// && touching < 1 && stars[i].touching < 1) { // If it's not me
float xd = stars[i].x - x;
float yd = stars[i].y - y;
float diff = xd*xd + yd*yd;
float radii = stars[i].diameter/2 + diameter/2;
// If touching
if(diff < radii*radii) {
springAdd(stars[i].x, stars[i].y, radii);
// Assimilate Velocity
xv += (stars[i].xv - xv) * .01;
yv += (stars[i].yv - yv) * .01;
// Color changes with distance
float dist = sqrt(diff);
if(dist < 30) {
stroke(255, ((30 - dist) * 6) * (min(inside, stars[i].inside) / 60));
line(x, y, stars[i].x, stars[i].y);
}
if(!connected[i]) {
inside += diameter / (maxD / 5);
connected[i] = true;
}
} else {
connected[i] = false;
}
}
}
inside = constrain(inside, 0, 60);
}
void display()
{
ellipseMode(CENTER_DIAMETER);
if(keyPressed && key == '`') {
ellipse(x, y, diameter, diameter);
}
if(inside > 1) {
imageMode(CENTER_DIAMETER);
tint(255, (inside-4)*64);
push();
translate(0,0,-1);
image(basicStar, x, y, inside, inside);
pop();
}
//line(x, y, x+xv, y+yv);
x += xv;
y += yv;
// Constrain to screen
float d2 = diameter/2;
if(x < d2) { x = d2; }
if(x > width - d2) { x = width - d2; }
if(y < d2) { y = d2; }
if(y > height - d2) { y = height - d2; }
xv *= .8;
yv *= .8;
age++;
}
float dx, dy, mag, ext;
void springAdd(float sx, float sy, float rest)
{
dx = sx - x;
dy = sy - y;
if(dx != 0 || dy != 0) { // Prevent / by zero
mag = sqrt(dx*dx + dy*dy);
ext = mag - rest;
xv += (dx / mag * ext) * .1;
yv += (dy / mag * ext) * .1;
}
}
}
void brightToAlpha(BImage b)
{
b.format = RGBA;
for(int i=0; i < b.pixels.length; i++) {
b.pixels[i] = color(255,255,255,brightness(b.pixels[i]));
}
}
The only problem is that it was built for processing 1.0 and therefore there are a lot of changes that need to be made to the code to update it.
I was also lucky to find an updated version online from the following website:
http://processing.org/discourse/yabb2/YaBB.pl?num=1206398682
import processing.video.*;
// Star Nursery
// by Ryan Alexander at Motion Theory
//
// Press tilde (~) to show the bounding circles
// Press the mouse to hide the video
//
// Make sure to have your camera turned on before you run me!
//
// Deep currents
// Like the sky
// Use no pentameter
// Mike Stipe is just this guy
int maxStars = 10000;
int nStars = 0;
Star stars[] = new Star[maxStars];
PImage basicStar, vidThumb;
boolean newFrame;
float brightest = 255;
float darkest = 0;
float brightX[][] = new float[8][6];
float brightY[][] = new float[8][6];
float brightVelX[][] = new float[8][6];
float brightVelY[][] = new float[8][6];
boolean firstFrame = true;
Capture video;
void setup()
{
size(800, 600);
background(0);
basicStar = loadImage("pfx_star.gif");
brightToAlpha(basicStar);
video = new Capture(this, width, height, 15);
frameRate(30);
conceiveStars(1000);
}
void captureEvent(Capture video) {
video.read();
}
void draw()
{
image(video, 0, 0);
// Calibrate the video for next frame
if(newFrame) {
calibrateVideo();
newFrame = false;
firstFrame = false;
}
if(mousePressed) {
background(0);
} else {
background(video);
}
noFill();
stroke(255,0,0,40);
for(int i=0; i < nStars; i++) {
stars[i].update();
}
stroke(128,128,128,40);
for(int i=0; i < nStars; i++) {
stars[i].display();
}
}
//void mouseReleased()
//{
// background(0);
//}
void videoEvent()
{
newFrame = true;
}
void conceiveStars(int n)
{
n += nStars;
for(int i=nStars; i < n; i++) {
stars[i] = new Star(i, random(width), random(height), random(-5, 5), random(-5, 5));
}
nStars += n;
}
void calibrateVideo()
{
vidThumb.copy(video, 0, 0 ,width, height, 0, 0, 40, 30);
float tempb = brightness(vidThumb.pixels[0]);
brightest = tempb;
darkest = tempb;
for(int i=1; i < 1200; i++) {
tempb = brightness(vidThumb.pixels[i]);
if(tempb > brightest) {
brightest = tempb;
}
if(tempb < darkest) {
darkest = tempb;
}
}
// Make sure that lightest is > darkest
if(brightest <= darkest) brightest = darkest + 1;
// Calculate the changes in general brightness
float tempx, tempy, totalBright;
int pxx, pxy;
for(int j=0; j < 6; j++) {
for(int i=0; i < 8; i++) {
tempx = 0;
tempy = 0;
totalBright = 0;
for(int jj=0; jj < 5; jj++) {
for(int ii=0; ii < 5; ii++) {
pxx = i*5 + ii;
pxy = j*5 + jj;
tempb = brightness(vidThumb.pixels[pxx + pxy * 40]);
tempx += pxx * tempb;
tempy += pxy * tempb;
totalBright += tempb;
}
}
// Adjust the general velocity of the brightness
if(totalBright == 0) { // Avoid divide by 0
if(firstFrame) {
brightX[i][j] = i * (width/8) + (width/16);
brightY[i][j] = j * (height/6) + (height/12);
}
} else {
tempx = (tempx / totalBright + .5) * (width / 40.0);
tempy = (tempy / totalBright + .5) * (height / 30.0);
if(firstFrame) {
brightX[i][j] = tempx;
brightY[i][j] = tempy;
} else {
brightX[i][j] += brightVelX[i][j];
brightY[i][j] += brightVelY[i][j];
brightVelX[i][j] = ((tempx - brightX[i][j]) - brightVelX[i][j]) * .2;
brightVelY[i][j] = ((tempy - brightY[i][j]) - brightVelY[i][j]) * .2;
}
}
}
}
}
// //
// Star //
// //
class Star
{
float x, y, xv, yv;
float diameter, inside, minD, maxD;
int id, age;
boolean connected[] = new boolean[maxStars];
float red, green, blue;
Star(int iid, float ix, float iy, float ixv, float iyv)
{
x = ix; y = iy;
xv = ixv; yv = iyv;
id = iid;
age = (int)random(500);
minD = 20;
maxD = 60;
}
void update()
{
// Decay the inside diameter
if(inside > 0) inside -= 1;
// React to video input
if(x >= 0 && x < width && y >= 0 && y < height) {
color tempPixel = video.pixels[(int)x + (int)y*width];
// Diameter grows with brightness
float multiplier = 255.0 / (brightest - darkest);
float bright = constrain(((brightness(tempPixel) - darkest) * multiplier) / 255, 0, 1);
float sizeMult = sin(age * .05) * .4 + .6;
diameter += ( (((1 - bright) * (maxD - minD) + minD) * sizeMult) - diameter ) * .2;
// Influence by movement of general brightness
xv += brightVelX[(int)floor(x / (width/8.0))][(int)floor(y / (height/6.0))] * 1;
yv += brightVelY[(int)floor(x / (width/8.0))][(int)floor(y / (height/6.0))] * 1;
}
// Check for new connections
for(int i=0; i < nStars; i++) {
if(i != id) {// && touching < 1 && stars[i].touching < 1) { // If it's not me
float xd = stars[i].x - x;
float yd = stars[i].y - y;
float diff = xd*xd + yd*yd;
float radii = stars[i].diameter/2 + diameter/2;
// If touching
if(diff < radii*radii) {
springAdd(stars[i].x, stars[i].y, radii);
// Assimilate Velocity
xv += (stars[i].xv - xv) * .01;
yv += (stars[i].yv - yv) * .01;
// Color changes with distance
float dist = sqrt(diff);
if(dist < 30) {
stroke(255, ((30 - dist) * 6) * (min(inside, stars[i].inside) / 60));
line(x, y, stars[i].x, stars[i].y);
}
if(!connected[i]) {
inside += diameter / (maxD / 5);
connected[i] = true;
}
} else {
connected[i] = false;
}
}
}
inside = constrain(inside, 0, 60);
}
void display()
{
ellipseMode(CENTER_DIAMETER);
if(keyPressed && key == '`') {
ellipse(x, y, diameter, diameter);
}
if(inside > 1) {
imageMode(CENTER_DIAMETER);
tint(255, (inside-4)*64);
pushMatrix();
translate(0,0,-1);
image(basicStar, x, y, inside, inside);
popMatrix();
}
//line(x, y, x+xv, y+yv);
x += xv;
y += yv;
// Constrain to screen
float d2 = diameter/2;
if(x < d2) { x = d2; }
if(x > width - d2) { x = width - d2; }
if(y < d2) { y = d2; }
if(y > height - d2) { y = height - d2; }
xv *= .8;
yv *= .8;
age++;
}
float dx, dy, mag, ext;
void springAdd(float sx, float sy, float rest)
{
dx = sx - x;
dy = sy - y;
if(dx != 0 || dy != 0) { // Prevent / by zero
mag = sqrt(dx*dx + dy*dy);
ext = mag - rest;
xv += (dx / mag * ext) * .1;
yv += (dy / mag * ext) * .1;
}
}
}
void brightToAlpha(PImage b)
{
b.format = ARGB;
for(int i=0; i < b.pixels.length; i++) {
b.pixels[i] = color(255,255,255,brightness(b.pixels[i]));
}
}
import processing.video.*;
// Star Nursery
// by Ryan Alexander at Motion Theory
//
// Press tilde (~) to show the bounding circles
// Press the mouse to hide the video
//
// Make sure to have your camera turned on before you run me!
//
// Deep currents
// Like the sky
// Use no pentameter
// Mike Stipe is just this guy
int maxStars = 10000;
int nStars = 0;
Star stars[] = new Star[maxStars];
PImage basicStar, vidThumb;
boolean newFrame;
float brightest = 255;
float darkest = 0;
float brightX[][] = new float[8][6];
float brightY[][] = new float[8][6];
float brightVelX[][] = new float[8][6];
float brightVelY[][] = new float[8][6];
boolean firstFrame = true;
Capture video;
void setup()
{
size(800, 600);
background(0);
basicStar = loadImage("pfx_star.gif");
brightToAlpha(basicStar);
video = new Capture(this, width, height, 15);
frameRate(30);
conceiveStars(1000);
}
void captureEvent(Capture video) {
video.read();
}
void draw()
{
image(video, 0, 0);
// Calibrate the video for next frame
if(newFrame) {
calibrateVideo();
newFrame = false;
firstFrame = false;
}
if(mousePressed) {
background(0);
} else {
background(video);
}
noFill();
stroke(255,0,0,40);
for(int i=0; i < nStars; i++) {
stars[i].update();
}
stroke(128,128,128,40);
for(int i=0; i < nStars; i++) {
stars[i].display();
}
}
//void mouseReleased()
//{
// background(0);
//}
void videoEvent()
{
newFrame = true;
}
void conceiveStars(int n)
{
n += nStars;
for(int i=nStars; i < n; i++) {
stars[i] = new Star(i, random(width), random(height), random(-5, 5), random(-5, 5));
}
nStars += n;
}
void calibrateVideo()
{
vidThumb.copy(video, 0, 0 ,width, height, 0, 0, 40, 30);
float tempb = brightness(vidThumb.pixels[0]);
brightest = tempb;
darkest = tempb;
for(int i=1; i < 1200; i++) {
tempb = brightness(vidThumb.pixels[i]);
if(tempb > brightest) {
brightest = tempb;
}
if(tempb < darkest) {
darkest = tempb;
}
}
// Make sure that lightest is > darkest
if(brightest <= darkest) brightest = darkest + 1;
// Calculate the changes in general brightness
float tempx, tempy, totalBright;
int pxx, pxy;
for(int j=0; j < 6; j++) {
for(int i=0; i < 8; i++) {
tempx = 0;
tempy = 0;
totalBright = 0;
for(int jj=0; jj < 5; jj++) {
for(int ii=0; ii < 5; ii++) {
pxx = i*5 + ii;
pxy = j*5 + jj;
tempb = brightness(vidThumb.pixels[pxx + pxy * 40]);
tempx += pxx * tempb;
tempy += pxy * tempb;
totalBright += tempb;
}
}
// Adjust the general velocity of the brightness
if(totalBright == 0) { // Avoid divide by 0
if(firstFrame) {
brightX[i][j] = i * (width/8) + (width/16);
brightY[i][j] = j * (height/6) + (height/12);
}
} else {
tempx = (tempx / totalBright + .5) * (width / 40.0);
tempy = (tempy / totalBright + .5) * (height / 30.0);
if(firstFrame) {
brightX[i][j] = tempx;
brightY[i][j] = tempy;
} else {
brightX[i][j] += brightVelX[i][j];
brightY[i][j] += brightVelY[i][j];
brightVelX[i][j] = ((tempx - brightX[i][j]) - brightVelX[i][j]) * .2;
brightVelY[i][j] = ((tempy - brightY[i][j]) - brightVelY[i][j]) * .2;
}
}
}
}
}
// //
// Star //
// //
class Star
{
float x, y, xv, yv;
float diameter, inside, minD, maxD;
int id, age;
boolean connected[] = new boolean[maxStars];
float red, green, blue;
Star(int iid, float ix, float iy, float ixv, float iyv)
{
x = ix; y = iy;
xv = ixv; yv = iyv;
id = iid;
age = (int)random(500);
minD = 20;
maxD = 60;
}
void update()
{
// Decay the inside diameter
if(inside > 0) inside -= 1;
// React to video input
if(x >= 0 && x < width && y >= 0 && y < height) {
color tempPixel = video.pixels[(int)x + (int)y*width];
// Diameter grows with brightness
float multiplier = 255.0 / (brightest - darkest);
float bright = constrain(((brightness(tempPixel) - darkest) * multiplier) / 255, 0, 1);
float sizeMult = sin(age * .05) * .4 + .6;
diameter += ( (((1 - bright) * (maxD - minD) + minD) * sizeMult) - diameter ) * .2;
// Influence by movement of general brightness
xv += brightVelX[(int)floor(x / (width/8.0))][(int)floor(y / (height/6.0))] * 1;
yv += brightVelY[(int)floor(x / (width/8.0))][(int)floor(y / (height/6.0))] * 1;
}
// Check for new connections
for(int i=0; i < nStars; i++) {
if(i != id) {// && touching < 1 && stars[i].touching < 1) { // If it's not me
float xd = stars[i].x - x;
float yd = stars[i].y - y;
float diff = xd*xd + yd*yd;
float radii = stars[i].diameter/2 + diameter/2;
// If touching
if(diff < radii*radii) {
springAdd(stars[i].x, stars[i].y, radii);
// Assimilate Velocity
xv += (stars[i].xv - xv) * .01;
yv += (stars[i].yv - yv) * .01;
// Color changes with distance
float dist = sqrt(diff);
if(dist < 30) {
stroke(255, ((30 - dist) * 6) * (min(inside, stars[i].inside) / 60));
line(x, y, stars[i].x, stars[i].y);
}
if(!connected[i]) {
inside += diameter / (maxD / 5);
connected[i] = true;
}
} else {
connected[i] = false;
}
}
}
inside = constrain(inside, 0, 60);
}
void display()
{
ellipseMode(CENTER_DIAMETER);
if(keyPressed && key == '`') {
ellipse(x, y, diameter, diameter);
}
if(inside > 1) {
imageMode(CENTER_DIAMETER);
tint(255, (inside-4)*64);
pushMatrix();
translate(0,0,-1);
image(basicStar, x, y, inside, inside);
popMatrix();
}
//line(x, y, x+xv, y+yv);
x += xv;
y += yv;
// Constrain to screen
float d2 = diameter/2;
if(x < d2) { x = d2; }
if(x > width - d2) { x = width - d2; }
if(y < d2) { y = d2; }
if(y > height - d2) { y = height - d2; }
xv *= .8;
yv *= .8;
age++;
}
float dx, dy, mag, ext;
void springAdd(float sx, float sy, float rest)
{
dx = sx - x;
dy = sy - y;
if(dx != 0 || dy != 0) { // Prevent / by zero
mag = sqrt(dx*dx + dy*dy);
ext = mag - rest;
xv += (dx / mag * ext) * .1;
yv += (dy / mag * ext) * .1;
}
}
}
void brightToAlpha(PImage b)
{
b.format = ARGB;
for(int i=0; i < b.pixels.length; i++) {
b.pixels[i] = color(255,255,255,brightness(b.pixels[i]));
}
}
0 comments:
Post a Comment