double Interpolate(double x, double y, double a)
{
double val = (1 - cos((float)a * PI)) * .5;
return x * (1 - val) + y * val;
}
double Noise(int x, int y)
{
int n = x + y * 57;
n = (n<<13) ^ n;
return ( 1.0 - ( (int)(n * (n * n * r1 + r2) + r3) & 0x7fffffff) / 1073741824.0);
}
double Smooth(double x, double y)
{
double n1 = Noise((int)x, (int)y);
double n2 = Noise((int)x + 1, (int)y);
double n3 = Noise((int)x, (int)y + 1);
double n4 = Noise((int)x + 1, (int)y + 1);
double i1 = Interpolate(n1, n2, x - (int)x);
double i2 = Interpolate(n3, n4, x - (int)x);
return Interpolate(i1, i2, y - (int)y);
}
float PerlinNoise2d(int x, int y)
{
double total = 0.0;
double cloud_frequency = global_cloud_frequency; // USER ADJUSTABLE
double cloud_persistence = global_cloud_persistence; // USER ADJUSTABLE
double cloud_octaves = global_cloud_octaves; // USER ADJUSTABLE
double cloud_amplitude = global_cloud_amplitude; // USER ADJUSTABLE
double cloud_coverage = global_cloud_coverage; // USER ADJUSTABLE
double cloud_density = global_cloud_density; // USER ADJUSTABLE
//println(global_cloud_frequency + "/" + cloud_frequency);
for(int lcv = 0; lcv < cloud_octaves; lcv++)
{
total = total + Smooth(x * cloud_frequency, y * cloud_frequency) * cloud_amplitude;
cloud_frequency = cloud_frequency * 2;
cloud_amplitude = cloud_amplitude * cloud_persistence;
}
total = (total + cloud_coverage) * cloud_density;
if(total < 0) total = 0.0;
if(total > 1) total = 1.0;
return (float)total;
}
class Attractor
{
float pnoise;
float strength;
Attractor(float pnoise, float strength)
{
this.pnoise = pnoise;
this.strength = strength * 100;
}
PVector getForce()
{
float theta = map(pnoise, minf, maxf, 0,TWO_PI) + global_offset_theta;
return new PVector(strength * cos(theta), strength * sin(theta));
}
}
class WorldField
{
ArrayList things;
WorldField()
{
things = new ArrayList();
}
public void addThings(int num)
{
for (int i = 0; i < num ; i++)
{
things.add(new Thingy(new PVector(random(0,width),random(0,height))));
}
}
public void addThing(Thingy th)
{
things.add(th);
}
public void update(Attractor[][] hiddenfield)
{
for (int i = 0; i < things.size() ; i++)
{
Thingy t = (Thingy)things.get(i);
if (t.dead)
{
t.loc = new PVector(random(width),random(height),random(0,1) * -2);
t.live();
}
else
{
int xx = constrain( int(t.loc.x) , 0 , width )/ spacing;
int yy = constrain ( int(t.loc.y) , 0 , height )/ spacing;
if (fieldUpdated[xx][yy] == false)
{
float f = PerlinNoise2d(int(xx + global_offset_x),int(yy + global_offset_y));
flowField[xx][yy] = new Attractor(f, 5);
fieldUpdated[xx][yy] = true;
}
PVector force_field = hiddenfield[ xx ][ yy ].getForce();
force_field.z = 0.2;
//println(force.x + "," + force.y + "," + force.z);
t.applyForce(force_field.get());
t.update();
}
}
}
public void display()
{
for (int i = 0; i < things.size() ; i++)
{
Thingy t = (Thingy)things.get(i);
t.display();
}
}
}
Attractor [][]flowField;
boolean [][]fieldUpdated;
WorldField world;
color colorSmoke;
float global_cloud_frequency; // USER ADJUSTABLE
float global_cloud_persistence; // USER ADJUSTABLE
float global_cloud_octaves; // USER ADJUSTABLE
float global_cloud_amplitude; // USER ADJUSTABLE
float global_cloud_coverage; // USER ADJUSTABLE
float global_cloud_density; // USER ADJUSTABLE
double r1 = 1000 + random(9000);
double r2 = 100000 + random(900000);
double r3 = 1000000000 + random(1000000000);
int spacing = 15;
int refreshFrameCount = 300;
float global_offset_x;
float global_offset_y;
float global_offset_theta;
float minf = 20;
float maxf = 0;
void resetFlowField()
{
global_cloud_frequency = 0.08; // USER ADJUSTABLE
global_cloud_persistence = 0.2; // USER ADJUSTABLE
global_cloud_octaves = 12; // USER ADJUSTABLE
global_cloud_amplitude = 0.00001; // USER ADJUSTABLE
global_cloud_coverage = 0.09; // USER ADJUSTABLE
global_cloud_density = 0.01; // USER ADJUSTABLE
global_offset_x = random(1000,10000);
global_offset_y = random(1000,10000);
global_offset_theta = random(0,PI / 2);
flowField = new Attractor[width][height];
fieldUpdated = new boolean[width][height];
minf = 20;
maxf = 0;
for (int i = 0; i < height ; i++)
{
for (int j = 0; j < width ; j++)
{
float q = 1;//random(10000);
float f = PerlinNoise2d(int(j * q + global_offset_x),int(i * q + global_offset_y));
if (f > maxf)
{
maxf = f;
}
if (f < minf)
{
minf = f;
}
//print(f + ",");
flowField[j][i] = new Attractor(f, 10);
fieldUpdated[j][i] = true;
}
}
println(minf + ", " + maxf);
resetColor();
}
void setup() {
size(800,450);
smooth();
resetBg();
resetColor();
world = new WorldField();
resetFlowField();
for (int i = 0; i < height/spacing ; i++)
{
for (int j = 0; j < width/spacing ; j++)
{
Thingy t = new Thingy(new PVector(j * spacing + spacing/2, i * spacing + spacing/2,random(0,1) * -1));
world.addThing(t);
}
}
}
void draw() {
//background(255,1);
world.update(flowField);
world.display();
if (frameCount >= refreshFrameCount && (frameCount % refreshFrameCount == 0))
{
resetField();
}
}
void resetField()
{
for (int i = 0; i < width ; i++)
{
for (int j = 0; j < height ; j++)
{
fieldUpdated[i][j] = false;
}
}
global_offset_x = random(1000,10000);
global_offset_y = random(1000,10000);
global_offset_theta = random(0,PI / 2);
println("field updated");
}
void resetColor()
{
colorMode(HSB,360,100,100,100);
colorSmoke = color(random(360),random(70,100),random(70,100));
colorMode(RGB,255,255,255,100);
}
void resetBg()
{
colorMode(HSB,360,100,100,100);
background(random(360),random(100),random(0,15));
colorMode(RGB,255,255,255,100);
}
void keyPressed()
{
if (key == ' ')
{
resetBg();
resetField();
}
if (key == 'c')
{
resetColor();
}
if (key == 'p')
{
saveFrame("########.tif");
}
}
class Thingy
{
private PVector last_loc;
public PVector loc;
public PVector acc;
public PVector vel;
public float mass;
public boolean dead = false;
float grayscale = 0;
float age = 0;
Thingy()
{
this.acc = new PVector(0,0);
this.vel = new PVector(0,0);
this.loc = new PVector(0,0);
this.last_loc = new PVector(0,0);
this.mass = 0;
}
Thingy(PVector initial_loc)
{
this.acc = new PVector(0,0);
float theta = random(0,TWO_PI);
this.vel = new PVector(random(1,3) * cos(theta),random(1,3) * sin(theta));
this.loc = initial_loc.get();
this.last_loc = initial_loc.get();
this.mass = random(0,1) * 1000 + 700;
//println("mass:" + this.mass);
this.grayscale = 255;//map(random(1,5),1,5,0,255);
}
public void die()
{
dead = true;
}
public void live()
{
this.last_loc = this.loc.get();
dead = false;
age = 0;
}
void applyForce(PVector force)
{
force.div(this.mass);
this.acc.add(force);
}
void update()
{
if (this.loc.x > width || this.loc.x < 0 || this.loc.y > height || this.loc.y < 0)
{
die();
}
else
{
this.last_loc = this.loc.get();
this.vel.add(this.acc);
this.loc.add(this.vel);
this.vel.mult(0.95);
this.age++;
}
}
void display()
{
if (!dead)
{
strokeWeight(0.15f);
//stroke(71,121,172,10);
stroke(colorSmoke,10);
noFill();
line(this.loc.x,this.loc.y,this.last_loc.x,this.last_loc.y);
this.acc.mult(0);
}
}
}
midterm experiment for class of nature of code.
use 'c' to switch color. space to start over.