diff options
Diffstat (limited to 'src/chunk.c')
| -rw-r--r-- | src/chunk.c | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/src/chunk.c b/src/chunk.c new file mode 100644 index 0000000..50fe5c3 --- /dev/null +++ b/src/chunk.c @@ -0,0 +1,138 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "voxel.h" +#include "list.h" +#include "cube.h" +#include "mesh.h" + +Chunk *chunk_init(int x, int y, int z) +{ + Chunk *chunk = malloc(sizeof(Chunk)); + chunk->x = x; + chunk->y = y; + chunk->z = z; + memset(chunk->blocks, AIR, sizeof(chunk->blocks)); + return chunk; +} + +void chunk_free(Chunk *chunk) +{ + free(chunk); +} + +void chunk_generate(Chunk *chunk) +{ + 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); + + char block = AIR; + int temp = x + z - y; + if (temp > 16) + block = DIRT; + + chunk->blocks[i] = block; + } +} + +typedef struct { + Chunk *chunk; + List pos; + List data; + int vertex_count; +} MeshState; + +static void add_vertex(MeshState *state, const vec3 pos, const vec3 xyz, unsigned int data) +{ + 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++; +} + +static void add_quad(MeshState *state, const vec3 xyz, Face face, Block block) +{ + unsigned int data = (face << 2) | block; + const vec3 *verts = CUBE[face]; + + 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); +} + +Mesh chunk_mesh(Chunk *chunk) +{ + 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 }; + + 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); + + if (px == AIR) + add_quad(&state, xyz, POS_X, block); + if (nx == AIR) + add_quad(&state, xyz, NEG_X, block); + if (py == AIR) + add_quad(&state, xyz, POS_Y, block); + if (ny == AIR) + add_quad(&state, xyz, NEG_Y, block); + if (pz == AIR) + add_quad(&state, xyz, POS_Z, block); + if (nz == AIR) + 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(); + + list_free(&state.pos); + list_free(&state.data); + + return mesh; +} + +Block chunk_at(Chunk *chunk, int x, int y, int z) +{ + if (x < 0 || x >= CHUNK_SIZE) + return AIR; + if (y < 0 || y >= CHUNK_SIZE) + return AIR; + if (z < 0 || z >= CHUNK_SIZE) + return AIR; + + int i = 0; + i += x; + i += z * CHUNK_SIZE; + i += y * CHUNK_SIZE * CHUNK_SIZE; + + return chunk->blocks[i]; +} |