#include "const.h" #include #include #include #include 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; }