Blame projects/forest/chunk.c

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