186 lines
No EOL
4 KiB
C
186 lines
No EOL
4 KiB
C
#include "const.h"
|
|
#include <math.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
Chunk *chunks = NULL;
|
|
int lastI = 0;
|
|
int seed = 69420;
|
|
int prevExists = 0;
|
|
double interpolate(double a0, double a1, double w) {
|
|
return (a1 - a0) * (3.0 - w * 2.0) * w * w + a0;
|
|
}
|
|
|
|
int hash_combine(int a, int b) { return b + 0x9e3779b9 + (a << 6) + (a >> 2); }
|
|
|
|
Vertex2 perlin_grad(int x, int y) {
|
|
int x_hash = hash_combine(x, seed);
|
|
int y_hash = hash_combine(seed, y);
|
|
|
|
double random = hash_combine(x_hash, y_hash) * (M_PI / ~(~0u >> 1));
|
|
Vertex2 out = {cos(random), sin(random)};
|
|
return out;
|
|
}
|
|
|
|
double perlin_dot(double ix, double iy, double x, double y) {
|
|
Vertex2 grad = perlin_grad(ix, iy);
|
|
|
|
double dx = x - (double)ix;
|
|
double dy = y - (double)iy;
|
|
return (dx * grad.pos[0] + dy * grad.pos[1]);
|
|
}
|
|
|
|
double perlin_calc(double x, double y, double s) {
|
|
x /= s;
|
|
y /= s;
|
|
|
|
int x0 = (int)floor(x);
|
|
int x1 = x0 + 1;
|
|
int y0 = (int)floor(y);
|
|
int y1 = y0 + 1;
|
|
|
|
float sx = x - (float)x0;
|
|
float sy = y - (float)y0;
|
|
|
|
float n0, n1, ix0, ix1, value;
|
|
|
|
n0 = perlin_dot(x0, y0, x, y);
|
|
n1 = perlin_dot(x1, y0, x, y);
|
|
ix0 = interpolate(n0, n1, sx);
|
|
|
|
n0 = perlin_dot(x0, y1, x, y);
|
|
n1 = perlin_dot(x1, y1, x, y);
|
|
ix1 = interpolate(n0, n1, sx);
|
|
|
|
value = interpolate(ix0, ix1, sy);
|
|
|
|
return value;
|
|
}
|
|
|
|
Chunk fetch_chunk(int x, int y, int z, int ci, int h, int r_order) {
|
|
|
|
Chunk *chunks2 = chunks; // &chunks[CBUF_ALL * ci];
|
|
|
|
Chunk chunk;
|
|
|
|
if (x < 0 || y < 0 || z < 0) {
|
|
chunk.exists = 0;
|
|
return chunk;
|
|
}
|
|
|
|
int cbuf2 = CHUNK_ALL; // CBUF_ALL * (CHUNK_DIAMETER_H + (MAX_R * 2));
|
|
|
|
int i, j;
|
|
int r = (h == 0);
|
|
|
|
h = h * 16;
|
|
|
|
for (j = 0; j < (r ? 16 : 1) && h; j++) {
|
|
i = (j + h + cbuf2) % cbuf2;
|
|
chunk = chunks2[i];
|
|
if (chunk.x == x && chunk.y == y && chunk.z == z && chunk.exists != 0) {
|
|
|
|
chunk.exists = i / 16;
|
|
if (chunk.exists == 0)
|
|
chunk.exists = 1;
|
|
return chunk;
|
|
}
|
|
}
|
|
|
|
// printf("fail\n");
|
|
for (j = 0; j < cbuf2; j += 16) {
|
|
i = (j + h + cbuf2) % cbuf2;
|
|
chunk = chunks2[i];
|
|
if (chunk.exists == 0) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
char fname[1024];
|
|
snprintf(fname, 1023, "./db/chunk_%i_%i_%i.dat", x, y, z);
|
|
|
|
FILE *fp = fopen(fname, "rb+");
|
|
|
|
int code = (fp) ? fread(&chunk, sizeof(Chunk), 1, fp) : 0;
|
|
if (code != 0) {
|
|
fclose(fp);
|
|
fp = 0;
|
|
if (chunk.exists != 0) {
|
|
chunk.exists = i / 16;
|
|
if (chunk.exists == 0)
|
|
chunk.exists = 1;
|
|
return chunk;
|
|
}
|
|
}
|
|
if (!fp) {
|
|
fp = fopen(fname, "wb");
|
|
}
|
|
|
|
lastI = i;
|
|
|
|
chunk.exists = i / 16;
|
|
if (chunk.exists == 0)
|
|
chunk.exists = 1;
|
|
chunk.x = x;
|
|
chunk.y = y;
|
|
chunk.z = z;
|
|
|
|
int c = 0;
|
|
|
|
for (int x2 = 0; x2 < CHUNK_LENGTH; x2++) {
|
|
int x3 = x2 + x * CHUNK_LENGTH;
|
|
for (int z2 = 0; z2 < CHUNK_LENGTH; z2++) {
|
|
int z3 = z2 + z * CHUNK_LENGTH;
|
|
double hp = perlin_calc(x3, z3, 128.0);
|
|
hp = ((hp > 0.0) ? -1.0 : 1.0) * (pow(fabs(hp), 0.7));
|
|
hp *= 32.0;
|
|
int h = hp + 32;
|
|
|
|
for (int y2 = 0; y2 < CHUNK_LENGTH; y2++) {
|
|
int y3 = y2 + y * CHUNK_LENGTH;
|
|
chunk.blocks[c] = (y3 < h) ? (((int)((hp + 64.0) * 2.98) % 3) + 1) : 0;
|
|
c++;
|
|
}
|
|
}
|
|
}
|
|
|
|
chunks2[i] = chunk;
|
|
|
|
if (!fp) {
|
|
return chunk;
|
|
}
|
|
|
|
fwrite(&chunk, sizeof(Chunk), 1, fp);
|
|
fclose(fp);
|
|
|
|
return chunk;
|
|
}
|
|
|
|
void purge_chunks(int ci) {
|
|
/*
|
|
free(chunks);
|
|
chunks = calloc(CBUF_ALL, sizeof(Chunk));
|
|
*/
|
|
if (chunks == NULL) {
|
|
chunks = calloc(CHUNK_ALL, sizeof(Chunk));
|
|
}
|
|
// memset(chunks, 0, sizeof(Chunk) *CHUNK_ALL);
|
|
}
|
|
|
|
int cube_exists(int x, int y, int z, Chunk dat, int ci, int r_order) {
|
|
if (x < 0 || y < 0 || z < 0)
|
|
return 0;
|
|
|
|
if (dat.exists == 0 || dat.x != (x / CHUNK_LENGTH) ||
|
|
dat.y != (y / CHUNK_LENGTH) || dat.z != (z / CHUNK_LENGTH)) {
|
|
dat = fetch_chunk((x / CHUNK_LENGTH), (y / CHUNK_LENGTH),
|
|
(z / CHUNK_LENGTH), ci, dat.exists, r_order);
|
|
prevExists = dat.exists;
|
|
}
|
|
|
|
int h = dat.blocks[(y % CHUNK_LENGTH) + (z % CHUNK_LENGTH) * CHUNK_LENGTH +
|
|
(x % CHUNK_LENGTH) * CHUNK_LENGTH * CHUNK_LENGTH];
|
|
|
|
return h;
|
|
} |