// terrain generation globals

int           tg_cols, tg_rows;
int           tg_scale = 40;
float         tg_t = 0;
float[][]     tg_grid;
float         tg_speed;
float         tg_height;
Star[]        tg_stars = new Star[500];
int           tg_starfield_speed = 1;

void midi_terrain_generation(int status, int chan, int value)
{
    if (status == -80 && chan == 7)
        tg_speed = float(value) / float(10);
    if (status == -79 && chan == 7)
        tg_height = (log(128) - log(128 - value)) * float(1000);
    if (status == -78 && chan == 7)
        tg_starfield_speed = 1 + value;
}

void setup_terrain_generation()
{
    tg_cols = width / tg_scale;
    tg_rows = height / tg_scale;
    tg_grid = new float[tg_cols + 200][tg_rows + 100];
    for (int y = -100; y < tg_rows; y++)
        for (int x = -100; x < tg_cols + 100; x++)
        {
            if (x < width/2 - 100 || x > width / 2 + 100)
                tg_grid[x + 100][y + 100] = noise(float(x) / 5, float(y) / 5) * 1000;
            else
                tg_grid[x + 100][y + 100] = 0;
        }
   tg_setup_star();
}

void draw_terrain_generation()
{
    background(0);
    stroke(255, 0, 128);
    fill(255, 0, 128);
    noFill();
    pushMatrix();
    translate(0, height /2 + tg_height);
    
    if (tg_height < 4000)
    {
        pushMatrix();
        rotateX(PI / 3);
        for (int y = -100; y < tg_rows - 1; y++)
        {
            beginShape(TRIANGLE_STRIP);
            for (int x = -100; x < tg_cols + 100; x++)
            {
                strokeWeight(1);
                if ((x < tg_cols/2 - 4 || x > tg_cols / 2 + 4))
                {
                    stroke(100 * 255 / tg_grid[x + 100][y + 100], 0, 100 * 128 / tg_grid[x + 100][y + 100] + abs(tg_t % 512 - 255));
                    vertex(x * tg_scale, y * tg_scale, tg_grid[x + 100][y + 100]);
                    stroke(100 * 255 / tg_grid[x + 100][y + 100], 0, 100 * 128 / tg_grid[x + 100][y + 1 + 100] + abs(tg_t % 512 - 255));
                    vertex(x * tg_scale,(y + 1) * tg_scale, tg_grid[x + 100][y + 1 + 100]);
                }
                else
                {
                    stroke(0, 100 * 255 / tg_grid[x + 100][y + 100], 100 * 128 / tg_grid[x + 100][y + 100] + abs(tg_t % 512 - 255));
                    vertex(x * tg_scale, y * tg_scale, 0);
                    stroke(0, 100 * 255 / tg_grid[x + 100][y + 100], 100 * 128 / tg_grid[x + 100][y + 1 + 100] + abs(tg_t % 512 - 255));
                    vertex(x * tg_scale,(y + 1) * tg_scale, 0);
                }
                tg_grid[x + 100][y + 100] = noise((float(x)) / 5, (y + tg_t) / 5) * 300;
            }
            endShape();
        }
        popMatrix();
    }
    translate(0, -height * 7.5);
    tg_manage_star();
    popMatrix();
    tg_t -= tg_speed;
}
