Blob Blame Raw

#include <stdlib.h>
#include <math.h>
#include <helianthus.h>




int seed;
double t;

const double segmentLength = 5;
const double segmentWidth = 0.05;
const double minWidth = 0.5;
const double branchesPerSegment = 0.2;
const double leafSize = 200;
const double leafPerBranch = 1;
const double leafThreshold = 1 + 200/5*0.05/4*0.5;


double randomRange(double min, double max)
  { return randomFloat()*(max - min) + min; }

double randomIncrement(double deviation)
  { return randomRange(-deviation, deviation); }

double randomAmplifier(double deviation)
  { return randomRange(1 - deviation, 1 + deviation); }


void leaf(double x, double y, double size) {
  double r = 0.5*size;//*randomAmplifier(0.5);
  saveState();
  noStroke();
  circle(x, y, r);
  restoreState();
}


void branch(double x, double y, double angle, double width) {
  double da = sin(t*randomRange(0.5, 1) + randomIncrement(PI));

  saveState();
  while(TRUE) {
    double length = segmentLength * randomAmplifier(0.1);

    double s = sin(angle/180*PI);
    double c = cos(angle/180*PI);
    double nx = x + c*length;
    double ny = y + s*length;
    double nw = width - segmentWidth;
    strokeWidth(width);
    line(x, y, nx, ny);

    if (width > leafThreshold && nw <= leafThreshold && randomFloat() < leafPerBranch && y > leafSize/2) {
      double dl = randomRange(0, length);
      leaf(x + c*dl, y + s*dl, leafSize);
    }

    if (width < minWidth || ny < 0)
      break;

    x = nx;
    y = ny;
    s += randomRange(0, 0.2);
    c += randomIncrement(0.15);
    angle = atan2(s, c)/PI*180;
    width -= segmentWidth;

    translate(x, y);
    rotate(da*pow(minWidth/width, 2));
    translate(-x, -y);

    if (randomFloat() < branchesPerSegment) {
      double k = randomRange(0.1, 0.3);
      double w = sqrt(width*width*k);
      if (w > minWidth) {
        width = sqrt(width*width*(1-k));
        double a = randomNumber(0, 1) ? angle - 90 + randomRange(0, 45)
                                      : angle + 90 - randomRange(0, 45);
        branch(x, y, a, w);
      }
    }
  }
  restoreState();
}


void tree(int seed, double x, double y, double width) {
  srand(seed);
  double angle = 90 + randomIncrement(30);
  width *= randomAmplifier(0.5);
  int s = randomNumber(0, 1000000);

  saveState();
  noStroke();
  srand(s);
  branch(x, y, angle, width);
  restoreState();

  saveState();
  noFill();
  srand(s);
  branch(x, y, angle, width);
  restoreState();
}


void init() {
  seed = randomNumber(0, 1000000);
}


void draw() {
  double w = windowGetWidth();
  double h = windowGetHeight();
  t += windowGetFrameTime();

  if (keyWentDown("space")) seed = randomNumber(0, 1000000);

  saveState();
  translate(w/2, h*0.9);
  scale(1, -1);

  fill(colorByName("green"));
  stroke(colorByName("black"));
  tree(seed, 0, 0, 20);

  restoreState();
}


int main() {
  windowSetTitle("Tree");
  windowSetVariableFrameRate();
  windowSetResizable(TRUE);
  windowSetInit(&init);
  windowSetDraw(&draw);
  windowRun();
}