White Room : I tried to express the rhythm and density in this animation.

Expressing the rhythm and density in a creative coding animation.

Expressing the rhythm and density in a creative coding animation.

I tried to express the rhythm and density in a creative coding animation.
I've been reading Paul Klee's book. It's an exercise that will help me to understand this book well.

At first, I drew a still image that expresses density.

A still image that expresses density.

And I added some deviation to it.

I added some deviation to it.
Deviation example 02.

I drew still images that express rhythm also.

Rhythm example that expresses 'three'.
Rhythm example that expresses 'four'.

Then, I combined these and added some deviations.

express the rhythm and density.

And I added express of 'weight' and some structure instead of a simple rectangle.

Example image of light object.
Example image of heavy object.
Example image of structures.

Yet another example images.

Yet another example images.
Yet another example images.

An example source code of Processing.

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.
To see other works based on my code is my pleasure. And my honor.



/**
 * White Room.
 * Expressing the rhythm and density in a creative coding animation.
 * 
 * @author @deconbatch
 * @version 0.1
 * @license GPL Version 3 http://www.gnu.org/licenses/
 * Processing 3.5.3
 * 2020.10.25
 */

void setup() {
  size(720, 720);
  colorMode(HSB, 360.0, 100.0, 100.0, 100.0);
  noLoop();
}

void draw() {
  int   rhythm   = 3;
  int   virtMax  = 6;
  int   horiMax  = 6;
  int   frmMorph = 24 * 5;            // morphing duration frames
  int   cycles   = 3;                 // animation cycle no.
  int   frmMax   = frmMorph * cycles; // whole frames
  float margin   = 20.0;
  float baseBri  = 800.0 * (virtMax + horiMax);
  float rndHue   = random(360.0);

  // set whole nodes
  ArrayList<ArrayList<Node>> nodes = new ArrayList<ArrayList<Node>>();
  for (int i = 0; i < cycles; i++) {
    nodes.add(setNodes(divide(virtMax), divide(horiMax), margin, rhythm, baseBri));
  }
  ArrayList<Node> nodesFrom = new ArrayList<Node>();
  ArrayList<Node> nodesTo   = new ArrayList<Node>();

  for (int frmCnt = 0; frmCnt < frmMax; frmCnt++) {
      
    // nodes for morphing animation. loops cyclic.
    if (frmCnt % frmMorph == 0) {
      nodesFrom = nodes.get(frmCnt / frmMorph);
      nodesTo   = nodes.get((frmCnt / frmMorph + 1) % cycles);
    }

    background(0.0, 0.0, 100.0, 100.0);
    stroke(0.0, 0.0, 30.0, 100.0);
  
    float toRatio = InFourthPow(map(frmCnt % frmMorph, 0, frmMorph - 1, 0.0, 1.0));
    float frRatio = 1.0 - toRatio;
    for (int i = 0; i < nodesTo.size(); i++) {
      // morphing calculations
      float nB = nodesFrom.get(i).bri * frRatio + nodesTo.get(i).bri * toRatio;
      float nX = nodesFrom.get(i).x * frRatio + nodesTo.get(i).x * toRatio;
      float nY = nodesFrom.get(i).y * frRatio + nodesTo.get(i).y * toRatio;
      float nW = nodesFrom.get(i).w * frRatio + nodesTo.get(i).w * toRatio;
      float nH = nodesFrom.get(i).h * frRatio + nodesTo.get(i).h * toRatio;
      float eX = nodesFrom.get(i).ex * frRatio + nodesTo.get(i).ex * toRatio;
      float eY = nodesFrom.get(i).ey * frRatio + nodesTo.get(i).ey * toRatio;
      float eR = nodesFrom.get(i).er * frRatio + nodesTo.get(i).er * toRatio;

      // draw base matrix
      strokeWeight(5);
      fill(0.0, 0.0, nB, 100.0);
      rect(nX, nY, nW, nH);

      // draw some construction
      strokeWeight(1);
      pushMatrix();
      translate(nX, nY);
      for (int j = 0; j < 10; j++) {
        rect(0.0, 0.0, nW - j * 10, nH - j * 10, eR * 0.25);
        translate(5, 5);
      }
      popMatrix();

      // draw light/heavy objects
      float eRatio = (nH * eR) / (height * 15.0 / horiMax);
      strokeWeight(constrain(eRatio, 0.0, 3.0));
      if (eRatio > 0.5 && eRatio < 2.0) {
        if (nB > 67.0) {
          // heavy
          line(eX, eY, eX, nY);
          fill(0.0, 0.0, 100.0 - nB * 0.5, 100.0);
          ellipse(eX, eY, eR, eR);
          fill(0.0, 0.0, nB, 100.0);
          ellipse(eX, eY, eR * 0.5, eR * 0.5);
        } else {
          // light
          line(eX, eY, eX, nY + nH);
          fill(0.0, 0.0, 100.0 - nB * 0.5, 100.0);
          ellipse(eX, eY, eR, eR);
        }
      }
    }

    // draw casing
    strokeWeight(10);
    stroke(0.0, 0.0, 30.0, 100.0);
    noFill();
    rect(margin, margin, width - margin * 2.0, height - margin * 2.0);

    saveFrame("frames/" + String.format("%04d", frmCnt) + ".png");
  }
  exit();
}

/**
 * Node : holds node informations.
 */
class Node {
  public float x, y, w, h; // rectangle
  public float ex, ey, er; // ellipse (navel)
  public float bri;        // brightness

  Node(float _x, float _y, float _w, float _h, float _ex, float _ey, float _bri) {
    x = _x;
    y = _y;
    w = _w;
    h = _h;
    ex = _ex;
    ey = _ey;
    bri = _bri;
    er = 0.0;
  }

  void setNavel() {
    er = (w + h) * 0.07;
  }
}

/**
 * setNodes : calculate the nodes location and size.
 * @param  _xs, _ys : divided ratios of canvas.
 * @param  _margin  : canvas margin.
 * @param  _rhythm  : rhythm number.
 * @param  _baseBri : base brightness.
 * @return : array of nodes.
 */
ArrayList<Node> setNodes(ArrayList<Float> _xs, ArrayList<Float> _ys, float _margin, int _rhythm, float _baseBri) {

  ArrayList<Node> ns = new ArrayList<Node>();

  float w = width  - _margin * 2.0;
  float h = height - _margin * 2.0;

  int   xCnt = 0;
  float xSum = 0.0;
  for (float x : _xs) {

    int   yCnt = 0;
    float ySum = 0.0;
    for (float y : _ys) {

      float rW = x * w;
      float rH = y * h;
      float pX = xSum * w + _margin;
      float pY = ySum * h + _margin;
      float eX = pX + rW * 0.5;
      float eY = pY + rH * 0.5;

      float rVal = (1.0 + (xCnt + yCnt) % _rhythm) / _rhythm;
      float rBri = constrain((x * y * _baseBri * rVal), 0.0, 100.0);

      // brightness deviation
      if (random(1.0) < 0.4) {
        rBri = rVal * 90.0;
      }

      // size deviation
      if (random(1.0) < 0.2) {
        rW = x * w * random(0.5, 2.5);
        rW = (pX + rW >= w + _margin) ? rW - (rW - _margin) : rW;
        rH = y * h * random(0.5, 2.5);
        rH = (pY + rH >= h + _margin) ? rH - (rH - _margin) : rH;
      }

      Node n = new Node(pX, pY, rW, rH, eX, eY, rBri);

      if (xCnt % (_rhythm) == 0 || yCnt % (_rhythm - 1) == 0) {
        if (random(1.0) < 0.5) {
          n.setNavel();
        }
      }
        
      ns.add(n);
        
      yCnt++;
      ySum += y;
    }

    xCnt++;
    xSum += x;
  }
  return ns;
}

/**
 * divide : divide the canvas randomly and returns ratios of divided spaces.
 * @param  _div : divide number.
 * @return : ratios(0.0 - 1.0) of divided spaces per canvas.
 */
ArrayList<Float> divide(int _div) {
  ArrayList<Float> ratios = new ArrayList<Float>();
  float rndPhase = random(TWO_PI);
  float rndCycle = random(0.5, 2.5);
  float rndMulti = random(0.5, 1.0);
  float lenSum = 0.0;
  for (int i = 0; i < _div; i++) {
    float len = 2.0 + sin(map(i, 0, _div, 0.0, TWO_PI) * rndCycle + rndPhase) * rndMulti;
    ratios.add(len);
    lenSum += len;
  }
  for (int i = 0; i < _div; i++) {
    ratios.set(i, ratios.get(i) / lenSum); // normalize
  }
  return ratios;
}
  
/**
 * InFourthPow : easing function.
 * @param  _t    0.0 - 1.0 : linear value.
 * @return       0.0 - 1.0 : eased value.
 */
private float InFourthPow(float _t) {
  return 1.0 - pow(1.0 - _t, 4);
}


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


No comments :

Post a Comment