summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/block.c5
-rw-r--r--src/block.h9
-rw-r--r--src/chunk.c54
-rw-r--r--src/chunk.h29
-rw-r--r--src/engine.c82
-rw-r--r--src/engine.h11
-rw-r--r--src/world.c37
-rw-r--r--src/world.h7
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]);