xxxxxxxxxx
/* OpenProcessing Tweak of *@*http://www.openprocessing.org/sketch/64754*@* */
/* !do not delete the line above, required for linking your tweak if you upload again */
// Pierre MARZIN
// Trying to learn Processing... First project, much inspired by "Mycelium" by Scloopy?
// http://marzinp.free.fr/applets
//GUI and Drag 'n drop: great libraries ! Thanks to Andreas Schlegel (http://www.sojamo.de/libraries/index.html)
//GUI variables
//SDrop drop;
public String mUrl;
/* @pjs preload="tiger.jpg"; */
PImage source; // Source image
//for each "worm", variables: position
//aimed direction
PVector vise=new PVector();
int locPixel;
ArrayList <Seeker> seekersArray;
float seekX,seekY;
//worm's length
int maxLength;
int maxLayers;
//like pixels[], to keep track of how many times a point is reached by a worm
int [] buffer;
int [] limiteDown;
//number of worms at the beginning
int nbePoints;
public float inertia;
//width and length of the drawing area
int larg;
int haut;
int largI;
int hautI;
//brightness of the destination pixel
float briMax;
//minimum brightness threshold
public int seuilBrillanceMini;
//maximum brightness threshold
public int seuilBrillanceMaxi;
//location of the tested point in pixels[]
int locTest;
int locTaX;
int locTaY;
int brightnessTemp;
//around a point (worms position), how many pixels will we look at...
int amplitudeTest;
//constrain the acceleration vector into a devMax radius circle
float devMax;
//constrain the speed vector into a vMax radius circle
float vMax;
//not used:random factor
int hasard;
//stroke's weight (slider) or radius of ellipse used for drawing
public float myweight;
//draw or not (button onOffButton)
public boolean dessine=true;
//different drawing options
public int modeCouleur;
//fill color
int macouleur;
boolean limite;
//setup only sets up what won't change:GUI and window params
//I use initialiser() to set up what has to be initialised
//when you hit "ResetButton" and dessin() to set the drawing parameters
void setup() {
larg=largI=800;
haut=hautI=600;
size(800,600);
//sound useSound=false;
limite=false;
//sound minim = new Minim(this);
//drop = new SDrop(this);
// f = loadFont("ArialUnicodeMS-12.vlw");
source = loadImage("tiger.jpg");
if(hautI*source.width>largI*source.height){
larg=largI;
haut=larg*source.height/source.width;
}else{
haut=hautI;
larg=haut*source.width/source.height;
}
source.resize(larg,haut);
source.loadPixels();
fill(0);
initialiser();
}
//launched after setup and any time you hit the ResetButton button
public void initialiser() {
dessine=true;
nbePoints=6;
fill( 255 );
stroke( 255 );
rect( 0, 0, larg,haut );
buffer=new int[haut*larg];
smooth();
inertia=6;
maxLayers=10;
myweight=.2;
seuilBrillanceMaxi=200;
seuilBrillanceMini=0;
amplitudeTest=1;
maxLength=300;
limite=true;
hasard=0;
devMax=4;
vMax=50;
modeCouleur=1;
strokeJoin(ROUND);
seekersArray=new ArrayList <Seeker>();
for(int i=0;i<nbePoints;i++) {
Seeker mSeeker=new Seeker(new PVector(random(larg),random(haut)),new PVector(random(-3,3),random(-3,3)),inertia);
while((brightness(mSeeker.getImgPixel())>seuilBrillanceMaxi)||(brightness(mSeeker.getImgPixel())<seuilBrillanceMini))
{
mSeeker.setP(int(random(larg)),int(random(haut)));
}
seekersArray.add(mSeeker);
}
}
void draw() {
if (dessine){
for (int i = 0; i < nbePoints; i++) {
Seeker mSeeker = seekersArray.get(i);
dessin(mSeeker);
if (mSeeker.isDeplace()) {
mSeeker.setDeplace(false);
}
}
}
}
void dessin(Seeker mySeeker) {
// for each "seeker" (worm's head)
// //on va tester les pixels autour du mobile p[t] en direction de la
// vitesse du mobile
// //calcul du barycentre des points testes ponderes de la brillance
// (vise.x, vise.y)
// //for each seeker, we gonna test pixels around the seeker's position
// and calculate their barycenter, loaded by pixels values (0/255
// dark/light);
// barycenter's coordinates
//myweight=window.inertia;
vise.x = 0;
vise.y = 0;
// avoid looking for mySeeker.p.x for every pixels
seekX = mySeeker.getP().x;
seekY = mySeeker.getP().y;
int pixelsPosition = floor(seekX) + floor(seekY) * larg;
int locTestX = floor(seekX);
int locTestY = floor(seekY);
// barycenter calculation
for (int i = -amplitudeTest; i < amplitudeTest + 1; i++) {// /rdessin
for (int j = -amplitudeTest; j < amplitudeTest + 1; j++) {
locTaX = locTestX + i;
locTaY = locTestY + j;
// does the point belongs to the source image?
if ((locTaX > 0) && (locTaY > 0) && (locTaX < larg - 1) && (locTaY < haut - 1)) {
brightnessTemp = int(brightness(source.pixels[locTaX + larg * locTaY]));
vise.sub(new PVector(i * brightnessTemp, j * brightnessTemp));
}
}
}
// coeur du comportement de seeker:
// core of the behaviour of the seeker (http://www.shiffman.net/ see
// wanderer's code)
vise.normalize();
vise.mult(100f/mySeeker.inertia);
mySeeker.getV().add(new PVector(vise.x,vise.y));
PVector deviation = mySeeker.getV().get();
deviation.normalize();
deviation.mult(devMax);
mySeeker.getV().normalize();
mySeeker.getV().mult(vMax);
mySeeker.getP().add(deviation);
// ******************different cases that lead to move the seeker to
// another random place**************
// outside window
// on compte les segments de chaque ver
// worm's length is increased
mySeeker.setLongueur(mySeeker.getLongueur() + 1);
float positionBrightness=brightness(mySeeker.getImgPixel());
//println(positionBrightness+" "+mySeeker.getP().x+" "+mySeeker.getP().y);
//dessine=false;
// si c'est trop long on demenage
// seeker's moved if worm's too long
if (mySeeker.getLongueur() > maxLength) {
deplacePoint(mySeeker);
}
if ((mySeeker.getP().x < 1) || (mySeeker.getP().y < 1) || (mySeeker.getP().x > larg - 1) || (mySeeker.getP().y > haut - 1))// ||
{
mySeeker.setDeplace(true);
deplacePoint(mySeeker);
return;
}
// buffer est une copie vide de l'image. on l'augmente pour chaque point
// parcouru
// buffer is an empty copy of the source image. It's increased every
// time a point is reached.
buffer[pixelsPosition]++;
// si on est passe plus de n fois on demenage le point
// If a point is reached n times, seeker is moved
if (buffer[pixelsPosition] > maxLayers) {
deplacePoint(mySeeker);
}
// inside window, limite on and inside value range
if ((limite) && (positionBrightness <= seuilBrillanceMaxi) && (positionBrightness >= seuilBrillanceMini)) {
if (mySeeker.getLimiteDown() != 0) {
mySeeker.setLimiteDown(mySeeker.getLimiteDown() - 2);
}
}
// limite on and outside value range
if ((limite) && ((positionBrightness > seuilBrillanceMaxi) || (positionBrightness < seuilBrillanceMini))) {
if (mySeeker.getLimiteDown() == 0) {
mySeeker.setLimiteDown(2);
}
mySeeker.setLimiteDown(mySeeker.getLimiteDown() + 4);// print(mySeeker.limiteDown+" ");
if (mySeeker.getLimiteDown() >= 152 / myweight) {
mySeeker.setLimiteDown(0);
deplacePoint(mySeeker);
}
}
// null deviation
if ((deviation.x == 0) && (deviation.y == 0)) {
mySeeker.setLimiteDown(0);
deplacePoint(mySeeker);
}
else briMax = brightness(source.pixels[pixelsPosition]);
// go draw the seeker's shape
mySeeker.setDia((float) (myweight * (1 - cos((mySeeker.getLongueur()) * PI * 2 / (float) maxLength))));
mySeeker.setAlpha((max(0, (round(127 * mySeeker.getDia() / myweight) - (int) briMax / 2))));
stroke(0,mySeeker.getAlpha());
strokeWeight(mySeeker.getDia());
line(seekX,seekY,mySeeker.getP().x,mySeeker.getP().y);
//println("Size "+mySeeker.getDia());
// on cree un nouveau vers de temps en temps (on pourrait tester selon
// la brilance de la zone...)
// from times to times a new worm is created
if (random(1) > 1 - (255 - briMax) / (500 * seekersArray.size())) {
seekersArray.add(new Seeker(new PVector(seekX, seekY), new PVector(mySeeker.getV().x * random(-3,3), mySeeker.getV().x
* random(-3,3)), inertia));
nbePoints++;
// Log.d("DrawingView","Size "+seekersArray.size());
}
}
// *****************move the seeker function***************************
void deplacePoint(Seeker seeker) {
seeker.setLongueur(0);
seeker.setP(random(1, larg - 1), random(1, haut - 1));
while ((brightness(seeker.getImgPixel()) > seuilBrillanceMaxi)
|| (brightness(seeker.getImgPixel()) < seuilBrillanceMini)) {
seeker.setP(random(1, larg - 1), random(1, haut - 1));
}
seekX = seeker.getP().x;
seekY = seeker.getP().y;
}
public void setDevMax(float devMax) {
this.devMax = devMax;
}
public class Seeker {
// position
private PVector p = new PVector();
// speed
private PVector v = new PVector();
private int imgPixel;
private float inertia;
// worm's length
private float longueur;
// worm's limite
private int limiteDown;
private int couleur;
private int red = int(random(0, 100));
// stroke weight
private float dia;
private boolean deplace;
private int alpha;
private float greenfade = random(1);
private float bluefade = random(1);
private float redfade = random(1);
private float vegRatio = random(.75, 1);
// Constructor
public Seeker(PVector P, PVector V, float Inertia) {
p = P;
v = V;
limiteDown = 0;
longueur = 0;
setInertia(random(-2, 2) + Inertia);
setDeplace(false);
}
public int updateCouleur() {
float green = green(couleur);
float blue = blue(couleur);
// if (view.getStyle() == DrawingView.STYLE_VEGETAL) {
// if ((green > 150) || (green < 1))
// greenfade = -greenfade;
// green += greenfade;
// if ((blue > 50) || (blue < 1))
// bluefade = -bluefade;
// blue += bluefade;
// if ((red > 50) || (red < 1))
// redfade = -redfade;
// red += redfade;
// couleur = Color.argb(alpha, red, green, blue);
// } else if (view.getStyle() == DrawingView.STYLE_NORMAL) {
if ((green > 100) || (green < 1))
greenfade = -greenfade;
green += greenfade;
if ((blue > 100) || (blue < 1))
bluefade = -bluefade;
blue += bluefade;
couleur =color(alpha, red, green, blue);
// }
// else if (view.getStyle() == DrawingView.STYLE_NEGATIF) {
// couleur = Color.WHITE;
// }
return couleur;
}
public float getLongueur() {
return longueur;
}
public void setLongueur(float longueur) {
this.longueur = longueur;
}
public PVector getP() {
return p;
}
public void setP(PVector p) {
this.p = p;
}
public void setP(float a, float b) {
this.p.x = a;
this.p.y = b;
}
public PVector getV() {
return v;
}
public void setV(PVector v) {
this.v = v;
}
public void setV(float a, float b) {
this.v.x = a;
this.v.y = b;
}
public int getLimiteDown() {
return limiteDown;
}
public void setLimiteDown(int limiteDown) {
this.limiteDown = limiteDown;
}
public boolean isDeplace() {
return deplace;
}
public void setDeplace(boolean deplace) {
this.deplace = deplace;
}
public float getDia() {
return dia;
}
public void setDia(float dia) {
this.dia = dia;
}
public int getAlpha() {
return alpha;
}
public void setAlpha(int alpha) {
this.alpha = alpha;
}
public float getInertia() {
return inertia;
}
public void setInertia(float inertia) {
this.inertia = inertia;
}
public int getCouleur() {
return couleur;
}
public void setCouleur(int couleur) {
this.couleur = couleur;
}
public float getVegRatio() {
return vegRatio;
}
public void setVegRatio(float vegRatio) {
this.vegRatio = vegRatio;
}
public int getImgPixel(){
if(getP().x>0 && getP().x<larg &&getP().y>0 && getP().y<haut)
return source.pixels[floor(getP().x)+floor(getP().y)*larg];
else{
//println("Out of range");
return 0;
}
}
}