Blame projects/forest/tree.c

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