Flow Field Visualization with normal colors
//Magnus Pfleghar
class FlowField {
  float dragX=0.0;
  float dragY=0.0;
  PVector[][] grid;
  int res;
  int cols, rows;

  FlowField(int resolution) {
    res=resolution;
    cols = (int)width/res;
    rows = (int)height/res;
    grid = new PVector[cols][rows];
    println(res+" "+cols+" "+rows);
    init();
  }
  void init() {
    noiseSeed((int)random(10000));
    float xoff = 0;
    for (int i = 0; i < cols; i++) {
      float yoff = 0;
      for (int j = 0; j < rows; j++) {
        float theta = map(noise(xoff, yoff), 0, 1, 0, TWO_PI);
        grid[i][j] = new PVector(cos(theta), sin(theta), cos(theta));
        println(this.grid[i][j].x+" "+this.grid[i][j].y);
        println("CosTheta"+cos(theta));
        yoff += 0.1;
      }
      xoff += 0.1;
    }
  }
  void flowFieldAnim() {
    float xoff=0;
    for (int i=0; i<cols; i++) {
      float yoff=0;
      for (int a=0; a<rows; a++) {
        float theta=map(noise(xoff+dragX, yoff+dragY), 0, 1, 0, TWO_PI);
        grid[i][a]=  new PVector(cos(theta), sin(theta), cos(theta));
        println("CosTheta"+cos(theta));
        yoff+=0.1;
      }
      xoff+=0.1;
    }
    dragX+=0.005;
    dragY+=0.005;
  }
  void vis() {
    for (int i=0; i<cols; i++) {
      for (int a=0; a<rows; a++) {
        show(grid[i][a], i*res, a*res-2);
      }
    }
  }
  void show(PVector v, float x, float y) {
    pushMatrix();
    translate(x+(width/cols)/2, y+(height/rows)/2);
    fill(normalComp(v));
    if (!dispToggle) {noStroke();}
    rect(-(width/cols)/2, -(height/rows)/2, width/cols, height/rows);
    
    if (dispToggle) {
      rotate(v.heading2D());
      float len = v.mag()*20;
      strokeWeight(3);
      stroke(255);
      line(0, 0, len, 0);
      fill(0, 0, 120, 255);
      noFill();
      //println(this.grid[i][a].x+" "+this.grid[i][a].y);
      point(0, 0);
    }
    popMatrix();
  }

  color normalComp(PVector dir) {
    //https://en.wikipedia.org/wiki/Normal_mapping
    /*  X: -1 to +1 :  Red:     0 to 255
     Y: -1 to +1 :  Green:   0 to 255
     Z:  0 to -1 :  Blue:  128 to 255
     */
    dir.normalize();
    //float angle=degrees(dir.heading());
    float z = sqrt(1 - dir.x*dir.x + dir.y*dir.y);
    println("Z"+z);
    float r=map(dir.x, -1, 1, 0, 255);
    float g=map(dir.y, -1, 1, 255, 0);
    float b=map(dir.z, 0, 1, 128, 255);
    b=128;
    color c = color(r, g, b);
    return c;
  }
}
//Magnus Pfleghar
FlowField flowField;
boolean dispToggle=false;
boolean moveToggle=false;
void setup() {
  size(2000, 2000);
  frameRate(60);
  flowField=new FlowField(50);
}
void draw() {
  background(0);
  flowField.vis();
  if (moveToggle) {
    flowField.flowFieldAnim();
  }
} 
void keyPressed() {
  dispToggle=!dispToggle;
}
void mousePressed() {
  moveToggle=!moveToggle;
}