terrain

Real-time terrain generation using marching cubes
git clone git://git.christianermann.dev/terrain
Log | Files | Refs | README | LICENSE

commit 278db91aa4fe744eed70175ac422994071fcb517
parent 3a705c1c04cacb3565003db5b1ecea490602979e
Author: Christian Ermann <christianermann@gmail.com>
Date:   Wed, 14 Jul 2021 18:11:47 -0700

Start of a chunking system

Diffstat:
Ainclude/chunk.h | 15+++++++++++++++
Ainclude/chunk_manager.h | 18++++++++++++++++++
Asrc/chunk.c | 89+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/chunk_manager.c | 77+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/main.c | 44++++++++++++++++++++++++++++----------------
5 files changed, 227 insertions(+), 16 deletions(-)

diff --git a/include/chunk.h b/include/chunk.h @@ -0,0 +1,15 @@ +#ifndef CHUNK_H +#define CHUNK_H + +extern const int CHUNK_RADIUS; + +typedef struct { + float center[3]; +} Chunk; + +Chunk Chunk_create(float x, float y, float z); + +void Chunk_outline(const Chunk* chunk, float corners[24], unsigned int offset, + unsigned int indices[24]); + +#endif diff --git a/include/chunk_manager.h b/include/chunk_manager.h @@ -0,0 +1,18 @@ +#ifndef CHUNK_MANAGER_H +#define CHUNK_MANAGER_H + +#include "chunk.h" + +typedef struct { + int radius; + int chunk_count; + int center[3]; + int* offsets; + Chunk* chunks; +} ChunkManager; + +ChunkManager ChunkManager_create(int radius, float player[3]); + +void ChunkManager_update(ChunkManager* chunk_manager, float player[3]); + +#endif diff --git a/src/chunk.c b/src/chunk.c @@ -0,0 +1,89 @@ +#include "chunk.h" + +const int CHUNK_RADIUS = 8; + +Chunk Chunk_create(float x, float y, float z) +{ + Chunk chunk; + + chunk.center[0] = x; + chunk.center[1] = y; + chunk.center[2] = z; + + return chunk; +} + +void Cube_corners(const float center[3], float radius, float corners[24]) +{ + corners[0] = center[0] - radius; + corners[1] = center[1] - radius; + corners[2] = center[2] - radius; + + corners[3] = center[0] + radius; + corners[4] = center[1] - radius; + corners[5] = center[2] - radius; + + corners[6] = center[0] + radius; + corners[7] = center[1] - radius; + corners[8] = center[2] + radius; + + corners[9] = center[0] - radius; + corners[10] = center[1] - radius; + corners[11] = center[2] + radius; + + corners[12] = center[0] - radius; + corners[13] = center[1] + radius; + corners[14] = center[2] - radius; + + corners[15] = center[0] + radius; + corners[16] = center[1] + radius; + corners[17] = center[2] - radius; + + corners[18] = center[0] + radius; + corners[19] = center[1] + radius; + corners[20] = center[2] + radius; + + corners[21] = center[0] - radius; + corners[22] = center[1] + radius; + corners[23] = center[2] + radius; +} + +void Cube_outlineIndices(unsigned int offset, unsigned int indices[24]) +{ + // Bottom edges + indices[0] = 0 + offset; + indices[1] = 1 + offset; + indices[2] = 1 + offset; + indices[3] = 2 + offset; + indices[4] = 2 + offset; + indices[5] = 3 + offset; + indices[6] = 3 + offset; + indices[7] = 0 + offset; + + // Top edges + indices[8] = 4 + offset; + indices[9] = 5 + offset; + indices[10] = 5 + offset; + indices[11] = 6 + offset; + indices[12] = 6 + offset; + indices[13] = 7 + offset; + indices[14] = 7 + offset; + indices[15] = 4 + offset; + + // Middle edges + indices[16] = 0 + offset; + indices[17] = 4 + offset; + indices[18] = 1 + offset; + indices[19] = 5 + offset; + indices[20] = 2 + offset; + indices[21] = 6 + offset; + indices[22] = 3 + offset; + indices[23] = 7 + offset; +} + +void Chunk_outline(const Chunk* chunk, float corners[24], + unsigned int offset, unsigned int indices[24]) +{ + Cube_corners(chunk->center, CHUNK_RADIUS, corners); + Cube_outlineIndices(offset, indices); +} diff --git a/src/chunk_manager.c b/src/chunk_manager.c @@ -0,0 +1,77 @@ + +#include "chunk_manager.h" + +#include <stdlib.h> +#include <math.h> + +int ChunkManager_offsets(int radius, int* offsets) +{ + int count = 0; + for (int x = -radius; x <= radius; x++) + { + for (int y = -radius; y <= radius; y++) + { + for (int z = -radius; z <= radius; z++) + { + if (x * x + y * y + z * z <= radius * radius) + { + if (offsets != NULL) + { + offsets[count] = x * 2 * CHUNK_RADIUS; + offsets[count + 1] = y * 2 * CHUNK_RADIUS; + offsets[count + 2] = z * 2 * CHUNK_RADIUS; + } + count += 3; + } + } + } + } + return count; +} + +ChunkManager ChunkManager_create(int radius, float player[3]) +{ + ChunkManager chunk_manager; + + chunk_manager.radius = radius; + + int offset_count = ChunkManager_offsets(radius, NULL); + chunk_manager.offsets = (int*)malloc(offset_count * sizeof(int)); + ChunkManager_offsets(radius, chunk_manager.offsets); + + chunk_manager.chunk_count = offset_count / 3; + chunk_manager.chunks = (Chunk*)malloc(chunk_manager.chunk_count + * sizeof(Chunk)); + + chunk_manager.center[0] = 0; + chunk_manager.center[1] = 0; + chunk_manager.center[2] = 0; + ChunkManager_update(&chunk_manager, player); + + return chunk_manager; +} + +void ChunkManager_update(ChunkManager* chunk_manager, float player[3]) +{ + int chunk_x = (int)floor(player[0] / (2 * CHUNK_RADIUS)); + int chunk_y = (int)floor(player[1] / (2 * CHUNK_RADIUS)); + int chunk_z = (int)floor(player[2] / (2 * CHUNK_RADIUS)); + chunk_x = chunk_x * 2 * CHUNK_RADIUS + CHUNK_RADIUS; + chunk_y = chunk_y * 2 * CHUNK_RADIUS + CHUNK_RADIUS; + chunk_z = chunk_z * 2 * CHUNK_RADIUS + CHUNK_RADIUS; + if (chunk_x != chunk_manager->center[0] || chunk_y + != chunk_manager->center[1] || chunk_z != chunk_manager->center[2]) + { + chunk_manager->center[0] = chunk_x; + chunk_manager->center[1] = chunk_y; + chunk_manager->center[2] = chunk_z; + for (int i = 0; i < chunk_manager->chunk_count; i++) + { + chunk_manager->chunks[i] = Chunk_create( + chunk_x + chunk_manager->offsets[i * 3], + chunk_y + chunk_manager->offsets[i * 3 + 1], + chunk_z + chunk_manager->offsets[i * 3 + 2] + ); + } + } +} diff --git a/src/main.c b/src/main.c @@ -1,4 +1,6 @@ #include "camera.h" +#include "chunk.h" +#include "chunk_manager.h" #include "glh/buffer.h" #include "glh/shader.h" @@ -9,6 +11,7 @@ #include <SDL2/SDL.h> #include <SDL2/SDL_opengl.h> #include <stdbool.h> +#include <stdio.h> const int WIDTH = 512, HEIGHT = 512; @@ -69,21 +72,19 @@ int main(int argc, char** argv) glClearColor(0.4f, 0.4f, 0.6f, 1.0f); - GLuint vertex_buffer = createVertexBuffer(3 * sizeof(vec3), NULL, - GL_STATIC_DRAW); - vec3 vertices[] = { - {-0.5, -0.5, 0.0}, - { 0.0, 0.5, 0.0}, - { 0.5, -0.5, 0.0} - }; - glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer); - glBufferSubData(GL_ARRAY_BUFFER, 0, 3 * sizeof(vec3), vertices); - - GLuint index_buffer = createIndexBuffer(3 * sizeof(GLuint), NULL, - GL_STATIC_DRAW); - GLuint indices[] = {0, 1, 2}; - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer); - glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, 3 * sizeof(GLuint), indices); + ChunkManager chunk_manager = ChunkManager_create(2, camera.position); + + float vertices[24 * chunk_manager.chunk_count]; + unsigned int indices[24 * chunk_manager.chunk_count]; + for (int i = 0; i < chunk_manager.chunk_count; i++) + { + Chunk_outline(&chunk_manager.chunks[i], &vertices[i * 24], i * 8, + &indices[i * 24]); + } + GLuint vertex_buffer = createVertexBuffer(24 * chunk_manager.chunk_count + * sizeof(float), vertices, GL_DYNAMIC_DRAW); + GLuint index_buffer = createIndexBuffer(24 * chunk_manager.chunk_count + * sizeof(unsigned int), indices, GL_STATIC_DRAW); int vertex[] = { 3 }; GLuint vertex_array = createVertexArray(vertex_buffer, index_buffer, 1, @@ -122,8 +123,19 @@ int main(int argc, char** argv) Camera_update(&camera); glUniformMatrix4fv(cam_loc, 1, GL_FALSE, camera.matrix[0]); + ChunkManager_update(&chunk_manager, camera.position); + for (int i = 0; i < chunk_manager.chunk_count; i++) + { + Chunk_outline(&chunk_manager.chunks[i], &vertices[i * 24], i * 8, + &indices[i * 24]); + } + glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer); + glBufferSubData(GL_ARRAY_BUFFER, 0, 24 * chunk_manager.chunk_count + * sizeof(float), vertices); + glBindVertexArray(vertex_array); - glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0); + glDrawElements(GL_LINES, 24 * chunk_manager.chunk_count, + GL_UNSIGNED_INT, 0); SDL_GL_SwapWindow(window); }