diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/block.c | 5 | ||||
| -rw-r--r-- | src/block.h | 9 | ||||
| -rw-r--r-- | src/chunk.c | 54 | ||||
| -rw-r--r-- | src/chunk.h | 29 | ||||
| -rw-r--r-- | src/engine.c | 82 | ||||
| -rw-r--r-- | src/engine.h | 11 | ||||
| -rw-r--r-- | src/world.c | 37 | ||||
| -rw-r--r-- | src/world.h | 7 |
8 files changed, 176 insertions, 58 deletions
diff --git a/src/block.c b/src/block.c index 80a62d2..2197b2a 100644 --- a/src/block.c +++ b/src/block.c @@ -1,3 +1,4 @@ +#include "cglm/affine.h" #include "cglm/cam.h" #include "cglm/cglm.h" #include "cglm/io.h" @@ -131,7 +132,7 @@ void block_update(struct block* blk) { // RTS matrix - rotate, translate, scale glm_mat4_identity(blk->model); float angle = glm_rad(blk->angle); - vec3 scale = { 0.90f, 0.90f, 0.90f }; + // vec3 scale = { 0.90f, 0.90f, 0.90f }; glm_translate(blk->model, blk->coords); // glm_scale(blk->model, scale); // glm_rotate_at(blk->model, pivot, angle, rot_axis); @@ -159,7 +160,7 @@ int block_draw(struct block* blk, struct shader* shader) { }; glUniform3fv(loc, 6, (void*)colors); glDrawElements(GL_TRIANGLES, blk->_vertex_count, GL_UNSIGNED_INT, 0); - block_update(blk); + glBindVertexArray(0); return 0; } diff --git a/src/block.h b/src/block.h index 1da88ac..b19265d 100644 --- a/src/block.h +++ b/src/block.h @@ -12,6 +12,15 @@ struct block { mat4 model; float angle; }; +/** + * Create a "block" object, which is the building blocks of this world. + * Blocks belong in chunks, and chunks belong in worlds. vec3 pos here is the coordinates of the block in WORLD space. + * However, a common method to render these blocks will be that the chunk will set the coordinates in "chunk space", and + * on a chunk_load, we will translate the blocks to wherever the chunk is loaded + * + * + */ int block_init(vec3 pos, struct block* blk); int block_draw(struct block* blk, struct shader* shader); void block_debug(struct block* blk); +void block_update(struct block* blk); diff --git a/src/chunk.c b/src/chunk.c index 3741629..4d15486 100644 --- a/src/chunk.c +++ b/src/chunk.c @@ -1,15 +1,9 @@ #include "chunk.h" #include "block.h" -#include "cglm/io.h" -#include "cglm/util.h" -#include "cglm/vec2.h" -#include "cglm/vec3.h" #include "world.h" -#include <math.h> -#include <stdio.h> +#include "cglm/cglm.h" #include <stdlib.h> #include <string.h> -#include <time.h> #define MIN(x, y) (x < y) ? x : y @@ -103,8 +97,8 @@ void _chunk_plains_gen(struct chunk* chunk) { vec3 poi1 = { rand() % CHUNK_WIDTH, rand() % CHUNK_LENGTH, poi_min + (rand() % (poi_max - poi_min))}; vec3 poi2 = { rand() % CHUNK_WIDTH, rand() % CHUNK_LENGTH, -poi_min + (rand() % (poi_max - poi_min))}; - for (int x = 0; x < CHUNK_LENGTH; x++) { - for (int y = 0; y < CHUNK_WIDTH; y++) { + for (int x = 0; x < CHUNK_WIDTH; x++) { + for (int y = 0; y < CHUNK_LENGTH; y++) { // Minimum z height // Interpolation formula - simple linear vec2 target = { x, y }; @@ -114,10 +108,50 @@ void _chunk_plains_gen(struct chunk* chunk) { for (int h = 0; h < z_final; h++) { struct block* blk = malloc(sizeof(struct block)); // Adjust block coordinates with global chunk coordinates - vec3 pos = {x + (CHUNK_WIDTH * chunk->coord[0]), h, -y - (CHUNK_LENGTH * chunk->coord[1])}; + vec3 pos = {x, h, -y }; block_init(pos, blk); chunk->blocks[x][y][h] = blk; } } } } + + +// Kind of like the block_update of chunks +void chunk_load(struct chunk *chunk, int coord[2]) { + vec3 translation = {CHUNK_WIDTH * coord[0], 0, - (CHUNK_LENGTH * coord[1])}; + for (int x = 0; x < CHUNK_WIDTH; x++) { + for (int y = 0; y < CHUNK_HEIGHT; y++) { + for (int z = 0; z < CHUNK_LENGTH; z++) { + struct block* blk = chunk->blocks[x][z][y]; + if (blk != NULL) { + // Translate to world coordinates + // First do block updates, set the position of the block in local + // chunk coordinates + block_update(blk); + // Then translate them to world coordinates + glm_translate(blk->model, translation); + } + } + } + } +} + +void chunk_draw(struct chunk* chunk, struct shader* shader) { + int counter = 0; + for (int i = 0; i < CHUNK_WIDTH; i++) { + for (int j = 0; j < CHUNK_LENGTH; j++) { + for (int k = 0; k < CHUNK_HEIGHT; k++) { + struct block* blk = chunk->blocks[i][j][k]; + if (blk == NULL) { + continue; + } + block_draw(blk, shader); + counter += 1; + } + } + } +} + +void chunk_unload(struct chunk* chunk) { +} diff --git a/src/chunk.h b/src/chunk.h index 4d06f5f..ac24a2d 100644 --- a/src/chunk.h +++ b/src/chunk.h @@ -22,6 +22,31 @@ struct chunk { vec2 coord; }; +/** + * Generate a chunk at coords for the given world. Memory allocation for chunk is + * handled by the function. + * + */ int chunk_gen(struct world* wld, vec2 coord, struct chunk** chunk); -int chunk_gen_structures(void* neighbor_data, struct chunk* chunk); -int chunk_gen_terrain(void* neighbor_data, struct chunk* chunk); +/** + * Load a chunk to the given coordinates. Essentially, a chunk only knows of + * it's local coordinate system. We want to load this particular chunk to a + * location in WORLD coordinates, which is what coord is. This vec2 will be + * used to translate the blocks that constitute the chunk + * @param chunk Chunk to load + * @param coord coordinates in world space + */ +void chunk_load(struct chunk* chunk, int coord[2]); +/** + * Unload a chunk. Delete GPU data, not the chunk data itself + * + * @param chunk Chunk to load + */ +void chunk_unload(struct chunk* chunk); +/* + * Similar to block_draw, this dispatches calls to OpenGL to draw the chunk. + * Technically this wraps block_draw, so block_draw is the one doing all the work + * @param chunk Chunk to draw + * @param shader Shader to pass to block_draw + */ +void chunk_draw(struct chunk* chunk, struct shader* shader); diff --git a/src/engine.c b/src/engine.c index ed2b6c2..2d509f3 100644 --- a/src/engine.c +++ b/src/engine.c @@ -1,11 +1,13 @@ #include "engine.h" #include "block.h" #include "camera.h" +#include "cglm/io.h" #include "chunk.h" #include "input.h" #include "window.h" #include "world.h" #include <junk/vector.h> +#include <string.h> #include <time.h> void _engine_insert_chunk_ptrs(struct engine* engine, struct chunk* chunk); @@ -31,42 +33,49 @@ int engine_init(struct engine *engine) { engine->shader = shader; // Setup Objects to draw - vector_init(&engine->objects); - // Setup root chunk - struct world* world; - world_init(time(NULL), &world); - vec2 curr_chunk = { 0, 0 }; - int chunk_distance = 2; - for (int i = 0; i < chunk_distance; i++) { - for (int j = 0; j < chunk_distance; j++) { - struct chunk* chunk; - vec2 chunk_coord = { curr_chunk[0] + i, curr_chunk[1] + j }; - world_get_chunk(world, chunk_coord, &chunk); - _engine_insert_chunk_ptrs(engine, chunk); - } - } - + // memset(engine->loaded_chunks, 0, (1 + CHUNK_DISTANCE * 2) * (1 + CHUNK_DISTANCE * 2)); // Setup camera camera_init(&engine->camera); - vec3 camera_pos = { 0.0f, 5.0f, 0.0f }; + vec3 camera_pos = { 0.0f, 15.0f, 0.0f }; camera_set_position(engine->camera, camera_pos); + // Setup root chunk + struct world* world; + world_init(time(NULL), &world); + engine->world = world; // Final step - Start the game engine->game_loop = 1; return 0; } -void _engine_insert_chunk_ptrs(struct engine* engine, struct chunk* chunk) { - int counter = 0; - for (int i = 0; i < CHUNK_WIDTH; i++) { - for (int j = 0; j < CHUNK_LENGTH; j++) { - for (int k = 0; k < CHUNK_HEIGHT; k++) { - struct block* blk = chunk->blocks[i][j][k]; - if (blk == NULL) { - continue; - } - if (VECTOR_INSERT(engine->objects, (void*)blk) == -1) exit(1); - counter += 1; + +void engine_update(struct engine* engine) { + int curr_chunk[2] = { (engine->camera->position[0] / CHUNK_WIDTH), (engine->camera->position[2]) / CHUNK_LENGTH }; + // Chunk update + struct chunk* c = {0}; + int coord[2] = { curr_chunk[0], curr_chunk[1] }; + world_get_chunk(engine->world, coord, &c); + + // We moved a chunk - load new chunks with chunk_load + if (engine->curr_chunk[0] != curr_chunk[0] || engine->curr_chunk[1] != curr_chunk[1]) { + fprintf(stderr, "CHUNK Update! From (%d, %d) to (%d, %d)\n", + engine->curr_chunk[0], + engine->curr_chunk[1], + curr_chunk[0], + curr_chunk[1]); + // Update the curr_chunk + memcpy(engine->curr_chunk, curr_chunk, sizeof(vec2)); + // Load chunks of CHUNK_DISTANCE around curr_chunk + for (int i = -CHUNK_DISTANCE; i <= CHUNK_DISTANCE; i++) { + for (int j = -CHUNK_DISTANCE; j <= CHUNK_DISTANCE; j++) { + struct chunk* chunk; + int chunk_coord[2] = { engine->curr_chunk[0] + i, engine->curr_chunk[1] + j }; + world_get_chunk(engine->world, chunk_coord, &chunk); + // Get "real" coords as in non-negative numbers, that can go in a array + int real_coord[2] = { i + CHUNK_DISTANCE, j + CHUNK_DISTANCE }; + // engine->loaded_chunks[real_coord[0]][real_coord[1]] = chunk; + // Load chunk + chunk_load(chunk, chunk_coord); } } } @@ -79,10 +88,21 @@ void engine_draw(struct engine* engine) { glEnable(GL_DEPTH_TEST); //glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); glUseProgram(engine->shader->program); - for (int i = 0; i < vector_length(engine->objects); i++) { - struct block* block = vector_get(engine->objects, i); - camera_update(engine->camera, engine->shader); - block_draw(block, engine->shader); + // Update engine managed objects + engine_update(engine);//(1 + CHUNK_DISTANCE * 2) * (1 + CHUNK_DISTANCE * 2) + camera_update(engine->camera, engine->shader); + for (int i = -CHUNK_DISTANCE; i <= CHUNK_DISTANCE; i++) { + for (int j = -CHUNK_DISTANCE; j <= CHUNK_DISTANCE; j++) { + struct chunk* chunk = {0}; + // // Load chunk + // Ensure the y coordinate is negative, because in OpenGL +z-axis (y in chunk system) is towards + // user, so we want inwards to be positive, so flip sign + int chunk_coord[2] = { engine->curr_chunk[0] + i, -engine->curr_chunk[1] + j }; + world_get_chunk(engine->world, chunk_coord, &chunk); + // Load chunk + chunk_load(chunk, chunk_coord); + chunk_draw(chunk, engine->shader); + } } SDL_RenderPresent(engine->window->renderer); } diff --git a/src/engine.h b/src/engine.h index 2eb7518..0633bcc 100644 --- a/src/engine.h +++ b/src/engine.h @@ -2,12 +2,21 @@ #include "window.h" #include "shader.h" #include "junk/vector.h" +// CHUNK_DISTANCE is essentially render distance, it shows you how many chunks +// around the user you can see +// The number of loaded chunks can be determined as follows: +// We want a square around curr_chunk, and a side of the square will be 1 +// (center chunk) + 2 * CHUNK_DISTANCE (either side of center) +// loaded chunks = (1 + CHUNK_DISTANCE * 2)^2 +#define CHUNK_DISTANCE 5 + struct engine { struct window* window; struct shader* shader; - struct vector* objects; struct camera* camera; int game_loop; + int curr_chunk[2]; + struct world* world; }; /** diff --git a/src/world.c b/src/world.c index 72a0c21..41fdd17 100644 --- a/src/world.c +++ b/src/world.c @@ -1,29 +1,48 @@ #include "world.h" +#include "cglm/io.h" +#include "chunk.h" #include <stdlib.h> #include <string.h> +// LOAD_DISTANCE determines how many chunks are loaded on world creation +#define LOAD_DISTANCE 4 + int world_init(int32_t seed, struct world** world) { srand(seed); struct world* wld = malloc(sizeof(struct world)); memset(wld, 0, sizeof(struct world)); wld->seed = seed; //TODO: Improve loading here - for (int i = 0; i < 2; i++) { - for (int j = 0; j < 2; j++) { + for (int i = 0; i < LOAD_DISTANCE; i++) { + for (int j = 0; j < LOAD_DISTANCE; j++) { struct chunk* chunk; - vec2 coords = { i, j }; - chunk_gen(wld, coords, &chunk); - wld->chunks[i][j] = chunk; - + int coords[2] = { i, j }; + world_get_chunk(wld, coords, &chunk); } } *world = wld; return 0; } -int world_get_chunk(struct world* world, vec2 coord, struct chunk** chunk) { +int world_get_chunk(struct world* world, int coord[2], struct chunk** chunk) { + int w = ((abs(coord[0]) / WORLD_WIDTH) + 1) * WORLD_WIDTH; + int l = ((abs(coord[1]) / WORLD_LENGTH) + 1) * WORLD_LENGTH; + int x = (coord[0] + w) % WORLD_WIDTH; + int y = (coord[1] + l) % WORLD_LENGTH; + vec2 new_coord = { x, y }; + struct chunk* c = world->chunks[x][y]; + if (c != NULL) { + *chunk = c; + } else { + chunk_gen(world, new_coord, chunk); + world->chunks[x][y] = *chunk; + } + return 0; +} + +void world_get_chunk_real_coord(struct world* world, vec2 coord, int out[2]) { int x = (int)coord[0] % WORLD_WIDTH; int y = (int)coord[1] % WORLD_LENGTH; - *chunk = world->chunks[x][y]; - return 0; + out[0] = x; + out[1] = y; } diff --git a/src/world.h b/src/world.h index c65a1d0..ec0328b 100644 --- a/src/world.h +++ b/src/world.h @@ -1,8 +1,8 @@ #pragma once #include "chunk.h" #include <stdint.h> -#define WORLD_LENGTH 32 -#define WORLD_WIDTH 32 +#define WORLD_LENGTH 6 +#define WORLD_WIDTH 6 struct world { struct chunk* chunks[WORLD_WIDTH][WORLD_LENGTH]; @@ -11,4 +11,5 @@ struct world { int world_init(int32_t seed, struct world** world); int world_save(int32_t seed); -int world_get_chunk(struct world* world, vec2 coord, struct chunk** chunk); +int world_get_chunk(struct world* world, int coord[2], struct chunk** chunk); +void world_get_chunk_real_coord(struct world* world, vec2 coord, int out[2]); |
