http://www.youtube.com/watch?v=A4Bt7SQn37g
/**
* FlockingCamera
*
* por Sandro Miccoli
*
* As partículas simulam o voo de pássaros e pintam dinamicamente a tela.
*
* Para interagir:
*
* c - Alterna entre o modo de pintura e o modo de visualização do movimento dos pássaros
* n - Cria um pássaro novo na tela
*
* Clique na tela para gerar mais pássaros.
*/
import processing.video.*;
Flock flock;
Capture video;
int myWidth = 640;
int myHeight = 480;
boolean flag=false;
void setup() {
//img = loadImage("crows.jpg");
video = new Capture(this, myWidth, myHeight);
//video.start(); // For Linux, this will only work in newer versions of Processing (2.0+)
noStroke();
smooth();
size(myWidth, myHeight);
background(0);
smooth();
flock = new Flock();
// Add an initial set of boids into the system
for (int i = 0; i < 10; i++) {
flock.addBoid(new Boid(480+random(120), 75+random(100)));
}
}
void draw() {
if (video.available()){
video.read();
video.loadPixels();
}
flock.run();
if (flag){
background(0);
}
if (keyPressed) {
switch(key) {
case 'c' :
if (flag)
flag=false;
else
flag=true;
break;
case 'n' :
flock.addBoid(new Boid(random(width), random(height)));
break;
}
}
for (int i=0; i < flock.boids.size(); i++) {
draw_line(int(flock.boids.get(i).location.x), int(flock.boids.get(i).location.y));
}
}
// Add a new boids into the System
void mousePressed() {
for (int i=0; i<5; i++){
flock.addBoid(new Boid(mouseX, mouseY));
}
}
void draw_line(int x, int y) {
int loc = x + y*myWidth;
loadPixels();
float r = 0;
float g = 0;
float b = 0;
// Condição pra só pegar a cor do pixel quando tiver dentro da tela, ou seja, dentro do limite da imagem.
if ((loc>0)&&(loc<video.pixels.length)) {
r = red(video.pixels[loc]);
g = green(video.pixels[loc]);
b = blue(video.pixels[loc]);
}
pushStyle();
strokeWeight(2);
stroke(r, g, b, 225); // Necessário pra dar "fill" na linha
line(x,y,x+random(-5,5),y+random(-5,5));
popStyle();
}
// The Boid class
class Boid {
PVector location;
PVector velocity;
PVector acceleration;
float r;
float maxforce; // Maximum steering force
float maxspeed; // Maximum speed
Boid(float x, float y) {
acceleration = new PVector(0,0);
velocity = new PVector(random(-1,1),random(-1,1));
location = new PVector(x,y);
r = 2.0;
maxspeed = 2;
maxforce = 0.03;
}
void run(ArrayList<Boid> boids) {
flock(boids);
update();
borders();
render();
}
void applyForce(PVector force) {
// We could add mass here if we want A = F / M
acceleration.add(force);
}
// We accumulate a new acceleration each time based on three rules
void flock(ArrayList<Boid> boids) {
PVector sep = separate(boids); // Separation
PVector ali = align(boids); // Alignment
PVector coh = cohesion(boids); // Cohesion
// Arbitrarily weight these forces
sep.mult(1.5);
ali.mult(1.0);
coh.mult(1.0);
// Add the force vectors to acceleration
applyForce(sep);
applyForce(ali);
applyForce(coh);
}
// Method to update location
void update() {
// Update velocity
velocity.add(acceleration);
// Limit speed
velocity.limit(maxspeed);
location.add(velocity);
// Reset accelertion to 0 each cycle
acceleration.mult(0);
}
// A method that calculates and applies a steering force towards a target
// STEER = DESIRED MINUS VELOCITY
PVector seek(PVector target) {
PVector desired = PVector.sub(target,location); // A vector pointing from the location to the target
// Normalize desired and scale to maximum speed
desired.normalize();
desired.mult(maxspeed);
// Steering = Desired minus Velocity
PVector steer = PVector.sub(desired,velocity);
steer.limit(maxforce); // Limit to maximum steering force
return steer;
}
void render() {
// Draw a triangle rotated in the direction of velocity
/* float theta = velocity.heading2D() + radians(90);
fill(200,100);
stroke(255);
pushMatrix();
translate(location.x,location.y);
rotate(theta);
beginShape(TRIANGLES);
vertex(0, -r*2);
vertex(-r, r*2);
vertex(r, r*2);
endShape();
popMatrix();*/
}
// Wraparound
void borders() {
if (location.x < -r) location.x = width+r;
if (location.y < -r) location.y = height+r;
if (location.x > width+r) location.x = -r;
if (location.y > height+r) location.y = -r;
}
// Separation
// Method checks for nearby boids and steers away
PVector separate (ArrayList<Boid> boids) {
float desiredseparation = 25.0f;
PVector steer = new PVector(0,0,0);
int count = 0;
// For every boid in the system, check if it's too close
for (Boid other : boids) {
float d = PVector.dist(location,other.location);
// If the distance is greater than 0 and less than an arbitrary amount (0 when you are yourself)
if ((d > 0) && (d < desiredseparation)) {
// Calculate vector pointing away from neighbor
PVector diff = PVector.sub(location,other.location);
diff.normalize();
diff.div(d); // Weight by distance
steer.add(diff);
count++; // Keep track of how many
}
}
// Average -- divide by how many
if (count > 0) {
steer.div((float)count);
}
// As long as the vector is greater than 0
if (steer.mag() > 0) {
// Implement Reynolds: Steering = Desired - Velocity
steer.normalize();
steer.mult(maxspeed);
steer.sub(velocity);
steer.limit(maxforce);
}
return steer;
}
// Alignment
// For every nearby boid in the system, calculate the average velocity
PVector align (ArrayList<Boid> boids) {
float neighbordist = 50;
PVector sum = new PVector(0,0);
int count = 0;
for (Boid other : boids) {
float d = PVector.dist(location,other.location);
if ((d > 0) && (d < neighbordist)) {
sum.add(other.velocity);
count++;
}
}
if (count > 0) {
sum.div((float)count);
sum.normalize();
sum.mult(maxspeed);
PVector steer = PVector.sub(sum,velocity);
steer.limit(maxforce);
return steer;
} else {
return new PVector(0,0);
}
}
// Cohesion
// For the average location (i.e. center) of all nearby boids, calculate steering vector towards that location
PVector cohesion (ArrayList<Boid> boids) {
float neighbordist = 50;
PVector sum = new PVector(0,0); // Start with empty vector to accumulate all locations
int count = 0;
for (Boid other : boids) {
float d = PVector.dist(location,other.location);
if ((d > 0) && (d < neighbordist)) {
sum.add(other.location); // Add location
count++;
}
}
if (count > 0) {
sum.div(count);
return seek(sum); // Steer towards the location
} else {
return new PVector(0,0);
}
}
}
// The Flock (a list of Boid objects)
class Flock {
ArrayList<Boid> boids; // An ArrayList for all the boids
Flock() {
boids = new ArrayList<Boid>(); // Initialize the ArrayList
}
void run() {
for (Boid b : boids) {
b.run(boids); // Passing the entire list of boids to each boid individually
}
}
void addBoid(Boid b) {
boids.add(b);
}
}
This will not work on the browser.
This sketch will only work on newer versions of Processing (2.0+), or in Windows and Macs.
Only a little tweak for this sketch:
http://www.openprocessing.org/sketch/67038
Sandro Miccoli