Skip to content

Commit

Permalink
🐎 Only render voxels w/ exposed faces.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
andrewvy committed May 14, 2016
1 parent 3990780 commit 7f06f98
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 29 deletions.
83 changes: 59 additions & 24 deletions src/chunk.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,39 +6,69 @@

chunk *create_chunk(GLfloat x, GLfloat z) {
chunk *new_chunk = malloc(sizeof(chunk));
new_chunk->blocks = (uint8_t *) calloc(1, sizeof(CHUNK_SIZE));
new_chunk->blocks = (uint8_t *) calloc(1, sizeof(uint8_t) * CHUNK_SIZE);

// Sets all blocks to a non-air type. (1)
for (int i = 0; i < CHUNK_SIZE; i++) {
new_chunk->blocks[i] = 1;
}

new_chunk->x = x;
new_chunk->z = z;

return new_chunk;
}

void generate_chunk_mesh(chunk *render_chunk) {
GLfloat *buffer = malloc(sizeof(GLfloat) * (6 * 5 * 5) * CHUNK_SIZE);
GLfloat *buffer = malloc(sizeof(GLfloat) * (6 * 6 * 5) * CHUNK_SIZE);
GLfloat *buffer_pointer = buffer;

for (int x = 0; x < CHUNK_WIDTH; x++) {
for (int z = 0; z < CHUNK_HEIGHT; z++) {
for (int y = 0; y < CHUNK_DEPTH; y++) {
uint32_t index = x + z + y;
uint8_t block = render_chunk->blocks[index];

create_cube_mesh(&buffer_pointer,
1, 1, 1, 0, 1, 1,
1, 1, 1, 1, 1, 1,
x, y, z, 0.5
);
}
}
int vertices_count = 0;

for (int i = 0; i < CHUNK_SIZE; i++) {
int x = i % CHUNK_X;
int z = (i / CHUNK_X) % CHUNK_Z;
int y = i / (CHUNK_X * CHUNK_Z);

uint8_t block = render_chunk->blocks[i];

// left(-x), right(+x), top(+y), bottom(-y), front(-z), back(+z)
uint8_t neighbors[6] = {1, 1, 1, 1, 1, 1};

// Calculate neighboring voxels and check if they are solid or not.
// If they are not solid, we should render a face. Otherwise, it is
// unnecessary to include the face. This resulting mesh will be
// contain only the exposed faces. Perf++.
//
// TODO(vy): Need to check between chunk boundaries for checking
// face exposure.
neighbors[0] = (x - 1 < 0) ? 1 : render_chunk->blocks[i - 1] == 0;
neighbors[1] = (x + 1 >= CHUNK_X) ? 1 : render_chunk->blocks[i + 1] == 0;
neighbors[2] = (y + 1 >= CHUNK_Y) ? 1 : render_chunk->blocks[i + (CHUNK_X * CHUNK_Z)] == 0;
neighbors[3] = (y - 1 < 0) ? 1 : render_chunk->blocks[i - (CHUNK_X * CHUNK_Z)] == 0;
neighbors[4] = (z - 1 < 0) ? 1 : render_chunk->blocks[i - CHUNK_X] == 0;
neighbors[5] = (z + 1 >= CHUNK_Z) ? 1 : render_chunk->blocks[i + CHUNK_X] == 0;

vertices_count += create_cube_mesh(&buffer_pointer,
neighbors[0], neighbors[1], neighbors[2], neighbors[3], neighbors[4], neighbors[5],
1, 1, 1, 1, 1, 1,
x, y, z, 0.5
);
}


// Resize the mesh buffer to the actual size, since we allocated
// the largest size, but during mesh creation, we could have
// omitted faces, causing the buffer to be smaller than the
// maximum size.
buffer = realloc(buffer, (sizeof(GLfloat) * vertices_count * 5));

// TODO(vy): Figure out how to calculate vertices of exposed faces:
// 6 vertices per face * NUMBER OF FACES
render_chunk->render_object = create_render_obj(
GL_TRIANGLES,
buffer,
(6 * 5 * 5) * CHUNK_SIZE,
(6 * 5) * CHUNK_SIZE
(6 * 6 * 5) * CHUNK_SIZE,
vertices_count
);

// Bind Vertices
Expand Down Expand Up @@ -69,9 +99,9 @@ void generate_chunk_mesh(chunk *render_chunk) {
render_chunk->render_object->transform = m4_transpose(
m4_translation(
vec3(
render_chunk->x * CHUNK_WIDTH,
render_chunk->x * CHUNK_X,
0,
render_chunk->z * CHUNK_HEIGHT
render_chunk->z * CHUNK_Z
)
)
);
Expand All @@ -91,13 +121,15 @@ void generate_chunk_mesh(chunk *render_chunk) {
// vertices, normals, uvs of ONLY the exposed faces. This impacts
// mem space on the overall mesh significantly.

void create_cube_mesh(
int create_cube_mesh(
GLfloat **data_pointer,
int left, int right, int top, int bottom, int front, int back,
int wleft, int wright, int wtop, int wbottom, int wfront, int wback,
GLfloat x, GLfloat y, GLfloat z, GLfloat cube_size
) {

int vertices_count = 0;

static const GLfloat vertices[6][4][3] = {
{{-1, -1, -1}, {-1, -1, +1}, {-1, +1, -1}, {-1, +1, +1}},
{{+1, -1, -1}, {+1, -1, +1}, {+1, +1, -1}, {+1, +1, +1}},
Expand Down Expand Up @@ -163,8 +195,11 @@ void create_cube_mesh(
*((*data_pointer)++) = z + cube_size * vertices[i][j][2];
*((*data_pointer)++) = (uvs[i][j][0] ? b : a);
*((*data_pointer)++) = (uvs[i][j][1] ? b : a);
vertices_count++;
}
}

return vertices_count;
}

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

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

uint32_t x_length = CHUNK_WIDTH;
uint32_t z_length = CHUNK_HEIGHT;
uint32_t y_length = CHUNK_DEPTH;
uint32_t x_length = CHUNK_X;
uint32_t z_length = CHUNK_Z;
uint32_t y_length = CHUNK_Y;
if (x > x_length) x = x_length;
if (y > y_length) y = y_length;
if (z > z_length) z = z_length;
Expand Down
10 changes: 5 additions & 5 deletions src/chunk.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
#include "third-party/math_3d.h"
#include "gl.h"

#define CHUNK_WIDTH 16
#define CHUNK_HEIGHT 16
#define CHUNK_DEPTH 256
#define CHUNK_SIZE CHUNK_WIDTH * CHUNK_HEIGHT * CHUNK_DEPTH
#define CHUNK_X 16
#define CHUNK_Z 16
#define CHUNK_Y 256
#define CHUNK_SIZE CHUNK_X * CHUNK_Z * CHUNK_Y
#define LOADED_CHUNK_BOUNDARY 3

typedef struct {
Expand All @@ -23,7 +23,7 @@ typedef struct {

chunk *create_chunk(GLfloat x, GLfloat z);
void generate_chunk_mesh(chunk *render_chunk);
void create_cube_mesh(
int create_cube_mesh(
GLfloat **data_pointer,
int left, int right, int top, int bottom, int front, int back,
int wleft, int wright, int wtop, int wbottom, int wfront, int wback,
Expand Down

0 comments on commit 7f06f98

Please sign in to comment.