# Flow field generator in P5js

This is a further exploration of Daniel Shiffman visualization of a flow field. Using perlin noise and vector math in P5js.

```var scl = 20; var cols; var rows;```
```function setup() { createCanvas(windowWidth,windowHeight); cols = floor(width/scl); rows = floor(height/scl); }```

```function draw() { background(255); stroke(255); noFill(); beginShape(); for(var y=0; y<rows;y++){ xoff =0; for(var x=0; x<cols;x++){ var index = (x+y*width); stroke(0); push(); translate(x*scl,y*scl); pop(); rect(x*scl, y*scl,scl,scl); } } }```

We’ll create a couple of increment variables”xoff” and “yoff”. These will increment with a low coefficient on each loop so we can create a two dimensional perlin noise variable called “angle”. We’ll create a vector with that angle using the p5.Vector.fromAngle() function, and draw lines instead of the grid at their corresponding x and y.

```var inc = 0.1; var scl = 20; var cols; var rows; var yoff; var xoff;```
```function setup() { createCanvas(windowWidth,windowHeight); cols = floor(width/scl); rows = floor(height/scl); }```
```function draw() { background(255); stroke(255); noFill(); beginShape(); yoff =0; for(var y=0; y<rows;y++){ xoff =0; for(var x=0; x<cols;x++){ var index = (x+y*width); var angle = noise(xoff,yoff)* TWO_PI; var v = p5.Vector.fromAngle(angle); stroke(0); push(); translate(x*scl,y*scl); rotate(angle); line(0,0,scl,0); pop(); } } }```

We’ll increment the xoff +=inc; and yoff +=inc;

Let’s add a z dimension into the perlin noise angle variable and also store all

```var inc = 0.1; var scl = 20; var cols; var rows; var zoff = 0;```
```function setup() { createCanvas(windowWidth,windowHeight); cols = floor(width/scl); rows = floor(height/scl); }```
```function draw() { background(255); beginShape(); var yoff =0; for(var y=0; y<rows;y++){ xoff =0; for(var x=0; x<cols;x++){ var index = x+y*cols; var angle = noise(xoff,yoff,zoff)* TWO_PI; var v = p5.Vector.fromAngle(angle); stroke(0); push(); translate(x*scl,y*scl); rotate(angle); strokeWeight(1); line(0,0,scl,0); pop(); xoff +=inc; zoff +=0.00001; } yoff +=inc; } ```

We’ll add a particles object and we’ll try to make sure the angle force gets applied to them. It will look as if the particles are following the nearest vector path.

```var inc = 0.1; var scl = 20; var cols; var rows; var zoff = 0; var particles = []; var flowField; ```
```function setup() { createCanvas(600,600); cols = floor(width/scl); rows = floor(height/scl); flowField = new Array(cols*rows);//store all of the coordinates of the flowfield for(var i=0; i<100;i++){ particles[i] = new Particle();//start object } } ```
```function draw() { background(255); beginShape(); var yoff =0; for(var y=0; y<rows;y++){ xoff =0; for(var x=0; x<cols;x++){ var index = x+y*cols;//position of each field var angle = noise(xoff,yoff,zoff)* TWO_PI; var v = p5.Vector.fromAngle(angle); v.setMag(0.1);//normalize this vector flowField[index] = v;//store all of the vectors calculated into flowField stroke(0); push(); translate(x*scl,y*scl); rotate(angle); strokeWeight(1); line(0,0,scl,0); pop(); xoff +=inc; zoff +=0.00001; } yoff +=inc; } //addParticles(); for(var i=0; i<particles.length;i++){ particles[i].follow(flowField) particles[i].show(); particles[i].update(); particles[i].edges(); } } ```
``` //PARTICLES OBJECT CONSTRUCTOR function Particle(){ this.pos = createVector(random(width),random(height)); this.vel= createVector(0,0); this.acc= createVector(0,0); this.update = function(){ this.vel.add(this.acc); this.pos.add(this.vel); this.acc.mult(0);//Reset acceleration } this.applyForce = function(force){ this.acc.add(force); } this.show = function(){ strokeWeight(4); stroke(2); point(this.pos.x,this.pos.y);//let's make some points } this.edges = function(){ if(this.pos.x>width)this.pos.x = 0; if(this.pos.x<0)this.pos.x = width; if(this.pos.y<0)this.pos.y = height; if(this.pos.y>height)this.pos.y = 0; }//keep the particles inside the canvas this.follow = function(vectors){ var x = floor(this.pos.x/scl);//position in relationship to scale "vectr unit or grid" var y = floor(this.pos.y/scl); var index = x+y * cols; var force = vectors[index]; this.applyForce(force); } } ```

We’ll fix the speed of the particles with a var called maxspeed, and add a function that follows the path of the flow field vectors. We’ll draw some lines to follow this path.

```var inc = 0.1; var scl = 20; var cols; var rows; var zoff = 0; var particleObejct = 7000; var particles = []; var flowField; function setup() { background(255); createCanvas(windowWidth,windowHeight); cols = floor(width/scl); rows = floor(height/scl); flowField = new Array(cols*rows); for(var i=0; i<particleObejct;i++){ particles[i] = new Particle(); } } function draw() { beginShape(); var yoff =0; for(var y=0; y<rows;y++){ xoff =0; for(var x=0; x<cols;x++){ var index = x+y*cols; var angle = noise(xoff,yoff,zoff)* TWO_PI; var v = p5.Vector.fromAngle(angle); v.setMag(1); flowField[index] = v;//store all of the vectors calculated into flow field //push(); //translate(x*scl,y*scl) //rotate(angle); //strokeWeight(1); //stroke(0,5); //line(0,0,scl,0); //pop(); xoff +=inc; } yoff +=inc; } for(var i=0; i<particles.length;i++){ particles[i].follow(flowField); particles[i].edges(); particles[i].show(); particles[i].update(); } } function Particle(){ this.pos = createVector(random(width),random(height)); this.vel= createVector(0,0); this.acc= createVector(0,0); this.maxspeed = 10; this.prePos = this.pos.copy(); this.update = function(){ this.vel.add(this.acc); this.vel.limit(this.maxspeed); this.pos.add(this.vel); this.acc.mult(0); } this.applyForce = function(force){ this.acc.add(force); } this.show = function(){ stroke(0,20); strokeWeight(1); line(this.pos.x,this.pos.y,this.prePos.x,this.prePos.y); this.updatePrev(); } this.updatePrev = function(){ this.prePos.x = this.pos.x; this.prePos.y = this.pos.y; } this.edges = function(){ if(this.pos.x>width){ this.pos.x = 0; this.updatePrev(); } if(this.pos.x<0){ this.pos.x = width; this.updatePrev(); } if(this.pos.y<0){ this.pos.y = height; this.updatePrev(); } if(this.pos.y>height){ this.pos.y = 0; this.updatePrev(); } } this.follow = function(vectors){ var x = floor(this.pos.x/scl);//position in relationship to scale "vector" unit or grid" var y = floor(this.pos.y/scl); var index = x+y * cols; var force = vectors[index]; this.applyForce(force); } } ```