diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3c7e452 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +/*/* +!/*/**/ +!/*/*.* +/*.kdev4 diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..70e0f55 --- /dev/null +++ b/build.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +set -e + +for dir in forest; do + echo "-- $dir --" + cd $dir + ./build.sh + cd .. +done + +echo "-- done --" diff --git a/forest/build.sh b/forest/build.sh new file mode 100755 index 0000000..507eb4a --- /dev/null +++ b/forest/build.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +set -e + +c++ -Wall -g -O0 `pkg-config --cflags --libs helianthus` *.c -o forest diff --git a/forest/tree.c b/forest/tree.c new file mode 100644 index 0000000..053356d --- /dev/null +++ b/forest/tree.c @@ -0,0 +1,139 @@ + +#include +#include +#include + + + + +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 = worldGetWidth(); + double h = worldGetHeight(); + t += worldGetFrameTime(); + + 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() { + worldSetVariableFrameRate(); + worldSetResizable(TRUE); + worldSetInit(&init); + worldSetDraw(&draw); + worldRun(); +} diff --git a/forest/tree.h b/forest/tree.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/forest/tree.h