Reputation: 833
I am trying to animate a flying cloth, which consists of individual rectangles, in Processing. I built the cloth from a nested loop. Now I want to use the noise function to manipulate the height of the individual points. Unfortunately, I can't do that properly - apparently I don't understand the function. I took a detour, drew noise clouds on a PGraphics, then read the brightness value - and use that to control the z-position of each rectangle. This works the way I want it to work!
Only - how can I achieve the same effect without going the detour via PGraphics? This is my code the way I want it (the detour):
PGraphics pg;
float increment = 0.002;
float xoff;
float yoff;
float zoff = 0.0;
float zincrement = 0.1;
float size;
float pixel = 200;
void setup() {
size(1920, 1080, P3D);
frameRate(30);
size = width/pixel;
rectMode(CENTER);
pg = createGraphics(width, width);
}
void draw() {
//PGraphics
pg.beginDraw();
pg.loadPixels();
xoff = 0.0;
for (int x = 0; x < width; x++) {
xoff += increment;
yoff = 0.0;
for (int y = 0; y < width; y++) {
yoff += increment;
float bright = noise(xoff, yoff, zoff)*255;
pg.pixels[x+y*width] = color(bright, bright, bright);
}
}
pg.updatePixels();
pg.endDraw();
zoff += zincrement;
//SCENE
background(0);
stroke(255,0,0);
line(width/2, 0, width/2, height);
translate(0, 0, mouseX);
pushMatrix();
rotateX(radians(45));
translate(pixel*size/2, -pixel*size, -pixel*size);
rotateZ(radians(mouseX));
translate(-pixel*size/2, -pixel*size/2, -pixel*size/4);
pushMatrix();
for (int y = 0; y < pixel; y++) {
for (int x = 0; x < pixel; x++) {
color c = pg.get(int(size*x), int(size*y));
float zpoint = map(brightness(c), 0, 255, -500, 500);
pushMatrix();
noiseDetail(3, 0.5f);
translate(x*size, y*size, zpoint);
rotate(radians(45));
noStroke();
fill(255);
rect(0, 0, size, size);
popMatrix();
}
}
popMatrix();
popMatrix();
}
And this is how I would like to write it in a simpler way:
float size;
float pixel = 200;
float xoff;
float yoff;
float zoff;
float increment = 0.01;
void setup() {
size(1920, 1080, P3D);
frameRate(30);
size = width/pixel;
rectMode(CENTER);
}
void draw() {
background(0);
stroke(255,0,0);
line(width/2, 0, width/2, height);
translate(0,0,mouseX);
pushMatrix();
rotateX(radians(45));
translate(pixel*size/2,-pixel*size,-pixel*size);
rotateZ(radians(mouseX));
translate(-pixel*size/2,-pixel*size/2,-pixel*size/4);
pushMatrix();
for (int y = 0; y < pixel; y++) {
for (int x = 0; x < pixel; x++) {
pushMatrix();
noiseDetail(1, 0.25f);
float n = noise(x*size + xoff, y*size + yoff, zoff)*255;
translate(x*size, y*size, n);
rotate(radians(45));
noStroke();
fill(255);
rect(0, 0, size, size);
popMatrix();
}
}
popMatrix();
popMatrix();
yoff += 0.11;
xoff += 0.02;
zoff += 0.03;
}
I think this line is the problem - because currently it doesn't create a real cloth like this.
float n = noise(x*size + xoff, y*size + yoff, zoff)*255;
Upvotes: 1
Views: 251
Reputation: 550
You are correct, the problem is in this line
float n = noise(x*size + xoff, y*size + yoff, zoff)*255;
The changes in the x and y input parameters from one iteration to the other is too large (it is equal to size). If you read about the Perlin noise you will know that with a large step it will just look like random noise. My suggestion to edit this line to something like:
float n = noise(xx + xoff, yy + yoff, zoff)*255;
where xx and yy are other variables that you increment slowly in the for loop
My solution:
void draw() {
background(0);
stroke(255,0,0);
line(width/2, 0, width/2, height);
translate(0,0,mouseX);
pushMatrix();
rotateX(radians(45));
translate(pixel*size/2,-pixel*size,-pixel*size);
rotateZ(radians(mouseX));
translate(-pixel*size/2,-pixel*size/2,-pixel*size/4);
pushMatrix();
float xx = 0;
float yy = 0;
for (int y = 0; y < pixel; y++) {
xx = 0;
for (int x = 0; x < pixel; x++) {
pushMatrix();
noiseDetail(1, 0.25f);
float n = noise(xx + xoff, yy + yoff)*255;
translate(x*size, y*size, n);
rotate(radians(45));
noStroke();
fill(255);
rect(0, 0, size, size);
popMatrix();
xx += 0.1;
}
yy += 0.1;
}
popMatrix();
popMatrix();
yoff += 0.11;
xoff += 0.02;
zoff += 0.03;
}
Changing the increment of xx and yy can make the flag look like its flowing in 1 direction...
Upvotes: 2