Down on the Corner.

Some shapes that have the same margin inner lines.

Some shapes that have the same margin inner lines.



Description of this creative coding example.

It's a creative coding example work made with Processing.

I made some animation with the idea by creative coder おかず (@okazz_) how to draw geometric patterns.

シンプルな図形から幾何学的な模様を作る by Processing
https://note.mu/outburst/n/n9fdea683c079

I chose some shapes that have inner lines. These lines have the same margin. So these lines connect each other when the shape rotates.

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

Processing code example.

Please feel free to use this example code.
To see other works based on my code is my pleasure. And my honor.



/**
 * Down on the Corner.
 * Rotate shape animation with step easing.
 * I like the lines in the shapes.
 * reference : https://note.mu/outburst/n/n9fdea683c079
 * 
 * @author @deconbatch
 * @version 0.1
 * Processing 3.2.1
 * 2019.03.17
 */

/**
 * main
 */

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

void draw() {

  int   frmCntMax = 24 * 6;
  int   stopCnt   = random(1.0) > 0.5 ? 4 : 2; // stop motion count
  float hueBase   = random(360.0);

  StepEasing se = new StepEasing(stopCnt - 1);
  EasingCalc ec = (random(1.0) > 0.5) ? new InFourthPow() : new InOutCubic();

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

    float easeRatio = se.calculate(ec, map(frmCnt, 0, frmCntMax, 0.0, 1.0));
    float hueDiv    = 60.0 * sin(PI * easeRatio);
    
    background((hueBase + hueDiv) % 360.0, 40.0, 30.0, 100.0);
    fill((30 + hueBase + hueDiv) % 360.0, 40, 80, 100);
    strokeWeight(8.0);
    stroke((hueBase + hueDiv) % 360.0, 40.0, 30.0, 100.0);
  
    float cellW  = width / 2.0;
    float shapeW = cellW * (0.5 - 0.5 * sin(PI * (easeRatio % (1.0 / stopCnt)) * stopCnt));

    // 2x2 cells
    for (int cellX = 0; cellX < 2; ++cellX) {
      for (int cellY = 0; cellY < 2; ++cellY) {

        int   selector = (cellX + cellY) % 2;
        float rotater  = floor(noise(cellX * 0.5, cellY * 0.5) * 5.0) + easeRatio * 4.0; // use noise as array of random.
  
        pushMatrix();
        translate((cellX + 0.5) * cellW, (cellY + 0.5) * cellW);
        rotate(HALF_PI * rotater);
        if (selector == 0) {
          arc(0, -shapeW, shapeW * 2.0, shapeW * 2.0, 0, PI);
          arc(0, -shapeW, shapeW, shapeW, 0, PI);
          line(-shapeW, -shapeW, shapeW, -shapeW);
        } else {
          // do not change the triangle size
          triangle(-cellW * 0.5, -cellW * 0.5, cellW * 0.5, cellW * 0.5, -cellW * 0.5, cellW * 0.5);
          triangle(-cellW * 0.25, -cellW * 0.25, cellW * 0.25, cellW * 0.25, -cellW * 0.25, cellW * 0.25);
        }
        popMatrix();

      }
    }

    // draw rect at the center
    pushMatrix();
    translate(width * 0.5, height * 0.5);
    rect(0.0, 0.0, shapeW * 2.0, shapeW * 2.0);
    line(-shapeW, -shapeW * 0.5, shapeW, -shapeW * 0.5);
    line(-shapeW, shapeW * 0.5, shapeW, shapeW * 0.5);
    line(-shapeW * 0.5, -shapeW, -shapeW * 0.5, shapeW);
    line(shapeW * 0.5, -shapeW, shapeW * 0.5, shapeW);
    popMatrix();

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

  }
  exit();
}

/**
 * StepEasing : calculate easing value with step landing. It just has one easing function yet.
 * @param  _landingCount : 1 - any int value : landing number.
 */
private class StepEasing {

  private float landingPoint;
  private float easePrev;
  private float easeRatio;
  
  StepEasing(int _landingCount) {
    landingPoint = 1.0 / (_landingCount + 1);
    reset();
  }

  StepEasing() {
    landingPoint = 1.0;
    reset();
  }

  private void reset() {
    easePrev  = 0.0;
    easeRatio = 0.0;
  }
  
  /**
   * calculate : calculate easing value with step landing.
   * @param  _t    0.0 - 1.0 : linear value.
   * @return float 0.0 - 1.0 : eased value with step landing.
   */
  public float calculate(EasingCalc _calc, float _t) {
    float easeCurr = _calc.calculate(map(_t % landingPoint, 0.0, landingPoint, 0.0, 1.0));
    easeRatio += constrain((easeCurr - easePrev) * landingPoint, 0.0, 1.0);
    easePrev = easeCurr;

    return easeRatio;
  }

}

/**
 * easeInOutCubic easing function.
 * @param  _t    : 0.0 - 1.0 : linear value.
 * @return float : 0.0 - 1.0 : eased value.
 */
interface EasingCalc {
  float calculate(float _t);
}

private class InOutCubic implements EasingCalc {
  public float calculate(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;
  }
}

private class InFourthPow implements EasingCalc {
  public float calculate(float _t) {
    return 1.0 - pow(1.0 - _t, 4);
  }
}


/*
Copyright (C) 2019- 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 
*/




No comments :

Post a Comment