Spin the Wheel.

An example image of circle packing wheel animation.

Description of this creative coding animation.

It's a creative coding animation made with Processing. It draws the spinning wheel located with circle packing.

I took part in an event 'Daily Coding Challenge' that was held by Processing Community Japan. And I made an animation about a theme 'ま' 丸み (Roundness). It draws a sphere look with a rectangle.
Daily Coding Challenge' Processing Community Japan.


Roundness.

I proceeded to draw rotating fans with an ellipse. And I use the Circle Packing method to locate the fans.
Rotating fans with an ellipse.


Circle packing location.

For cyclic animation, I made it start and end with circle not ellipse.
An example image of circle packing wheel animation.


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



/**
 * Spin the Wheel.
 * the rotating fans located with circle packing.
 *
 * Processing 3.5.3
 * @author @deconbatch
 * @version 0.1
 * created 0.1 2020.05.03
 */

void setup() {

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

}

void draw() {

  int frmMax = 24 * 10; // for 24fps x 10s animation
  ArrayList<Fan> fans = circlePacking();
  
  background(0.0, 0.0, 100.0, 100.0);
  for (int frmCnt = 0; frmCnt < frmMax; frmCnt++) {

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

    // after image effect
    noStroke();
    fill(0.0, 0.0, 100.0, 100.0 - 90.0 * sin(PI * frmRatio));
    rect(0.0, 0.0, width, height);

    // draw fans
    for (Fan f : fans) {
      f.draw(sin(PI * easeInOutCubic(frmRatio)));
    }    

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

  }
  exit();
}

/**
 * circlePacking : locate fans with the Circle Packing method.
 */
ArrayList<Fan> circlePacking() {

  int   tryMax  = 10000; // a trying count to add and grow fans.
  float gap     = 12.0;  // gap between fans
  float margin  = 50.0;
  float baseHue = random(360.0);
  ArrayList<Fan> fans = new ArrayList<Fan>();

  for (int tryCnt = 0; tryCnt < tryMax; tryCnt++) {

    float fX = random(margin, width - margin);
    float fY = random(margin, height - margin);

    // add new fan
    boolean inner = false;
    for (Fan f : fans) {
      if (dist(fX, fY, f.x, f.y) < f.r + gap) {
        inner = true;
        break;
      }
    }
    if (!inner) {
      fans.add(new Fan(fX, fY, baseHue + noise(fX * 0.01, fY * 0.01) * 240.0));
    }

    // grow fans
    for (Fan fThis : fans) {
      boolean collision = false;
      for (Fan fThat : fans) {
        if (fThis != fThat) {
          if (dist(fThis.x, fThis.y, fThat.x, fThat.y) < (fThis.r + fThat.r) * 0.5 + gap) {
            collision = true;
            break;
          }
        }
      }
      if (!collision) {
        fThis.grow();
      }
    }

  }

  return fans;
}

/**
 * casing : draw fancy casing.
 */
private void casing() {
  
  fill(0.0, 0.0, 0.0, 0.0);
  strokeWeight(30.0);
  stroke(0.0, 0.0, 0.0, 100.0);
  rect(0.0, 0.0, width, height);
  strokeWeight(26.0);
  stroke(0.0, 0.0, 100.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.
 */
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;

}

/**
 * Fan : draw and hold location, size and color.
 */
public class Fan {

  public  float x, y;   // coordinate of fan
  public  float r;      // radius
  private float elpVal; // ellipticity
  private float hueVal; // hue value of fan
  private float satVal; // saturation value of fan
  private float rotVal; // rotation radians
  private float incRot; // increment value of radians

  Fan(float _x, float _y, float _c) {
    x = _x;
    y = _y;
    r = 10.0;  // initial radius of the fan
    elpVal = random(0.1, 0.5);
    hueVal = _c;
    satVal = random(40.0, 60.0);
    rotVal = 0.0;
    incRot = random(0.1, 1.0) * HALF_PI;
  }

  public void grow() {
    r++;
  }

  public void draw(float _rate) {

    float sigmoid = 2.0 / (1.0 + exp(-10.0 * _rate)) - 1.0;
    rotVal += incRot * _rate;

    noFill();
    strokeWeight(map(sigmoid, 0.0, 1.0, 10.0, 2.0));
    stroke(hueVal % 360.0, satVal, 80.0, 100.0);
    pushMatrix();
    translate(x, y);
    rotate(rotVal);
    ellipse(0.0, 0.0, r, map(sigmoid, 0.0, 1.0, r, r * elpVal));
    popMatrix();

  }

}


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







An example image of circle packing wheel animation.





No comments :

Post a Comment