|
|
3395b9 |
|
|
|
3395b9 |
#include <math.h></math.h>
|
|
|
3395b9 |
#include <stdlib.h></stdlib.h>
|
|
|
3395b9 |
#include <string.h></string.h>
|
|
|
3395b9 |
|
|
|
3395b9 |
#include <helianthus.h></helianthus.h>
|
|
|
3395b9 |
|
|
|
3395b9 |
#include "chunk.h"
|
|
|
3395b9 |
|
|
|
3395b9 |
|
|
|
3395b9 |
static void pregenerate(Chunk *c, int rootSeed, int index) {
|
|
|
3395b9 |
c->index = index;
|
|
|
3395b9 |
srand(c->index ^ rootSeed);
|
|
|
3395b9 |
c->x = c->index*CHUNK_WIDTH;
|
|
|
3395b9 |
c->width = CHUNK_WIDTH;
|
|
|
3395b9 |
c->dy = (randomFloat()*2 - 1)*CHUNK_HEIGHT;
|
|
|
3395b9 |
c->seed = rand();
|
|
|
3395b9 |
}
|
|
|
3395b9 |
|
|
|
3395b9 |
static void generateGround(double *p0, double *p1, double dh) {
|
|
|
3395b9 |
double *p = p0 + (p1 - p0)/2;
|
|
|
3395b9 |
if (p1 <= p0 || p == p0) return;
|
|
|
3395b9 |
*p = (*p0 + *p1)*0.5 + dh*(randomFloat()*2 - 1);
|
|
|
3395b9 |
generateGround(p0, p, 0.5*dh);
|
|
|
3395b9 |
generateGround(p, p1, 0.5*dh);
|
|
|
3395b9 |
}
|
|
|
3395b9 |
|
|
|
3395b9 |
|
|
|
3395b9 |
void chunkGenerate(Chunk *c, int rootSeed, const Chunk *base, int offset) {
|
|
|
3395b9 |
if (base == c) return;
|
|
|
3395b9 |
|
|
|
3395b9 |
memset(c, 0, sizeof(*c));
|
|
|
3395b9 |
|
|
|
3395b9 |
if (base) {
|
|
|
3395b9 |
c->index = base->index;
|
|
|
3395b9 |
c->seed = base->seed;
|
|
|
3395b9 |
c->dy = base->dy;
|
|
|
3395b9 |
c->y = base->y;
|
|
|
3395b9 |
} else {
|
|
|
3395b9 |
pregenerate(c, rootSeed, 0);
|
|
|
3395b9 |
}
|
|
|
3395b9 |
while(offset > 0) { c->y += c->dy; pregenerate(c, rootSeed, c->index + 1); --offset; }
|
|
|
3395b9 |
while(offset < 0) { pregenerate(c, rootSeed, c->index - 1); c->y -= c->dy; ++offset; }
|
|
|
3395b9 |
|
|
|
3395b9 |
srand(c->seed);
|
|
|
3395b9 |
|
|
|
3395b9 |
double *p0 = &c->ground[0];
|
|
|
3395b9 |
double *p1 = &c->ground[CHUNK_GROUND_POINTS - 1];
|
|
|
3395b9 |
*p0 = 0; *p1 = c->dy;
|
|
|
3395b9 |
generateGround(p0, p1, 0.5*CHUNK_HEIGHT);
|
|
|
3395b9 |
|
|
|
3395b9 |
c->treeCount = randomNumber(0, CHUNK_MAX_TREES);
|
|
|
3395b9 |
for(int i = 0; i < c->treeCount; ++i) {
|
|
|
3395b9 |
double x = randomFloat()*c->width;
|
|
|
3395b9 |
double y = chunkGroundLevel(c, c->x + x) - c->y;
|
|
|
3395b9 |
treeGenerate(&c->trees[i], x, y);
|
|
|
3395b9 |
}
|
|
|
3395b9 |
}
|
|
|
3395b9 |
|
|
|
3395b9 |
|
|
|
3395b9 |
double chunkGroundLevel(const Chunk *c, double x) {
|
|
|
3395b9 |
double xp = (x - c->x)/c->width*(CHUNK_GROUND_POINTS-1);
|
|
|
3395b9 |
int xi = floor(xp);
|
|
|
3395b9 |
if (xi < 0) xi = 0;
|
|
|
3395b9 |
if (xi > CHUNK_GROUND_POINTS-2) xi = CHUNK_GROUND_POINTS-2;
|
|
|
3395b9 |
xp -= xi;
|
|
|
3395b9 |
return c->y + c->ground[xi]*(1 - xp) + c->ground[xi + 1]*xp;
|
|
|
3395b9 |
}
|
|
|
3395b9 |
|
|
|
3395b9 |
|
|
|
3395b9 |
void chunkDraw(const Chunk *c, double time, int flags) {
|
|
|
3395b9 |
saveState();
|
|
|
3395b9 |
translate(c->x, c->y);
|
|
|
3395b9 |
|
|
|
3395b9 |
if (flags && FLAG_GROUND) {
|
|
|
3395b9 |
double step = c->width/(double)(CHUNK_GROUND_POINTS-1);
|
|
|
3395b9 |
moveTo(0, c->ground[0]);
|
|
|
3395b9 |
for(int i = 1; i < CHUNK_GROUND_POINTS; ++i)
|
|
|
3395b9 |
lineTo(i*step, c->ground[i]);
|
|
|
3395b9 |
strokePath();
|
|
|
3395b9 |
}
|
|
|
3395b9 |
|
|
|
3395b9 |
if (flags & (FLAG_LEAVES | FLAG_BRANCHES))
|
|
|
3395b9 |
for(int i = 0; i < c->treeCount; ++i)
|
|
|
3395b9 |
treeDraw(&c->trees[i], time, flags);
|
|
|
3395b9 |
|
|
|
3395b9 |
restoreState();
|
|
|
3395b9 |
}
|
|
|
3395b9 |
|