Cyrill
Cyrill

Reputation: 833

Using the noise function in Processing

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

Answers (1)

anthony yaghi
anthony yaghi

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

Related Questions