Blame projects/forest/chunk.c

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