summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaditya Dhruv <[email protected]>2026-01-31 18:34:55 -0600
committerAaditya Dhruv <[email protected]>2026-01-31 18:34:55 -0600
commitd5cad0e247ffffd4e985696809e46805177c6940 (patch)
tree519babc838c7d1cd620b61761245aca862e6e08a
parentb20a6103cb202c1721aa2d300b1e7bdafef3366d (diff)
Bugfixes, infinite loading works
-rw-r--r--src/chunk.c49
-rw-r--r--src/chunk.h2
-rw-r--r--src/engine.c34
-rw-r--r--src/engine.h2
-rw-r--r--src/input.c2
-rw-r--r--src/world.c2
6 files changed, 60 insertions, 31 deletions
diff --git a/src/chunk.c b/src/chunk.c
index 67631e9..d67d8cb 100644
--- a/src/chunk.c
+++ b/src/chunk.c
@@ -1,5 +1,6 @@
#include "chunk.h"
#include "block.h"
+#include "cglm/io.h"
#include "cglm/types.h"
#include "cglm/vec2.h"
#include "cglm/vec3.h"
@@ -122,9 +123,13 @@ int _chunk_check_neighbor_block(struct world* world, struct chunk* chunk, vec3 c
glm_vec2_add(left, chunk->coord, c);
int neighbor[] = { c[0], c[1] };
struct chunk* left_chunk = { 0 };
- world_get_chunk(world, neighbor, &chunk);
- // If unloaded, we don't care, it's not being rendered, so mark as no neighbor
- if (left_chunk == NULL || left_chunk->loaded == 0) {
+ world_get_chunk(world, neighbor, &left_chunk);
+ // If not created, we don't care, it's not being rendered, so mark as no neighbor
+ // TODO: Previously had chunk->loaded == 0, but this causes a problem. When we move
+ // from one chunk to another, everything gets unloaded, and then we start loading everything.
+ // This means that sometimes because of order of evaluation a chunk might think it's neighbor
+ // isn't loaded even though it will be
+ if (left_chunk == NULL) {
return 0;
}
// Otherwise we check if the neighbor block exists
@@ -137,9 +142,9 @@ int _chunk_check_neighbor_block(struct world* world, struct chunk* chunk, vec3 c
glm_vec2_add(right, chunk->coord, c);
int neighbor[] = { c[0], c[1] };
struct chunk* right_chunk = { 0 };
- world_get_chunk(world, neighbor, &chunk);
+ world_get_chunk(world, neighbor, &right_chunk);
// If unloaded, we don't care, it's not being rendered, so mark as no neighbor
- if (right_chunk == NULL || right_chunk->loaded == 0) {
+ if (right_chunk == NULL) {
return 0;
}
// Otherwise we check if the neighbor block exists
@@ -152,9 +157,9 @@ int _chunk_check_neighbor_block(struct world* world, struct chunk* chunk, vec3 c
glm_vec2_add(bottom, chunk->coord, c);
int neighbor[] = { c[0], c[1] };
struct chunk* bottom_chunk = { 0 };
- world_get_chunk(world, neighbor, &chunk);
+ world_get_chunk(world, neighbor, &bottom_chunk);
// If unloaded, we don't care, it's not being rendered, so mark as no neighbor
- if (bottom_chunk == NULL || bottom_chunk->loaded == 0) {
+ if (bottom_chunk == NULL) {
return 0;
}
// Otherwise we check if the neighbor block exists
@@ -167,9 +172,9 @@ int _chunk_check_neighbor_block(struct world* world, struct chunk* chunk, vec3 c
glm_vec2_add(top, chunk->coord, c);
int neighbor[] = { c[0], c[1] };
struct chunk* top_chunk = { 0 };
- world_get_chunk(world, neighbor, &chunk);
+ world_get_chunk(world, neighbor, &top_chunk);
// If unloaded, we don't care, it's not being rendered, so mark as no neighbor
- if (top_chunk == NULL || top_chunk->loaded == 0) {
+ if (top_chunk == NULL) {
return 0;
}
// Otherwise we check if the neighbor block exists
@@ -199,11 +204,11 @@ int _chunk_check_neighbor_block(struct world* world, struct chunk* chunk, vec3 c
void _chunk_plains_gen(struct chunk* chunk) {
// ============ KNOBS ============
// Minimum ground
- int z = 2;
+ int z = 20;
// Min POI block height
- int poi_min = 3;
+ int poi_min = 23;
// Max POI block height
- int poi_max = 5;
+ int poi_max = 25;
// Descent/Ascent rate
float m = -.5;
memset(chunk->blocks, 0, CHUNK_HEIGHT * CHUNK_LENGTH * CHUNK_WIDTH * sizeof(struct block*));
@@ -227,7 +232,6 @@ void _chunk_plains_gen(struct chunk* chunk) {
}
}
}
- chunk->loaded = 1;
}
@@ -261,7 +265,18 @@ float* _chunk_face_add(float* face, int size, vec3 pos) {
* NOTE: GPU
*/
void chunk_load(struct world* world, struct chunk *chunk, int coord[2]) {
- fprintf(stderr, "Loaded chunk (%d, %d)\n", coord[0], coord[1]);
+ // If we are already loaded, no need to do any GPU work at all. Just update the coordinates
+ if (chunk->loaded == 1) {
+ vec3 translation = {CHUNK_WIDTH * coord[0], 0, - (CHUNK_LENGTH * coord[1])};
+ // Set the matrix for world coordinate translation
+ glm_mat4_identity(chunk->model);
+ glm_translate(chunk->model, translation);
+ chunk->loaded = 1;
+ chunk->staged_for_load = 0;
+ return;
+
+ }
+ // fprintf(stderr, "Loaded chunk (%d, %d)\n", coord[0], coord[1]);
// ================ OpenGL work ================
// Initalize vertices and vertex order vectors. These will be dynamically
// sized buffer data we send to the GPU
@@ -445,8 +460,8 @@ void chunk_load(struct world* world, struct chunk *chunk, int coord[2]) {
}
float tmp_vertex[vector_length(vertices) * sizeof(front_face)];
int tmp_order[vector_length(vertex_order) * sizeof(vertex_draw_order)];
- fprintf(stderr, "Chunk blk_c: %d v_s: %d, v_o: %d\n", blk_c, vector_length(vertices) / 6, vector_length(vertex_order) / 6);
- fprintf(stderr, "%d|%d|%d|%d|%d|%d|", v_count[0], v_count[1], v_count[2], v_count[3], v_count[4], v_count[5]);
+ // fprintf(stderr, "Chunk blk_c: %d v_s: %d, v_o: %d\n", blk_c, vector_length(vertices) / 6, vector_length(vertex_order) / 6);
+ // fprintf(stderr, "%d|%d|%d|%d|%d|%d|", v_count[0], v_count[1], v_count[2], v_count[3], v_count[4], v_count[5]);
for (int i = 0; i < vector_length(vertices); i++) {
float* face = vector_get(vertices, i);
// Copy from heap mem to tmp buffer, and then free
@@ -497,6 +512,7 @@ void chunk_load(struct world* world, struct chunk *chunk, int coord[2]) {
glm_mat4_identity(chunk->model);
glm_translate(chunk->model, translation);
chunk->loaded = 1;
+ chunk->staged_for_load = 0;
}
void chunk_draw(struct chunk* chunk, struct shader* shader, struct texture* texture) {
@@ -515,6 +531,7 @@ void chunk_unload(struct chunk* chunk) {
// Clear VAO
glDeleteVertexArrays(1, &chunk->_vao);
chunk->loaded = 0;
+ chunk->staged_for_load = 0;
}
// Regenerate chunk data
diff --git a/src/chunk.h b/src/chunk.h
index c22fd36..52c0df3 100644
--- a/src/chunk.h
+++ b/src/chunk.h
@@ -34,7 +34,7 @@ struct chunk {
enum biome biome;
vec2 coord;
int loaded;
- int dirty;
+ int staged_for_load;
};
/**
diff --git a/src/engine.c b/src/engine.c
index 551ab65..0dd8089 100644
--- a/src/engine.c
+++ b/src/engine.c
@@ -46,7 +46,7 @@ int engine_init(struct engine *engine) {
// Setup camera
camera_init(&engine->camera);
- vec3 camera_pos = { 0.0f, 15.0f, 0.0f };
+ vec3 camera_pos = { 0.0f, 40.0f, 0.0f };
camera_set_position(engine->camera, camera_pos);
// Setup root chunk
@@ -72,9 +72,6 @@ void engine_update(struct engine* engine) {
//NOTE: OpenGL FLIP
int curr_chunk[2] = { floorf(engine->camera->position[0] / (float)CHUNK_WIDTH), floorf(-engine->camera->position[2] / (float)CHUNK_LENGTH) };
// Chunk update
- struct chunk* c = {0};
- world_get_chunk(engine->world, curr_chunk, &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",
@@ -82,6 +79,17 @@ void engine_update(struct engine* engine) {
engine->curr_chunk[1],
curr_chunk[0],
curr_chunk[1]);
+ // Stage relevant chunks for loading
+ 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] = { curr_chunk[0] + i, curr_chunk[1] + j };
+ world_get_chunk(engine->world, chunk_coord, &chunk);
+ // Stage for loading chunk
+ chunk->staged_for_load = 1;
+ // fprintf(stderr, "Staged (%d, %d)\n", chunk_coord[0], chunk_coord[1]);
+ }
+ }
// Unload existing chunks
for (int i = -CHUNK_DISTANCE; i <= CHUNK_DISTANCE; i++) {
for (int j = -CHUNK_DISTANCE; j <= CHUNK_DISTANCE; j++) {
@@ -89,22 +97,25 @@ void engine_update(struct engine* engine) {
int chunk_coord[2] = { engine->curr_chunk[0] + i, engine->curr_chunk[1] + j };
world_get_chunk(engine->world, chunk_coord, &chunk);
// unload chunk
- // TODO: Fix some VAO/VBO bug when negative y
- chunk_unload(chunk);
+ if (chunk->staged_for_load == 0) {
+ // fprintf(stderr, "Unloaded (%d, %d)\n", chunk_coord[0], chunk_coord[1]);
+ chunk_unload(chunk);
+ }
}
}
- // Update the curr_chunk
- memcpy(engine->curr_chunk, curr_chunk, sizeof(vec2));
- // Load chunks of CHUNK_DISTANCE around curr_chunk
+ // Load chunks that are needed
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 };
+ int chunk_coord[2] = { curr_chunk[0] + i, curr_chunk[1] + j };
world_get_chunk(engine->world, chunk_coord, &chunk);
- // Load chunk
+ // Load chunks - if already loaded will only update coords
chunk_load(engine->world, chunk, chunk_coord);
+ fprintf(stderr, "Loaded (%d, %d)\n", chunk_coord[0], chunk_coord[1]);
}
}
+ // Update the curr_chunk
+ memcpy(engine->curr_chunk, curr_chunk, sizeof(vec2));
}
}
@@ -132,7 +143,6 @@ void engine_start(struct engine* engine) {
frames = 0;
frame_last_time = now;
fprintf(stderr, "FPS: %.2f\n", fps);
- glm_vec3_print(engine->camera->position, stderr);
fprintf(stderr, "x: %d, y: %d\n", engine->curr_chunk[0], engine->curr_chunk[1]);
}
diff --git a/src/engine.h b/src/engine.h
index 413c74f..115f06f 100644
--- a/src/engine.h
+++ b/src/engine.h
@@ -8,7 +8,7 @@
// 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 0
+#define CHUNK_DISTANCE 10
struct engine {
struct window* window;
diff --git a/src/input.c b/src/input.c
index 06f63a5..472b043 100644
--- a/src/input.c
+++ b/src/input.c
@@ -5,6 +5,7 @@
#include <SDL2/SDL_events.h>
#include <SDL2/SDL_mouse.h>
#include <SDL2/SDL_stdinc.h>
+#include <SDL2/SDL_video.h>
pthread_t input_init(struct engine* engine) {
pthread_t thread;
@@ -17,6 +18,7 @@ void input_join(pthread_t thread, struct engine* engine) {
void input_handle(struct engine *engine) {
SDL_Event event;
SDL_SetRelativeMouseMode(SDL_TRUE);
+ SDL_SetWindowMouseGrab(engine->window->window, SDL_TRUE);
while (engine->game_loop) {
// Quit game
// TODO: Locks?
diff --git a/src/world.c b/src/world.c
index 4ce248b..8ae323e 100644
--- a/src/world.c
+++ b/src/world.c
@@ -5,7 +5,7 @@
#include <string.h>
// LOAD_DISTANCE determines how many chunks are loaded on world creation
-#define LOAD_DISTANCE 10
+#define LOAD_DISTANCE 1
int world_init(int32_t seed, struct world** world) {
srand(seed);