Trying to create wave / cloth flow pattern

Hello good people!

I found this picture in the internet few weeks ago:


and I have been trying to replicate this in p5.js but haven’t found the solution yet.

This is my code:

var woll = [];

function setup() {
  createCanvas(1000, 1000);
  colorMode(RGB);
  background(236, 236, 236);
  stroke(20, 20, 20);

  strokeWeight(1);
  noFill();
  for (var i = 0; i < 400; i++) {
    var x = 1 + (i / 2) / 5;
    woll[i] = new Woll(x, 0);
  }
}


function draw() {
  for (var i = 0; i < woll.length; i++) {
    woll[i].move();
  }
}

function Woll(templocX, templocY) {
  this.locX = templocX;
  this.locY = templocY;
  this.jitterMax = 30;
  this.jitter = 0;

  this.move = function() {
    translate(this.locX, this.locY);
    beginShape();
    for (var i = 0; i < 1000; i += 9) {
      this.jitter = map(i, 0, 1000, 0, this.jitterMax);
      this.y = i;
      this.a = i
      this.x = noise(this.jitter) * 100;
      curveVertex(this.x, this.y);

    }

    endShape();
    noLoop();
  }
}

See the live version in editor.p5js.org
https://editor.p5js.org/istiko@gmail.com/sketches/Mx7m38sl7

My solutions was to create noise line and then replicate that line with translate. I don’t know maybe the solution is wrong. Any help would appreciated :slight_smile:
Thanks!

1 Like

Would you not need to offset the lines with more noise?

might want to take a look at this, it could help.

2 Likes

I don’t want to offset the lines. But what I want is that each individual lines is going to top each other while maintain the angle

This could work, thanks for the suggestion :slight_smile:

I think although we only see straight lines there is in fact a grid of connections

So the parallel visible threads that you see are connected by invisible short threads

Those work like springs so they lift up the parallel thread

See height field or look at springs in the example section on the website

2 Likes

Take a look at this:

3 Likes

Hi @noob,

From what I see it looks like:

  • the waves are accentuated around the center
  • those waves follow a diagonal pattern

For the first point maybe try to increase then decrease the noise value based on the x coordinates.
For example if your width is 600 , increase the noise value from 0 to 300 and then decrease it from 300 to 600.

For the second point, I would suggest to mix the x and y coordinates (adding or summing them) when computing the 2D noise value.

Example sketch in Processing Python mode (needs a lot of improvements and fine tuning) :

def setup():
    size(600, 800, P2D)
    background("#F3F3F5")
    strokeWeight(2)
    smooth(8)
    
    points = []
    
    edge = 10
    step = 10
    res = (height - (edge*2)) / step
    nLines = ((width*2) - (edge*4)) / step
    
    factor = .001
    off = 0
    x2 = 0
    
    for i, x in enumerate(xrange(edge, (width*2) - edge, step)):
        
        if x > width:
            x2 -= step
            off += step
        else:
            x2 = x

        for y in xrange(edge, height - edge, step):
            n = noise(x2 * factor * 1.5, (x+y) * factor) 
            if i > 10 and i < nLines - 10:
                points.append(PVector(off + x2 * n, y ))
            
    
    for i in xrange(len(points)-1):
        if i%res != (res-1):
            line(points[i].x, points[i].y, points[i+1].x, points[i+1].y)

Edit: a simple P5.js sketch to get you started https://editor.p5js.org/solub/sketches/Q1GN0BL8C

3 Likes

Thank you so much @solub ! Your sketch is amazing. I am studying your code for a week now. Something that I am still doesn’t understand is this line of code if (id % res != (res - 1)) { would you mind to explain to me what is that mean by this?

Thanks

1 Like

Sure, res stands for ‘resolution’, it is the number of points contained in a single line.

You need to remember that these points are stored as vectors in a 1 dimensional array list:

points = [vector(10, 10), vector(10, 20), vector(10, 30), vector(10, 40), ...]

If you want to draw a line you need to connect the first vector to the second, the second to the third, the third to the fourth, and so on until you reach the end of the array.
However, if you do so, the last point of the first line will be connected to the first point of the second line, and this for each line.

In order to prevent this you need to stop the connexion mecanism at the end of each line. That’s what that line of code does:

if (id % res != (res - 1))
“as long as the current point is not the last point of a line” …(connect it to the next point)

Check the reference page of mudolo if that’s still obscure to you.

Here below a visual exaplanation with res = 5

Hope that helps

4 Likes

Ohhh… THANK YOU! Great explanation and crystal clear for me @solub :clap: :clap:
This new logic using res is very clever. I am sure I can use it to tweak another problem.