summaryrefslogtreecommitdiff
path: root/src/chunk.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/chunk.c')
-rw-r--r--src/chunk.c138
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];
+}