Skip to content

Commit 7f06f98

Browse files
committed
🐎 Only render voxels w/ exposed faces.
The mesh generation of a chunk will now take account of a voxel and its neighboring voxels and will only include the faces of voxels that are exposed. This is a half-baked implementation as there is no support for checking boundaries between chunks.
1 parent 3990780 commit 7f06f98

File tree

2 files changed

+64
-29
lines changed

2 files changed

+64
-29
lines changed

src/chunk.c

Lines changed: 59 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,39 +6,69 @@
66

77
chunk *create_chunk(GLfloat x, GLfloat z) {
88
chunk *new_chunk = malloc(sizeof(chunk));
9-
new_chunk->blocks = (uint8_t *) calloc(1, sizeof(CHUNK_SIZE));
9+
new_chunk->blocks = (uint8_t *) calloc(1, sizeof(uint8_t) * CHUNK_SIZE);
10+
11+
// Sets all blocks to a non-air type. (1)
12+
for (int i = 0; i < CHUNK_SIZE; i++) {
13+
new_chunk->blocks[i] = 1;
14+
}
15+
1016
new_chunk->x = x;
1117
new_chunk->z = z;
1218

1319
return new_chunk;
1420
}
1521

1622
void generate_chunk_mesh(chunk *render_chunk) {
17-
GLfloat *buffer = malloc(sizeof(GLfloat) * (6 * 5 * 5) * CHUNK_SIZE);
23+
GLfloat *buffer = malloc(sizeof(GLfloat) * (6 * 6 * 5) * CHUNK_SIZE);
1824
GLfloat *buffer_pointer = buffer;
19-
20-
for (int x = 0; x < CHUNK_WIDTH; x++) {
21-
for (int z = 0; z < CHUNK_HEIGHT; z++) {
22-
for (int y = 0; y < CHUNK_DEPTH; y++) {
23-
uint32_t index = x + z + y;
24-
uint8_t block = render_chunk->blocks[index];
25-
26-
create_cube_mesh(&buffer_pointer,
27-
1, 1, 1, 0, 1, 1,
28-
1, 1, 1, 1, 1, 1,
29-
x, y, z, 0.5
30-
);
31-
}
32-
}
25+
int vertices_count = 0;
26+
27+
for (int i = 0; i < CHUNK_SIZE; i++) {
28+
int x = i % CHUNK_X;
29+
int z = (i / CHUNK_X) % CHUNK_Z;
30+
int y = i / (CHUNK_X * CHUNK_Z);
31+
32+
uint8_t block = render_chunk->blocks[i];
33+
34+
// left(-x), right(+x), top(+y), bottom(-y), front(-z), back(+z)
35+
uint8_t neighbors[6] = {1, 1, 1, 1, 1, 1};
36+
37+
// Calculate neighboring voxels and check if they are solid or not.
38+
// If they are not solid, we should render a face. Otherwise, it is
39+
// unnecessary to include the face. This resulting mesh will be
40+
// contain only the exposed faces. Perf++.
41+
//
42+
// TODO(vy): Need to check between chunk boundaries for checking
43+
// face exposure.
44+
neighbors[0] = (x - 1 < 0) ? 1 : render_chunk->blocks[i - 1] == 0;
45+
neighbors[1] = (x + 1 >= CHUNK_X) ? 1 : render_chunk->blocks[i + 1] == 0;
46+
neighbors[2] = (y + 1 >= CHUNK_Y) ? 1 : render_chunk->blocks[i + (CHUNK_X * CHUNK_Z)] == 0;
47+
neighbors[3] = (y - 1 < 0) ? 1 : render_chunk->blocks[i - (CHUNK_X * CHUNK_Z)] == 0;
48+
neighbors[4] = (z - 1 < 0) ? 1 : render_chunk->blocks[i - CHUNK_X] == 0;
49+
neighbors[5] = (z + 1 >= CHUNK_Z) ? 1 : render_chunk->blocks[i + CHUNK_X] == 0;
50+
51+
vertices_count += create_cube_mesh(&buffer_pointer,
52+
neighbors[0], neighbors[1], neighbors[2], neighbors[3], neighbors[4], neighbors[5],
53+
1, 1, 1, 1, 1, 1,
54+
x, y, z, 0.5
55+
);
3356
}
3457

58+
59+
// Resize the mesh buffer to the actual size, since we allocated
60+
// the largest size, but during mesh creation, we could have
61+
// omitted faces, causing the buffer to be smaller than the
62+
// maximum size.
63+
buffer = realloc(buffer, (sizeof(GLfloat) * vertices_count * 5));
64+
3565
// TODO(vy): Figure out how to calculate vertices of exposed faces:
3666
// 6 vertices per face * NUMBER OF FACES
3767
render_chunk->render_object = create_render_obj(
3868
GL_TRIANGLES,
3969
buffer,
40-
(6 * 5 * 5) * CHUNK_SIZE,
41-
(6 * 5) * CHUNK_SIZE
70+
(6 * 6 * 5) * CHUNK_SIZE,
71+
vertices_count
4272
);
4373

4474
// Bind Vertices
@@ -69,9 +99,9 @@ void generate_chunk_mesh(chunk *render_chunk) {
6999
render_chunk->render_object->transform = m4_transpose(
70100
m4_translation(
71101
vec3(
72-
render_chunk->x * CHUNK_WIDTH,
102+
render_chunk->x * CHUNK_X,
73103
0,
74-
render_chunk->z * CHUNK_HEIGHT
104+
render_chunk->z * CHUNK_Z
75105
)
76106
)
77107
);
@@ -91,13 +121,15 @@ void generate_chunk_mesh(chunk *render_chunk) {
91121
// vertices, normals, uvs of ONLY the exposed faces. This impacts
92122
// mem space on the overall mesh significantly.
93123

94-
void create_cube_mesh(
124+
int create_cube_mesh(
95125
GLfloat **data_pointer,
96126
int left, int right, int top, int bottom, int front, int back,
97127
int wleft, int wright, int wtop, int wbottom, int wfront, int wback,
98128
GLfloat x, GLfloat y, GLfloat z, GLfloat cube_size
99129
) {
100130

131+
int vertices_count = 0;
132+
101133
static const GLfloat vertices[6][4][3] = {
102134
{{-1, -1, -1}, {-1, -1, +1}, {-1, +1, -1}, {-1, +1, +1}},
103135
{{+1, -1, -1}, {+1, -1, +1}, {+1, +1, -1}, {+1, +1, +1}},
@@ -163,8 +195,11 @@ void create_cube_mesh(
163195
*((*data_pointer)++) = z + cube_size * vertices[i][j][2];
164196
*((*data_pointer)++) = (uvs[i][j][0] ? b : a);
165197
*((*data_pointer)++) = (uvs[i][j][1] ? b : a);
198+
vertices_count++;
166199
}
167200
}
201+
202+
return vertices_count;
168203
}
169204

170205
uint8_t block_from_index(chunk *render_chunk, uint32_t index) {
@@ -178,9 +213,9 @@ uint32_t index_from_block(uint16_t x, uint16_t y, uint16_t z) {
178213

179214
// return (modz * SIZEXY) + (modx * SIZEY) + mody;
180215

181-
uint32_t x_length = CHUNK_WIDTH;
182-
uint32_t z_length = CHUNK_HEIGHT;
183-
uint32_t y_length = CHUNK_DEPTH;
216+
uint32_t x_length = CHUNK_X;
217+
uint32_t z_length = CHUNK_Z;
218+
uint32_t y_length = CHUNK_Y;
184219
if (x > x_length) x = x_length;
185220
if (y > y_length) y = y_length;
186221
if (z > z_length) z = z_length;

src/chunk.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44
#include "third-party/math_3d.h"
55
#include "gl.h"
66

7-
#define CHUNK_WIDTH 16
8-
#define CHUNK_HEIGHT 16
9-
#define CHUNK_DEPTH 256
10-
#define CHUNK_SIZE CHUNK_WIDTH * CHUNK_HEIGHT * CHUNK_DEPTH
7+
#define CHUNK_X 16
8+
#define CHUNK_Z 16
9+
#define CHUNK_Y 256
10+
#define CHUNK_SIZE CHUNK_X * CHUNK_Z * CHUNK_Y
1111
#define LOADED_CHUNK_BOUNDARY 3
1212

1313
typedef struct {
@@ -23,7 +23,7 @@ typedef struct {
2323

2424
chunk *create_chunk(GLfloat x, GLfloat z);
2525
void generate_chunk_mesh(chunk *render_chunk);
26-
void create_cube_mesh(
26+
int create_cube_mesh(
2727
GLfloat **data_pointer,
2828
int left, int right, int top, int bottom, int front, int back,
2929
int wleft, int wright, int wtop, int wbottom, int wfront, int wback,

0 commit comments

Comments
 (0)