Blame projects/forest/tree.c

Ivan Mahonin dd8bf2
Ivan Mahonin dd8bf2
#include <math.h>
Ivan Mahonin dab153
#include <stdlib.h>
Ivan Mahonin dab153
#include <string.h>
Ivan Mahonin dd8bf2
Ivan Mahonin dab153
#include <helianthus.h>
Ivan Mahonin dd8bf2
Ivan Mahonin dab153
#include "tree.h"
Ivan Mahonin dd8bf2
Ivan Mahonin dd8bf2
Ivan Mahonin dab153
static const double segmentLength = 0.2;
Ivan Mahonin dab153
static const double segmentWidth = 0.004;
Ivan Mahonin dab153
static const double minWidth = 0.02;
Ivan Mahonin dab153
static const double rootWidth = 0.8;
Ivan Mahonin 815578
static const double branchesPerSegment = 0.2;
Ivan Mahonin dab153
static const double leafSize = 8;
Ivan Mahonin dab153
static const double leafPerBranch = 1;
Ivan Mahonin dab153
static const double leafThreshold = 0.02 + 8/4/0.2*0.004; // minWidth + leafSize/4/segmentLength*segmentWidth
Ivan Mahonin dd8bf2
Ivan Mahonin dd8bf2
Ivan Mahonin dab153
static double randomRange(double min, double max)
Ivan Mahonin dd8bf2
  { return randomFloat()*(max - min) + min; }
Ivan Mahonin dd8bf2
Ivan Mahonin dab153
static double randomIncrement(double deviation)
Ivan Mahonin dd8bf2
  { return randomRange(-deviation, deviation); }
Ivan Mahonin dd8bf2
Ivan Mahonin dab153
static double randomAmplifier(double deviation)
Ivan Mahonin dd8bf2
  { return randomRange(1 - deviation, 1 + deviation); }
Ivan Mahonin dd8bf2
Ivan Mahonin dd8bf2
Ivan Mahonin dab153
static void leaf(double x, double y, double size) {
Ivan Mahonin dd8bf2
  double r = 0.5*size;//*randomAmplifier(0.5);
Ivan Mahonin dd8bf2
  saveState();
Ivan Mahonin dd8bf2
  noStroke();
Ivan Mahonin dd8bf2
  circle(x, y, r);
Ivan Mahonin dd8bf2
  restoreState();
Ivan Mahonin dd8bf2
}
Ivan Mahonin dd8bf2
Ivan Mahonin dd8bf2
Ivan Mahonin 815578
static void branch(double x, double y, double angle, double width, double time, int flags) {
Ivan Mahonin dab153
  double da = sin(time*randomRange(0.5, 1) + randomIncrement(PI));
Ivan Mahonin dd8bf2
Ivan Mahonin dd8bf2
  saveState();
Ivan Mahonin dd8bf2
  while(TRUE) {
Ivan Mahonin dd8bf2
    double length = segmentLength * randomAmplifier(0.1);
Ivan Mahonin dd8bf2
Ivan Mahonin dd8bf2
    double s = sin(angle/180*PI);
Ivan Mahonin dd8bf2
    double c = cos(angle/180*PI);
Ivan Mahonin dd8bf2
    double nx = x + c*length;
Ivan Mahonin dd8bf2
    double ny = y + s*length;
Ivan Mahonin dd8bf2
    double nw = width - segmentWidth;
Ivan Mahonin dd8bf2
    strokeWidth(width);
Ivan Mahonin dd8bf2
    line(x, y, nx, ny);
Ivan Mahonin dd8bf2
Ivan Mahonin dd8bf2
    if (width > leafThreshold && nw <= leafThreshold && randomFloat() < leafPerBranch && y > leafSize/2) {
Ivan Mahonin dd8bf2
      double dl = randomRange(0, length);
Ivan Mahonin dd8bf2
      leaf(x + c*dl, y + s*dl, leafSize);
Ivan Mahonin dd8bf2
    }
Ivan Mahonin dd8bf2
Ivan Mahonin dd8bf2
    if (width < minWidth || ny < 0)
Ivan Mahonin dd8bf2
      break;
Ivan Mahonin dd8bf2
Ivan Mahonin dd8bf2
    x = nx;
Ivan Mahonin dd8bf2
    y = ny;
Ivan Mahonin dd8bf2
    s += randomRange(0, 0.2);
Ivan Mahonin dd8bf2
    c += randomIncrement(0.15);
Ivan Mahonin dd8bf2
    angle = atan2(s, c)/PI*180;
Ivan Mahonin dd8bf2
    width -= segmentWidth;
Ivan Mahonin dd8bf2
Ivan Mahonin dd8bf2
    translate(x, y);
Ivan Mahonin dd8bf2
    rotate(da*pow(minWidth/width, 2));
Ivan Mahonin dd8bf2
    translate(-x, -y);
Ivan Mahonin dd8bf2
Ivan Mahonin dd8bf2
    if (randomFloat() < branchesPerSegment) {
Ivan Mahonin 815578
      double k = randomRange(0, 0.3);
Ivan Mahonin dd8bf2
      double w = sqrt(width*width*k);
Ivan Mahonin dd8bf2
      if (w > minWidth) {
Ivan Mahonin dd8bf2
        width = sqrt(width*width*(1-k));
Ivan Mahonin dd8bf2
        double a = randomNumber(0, 1) ? angle - 90 + randomRange(0, 45)
Ivan Mahonin dd8bf2
                                      : angle + 90 - randomRange(0, 45);
Ivan Mahonin 815578
        branch(x, y, a, w, time, flags);
Ivan Mahonin dd8bf2
      }
Ivan Mahonin dd8bf2
    }
Ivan Mahonin dd8bf2
  }
Ivan Mahonin dd8bf2
  restoreState();
Ivan Mahonin dd8bf2
}
Ivan Mahonin dd8bf2
Ivan Mahonin dd8bf2
Ivan Mahonin 3395b9
void treeGenerate(Tree *t, double x, double y) {
Ivan Mahonin dab153
  memset(t, 0, sizeof(*t));
Ivan Mahonin dab153
  t->seed = rand();
Ivan Mahonin 3395b9
  t->x = x;
Ivan Mahonin 3395b9
  t->y = y;
Ivan Mahonin dab153
  t->angle = 90 + randomIncrement(30);
Ivan Mahonin dab153
  t->width = rootWidth*randomAmplifier(0.5);
Ivan Mahonin dd8bf2
}
Ivan Mahonin dd8bf2
Ivan Mahonin dd8bf2
Ivan Mahonin 3395b9
void treeDraw(const Tree *t, double time, int flags) {
Ivan Mahonin dd8bf2
  saveState();
Ivan Mahonin dab153
  translate(t->x, t->y);
Ivan Mahonin 815578
  
Ivan Mahonin de7236
  fill(colorByRGBA(0, 0.5, 0, 0.5));
Ivan Mahonin de7236
  stroke(COLOR_BLACK);
Ivan Mahonin 815578
  srand(t->seed);
Ivan Mahonin de7236
  branch(0, 0, t->angle, t->width, time, flags);
Ivan Mahonin 815578
  
Ivan Mahonin 815578
  restoreState();
Ivan Mahonin 815578
}
Ivan Mahonin dd8bf2
Ivan Mahonin dab153
Ivan Mahonin 815578
void treePrerender(Tree *t, Framebuffer fb) {
Ivan Mahonin 815578
  srand(t->seed);
Ivan Mahonin 815578
  branch(0, 0, t->angle, t->width, 0, FLAG_BOUNDS);
Ivan Mahonin dd8bf2
}
Ivan Mahonin dd8bf2
Ivan Mahonin 815578
Ivan Mahonin 815578
void treeDrawPrerendered(Tree *t);