|
|
e5cc64 |
|
|
|
e5cc64 |
#include <stdlib.h></stdlib.h>
|
|
|
e5cc64 |
#include <math.h></math.h>
|
|
|
e5cc64 |
#include <helianthus.h></helianthus.h>
|
|
|
e5cc64 |
|
|
|
e5cc64 |
|
|
|
e5cc64 |
|
|
|
e5cc64 |
|
|
|
e5cc64 |
int seed;
|
|
|
e5cc64 |
double t;
|
|
|
e5cc64 |
|
|
|
e5cc64 |
const double segmentLength = 5;
|
|
|
e5cc64 |
const double segmentWidth = 0.05;
|
|
|
e5cc64 |
const double minWidth = 0.5;
|
|
|
e5cc64 |
const double branchesPerSegment = 0.2;
|
|
|
e5cc64 |
const double leafSize = 200;
|
|
|
e5cc64 |
const double leafPerBranch = 1;
|
|
|
e5cc64 |
const double leafThreshold = 1 + 200/5*0.05/4*0.5;
|
|
|
e5cc64 |
|
|
|
e5cc64 |
|
|
|
e5cc64 |
double randomRange(double min, double max)
|
|
|
e5cc64 |
{ return randomFloat()*(max - min) + min; }
|
|
|
e5cc64 |
|
|
|
e5cc64 |
double randomIncrement(double deviation)
|
|
|
e5cc64 |
{ return randomRange(-deviation, deviation); }
|
|
|
e5cc64 |
|
|
|
e5cc64 |
double randomAmplifier(double deviation)
|
|
|
e5cc64 |
{ return randomRange(1 - deviation, 1 + deviation); }
|
|
|
e5cc64 |
|
|
|
e5cc64 |
|
|
|
e5cc64 |
void leaf(double x, double y, double size) {
|
|
|
e5cc64 |
double r = 0.5*size;//*randomAmplifier(0.5);
|
|
|
e5cc64 |
saveState();
|
|
|
e5cc64 |
noStroke();
|
|
|
e5cc64 |
circle(x, y, r);
|
|
|
e5cc64 |
restoreState();
|
|
|
e5cc64 |
}
|
|
|
e5cc64 |
|
|
|
e5cc64 |
|
|
|
e5cc64 |
void branch(double x, double y, double angle, double width) {
|
|
|
e5cc64 |
double da = sin(t*randomRange(0.5, 1) + randomIncrement(PI));
|
|
|
e5cc64 |
|
|
|
e5cc64 |
saveState();
|
|
|
e5cc64 |
while(TRUE) {
|
|
|
e5cc64 |
double length = segmentLength * randomAmplifier(0.1);
|
|
|
e5cc64 |
|
|
|
e5cc64 |
double s = sin(angle/180*PI);
|
|
|
e5cc64 |
double c = cos(angle/180*PI);
|
|
|
e5cc64 |
double nx = x + c*length;
|
|
|
e5cc64 |
double ny = y + s*length;
|
|
|
e5cc64 |
double nw = width - segmentWidth;
|
|
|
e5cc64 |
strokeWidth(width);
|
|
|
e5cc64 |
line(x, y, nx, ny);
|
|
|
e5cc64 |
|
|
|
e5cc64 |
if (width > leafThreshold && nw <= leafThreshold && randomFloat() < leafPerBranch && y > leafSize/2) {
|
|
|
e5cc64 |
double dl = randomRange(0, length);
|
|
|
e5cc64 |
leaf(x + c*dl, y + s*dl, leafSize);
|
|
|
e5cc64 |
}
|
|
|
e5cc64 |
|
|
|
e5cc64 |
if (width < minWidth || ny < 0)
|
|
|
e5cc64 |
break;
|
|
|
e5cc64 |
|
|
|
e5cc64 |
x = nx;
|
|
|
e5cc64 |
y = ny;
|
|
|
e5cc64 |
s += randomRange(0, 0.2);
|
|
|
e5cc64 |
c += randomIncrement(0.15);
|
|
|
e5cc64 |
angle = atan2(s, c)/PI*180;
|
|
|
e5cc64 |
width -= segmentWidth;
|
|
|
e5cc64 |
|
|
|
e5cc64 |
translate(x, y);
|
|
|
e5cc64 |
rotate(da*pow(minWidth/width, 2));
|
|
|
e5cc64 |
translate(-x, -y);
|
|
|
e5cc64 |
|
|
|
e5cc64 |
if (randomFloat() < branchesPerSegment) {
|
|
|
e5cc64 |
double k = randomRange(0.1, 0.3);
|
|
|
e5cc64 |
double w = sqrt(width*width*k);
|
|
|
e5cc64 |
if (w > minWidth) {
|
|
|
e5cc64 |
width = sqrt(width*width*(1-k));
|
|
|
e5cc64 |
double a = randomNumber(0, 1) ? angle - 90 + randomRange(0, 45)
|
|
|
e5cc64 |
: angle + 90 - randomRange(0, 45);
|
|
|
e5cc64 |
branch(x, y, a, w);
|
|
|
e5cc64 |
}
|
|
|
e5cc64 |
}
|
|
|
e5cc64 |
}
|
|
|
e5cc64 |
restoreState();
|
|
|
e5cc64 |
}
|
|
|
e5cc64 |
|
|
|
e5cc64 |
|
|
|
e5cc64 |
void tree(int seed, double x, double y, double width) {
|
|
|
e5cc64 |
srand(seed);
|
|
|
e5cc64 |
double angle = 90 + randomIncrement(30);
|
|
|
e5cc64 |
width *= randomAmplifier(0.5);
|
|
|
e5cc64 |
int s = randomNumber(0, 1000000);
|
|
|
e5cc64 |
|
|
|
e5cc64 |
saveState();
|
|
|
e5cc64 |
noStroke();
|
|
|
e5cc64 |
srand(s);
|
|
|
e5cc64 |
branch(x, y, angle, width);
|
|
|
e5cc64 |
restoreState();
|
|
|
e5cc64 |
|
|
|
e5cc64 |
saveState();
|
|
|
e5cc64 |
noFill();
|
|
|
e5cc64 |
srand(s);
|
|
|
e5cc64 |
branch(x, y, angle, width);
|
|
|
e5cc64 |
restoreState();
|
|
|
e5cc64 |
}
|
|
|
e5cc64 |
|
|
|
e5cc64 |
|
|
|
e5cc64 |
void init() {
|
|
|
e5cc64 |
seed = randomNumber(0, 1000000);
|
|
|
e5cc64 |
}
|
|
|
e5cc64 |
|
|
|
e5cc64 |
|
|
|
e5cc64 |
void draw() {
|
|
|
ef1455 |
double w = windowGetWidth();
|
|
|
ef1455 |
double h = windowGetHeight();
|
|
|
ef1455 |
t += windowGetFrameTime();
|
|
|
e5cc64 |
|
|
|
e5cc64 |
if (keyWentDown("space")) seed = randomNumber(0, 1000000);
|
|
|
e5cc64 |
|
|
|
e5cc64 |
saveState();
|
|
|
e5cc64 |
translate(w/2, h*0.9);
|
|
|
e5cc64 |
scale(1, -1);
|
|
|
e5cc64 |
|
|
|
e5cc64 |
fill(colorByName("green"));
|
|
|
e5cc64 |
stroke(colorByName("black"));
|
|
|
e5cc64 |
tree(seed, 0, 0, 20);
|
|
|
e5cc64 |
|
|
|
e5cc64 |
restoreState();
|
|
|
e5cc64 |
}
|
|
|
e5cc64 |
|
|
|
e5cc64 |
|
|
|
e5cc64 |
int main() {
|
|
|
ef1455 |
windowSetVariableFrameRate();
|
|
|
ef1455 |
windowSetResizable(TRUE);
|
|
|
ef1455 |
windowSetInit(&init);
|
|
|
ef1455 |
windowSetDraw(&draw);
|
|
|
ef1455 |
windowRun();
|
|
|
e5cc64 |
}
|