I Wish I Were Your Mirror.

I organized Lissajous like figures in 2 shape rotate animation.
Lissajous like figures with some modification.



Description of this creative coding.

It's a creative coding work made with Processing.

My last work 'Piece in the Shape of a Square' became Lissajous like figures with some modification.
I organized it in 2 shape rotate animation.

And I introduced a new easing class.
This easing class provides step landing easing.

Two landing easing

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

Example Processing code.

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







// I Wish I Were Your Mirror.
// @author @deconbatch
// @version 0.1
// Processing 3.2.1
// 2019.02.08

void setup() {

  size(720, 720);
  colorMode(HSB, 360, 100, 100, 100);
  rectMode(CENTER);
  smooth();
  noLoop();
  
  // fix 0, 5, 10 or 15 for nice shape.
  // But I don't know it would work or not on other environment.
  noiseSeed(floor(random(4.0)) * 5);
  
}

void draw() {

  translate(width / 2.0, height / 2.0);
  noStroke();
  
  int   frameCntMax  = 24 * 6;
  int   easeLanding  = 1 + floor(random(3)); // easing will stop 1, 2 or 3 times on the way
  float hueBase      = random(360.0);
  float initRotation = random(PI);
  float initPosition = random(1.0);

  Easing es = new Easing(easeLanding);
  
  for (int frameCnt = 0; frameCnt < frameCntMax; ++frameCnt) {
    
    float easeRatio = es.calculate(map(frameCnt, 0, frameCntMax, 0.0, 1.0));

    background(0.0, 0.0, 90.0, 100);
    pushMatrix();
    rotate(initRotation);
    drawShapes(hueBase, initPosition, easeRatio);
    popMatrix();

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

  }

  exit();
  
}

/**
 * drawShapes : draw 2 shapes with Lissajous like figure.
 * @param  _hueBase      : 0.0 - 360.0 : base color of shape.
 * @param  _initPosition : 0.0 - 1.0   : start position of shape.
 * @param  _shapeFactor  : 0.0 - 1.0   : change factor of shape.
 */
private void drawShapes(float _hueBase, float _initPosition, float _shapeFactor) {

  int   plotCntMax = 15000;
  float plotScale  = 0.00024;
  
  for (int shapeCnt = 0; shapeCnt < 2; ++shapeCnt) {
    
    float xPrev = 0.0;
    float yPrev = 0.0;

    // rotate shape location with PI, not TWO_PI
    float xCurr = width * 0.24 * cos(PI * (_shapeFactor + shapeCnt + _initPosition));
    float yCurr = height * 0.24 * sin(PI * (_shapeFactor + shapeCnt + _initPosition));

    // for distorted shape
    float xDist = map(sin(TWO_PI * _shapeFactor), -1.0, 1.0, 0.95, 1.05);
    float yDist = map(xDist, 0.95, 1.05, 1.05, 0.95);
      
    float eHue = _hueBase + map(sin(TWO_PI * (_shapeFactor + shapeCnt * 0.5)), -1.0, 1.0, 0.0, 60.0);
      
    for (int plotCnt = 0; plotCnt < plotCntMax; ++plotCnt) {

      // As usual, I don't know why this formula make such a shape...
      xPrev += plotScale * cos(TWO_PI * noise(xCurr * 0.001, yCurr * 0.001) * 0.18) * xDist;
      yPrev += plotScale * sin(TWO_PI * noise(yCurr * 0.001, xCurr * 0.001) * 0.5) * yDist;
      xCurr += cos(TWO_PI * xPrev * 8.0);
      yCurr += cos(TWO_PI * yPrev * 8.0);
        
      float eSize = map(sin(PI * map(plotCnt, 0, plotCntMax, 0.0, 1.0)), 0.0, 1.0, 0.0, 3.0);
      fill(
           eHue % 360.0,
           map(plotCnt, 0, plotCntMax, 40.0, 10.0),
           map(plotCnt, 0, plotCntMax, 30.0, 80.0),
           100.0
           );
      ellipse(xCurr, yCurr, eSize, eSize);

    }
  }

}

/**
 * casing : draw fancy casing
 * @param  _hueBase : 0.0 - 360.0 :  casing color.
 */
private void casing(float _hueBase) {

  fill(0.0, 0.0, 0.0, 0.0);
  strokeWeight(54.0);
  stroke(_hueBase, 80.0, 30.0, 100.0);
  rect(0.0, 0.0, width, height);
  strokeWeight(50.0);
  stroke(0.0, 0.0, 100.0, 100.0);
  rect(0.0, 0.0, width, height);
  noStroke();
  noFill();

}

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

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

  Easing() {
    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(float _t) {
    float easeCurr = easeInOutCubic(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.
   */
  private 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;
  }

}

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