Express the 'Perspective' with simple shapes.

Saturday, December 5, 2020

Working on the Building.

It creates an animation of moving boxes.

Night by Night.

It creates an animation of moving panels.

Random walk boxes show us a nice perspective.

I tried to make something that expresses the 'Perspective'. These skeleton boxes express it well!

This is the creative coding animation code written in Processing. It creates an animation of moving boxes.

These boxes are located by the random walking method. And move to the next location by morphing method. It's a near relation work of 'Johnny on the Monorail' about this morphing way.

Random walk panels dancing.

I made another work with flat panels, not boxes. It killed the perspective sensation and left us a size sensation. 🤷‍♀️

It creates an animation of moving panels.


 


An example 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.


/**
 * Working on the Building.
 * Random walk boxes show us a nice perspective.
 * 
 * @author @deconbatch
 * @version 0.1
 * @license GPL Version 3 http://www.gnu.org/licenses/
 * Processing 3.5.3
 * 2020.12.05
 */

void setup() {
  size(720, 480, P3D);
  colorMode(HSB, 360, 100, 100, 100);
  noLoop();

  hint(DISABLE_DEPTH_TEST);
}

void draw() {
  float boxSize    = 80.0;
  float walkStep   = boxSize * 0.5;
  float cameraDist = 300.0;
  float baseHue    = random(200, 230);  // to make arc blue
  int   frmRate    = 24;
  int   frmMorph   = frmRate * 2;       // morphing duration frames
  int   cycles     = 5;                 // animation cycle no
  int   frmMax     = frmMorph * cycles; // whole frames
  int   nodeMax    = 10;                // boxes number
  int   cycleCnt   = 0;

  translate(width * 0.5, height * 0.5, 0.0);

  ArrayList<ArrayList<PVector>> shapes = new ArrayList<ArrayList<PVector>>();
  for (int i = 0; i < cycles; i++) {
    shapes.add(setNodes(nodeMax, walkStep));
  }

  ArrayList<PVector> nodesFrom = new ArrayList<PVector>();
  ArrayList<PVector> nodesTo   = new ArrayList<PVector>();
  for (int frmCnt = 0; frmCnt < frmMax; frmCnt++) {

    float frmRatio = map(frmCnt, 0, frmMax, 0.0, TWO_PI);

    background(50.0, 20.0, 100.0, 100.0);
    camera(
           0.0, 0.0, cameraDist,
           0.0, 0.0, 0.0,
           0, 1, 0
           );
    
    // nodes for morphing animation. loops cyclic.
    if (frmCnt % frmMorph == 0) {
      cycleCnt = frmCnt / frmMorph;
      nodesFrom = shapes.get(cycleCnt);
      nodesTo   = shapes.get((cycleCnt + 1) % cycles);
    }
    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 nX = nodesFrom.get(i).x * frRatio + nodesTo.get(i).x * toRatio;
      float nY = nodesFrom.get(i).y * frRatio + nodesTo.get(i).y * toRatio;
      float nZ = nodesFrom.get(i).z * frRatio + nodesTo.get(i).z * toRatio;

      drawBox(nX, nY, nZ, boxSize);
      drawBox(-nX, -nY, -nZ, boxSize);
      if (i == nodesTo.size() - 1) {
        drawWeight(nX, nY, nZ, boxSize, baseHue, toRatio);
        drawWeight(-nX, -nY, -nZ, boxSize, baseHue, toRatio);
      }
    }

    // stop motion
    if (frmCnt % frmMorph == 0) {
      for (int i = 0; i < frmRate; i++) {
        saveFrame("frames/" + String.format("%04d", cycleCnt) + ".00." + String.format("%04d", i) + ".png");
      }
    }
    
    saveFrame("frames/" + String.format("%04d", cycleCnt) + ".01." + String.format("%04d", frmCnt) + ".png");
  }

  exit();

}

/**
 * setNodes : calculate the nodes locations by random walking method. 
 * @param  _nodeMax : node number to calculate
 * @param  _step    : random walking step
 */
ArrayList<PVector> setNodes(int _nodeMax, float _step) {
  ArrayList<PVector> node = new ArrayList<PVector>();
  PVector prev = new PVector(0.0, 0.0, 0.0);
  for (int i = 0; i < _nodeMax; i++) {
    float rndZ = random(1.0);
    if (rndZ < 0.5) {
      prev.x += (floor(random(0.0, 3.0)) - 1) * _step;
      prev.y += (floor(random(0.0, 3.0)) - 1) * _step;
    } else if (rndZ < 0.8) {
      prev.z -= _step;
    } else {
      prev.z += _step;
    }
    node.add(prev.copy());
  }
  return node;
}

/**
 * drawBox : draw skeleton box.
 * @param _x, _y, _z : location to draw
 * @param _s : boz size
 */
private void drawBox(float _x, float _y, float _z, float _s) {
  strokeWeight(1.0);
  stroke(0.0, 0.0, 0.0, 100.0);
  pushMatrix();
  translate(_x, _y, _z);
  noFill();
  box(_s, _s, _s);
  popMatrix();
}

/**
 * drawWeight : draw arc and ellipse to express the weight.
 * @param _x, _y, _z : location to draw
 * @param _s     : base size
 * @param _hue   : base hue value
 * @param _ratio : rotation ratio
 */
private void drawWeight(float _x, float _y, float _z, float _s, float _hue, float _ratio) {
  strokeWeight(1.0);
  stroke(0.0, 0.0, 0.0, 100.0);
  pushMatrix();
  translate(_x, _y, _z);
  float bHue = (_hue + 360.0 + _x * 120.0 / width);
  float bSat = constrain(map(_y / height, -0.3, 0.3, 30.0, 90.0), 30.0, 90.0);
  float bBri = constrain(map(_y / height, -0.3, 0.3, 100.0, 40.0), 40.0, 100.0);
  float arcR = constrain(_s * map(_y / height, -0.3, 0.3, 0.8, 0.0), 0.0, _s);
  float eliS = constrain(_s * map(_y / height, -0.3, 0.3, 0.0, 0.5), 0.0, _s);
  fill(bHue % 360.0, bSat, bBri, 100.0);
  pushMatrix();
  rotateY(_ratio * PI);
  arc(0.0, 0.0, arcR, arcR, PI * 1.25, PI * 1.75, PIE);
  popMatrix();
  fill((bHue + 180.0) % 360.0, bSat, bBri, 100.0);
  ellipse(0.0, eliS * 0.5, eliS, eliS);
  popMatrix();
}
  
/**
 * 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/>
*/



Yet another example images.


These skeleton boxes express it well!

These skeleton boxes express it well!

Random walk panels dancing.



Comments

No comments :

Post a Comment