An example image of the image processing with Vector Field.]]


Express my nightmare with the Vector Field.

It was on the ceiling corner of my bedroom. It was eating something ignoring me. It had many arms or legs or tentacles and spikes or wiry hair. It looks horrible. And I should sit still, never move, and be silent not to be noticed by it. But I couldn't help screaming. That was my nightmare.
When I was playing with the Vector Field, I remembered that nightmare.

This is my creative coding artwork that invites you to my nightmare. It uses the Vector Field method. The noise calculation formula for Vector Field in this code is like this. You can make various types of nightmare by changing these formulas.


nx = noise(x', y', cos(PI * noise(y')));
ny = noise(y', x', cos(PI * noise(x')));


nested noise.


nx = noise(x', y', noise(y', x'));
ny = noise(y', x', noise(x', y'));


An example image of the image processing with Vector Field.]]


swirling.


nx = noise(cos(x'), sin(y'), cos(y'));
ny = noise(cos(y'), sin(x'), cos(x'));


An example image of the image processing with Vector Field.]]


direction limitting.


nx = floor(noise(x', y', noise(y', x')) * 6.0) / 6.0;
ny = floor(noise(y', x', noise(x', y')) * 6.0) / 6.0;


An example image of the image processing with Vector Field.]]


It's a near relation work of 'Picture This'.

 

An example code of the 'Processing'.







This code does not display any images on the screen but generates image files in frames directory.
Please feel free to use this example code under the terms of the GPL. To see other works based on my code is my pleasure. And my honor.


/**
 * Welcome to My Nightmare.
 * Express my nightmare with the Vector Field.
 * 
 * @author @deconbatch
 * @version 0.1
 * @license GPL Version 3 http://www.gnu.org/licenses/
 * Processing 3.5.3
 * 2020.12.08
 */

void setup() {
  size(980, 980);
  colorMode(HSB, 360, 100, 100, 100);
  rectMode(CENTER);
  smooth();
  noLoop();
}

void draw() {

  int   pathMax  = 2000;
  float curlMult = random(3.0, 9.0);       // curl ratio of the Vector Field path.
  float noiseDiv = random(0.0002, 0.0015); // noise parameter step ratio.
  float uneven   = random(5.0, 15.0);      // make uneven the Vector Field
  float baseHue  = random(360.0);
  
  background((baseHue + 60.0) % 360.0, 100.0, 30.0, 100.0);

  // background shape
  stroke(0.0, 0.0, 0.0, 100.0);
  strokeWeight(1.0);
  pushMatrix();
  translate(width * 0.5, height * 0.5);
  rotate(random(PI));
  for (int i = 0; i < 10; i++) {
    rotate(PI * 0.1);
    float iRatio = map(i, 0, 10, 1.0, 0.0);
    iRatio *= iRatio;
    fill((baseHue + 60.0) % 360.0, 100.0 * iRatio, 100.0 - 60.0 * iRatio, 100.0);
    rect(0.0, 0.0, width * iRatio * 1.5, height * iRatio * 1.5);
  }
  popMatrix();

  // outer
  int setMax = 10;
  for (int setCnt = 0; setCnt < setMax; setCnt++) {
    float setRatio = map(setCnt, 0, setMax, 0.0, 1.0);
    ArrayList<PVector> startPoints = getPoints(
                                               floor(map(setRatio, 0.0, 1.0, 1.0, 0.2) * pathMax),
                                               map(setRatio, 0.0, 1.0, 0.35, 0.16)
                                               );
    ArrayList<ArrayList<PVector>> paths = getPaths(startPoints, curlMult, noiseDiv, uneven);
    drawPaths(paths, setRatio, baseHue);
  }

  // middle
  baseHue += 120.0;
  setMax = 7;
  for (int setCnt = 0; setCnt < setMax; setCnt++) {
    float setRatio = map(setCnt, 0, setMax, 0.0, 1.0);
    ArrayList<PVector> startPoints = getPoints(
                                               floor(map(setRatio, 0.0, 1.0, 0.5, 0.1) * pathMax),
                                               map(setRatio, 0.0, 1.0, 0.16, 0.07)
                                               );
    ArrayList<ArrayList<PVector>> paths = getPaths(startPoints, curlMult, noiseDiv, uneven);
    drawPaths(paths, setRatio, baseHue);
  }

  // center
  baseHue += 120.0;
  setMax = 5;
  for (int setCnt = 0; setCnt < setMax; setCnt++) {
    float setRatio = map(setCnt, 0, setMax, 0.0, 1.0);
    ArrayList<PVector> startPoints = getPoints(
                                               floor(map(setRatio, 0.0, 1.0, 0.3, 0.1) * pathMax),
                                               map(setRatio, 0.0, 1.0, 0.07, 0.01)
                                               );
    ArrayList<ArrayList<PVector>> paths = getPaths(startPoints, curlMult, noiseDiv, uneven);
    drawPaths(paths, setRatio, baseHue);
  }

  casing();
  saveFrame("frames/0001.png");

  exit();

}

/**
 * casing : draw fancy casing
 */
private void casing() {
  blendMode(BLEND);
  fill(0.0, 0.0, 0.0, 0.0);
  strokeWeight(60.0);
  stroke(0.0, 0.0, 0.0, 100.0);
  rect(width * 0.5, height * 0.5, width, height);
  strokeWeight(50.0);
  stroke(0.0, 0.0, 100.0, 100.0);
  rect(width * 0.5, height * 0.5, width, height);
  noStroke();
  noFill();
}

/**
 * getPaths : calculate the Vector Field paths.
 * @param _pvs      : start points coordinate of the Vector Field.
 * @param _curlMult : curl ratio of the path.
 * @param _noiseDiv : noise parameter step ratio.
 * @param _uneven   : make uneven the Vector Field with 3rd parameter of the noise.
 * @return array of the Vector Field path, path is the array of the PVector coordinates.
 */
private ArrayList<ArrayList<PVector>> getPaths(ArrayList<PVector> _pvs, float _curlMult, float _noiseDiv, float _uneven) {


  int _direction = 4;
  
  ArrayList<ArrayList<PVector>> paths = new ArrayList<ArrayList<PVector>>();
  
  for (PVector p : _pvs) {

    ArrayList<PVector> path = new ArrayList<PVector>();

    int   plotMax = floor(random(100, 1000));
    float plotDiv = random(0.2, 0.8);
    float xInit = p.x;
    float yInit = p.y;
    float xPoint = xInit;
    float yPoint = yInit;

    for (int plotCnt = 0; plotCnt < plotMax; ++plotCnt) {

      float plotRatio = map(plotCnt, 0, plotMax, 0.0, 1.0);

      float xPrev = xPoint;
      float yPrev = yPoint;

      float nX = noise(xPrev * _noiseDiv, yPrev * _noiseDiv, cos(PI * noise(yPrev * _noiseDiv)) * _uneven);
      float nY = noise(yPrev * _noiseDiv, xPrev * _noiseDiv, cos(PI * noise(xPrev * _noiseDiv)) * _uneven);

      xPoint += plotDiv * cos(TWO_PI * nX * _curlMult);
      yPoint += plotDiv * sin(TWO_PI * nY * _curlMult);

      path.add(new PVector(xPoint, yPoint));

    }
    paths.add(path);
  }
  return paths;
}

/**
 * getPoints : get points randomly.
 * @param  _num    : return points number.
 * @param  _radius : points location range.
 * @return array of the point locations.
 */
private ArrayList<PVector> getPoints(int _num, float _radius) {

  float div = PI * 0.0002;
  ArrayList<PVector> pvs = new ArrayList<PVector>();

  for (float theta = 0.0; theta < TWO_PI; theta += div) {
    pvs.add(new PVector(round(width * (0.5 + _radius * cos(theta))), round(height * (0.5 + _radius * sin(theta)))));
  }

  int removeCnt = pvs.size() - _num;
  if (removeCnt > 0) {
    for (int i = 0; i < removeCnt; i++) {
      pvs.remove(floor(random(pvs.size())));
    }
  }

  return pvs;
  
}

/**
 * drawPaths : draw Vector Field.
 * @param  _paths     : paths to draw.
 * @param  _drawRatio : tune brightness, point's size.
 * @param  _baseHue   : draw color.
 */
private void drawPaths(ArrayList<ArrayList<PVector>> _paths, float _drawRatio, float _baseHue) {

  // background color
  blendMode(BLEND);
  pushMatrix();
  noStroke();
  float baseSiz = map(_drawRatio, 0.0, 1.0, 6.0, 1.0);
  pushMatrix();
  translate(1.0, 1.0);
  for (ArrayList<PVector> path : _paths) {
    for (int i = 0; i < path.size(); i++) {
      PVector p = path.get(i);
      float pRatio = i * 1.0 / path.size();
      fill((_baseHue + 0.0) % 360.0, 90.0, 50.0, 2.0);
      ellipse(p.x, p.y, baseSiz * pRatio, baseSiz * pRatio);
    }
  }
  popMatrix();

  // shadow
  blendMode(DARKEST);
  pushMatrix();
  translate(3.0, 3.0);
  for (ArrayList<PVector> path : _paths) {
    float xInit = path.get(0).x;
    float yInit = path.get(0).y;
    float xPoint = xInit;
    float yPoint = yInit;
    baseSiz = 0.5 + noise(xInit, yInit) * 3.0;
    baseSiz *= map(_drawRatio, 0.0, 1.0, 1.5, 0.5);
    for (int i = 0; i < path.size(); i++) {
      PVector p = path.get(i);
      float pRatio = i * 1.0 / path.size();
      float eHue = _baseHue + floor((sin(xInit) + cos(yInit)) * 10.0) * 6.0 + 360.0;
      float eBri = 40.0 * sin(PI * pRatio);
      float eSiz = baseSiz * sin(PI * pRatio);
      fill(eHue % 360.0, 100.0, eBri, 100);
      ellipse(p.x, p.y, eSiz, eSiz);
    }
  }
  popMatrix();

  // foreground
  blendMode(LIGHTEST);
  float baseBri = map(_drawRatio, 0.0, 1.0, 50.0, 100.0);
  for (ArrayList<PVector> path : _paths) {
    float xInit = path.get(0).x;
    float yInit = path.get(0).y;
    float xPoint = xInit;
    float yPoint = yInit;
    baseSiz = 0.5 + noise(xInit, yInit) * 3.0;
    baseSiz *= map(_drawRatio, 0.0, 1.0, 1.5, 0.5);
    for (int i = 0; i < path.size(); i++) {
      PVector p = path.get(i);
      float pRatio = i * 1.0 / path.size();
      float eHue = _baseHue + floor((sin(xInit) + cos(yInit)) * 10.0) * 6.0 + 360.0;
      float eSat = map(sin(PI * pRatio), 0.0, 1.0, 70.0, 90.0) * (6.0 + floor(((xInit * yInit) * 30000.0) % 4.0)) / 9.0;
      float eBri = baseBri * sin(PI * pRatio) * (8.0 + floor(((xInit * yInit) * 20000.0) % 5.0)) / 10.0;
      float eSiz = baseSiz * sin(PI * pRatio);
      fill(eHue % 360.0, eSat, eBri, 100.0);
      ellipse(p.x, p.y, eSiz, eSiz);
    }
  }
}

/*
Copyright (C) 2020- deconbatch

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>
*/