diff options
Diffstat (limited to 'src/chunk.c')
| -rw-r--r-- | src/chunk.c | 237 |
1 files changed, 169 insertions, 68 deletions
diff --git a/src/chunk.c b/src/chunk.c index 50fe5c3..f142788 100644 --- a/src/chunk.c +++ b/src/chunk.c @@ -1,98 +1,183 @@ -#include <stdio.h> +#include <cglm/vec3.h> #include <stdlib.h> -#include <string.h> +#include "utils.h" #include "voxel.h" #include "list.h" -#include "cube.h" -#include "mesh.h" +#include "gl.h" +#include "noise.h" -Chunk *chunk_init(int x, int y, int z) +void chunk_init(Chunk *chunk, i32 x, i32 y, i32 z) { - Chunk *chunk = malloc(sizeof(Chunk)); - chunk->x = x; - chunk->y = y; - chunk->z = z; - memset(chunk->blocks, AIR, sizeof(chunk->blocks)); - return chunk; + chunk->blocks = xzalloc(sizeof(Block) * CHUNK_BLOCKS); + chunk->pos[0] = x; + chunk->pos[1] = y; + chunk->pos[2] = z; + chunk->state = CHUNK_NEW; + chunk->has_mesh = false; } void chunk_free(Chunk *chunk) { - free(chunk); + if (chunk->state >= CHUNK_MESHED) + uniform_free(&chunk->mesh); + free(chunk->blocks); } -void chunk_generate(Chunk *chunk) +void chunk_generate(Chunk *chunk, seed_t seed) { - int size = sizeof(chunk->blocks); - for (int i = 0; i < size; i++) { - int x = i % CHUNK_SIZE; - int z = (i / CHUNK_SIZE) % CHUNK_SIZE; - int y = i / (CHUNK_SIZE * CHUNK_SIZE); + fnl_state noise; - char block = AIR; - int temp = x + z - y; - if (temp > 16) - block = DIRT; + if (chunk->state != CHUNK_NEW) + return; - chunk->blocks[i] = block; + chunk->state = CHUNK_GENERATING; + + noise = fnlCreateState(); + noise.seed = seed; + noise.noise_type = FNL_NOISE_PERLIN; + + for (i32 i = 0; i < CHUNK_BLOCKS; i++) { + i32 lx = i % CHUNK_SIZE; + i32 lz = (i / CHUNK_SIZE) % CHUNK_SIZE; + i32 ly = i / (CHUNK_SIZE * CHUNK_SIZE); + + i32 gx = lx + chunk->pos[0] * CHUNK_SIZE; + i32 gy = ly + chunk->pos[1] * CHUNK_SIZE; + i32 gz = lz + chunk->pos[2] * CHUNK_SIZE; + + double data = fnlGetNoise3D(&noise, gx, gy, gz); + data -= gy * 0.01; + if (data < 0.1) + continue; + + chunk->blocks[i] = A; } + + chunk->state = CHUNK_GENERATED; } typedef struct { - Chunk *chunk; - List pos; List data; - int vertex_count; + RcChunk *rc_chunks[7]; } MeshState; -static void add_vertex(MeshState *state, const vec3 pos, const vec3 xyz, unsigned int data) +typedef union { + struct { + u64 x : 5; + u64 y : 5; + u64 z : 5; + u64 width : 5; + u64 height : 5; + u64 face : 3; + u64 block : 4; + u64 : 32; + }; + u64 raw; +} Quad; + +static void mesh_state_init(MeshState *state, World *world, Chunk *chunk) +{ + i32 cx, cy, cz; + + cx = chunk->pos[0]; + cy = chunk->pos[1]; + cz = chunk->pos[2]; + + state->rc_chunks[0] = world_get_chunk(world, cx, cy, cz); + state->rc_chunks[1] = world_get_chunk(world, cx - 1, cy, cz); + state->rc_chunks[2] = world_get_chunk(world, cx + 1, cy, cz); + state->rc_chunks[3] = world_get_chunk(world, cx, cy - 1, cz); + state->rc_chunks[4] = world_get_chunk(world, cx, cy + 1, cz); + state->rc_chunks[5] = world_get_chunk(world, cx, cy, cz - 1); + state->rc_chunks[6] = world_get_chunk(world, cx, cy, cz + 1); + + list_init_u64(&state->data); +} + +static void mesh_state_free(MeshState *state) +{ + for (i32 i = 0; i < 7; i++) { + RcChunk *rc_chunk = state->rc_chunks[i]; + if (rc_chunk != NULL) + rcchunk_drop(rc_chunk); + } + + list_free(&state->data); +} + +static Block mesh_state_get_block(MeshState *state, i32 lx, i32 ly, i32 lz) { - list_pushf(&state->pos, pos[0] + xyz[0]); - list_pushf(&state->pos, pos[1] + xyz[1]); - list_pushf(&state->pos, pos[2] + xyz[2]); - list_pushu(&state->data, data); - state->vertex_count++; + RcChunk *rc_chunk; + i32 index = 0; + + if (lx < 0) { + index = 1; + lx += CHUNK_SIZE; + } else if (lx >= CHUNK_SIZE) { + index = 2; + lx -= CHUNK_SIZE; + } else if (ly < 0) { + index = 3; + ly += CHUNK_SIZE; + } else if (ly >= CHUNK_SIZE) { + index = 4; + ly -= CHUNK_SIZE; + } else if (lz < 0) { + index = 5; + lz += CHUNK_SIZE; + } else if (lz >= CHUNK_SIZE) { + index = 6; + lz -= CHUNK_SIZE; + } + + rc_chunk = state->rc_chunks[index]; + if (rc_chunk == NULL) + return AIR; + + return chunk_at(&rc_chunk->chunk, lx, ly, lz); } -static void add_quad(MeshState *state, const vec3 xyz, Face face, Block block) +static void add_quad(MeshState *state, const ivec3 xyz, Face face, Block block) { - unsigned int data = (face << 2) | block; - const vec3 *verts = CUBE[face]; + Quad quad = { 0 }; + quad.x = xyz[0]; + quad.y = xyz[1]; + quad.z = xyz[2]; + quad.width = 1; + quad.height = 1; + quad.face = face; + quad.block = block; - add_vertex(state, verts[0], xyz, data); - add_vertex(state, verts[1], xyz, data); - add_vertex(state, verts[2], xyz, data); - add_vertex(state, verts[3], xyz, data); - add_vertex(state, verts[4], xyz, data); - add_vertex(state, verts[5], xyz, data); + list_push_u64(&state->data, quad.raw); } -Mesh chunk_mesh(Chunk *chunk) +void chunk_mesh(Chunk *chunk, World *world) { MeshState state; - state.chunk = chunk; - state.vertex_count = 0; - list_initf(&state.pos); - list_initu(&state.data); - int size = sizeof(chunk->blocks); - for (int i = 0; i < size; i++) { - int x = i % CHUNK_SIZE; - int z = (i / CHUNK_SIZE) % CHUNK_SIZE; - int y = i / (CHUNK_SIZE * CHUNK_SIZE); - vec3 xyz = { x, y, z }; + if (chunk->state != CHUNK_GENERATED) + return; + + chunk->state = CHUNK_MESHING; + mesh_state_init(&state, world, chunk); + + for (i32 i = 0; i < CHUNK_BLOCKS; i++) { + i32 lx = i % CHUNK_SIZE; + i32 lz = (i / CHUNK_SIZE) % CHUNK_SIZE; + i32 ly = i / (CHUNK_SIZE * CHUNK_SIZE); + ivec3 xyz = { lx, ly, lz }; Block block = chunk->blocks[i]; if (block == AIR) continue; - Block px = chunk_at(chunk, x + 1, y, z); - Block nx = chunk_at(chunk, x - 1, y, z); - Block py = chunk_at(chunk, x, y + 1, z); - Block ny = chunk_at(chunk, x, y - 1, z); - Block pz = chunk_at(chunk, x, y, z + 1); - Block nz = chunk_at(chunk, x, y, z - 1); + Block px = mesh_state_get_block(&state, lx + 1, ly, lz); + Block nx = mesh_state_get_block(&state, lx - 1, ly, lz); + Block py = mesh_state_get_block(&state, lx, ly + 1, lz); + Block ny = mesh_state_get_block(&state, lx, ly - 1, lz); + Block pz = mesh_state_get_block(&state, lx, ly, lz + 1); + Block nz = mesh_state_get_block(&state, lx, ly, lz - 1); if (px == AIR) add_quad(&state, xyz, POS_X, block); @@ -108,19 +193,20 @@ Mesh chunk_mesh(Chunk *chunk) add_quad(&state, xyz, NEG_Z, block); } - Mesh mesh; - mesh_init(&mesh, state.vertex_count); - mesh_storef(&mesh, state.pos.fdata, state.pos.len, 3); - mesh_storeu(&mesh, state.data.udata, state.data.len, 1); - mesh_finish(); + if (chunk->has_mesh) + uniform_free(&chunk->mesh); - list_free(&state.pos); - list_free(&state.data); + Uniform uniform; + uniform_init(&uniform, state.data.len * sizeof(Quad)); + uniform_store(&uniform, 0, state.data.len * sizeof(Quad), state.data.data); + mesh_state_free(&state); - return mesh; + chunk->mesh = uniform; + chunk->has_mesh = true; + chunk->state = CHUNK_MESHED; } -Block chunk_at(Chunk *chunk, int x, int y, int z) +Block chunk_at(Chunk *chunk, i32 x, i32 y, i32 z) { if (x < 0 || x >= CHUNK_SIZE) return AIR; @@ -129,10 +215,25 @@ Block chunk_at(Chunk *chunk, int x, int y, int z) if (z < 0 || z >= CHUNK_SIZE) return AIR; - int i = 0; + i32 i = 0; i += x; i += z * CHUNK_SIZE; i += y * CHUNK_SIZE * CHUNK_SIZE; return chunk->blocks[i]; } + +AABB chunk_aabb(Chunk *chunk) +{ + AABB aabb = { 0 }; + + // min + aabb.min[0] = chunk->pos[0] * CHUNK_SIZE; + aabb.min[1] = chunk->pos[1] * CHUNK_SIZE; + aabb.min[2] = chunk->pos[2] * CHUNK_SIZE; + + // max + glm_vec3_adds(aabb.min, CHUNK_SIZE, aabb.max); + + return aabb; +} |