Gumowski Mira Attractors animation made with Processing.


An animation with the Gumowski Mira Attractors.

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

Yet another production with the Gumowski Mira Attractors.
I tried to make an effect like lights in thick fog with using multiple blendMode().

Related production : Lets Dance.

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

A Processing code example.

Please feel free to use this code, if you like it.
To see other works based on my code is my pleasure. And my honor.


// Fools Rush In.
// @author @deconbatch
// @version 0.1
// Processing 3.2.1
// 2018.12.29

void setup() {

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

}

void draw() {

  int   frameCntMax = 24 * 6;
  float baseHue     = random(360);
  GumowskiMira gm = new GumowskiMira(baseHue);

  translate(width / 2, height / 2);

  for (int frameCnt = 0; frameCnt < frameCntMax; ++frameCnt) {

    float frameRatio = map(frameCnt, 0, frameCntMax, 0.0, 1.0);

    background(baseHue, 100.0, 25.0, 100.0);
    pushMatrix();
    translate(-240, 0);
    gm.draw(frameRatio);
    popMatrix();

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

  }

  exit();

}

/**
 * GumowskiMira calculate and draw points in style of Gumowski-Miradraw attractor.
 * @param  baseHue 0.0 - 360.0 : draw points color.
 */
private class GumowskiMira {

  // Gumowski-Mira parameters
  float pA;
  float pB;
  float pM;
  // original parameter, some catalyst
  float pC;
  // just a color
  float baseHue;

  float initX;
  float initY;
  
  GumowskiMira(float baseHue) {
    
    this.baseHue = baseHue;

    float pAmin = 0.0;
    float pAmax = 0.1;
    float pBmin = 0.00;
    float pBmax = 0.05;
    float pMmin = 0.01;
    float pMmax = 0.05;
    float pCmin = 0.001;
    float pCmax = 0.003;

    pA = -random(pAmin, pAmax);
    pB = -random(pBmin, pBmax);
    pM = -random(pMmin, pMmax);
    pC = random(pCmin, pCmax);

    initX = random(-0.5, 0.5);
    initY = random(-0.5, 0.5);

  }

  private void draw(float frameRatio) {

    noStroke();

    int   idxTimeMax  = 9;
    int   phaseCntMax = 80;
    float pSizeMax    = width * 0.4;
    float pSizeMin    = width * 0.05;
    float catalystDiv = map(frameRatio, 0.0, 1.0, 0.0, TWO_PI);  // TWO_PI -> it loops.
    float shapeRate   = 1.0 - abs(map(frameRatio, 0.0, 1.0, -1.0, 1.0));  // 0.0 -> 1.0 -> 0.0

    for (int phaseCnt = 0; phaseCnt < phaseCntMax; ++phaseCnt) {

      catalystDiv += PI * pC;
        
      float prevX = initX;
      float prevY = initY;
      float prevC = 0.0;

      for (int idxTime = 0; idxTime < idxTimeMax; ++idxTime) {

        // in style of Gumowski-Mira attractor
        float pX = (prevY + pA * (1 - pB * prevY * prevY) * prevY + calcFunc(prevX)) * map(sin(prevC), -1.0, 1.0, 0.95, 1.053);
        float pY = (-prevX + calcFunc(pX)) * map(sin(prevC), -1.0, 1.0, 0.95, 1.053);
        float pC = prevC + catalystDiv;

        float pSiz = pSizeMin * (0.2 + shapeRate);
        float pSat = map(pSiz, 0.0, pSizeMin, 0.0, 60.0);
        float pBri = map(pSiz, 0.0, pSizeMin, 100.0, 90.0);

        float pHue = baseHue + map(phaseCnt, 0, phaseCntMax, 0.0, 30.0) - map(idxTime, 0, idxTimeMax, 0.0, 30.0);
        float pAlp = map(pSiz, 0.0, pSizeMax, 100.0, 0.0);

        blendMode(BLEND);
        fill(
             pHue % 360,
             pSat,
             pBri,
             pAlp
             );
        ellipse(
                pX * width * 0.13,
                pY * height * 0.13,
                pSiz,
                pSiz
                );

        pSiz = map(phaseCnt, 0, phaseCntMax, pSizeMin, pSizeMax);
        pSat = map(pSiz, 0.0, pSizeMax, 40.0, 100.0);
        pBri = map(pSiz, 0.0, pSizeMax, 5.0, 0.0);

        blendMode(SCREEN);
        fill(
             pHue % 360,
             pSat,
             pBri,
             100.0
             );
        ellipse(
                pX * width * 0.13,
                pY * height * 0.13,
                pSiz,
                pSiz
                );

        prevX = pX;
        prevY = pY;
        prevC = pC;
          
      }
    }
  }

  /**
   * main equation of Gumowski-Mira attractor.
   * @param  x : just an input value of equation.
   */
  private float calcFunc(float x) {
    return pM * x + 2 + (1 - pM) * x * x / (1 + x * x);
  }

}

/**
 * backdrop draw backdrop.
 * @param  baseHue 0.0 - 360.0 : backdrop color.
 */
private void backdrop(float baseHue) {

  noFill();
  strokeWeight(10.0);
  int radiusMin = 30;
  int radiusMax = ceil(width * 1.5);
  for (int radius = radiusMin; radius < radiusMax; radius += 5) {
    stroke(
           (baseHue + 30.0) % 360.0,
           40,
           map(radius, radiusMin, radiusMax, 0.0, 20.0),
           100
           );
    ellipse(240.0, 0.0, radius, radius);
  }
  
}

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

}

/**
 * casing : draw fancy casing
 * @param  hueBase : casing color.
 */
private void casing(float baseHue) {

  blendMode(BLEND);
  rectMode(CENTER);
  fill(0.0, 0.0, 0.0, 0.0);
  strokeWeight(40.0);
  stroke(baseHue, 100.0, 10.0, 100.0);
  rect(0.0, 0.0, width, height);
  strokeWeight(30.0);
  stroke(0.0, 0.0, 80.0, 100.0);
  rect(0.0, 0.0, width, height);
  noStroke();

}

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