The Perlin noise creates a swing of a pendulum.

It's a creative coding animation made with Processing.


A useless machine, made with creative coding.

It's a creative coding animation made with 'Processing'. It draws a moving machine that looks like some swing of a pendulum and it looks useless.

I used a Perlin noise to control the moving of this shape first. It worked sometimes fine, sometimes not. The Perlin noise does not always return the full range value from 0.0 to 1.0. So it was sometimes a little moving sometimes a big moving. I wrote a function NormalNoise that returns nearly full range noise to resolve this problem.

I implemented three different moving patterns. And I wanted to connect each moving pattern smoothly. So I added this formula to each moving calculation.

sin(PI * frmRate)






 

The 'Processing' example code.

This code does not display any images on the screen but generates image files in frames directory. You can make an animation with these files.

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.




/**
 * Machinery.
 * A creative coding animation that draws some moving like a swing of the pendulum.
 * 
 * Processing 3.5.3
 * @author @deconbatch
 * @version 0.1
 * created 0.1 2020.03.07
 */


void setup() {

  size(720, 720);
  colorMode(HSB, 360, 100, 100, 100);
  rectMode(CENTER);
  smooth();
  noLoop();

}

void draw() {

  int   moveMax   = 3;      // 3 different moving patterns
  int   frmMax    = 24 * 5; // 24fps x 5s animation per moving pattern
  float rndRotate = random(PI);
  float initHue   = random(360);

  ArrayList<PVector> initVs = initLayout();
  ArrayList<PVector> calcVs = new ArrayList<PVector>();
  
  translate(width / 2, height / 2);
  for (int moveCnt = 0; moveCnt < moveMax; moveCnt++) {

    // Normalized noises for the parameters of moving
    noiseSeed(floor(moveCnt + initHue));
    NormalNoise moveNoise01 = new NormalNoise(100.0, 0.1);
    NormalNoise moveNoise02 = new NormalNoise(200.0, 0.1);
    NormalNoise rotateNoise = new NormalNoise(300.0, 0.1);

    for (int frmCnt = 0; frmCnt < frmMax; frmCnt++) {

      float frmRate  = map(frmCnt, 0, frmMax, 0.0, 1.0);
      float easeRate = easeInOutCubic(frmRate);
      float baseHue  = initHue + (moveCnt + frmRate) * 360.0 / moveMax;

      // calculate the shape
      calcVs = calcShape(initVs, easeRate, moveNoise01, moveNoise02);

      // draw the shape
      background(0.0, 0.0, 90.0, 100.0);
      pushMatrix();
      rotate(rndRotate + PI * map(rotateNoise.getNoise(frmRate), 0.0, 1.0, -1.0, 1.0) * sin(PI * frmRate));
      drawMachine(baseHue, calcVs);
      popMatrix();  
      casing();
    
      saveFrame("frames/" + String.format("%02d", moveCnt) + "." + String.format("%04d", frmCnt) + ".png");

    }
  }
  exit();
}

/**
 * initLayout : define initial layout of points.
 * @return coodinates of the points as PVector array.
 */
ArrayList initLayout() {

  int pMax = 7; // 7 joints
  ArrayList<PVector> pvs = new ArrayList<PVector>();
  for (int pCnt = 0; pCnt < pMax; pCnt++) {
    float d = 2.0 / (pMax + 1);
    float px = (1.0 + pCnt) * d - 1.0;
    float py = random(-1.0, 1.0);
    pvs.add(new PVector(px, py));
  }
  return pvs;

}

/**
 * calcShape : calculate the coodinates of the joints.
 * @param  _pvs     : PVector array of the joints to be calculated.
 * @param  _frmRate : which frame value as 0.0 - 1.0
 * @param  _ns01    : noise value as 0.0 - 1.0
 * @param  _ns02    : noise value as 0.0 - 1.0
 */
ArrayList calcShape(ArrayList<PVector> _pvs, float _frmRate, NormalNoise _ns01, NormalNoise _ns02) {

  float radius = width / 4.0;
  float pRad = map(_ns01.getNoise(_frmRate) * sin(PI * _frmRate), 0.0, 1.0, -0.5, 0.5) * PI;
  float pDiv = map(_ns02.getNoise(_frmRate) * sin(PI * _frmRate), 0.0, 1.0, -0.5, 0.5);
  float pMult = map(abs(pDiv), 0.0, 0.5, 1.5, 1.0);

  ArrayList<PVector> rvs = new ArrayList<PVector>();
  for (PVector pv : _pvs) {
    float px = radius * (pv.x + pDiv) * cos(pv.y * pRad) * pMult;
    float py = radius * (pv.x + pDiv) * sin(pv.y * pRad) * pMult;
    rvs.add(new PVector(px, py));
  }
  return rvs;

}

/**
 * drawMachine : draws machine with calculated joints.
 * @param  _baseHue : drawing color.
 * @param  _pvs     : joints array to be drawn.
 */
void drawMachine(float _baseHue, ArrayList<PVector> _pvs) {

  float baseSize = 20.0;

  noStroke();
  fill(_baseHue % 360.0, 80.0, 60.0, 100.0);
  for (PVector pv : _pvs) {
    float ps = baseSize * (2.0 + dist(pv.x, pv.y, 0.0, 0.0) / (width * 0.25));
    ellipse(pv.x, pv.y, ps, ps);
  }

  strokeWeight(3.0);
  stroke(_baseHue % 360.0, 80.0, 60.0, 100.0);
  fill(0.0, 0.0, 100.0, 100.0);
  beginShape(TRIANGLE_STRIP);
  for (PVector pv : _pvs) {
    vertex(pv.x, pv.y);
  }
  endShape();

  for (PVector pv : _pvs) {
    float ps = baseSize * (2.0 + dist(pv.x, pv.y, 0.0, 0.0) / (width * 0.25)) * 0.6;
    ellipse(pv.x, pv.y, ps, ps);
  }

}

/**
 * casing : draw fancy casing
 */
private void casing() {
  
  fill(0.0, 0.0, 0.0, 0.0);
  strokeWeight(40.0);
  stroke(0.0, 0.0, 20.0, 100.0);
  rect(0.0, 0.0, width, height);
  strokeWeight(30.0);
  stroke(0.0, 0.0, 95.0, 100.0);
  rect(0.0, 0.0, width, height);
    
}

/**
 * easeInOutCubic easing function.
 * @param  t     0.0 - 1.0 : linear value.
 * @return float 0.0 - 1.0 : eased value.
 */
float easeInOutCubic(float t) {
  t *= 2.0;
  if (t < 1.0) {
    return pow(t, 3) / 2.0;
  }
  t -= 2.0;
  return (pow(t, 3) + 2.0) / 2.0;
}

/**
 * NormalNoise : returns (almost) normalized cyclic noise value
 * @param  _div   : any value. 
 * @param  _scale : any value.
 * @param  _step  : 0.0 - 1.0. noise step
 * @return 0.0 - 1.0. Perlin noise.
 */
class NormalNoise {

  float nMult;
  float nSubt;
  float nDiv;
  float nScale;

  NormalNoise(float _div, float _scale) {
    nDiv = _div;
    nScale = _scale;
    nMult = 1.0;
    nSubt = 0.0;

    float minVal = 1.0;
    float maxVal = 0.0;
    for (float step = 0.0; step < 1.0; step += 0.001) {
      float n = getNoise(step);
      minVal = min(minVal, n);
      maxVal = max(maxVal, n);
    }

    nSubt = minVal;
    nMult = 1.0 / (maxVal - minVal);
  }

  /**
   * getNoise : returns (almost) normalized cyclic noise value
   * @param  _step  : 0.0 - 1.0. noise step
   * @return 0.0 - 1.0. Perlin noise.
   */
  float getNoise(float _step) {
    return constrain(nMult * (noise(nDiv + nScale * cos(_step * TWO_PI), nDiv + nScale * sin(_step * TWO_PI)) - nSubt), 0.0, 1.0);
  }
  
}


/*
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/>
*/



 

Yet another example images.


It's a creative coding animation made with Processing.
It's a creative coding animation made with Processing.


Next Post Previous Post
No Comment
Add Comment
comment url