Desert Rose.

Beautiful shapes made with computer programming code.

Processing generative art code makes beautiful shapes.



Description of this creative coding work.

A creative coding animation made with Processing.

When I was playing with 'node garden', I found it can draw an interesting shape with node lines.
And I built it into jewel box style.

This code does not display any images on the screen but just generates image files.
You can make an animation with these files.
But I wonder an animation fits this? A still image is better?

Processing code example.

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


/**
 * Desert Rose.
 * draw desert roses in the jewel box.
 * 
 * Processing 3.2.1
 * @author @deconbatch
 * @version 0.1
 * created 0.1 2019.03.31
 */

void setup() {
  size(720, 720);
  colorMode(HSB, 360.0, 100.0, 100.0, 100.0);
  smooth();
  noLoop();
}

void draw() {

  int   frameCntMax = 24 * 5;  // for 24fps x 5sec animation
  int   colCntMax   = 4;
  float gap         = 2.0;
  float colWidth    = (width - (colCntMax + 1) * gap) * 1.0 / colCntMax;
  float hueBase     = random(360.0);
  float hueDiv      = 90.0;

  // shape parameters
  float[][] pCorner = new float[colCntMax][colCntMax];
  float[][] pJoint  = new float[colCntMax][colCntMax];
  float[][] pSoft   = new float[colCntMax][colCntMax];
  float[][] pRotate = new float[colCntMax][colCntMax];
  float[][] pHue    = new float[colCntMax][colCntMax];
  
  // make colCntMax x colCntMax cells
  background(0.0, 0.0, 60.0, 100.0);
  blendMode(BLEND);
  for (int colCnt = 0; colCnt < colCntMax; ++colCnt) {
    for (int rowCnt = 0; rowCnt < colCntMax; ++rowCnt) {
      pCorner[colCnt][rowCnt] = random(1.0);
      pJoint[colCnt][rowCnt]  = random(1.0);
      pSoft[colCnt][rowCnt]   = random(1.0);
      pRotate[colCnt][rowCnt] = random(1.0);
      pHue[colCnt][rowCnt]    = ((colCnt + rowCnt) % 3) * hueDiv * 0.25
                              + ((colCnt + rowCnt * colCntMax) * 1.0 / (colCntMax * colCntMax - 1)) * hueDiv * 0.5;
      fill((hueBase + pHue[colCnt][rowCnt] + 270.0) % 360.0, 40.0, 10.0, 100.0);
      rect(gap + (gap + colWidth) * colCnt, gap + (gap + colWidth) * rowCnt, colWidth, colWidth);
    }
  }
  noFill();

  // for drawing animation
  blendMode(SCREEN);
  for (int frameCnt = 1; frameCnt < frameCntMax; ++frameCnt) {

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

    for (int colCnt = 0; colCnt < colCntMax; ++colCnt) {
      for (int rowCnt = 0; rowCnt < colCntMax; ++rowCnt) {
      
        float roseX       = gap + colWidth * 0.5 + (gap + colWidth) * colCnt;
        float roseY       = gap + colWidth * 0.5 + (gap + colWidth) * rowCnt;
        int   roseCorners = floor(map(pCorner[colCnt][rowCnt], 0.0, 1.0, 2.5, 7.5));
        int   roseJoints  = floor(map(pJoint[colCnt][rowCnt], 0.0, 1.0, 2.0, 6.0));
        float roseSize    = colWidth * map(pJoint[colCnt][rowCnt], 0.0, 1.0, 0.6, 0.4);
        float roseSoft    = map(pSoft[colCnt][rowCnt], 0.0, 1.0, 0.02, 0.15);
        float roseHue     = hueBase + pHue[colCnt][rowCnt];
    
        pushMatrix();
        translate(roseX, roseY);
        rotate(HALF_PI * pRotate[colCnt][rowCnt]);
        drawRose(roseCorners, roseJoints, roseSize, roseSoft, roseHue, frameRatio);
        popMatrix();
    
      }
    }
    saveFrame("frames/" + String.format("%04d", frameCnt) + ".png");
  }

  // make 24fps x 1sec no moving images
  for (int frameCnt = frameCntMax; frameCnt < frameCntMax + 24 * 1; ++frameCnt) {
    saveFrame("frames/" + String.format("%04d", frameCnt) + ".png");
  }

  // make twitter thumbnail image
  saveFrame("frames/0000.png");
  exit();

}

/**
 * drawRose : draw rose image.
 * @param  _corners   : corner count of rose.
 * @param  _joints    : joint count of rose.
 * @param  _roseSize  : size of rose.
 * @param  _softness  : 0.02 - 0.2 : shape softness.
 * @param  _hueBase   : hue value of rose.
 * @param  _drawRatio : 0.0 - 1.0 : drawing ratio of the total.
 * too many parameters!
 */
private void drawRose(int _corners, int _joints, float _roseSize, float _softness, float _hueBase, float _drawRatio) {

  // make node list
  NodeList[] jointNodes = new NodeList[_joints];
  for (int jointCnt = 0; jointCnt < _joints; ++jointCnt) {

    float jointRatio = map(jointCnt, 0, _joints, 0.0, 1.0);
    jointNodes[jointCnt] = new NodeList();

    for (int cornerCnt = 0; cornerCnt < _corners; ++cornerCnt) {

      float cornerRatio = map(cornerCnt, 0, _corners, 0.0, 1.0);
      float shapeFactor = sin(TWO_PI * (cornerRatio + _drawRatio));

      float centerSize = noise(_hueBase * _corners + _joints) * 0.6;  // random center hole size
      float direction  = noise(_hueBase * _joints + _corners) < 0.5 ? 1.0 : -1.0; // random rotate direction
      float nRadius = _roseSize * (centerSize + (1.0 - centerSize) * jointRatio);
      float nRadian = direction * TWO_PI * (cornerRatio + map(shapeFactor, -1.0, 1.0, -_softness, _softness));

      float nX = nRadius * cos(nRadian);
      float nY = nRadius * sin(nRadian);
    
      Node joint = new Node(new PVector(nX, nY));
      jointNodes[jointCnt].add(joint);

    }
  }

  // draw lines with node lists
  for (int jointCnt = 0; jointCnt < _joints - 1; ++jointCnt) {
    float jointRatio = map(jointCnt, 0, _joints - 1, 0.0, 1.0);
    jointNodes[jointCnt].drawLines(jointNodes[jointCnt + 1], _hueBase, jointRatio, 5.0 / (_corners + _joints));
  }
  
}

/**
 * Keep node information.
 * @param  _position : node position
 */
class Node {
  PVector position;
  Node(PVector _position) {
    position = new PVector();
    position.set(_position);
  }
}

/**
 * Keep nodes in one joint.
 * number of nodes = number of corners.
 * draw lines from some joint to other joint.
 * @param  _otherNodes : draw lines to this nodes.
 * @param  _hueBase    : hue value of lines.
 * @param  _jointRatio : 0.0 - 1.0 : joint ratio of the total. from center to outer.
 * @param  _density    : 0.0 - 1.0 : to control stroke weight. bigger = thick.
 */
import java.util.Iterator;
class NodeList extends ArrayList {
  void drawLines(NodeList _otherNodes, float _hueBase, float _jointRatio, float _density) {

    Iterator itNode = this.iterator();
    Iterator itOther = _otherNodes.iterator();

    strokeWeight(0.2 + _jointRatio * map(_density, 0.0, 1.0, 0.0, 1.2));
    stroke(
           (_hueBase + map(_jointRatio, 0.0, 1.0, -15.0, 15.0)) % 360.0,
           60.0 - 20.0 * _jointRatio,
           50.0 - 20.0 * _jointRatio,
           100.0
           );

    beginShape();
    while (itNode.hasNext()) {
      Node node = itNode.next();
      vertex(node.position.x, node.position.y);
      if ((itOther.hasNext())) {
        Node other = itOther.next();
        vertex(other.position.x, other.position.y);
      }
    }
    endShape(CLOSE);
  }
}

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