diff --git a/.gitignore b/.gitignore index 3c7e452..3681d41 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ -/*/* -!/*/**/ -!/*/*.* -/*.kdev4 +* +!**/ +!*.* +*.o +*.kdev4 diff --git a/forest/build.sh b/forest/build.sh deleted file mode 100755 index 507eb4a..0000000 --- a/forest/build.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash - -set -e - -c++ -Wall -g -O0 `pkg-config --cflags --libs helianthus` *.c -o forest diff --git a/forest/chunk.c b/forest/chunk.c deleted file mode 100644 index 4875a2b..0000000 --- a/forest/chunk.c +++ /dev/null @@ -1,89 +0,0 @@ - -#include -#include -#include - -#include - -#include "chunk.h" - - -static void pregenerate(Chunk *c, int rootSeed, int index) { - c->index = index; - srand(c->index ^ rootSeed); - c->x = c->index*CHUNK_WIDTH; - c->width = CHUNK_WIDTH; - c->dy = (randomFloat()*2 - 1)*CHUNK_HEIGHT; - c->seed = rand(); -} - -static void generateGround(double *p0, double *p1, double dh) { - double *p = p0 + (p1 - p0)/2; - if (p1 <= p0 || p == p0) return; - *p = (*p0 + *p1)*0.5 + dh*(randomFloat()*2 - 1); - generateGround(p0, p, 0.5*dh); - generateGround(p, p1, 0.5*dh); -} - - -void chunkGenerate(Chunk *c, int rootSeed, const Chunk *base, int offset) { - if (base == c) return; - - memset(c, 0, sizeof(*c)); - - if (base) { - c->index = base->index; - c->seed = base->seed; - c->dy = base->dy; - c->y = base->y; - } else { - pregenerate(c, rootSeed, 0); - } - while(offset > 0) { c->y += c->dy; pregenerate(c, rootSeed, c->index + 1); --offset; } - while(offset < 0) { pregenerate(c, rootSeed, c->index - 1); c->y -= c->dy; ++offset; } - - srand(c->seed); - - double *p0 = &c->ground[0]; - double *p1 = &c->ground[CHUNK_GROUND_POINTS - 1]; - *p0 = 0; *p1 = c->dy; - generateGround(p0, p1, 0.5*CHUNK_HEIGHT); - - c->treeCount = randomNumber(0, CHUNK_MAX_TREES); - for(int i = 0; i < c->treeCount; ++i) { - double x = randomFloat()*c->width; - double y = chunkGroundLevel(c, c->x + x) - c->y; - treeGenerate(&c->trees[i], x, y); - } -} - - -double chunkGroundLevel(const Chunk *c, double x) { - double xp = (x - c->x)/c->width*(CHUNK_GROUND_POINTS-1); - int xi = floor(xp); - if (xi < 0) xi = 0; - if (xi > CHUNK_GROUND_POINTS-2) xi = CHUNK_GROUND_POINTS-2; - xp -= xi; - return c->y + c->ground[xi]*(1 - xp) + c->ground[xi + 1]*xp; -} - - -void chunkDraw(const Chunk *c, double time, int flags) { - saveState(); - translate(c->x, c->y); - - if (flags && FLAG_GROUND) { - double step = c->width/(double)(CHUNK_GROUND_POINTS-1); - moveTo(0, c->ground[0]); - for(int i = 1; i < CHUNK_GROUND_POINTS; ++i) - lineTo(i*step, c->ground[i]); - strokePath(); - } - - if (flags & (FLAG_LEAVES | FLAG_BRANCHES)) - for(int i = 0; i < c->treeCount; ++i) - treeDraw(&c->trees[i], time, flags); - - restoreState(); -} - diff --git a/forest/chunk.h b/forest/chunk.h deleted file mode 100644 index 6bb4cb4..0000000 --- a/forest/chunk.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef CHUNK_H -#define CHUNK_H - - -#include "common.h" -#include "tree.h" - - -#define CHUNK_WIDTH 10 -#define CHUNK_HEIGHT 2 -#define CHUNK_GROUND_SUBDIVISIONS 3 -#define CHUNK_GROUND_POINTS ((1 << CHUNK_GROUND_SUBDIVISIONS) + 1) -#define CHUNK_MAX_TREES 1 - - -typedef struct { - int index; - int seed; - - double x, y; - double width; - double dy; - double ground[CHUNK_GROUND_POINTS]; - - int treeCount; - Tree trees[CHUNK_MAX_TREES]; -} Chunk; - - -void chunkGenerate(Chunk *c, int rootSeed, const Chunk *base, int offset); -double chunkGroundLevel(const Chunk *c, double x); -void chunkDraw(const Chunk *c, double time, int flags); - - -#endif diff --git a/forest/common.h b/forest/common.h deleted file mode 100644 index d7565ba..0000000 --- a/forest/common.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef COMMON_H -#define COMMON_H - - -#define FLAG_GROUND 1 -#define FLAG_LEAVES 2 -#define FLAG_BRANCHES 4 - - -#endif diff --git a/forest/main.c b/forest/main.c deleted file mode 100644 index 7954881..0000000 --- a/forest/main.c +++ /dev/null @@ -1,132 +0,0 @@ - -#include -#include -#include -#include - -#include - -#include "chunk.h" - - -#define COUNT 100 - -double t; -double x, y; -double vx = 100, vy = 0; - -int rootSeed; - -Chunk chunks[COUNT]; - - -void initChunks() { - srand(time(NULL)); - rootSeed = rand(); - Chunk *c = &chunks[0]; - chunkGenerate(c, rootSeed, NULL, -COUNT/2); - for(int i = 1; i < COUNT; ++i, ++c) - chunkGenerate(c+1, rootSeed, c, 1); -} - - -void prepareChunks(double x) { - Chunk *first = chunks, *last = first + COUNT - 1; - int i0 = (int)floor(x/CHUNK_WIDTH) - COUNT/2; - int offset = i0 - chunks[0].index; - - if (offset < 0) { - Chunk *next = last, *prev = first; - if (offset > -COUNT) { - memmove(first - offset, first, sizeof(*chunks)*(COUNT + offset)); - prev = first - offset; - next = prev - 1; - offset = 1; - } - while(next >= first) - { chunkGenerate(next, rootSeed, prev, offset); prev = next--; offset = -1; } - } else - if (offset > 0) { - Chunk *next = first, *prev = last; - if (offset < COUNT) { - memmove(first, first + offset, sizeof(*chunks)*(COUNT - offset)); - prev = last - offset; - next = prev + 1; - offset = 1; - } else { - offset -= COUNT - 1; - } - while(next <= last) - { chunkGenerate(next, rootSeed, prev, offset); prev = next++; offset = 1; } - } -} - - -void drawChunks(double x, double range, double t) { - range += 5*2; - int i0 = (int)floor((x - 0.5*range)/CHUNK_WIDTH) - chunks->index; - int i1 = (int)floor((x + 0.5*range)/CHUNK_WIDTH) - chunks->index + 1; - if (i0 < 0) i0 = 0; - if (i1 > COUNT) i1 = COUNT; - - for(int i = i0; i < i1; ++i) chunkDraw(&chunks[i], t, FLAG_GROUND); - //for(int i = i0; i < i1; ++i) chunkDraw(&chunks[i], t, FLAG_LEAVES); - for(int i = i0; i < i1; ++i) chunkDraw(&chunks[i], t, FLAG_BRANCHES); -} - - -double groundLevel(double x) { - int i = (int)floor(x/CHUNK_WIDTH) - chunks->index; - if (i < 0) return chunks->y; - if (i > COUNT-1) return chunks[COUNT-1].y + chunks[COUNT-1].dy; - return chunkGroundLevel(&chunks[i], x); -} - - -void init() { - initChunks(); -} - - -void draw() { - double dt = worldGetFrameTime(); - t += dt; - int w = worldGetWidth(); - int h = worldGetHeight(); - double range = w; - - double gy = groundLevel(x); - vy = 0.5*(gy - y + 20); - x += dt*vx; - y += dt*vy; - - - if (keyWentDown("space")) initChunks(); - if (keyWentDown("right")) x += 10; - if (keyWentDown("left")) x -= 10; - if (keyWentDown("up")) y += 10; - if (keyWentDown("down")) y -= 10; - - saveState(); - translate(0.5*w, 0.5*h); - zoom(10); - scale(1, -1); - translate(-x, -y); - range /= 10; - - prepareChunks(x); - drawChunks(x, range, t); - - restoreState(); -} - - -int main() { - worldSetVariableFrameRate(); - worldSetResizable(TRUE); - worldSetInit(&init); - worldSetDraw(&draw); - worldRun(); - return 0; -} - diff --git a/forest/tree.c b/forest/tree.c deleted file mode 100644 index 3e68e2b..0000000 --- a/forest/tree.c +++ /dev/null @@ -1,119 +0,0 @@ - -#include -#include -#include - -#include - -#include "tree.h" - - -static const double segmentLength = 0.2; -static const double segmentWidth = 0.004; -static const double minWidth = 0.02; -static const double rootWidth = 0.8; -static const double branchesPerSegment = 0.05; -static const double leafSize = 8; -static const double leafPerBranch = 1; -static const double leafThreshold = 0.02 + 8/4/0.2*0.004; // minWidth + leafSize/4/segmentLength*segmentWidth - - -static double randomRange(double min, double max) - { return randomFloat()*(max - min) + min; } - -static double randomIncrement(double deviation) - { return randomRange(-deviation, deviation); } - -static double randomAmplifier(double deviation) - { return randomRange(1 - deviation, 1 + deviation); } - - -static void leaf(double x, double y, double size) { - double r = 0.5*size;//*randomAmplifier(0.5); - saveState(); - noStroke(); - circle(x, y, r); - restoreState(); -} - - -static void branch(double x, double y, double angle, double width, double time) { - double da = sin(time*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, time); - } - } - } - restoreState(); -} - - -void treeGenerate(Tree *t, double x, double y) { - memset(t, 0, sizeof(*t)); - t->seed = rand(); - t->x = x; - t->y = y; - t->angle = 90 + randomIncrement(30); - t->width = rootWidth*randomAmplifier(0.5); -} - - -void treeDraw(const Tree *t, double time, int flags) { - saveState(); - translate(t->x, t->y); - - if (flags & FLAG_LEAVES) { - fill(colorByName("green")); - noStroke(); - srand(t->seed); - branch(0, 0, t->angle, t->width, time); - } - - if (flags & FLAG_BRANCHES) { - noFill(); - stroke(colorByName("black")); - srand(t->seed); - branch(0, 0, t->angle, t->width, time); - } - - restoreState(); -} - diff --git a/forest/tree.h b/forest/tree.h deleted file mode 100644 index 2aa57bc..0000000 --- a/forest/tree.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef TREE_H -#define TREE_H - - -#include "common.h" - - -typedef struct { - int seed; - double x, y; - double angle; - double width; -} Tree; - - -void treeGenerate(Tree *t, double x, double y); -void treeDraw(const Tree *t, double time, int flags); - - -#endif diff --git a/projects/forest/build.sh b/projects/forest/build.sh new file mode 100755 index 0000000..507eb4a --- /dev/null +++ b/projects/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/projects/forest/chunk.c b/projects/forest/chunk.c new file mode 100644 index 0000000..4875a2b --- /dev/null +++ b/projects/forest/chunk.c @@ -0,0 +1,89 @@ + +#include +#include +#include + +#include + +#include "chunk.h" + + +static void pregenerate(Chunk *c, int rootSeed, int index) { + c->index = index; + srand(c->index ^ rootSeed); + c->x = c->index*CHUNK_WIDTH; + c->width = CHUNK_WIDTH; + c->dy = (randomFloat()*2 - 1)*CHUNK_HEIGHT; + c->seed = rand(); +} + +static void generateGround(double *p0, double *p1, double dh) { + double *p = p0 + (p1 - p0)/2; + if (p1 <= p0 || p == p0) return; + *p = (*p0 + *p1)*0.5 + dh*(randomFloat()*2 - 1); + generateGround(p0, p, 0.5*dh); + generateGround(p, p1, 0.5*dh); +} + + +void chunkGenerate(Chunk *c, int rootSeed, const Chunk *base, int offset) { + if (base == c) return; + + memset(c, 0, sizeof(*c)); + + if (base) { + c->index = base->index; + c->seed = base->seed; + c->dy = base->dy; + c->y = base->y; + } else { + pregenerate(c, rootSeed, 0); + } + while(offset > 0) { c->y += c->dy; pregenerate(c, rootSeed, c->index + 1); --offset; } + while(offset < 0) { pregenerate(c, rootSeed, c->index - 1); c->y -= c->dy; ++offset; } + + srand(c->seed); + + double *p0 = &c->ground[0]; + double *p1 = &c->ground[CHUNK_GROUND_POINTS - 1]; + *p0 = 0; *p1 = c->dy; + generateGround(p0, p1, 0.5*CHUNK_HEIGHT); + + c->treeCount = randomNumber(0, CHUNK_MAX_TREES); + for(int i = 0; i < c->treeCount; ++i) { + double x = randomFloat()*c->width; + double y = chunkGroundLevel(c, c->x + x) - c->y; + treeGenerate(&c->trees[i], x, y); + } +} + + +double chunkGroundLevel(const Chunk *c, double x) { + double xp = (x - c->x)/c->width*(CHUNK_GROUND_POINTS-1); + int xi = floor(xp); + if (xi < 0) xi = 0; + if (xi > CHUNK_GROUND_POINTS-2) xi = CHUNK_GROUND_POINTS-2; + xp -= xi; + return c->y + c->ground[xi]*(1 - xp) + c->ground[xi + 1]*xp; +} + + +void chunkDraw(const Chunk *c, double time, int flags) { + saveState(); + translate(c->x, c->y); + + if (flags && FLAG_GROUND) { + double step = c->width/(double)(CHUNK_GROUND_POINTS-1); + moveTo(0, c->ground[0]); + for(int i = 1; i < CHUNK_GROUND_POINTS; ++i) + lineTo(i*step, c->ground[i]); + strokePath(); + } + + if (flags & (FLAG_LEAVES | FLAG_BRANCHES)) + for(int i = 0; i < c->treeCount; ++i) + treeDraw(&c->trees[i], time, flags); + + restoreState(); +} + diff --git a/projects/forest/chunk.h b/projects/forest/chunk.h new file mode 100644 index 0000000..6bb4cb4 --- /dev/null +++ b/projects/forest/chunk.h @@ -0,0 +1,35 @@ +#ifndef CHUNK_H +#define CHUNK_H + + +#include "common.h" +#include "tree.h" + + +#define CHUNK_WIDTH 10 +#define CHUNK_HEIGHT 2 +#define CHUNK_GROUND_SUBDIVISIONS 3 +#define CHUNK_GROUND_POINTS ((1 << CHUNK_GROUND_SUBDIVISIONS) + 1) +#define CHUNK_MAX_TREES 1 + + +typedef struct { + int index; + int seed; + + double x, y; + double width; + double dy; + double ground[CHUNK_GROUND_POINTS]; + + int treeCount; + Tree trees[CHUNK_MAX_TREES]; +} Chunk; + + +void chunkGenerate(Chunk *c, int rootSeed, const Chunk *base, int offset); +double chunkGroundLevel(const Chunk *c, double x); +void chunkDraw(const Chunk *c, double time, int flags); + + +#endif diff --git a/projects/forest/common.h b/projects/forest/common.h new file mode 100644 index 0000000..ceb53bb --- /dev/null +++ b/projects/forest/common.h @@ -0,0 +1,11 @@ +#ifndef COMMON_H +#define COMMON_H + + +#define FLAG_GROUND 1 +#define FLAG_LEAVES 2 +#define FLAG_BRANCHES 4 +#define FLAG_BOUNDS 8 + + +#endif diff --git a/projects/forest/main.c b/projects/forest/main.c new file mode 100644 index 0000000..c34f0f5 --- /dev/null +++ b/projects/forest/main.c @@ -0,0 +1,132 @@ + +#include +#include +#include +#include + +#include + +#include "chunk.h" + + +#define COUNT 100 + +double t; +double x, y; +double vx = 10, vy = 0; + +int rootSeed; + +Chunk chunks[COUNT]; + + +void initChunks() { + srand(time(NULL)); + rootSeed = rand(); + Chunk *c = &chunks[0]; + chunkGenerate(c, rootSeed, NULL, -COUNT/2); + for(int i = 1; i < COUNT; ++i, ++c) + chunkGenerate(c+1, rootSeed, c, 1); +} + + +void prepareChunks(double x) { + Chunk *first = chunks, *last = first + COUNT - 1; + int i0 = (int)floor(x/CHUNK_WIDTH) - COUNT/2; + int offset = i0 - chunks[0].index; + + if (offset < 0) { + Chunk *next = last, *prev = first; + if (offset > -COUNT) { + memmove(first - offset, first, sizeof(*chunks)*(COUNT + offset)); + prev = first - offset; + next = prev - 1; + offset = 1; + } + while(next >= first) + { chunkGenerate(next, rootSeed, prev, offset); prev = next--; offset = -1; } + } else + if (offset > 0) { + Chunk *next = first, *prev = last; + if (offset < COUNT) { + memmove(first, first + offset, sizeof(*chunks)*(COUNT - offset)); + prev = last - offset; + next = prev + 1; + offset = 1; + } else { + offset -= COUNT - 1; + } + while(next <= last) + { chunkGenerate(next, rootSeed, prev, offset); prev = next++; offset = 1; } + } +} + + +void drawChunks(double x, double range, double t) { + range += 5*2; + int i0 = (int)floor((x - 0.5*range)/CHUNK_WIDTH) - chunks->index; + int i1 = (int)floor((x + 0.5*range)/CHUNK_WIDTH) - chunks->index + 1; + if (i0 < 0) i0 = 0; + if (i1 > COUNT) i1 = COUNT; + + for(int i = i0; i < i1; ++i) chunkDraw(&chunks[i], t, FLAG_GROUND); + //for(int i = i0; i < i1; ++i) chunkDraw(&chunks[i], t, FLAG_LEAVES); + for(int i = i0; i < i1; ++i) chunkDraw(&chunks[i], t, FLAG_BRANCHES); +} + + +double groundLevel(double x) { + int i = (int)floor(x/CHUNK_WIDTH) - chunks->index; + if (i < 0) return chunks->y; + if (i > COUNT-1) return chunks[COUNT-1].y + chunks[COUNT-1].dy; + return chunkGroundLevel(&chunks[i], x); +} + + +void init() { + initChunks(); +} + + +void draw() { + double dt = worldGetFrameTime(); + t += dt; + int w = worldGetWidth(); + int h = worldGetHeight(); + double range = w; + + double gy = groundLevel(x); + vy = 0.5*(gy - y + 20); + x += dt*vx; + y += dt*vy; + + + if (keyWentDown("space")) initChunks(); + if (keyWentDown("right")) x += 10; + if (keyWentDown("left")) x -= 10; + if (keyWentDown("up")) y += 10; + if (keyWentDown("down")) y -= 10; + + saveState(); + translate(0.5*w, 0.5*h); + zoom(10); + scale(1, -1); + translate(-x, -y); + range /= 10; + + prepareChunks(x); + drawChunks(x, range, t); + + restoreState(); +} + + +int main() { + worldSetVariableFrameRate(); + worldSetResizable(TRUE); + worldSetInit(&init); + worldSetDraw(&draw); + worldRun(); + return 0; +} + diff --git a/projects/forest/tree.c b/projects/forest/tree.c new file mode 100644 index 0000000..2a4c2f1 --- /dev/null +++ b/projects/forest/tree.c @@ -0,0 +1,118 @@ + +#include +#include +#include + +#include + +#include "tree.h" + + +static const double segmentLength = 0.2; +static const double segmentWidth = 0.004; +static const double minWidth = 0.02; +static const double rootWidth = 0.8; +static const double branchesPerSegment = 0.2; +static const double leafSize = 8; +static const double leafPerBranch = 1; +static const double leafThreshold = 0.02 + 8/4/0.2*0.004; // minWidth + leafSize/4/segmentLength*segmentWidth + + +static double randomRange(double min, double max) + { return randomFloat()*(max - min) + min; } + +static double randomIncrement(double deviation) + { return randomRange(-deviation, deviation); } + +static double randomAmplifier(double deviation) + { return randomRange(1 - deviation, 1 + deviation); } + + +static void leaf(double x, double y, double size) { + double r = 0.5*size;//*randomAmplifier(0.5); + saveState(); + noStroke(); + circle(x, y, r); + restoreState(); +} + + +static void branch(double x, double y, double angle, double width, double time, int flags) { + double da = sin(time*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, 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, time, flags); + } + } + } + restoreState(); +} + + +void treeGenerate(Tree *t, double x, double y) { + memset(t, 0, sizeof(*t)); + t->seed = rand(); + t->x = x; + t->y = y; + t->angle = 90 + randomIncrement(30); + t->width = rootWidth*randomAmplifier(0.5); +} + + +void treeDraw(const Tree *t, double time, int flags) { + saveState(); + translate(t->x, t->y); + + fill(colorByName("green")); + stroke(colorByName("black")); + srand(t->seed); + branch(0, 0, t->angle, t->width, time, int flags); + + restoreState(); +} + + +void treePrerender(Tree *t, Framebuffer fb) { + srand(t->seed); + branch(0, 0, t->angle, t->width, 0, FLAG_BOUNDS); +} + + +void treeDrawPrerendered(Tree *t); diff --git a/projects/forest/tree.h b/projects/forest/tree.h new file mode 100644 index 0000000..3efc841 --- /dev/null +++ b/projects/forest/tree.h @@ -0,0 +1,28 @@ +#ifndef TREE_H +#define TREE_H + + +#include + +#include "common.h" + + +typedef struct { + int seed; + double x, y; + double angle; + double width; + + unsigned int texId; + double bl, bt, br, bb; +} Tree; + + +void treeGenerate(Tree *t, double x, double y); +void treeDraw(const Tree *t, double time, int flags); +void treePrerender(Tree *t, Framebuffer fb); +void treeDrawPrerendered(Tree *t); + + + +#endif