summaryrefslogtreecommitdiff
path: root/state_mainstate
diff options
context:
space:
mode:
author0undefined <oscar@nelin.dk>2026-02-19 01:39:46 +0000
committer0undefined <oscar@nelin.dk>2026-02-19 01:39:46 +0000
commiteef15506347455593d0daf1159eaa1b2c5097802 (patch)
treebd80d01ae0a5fae17a1e120c9630910c275a6971 /state_mainstate
parentd623fb2cc40cb3648441f1818e172637b108f6a1 (diff)
Add chunking
Diffstat (limited to 'state_mainstate')
-rw-r--r--state_mainstate/include/states/mainstate.h7
-rw-r--r--state_mainstate/src/mainstate.c82
-rw-r--r--state_mainstate/src/worldgen.c107
3 files changed, 141 insertions, 55 deletions
diff --git a/state_mainstate/include/states/mainstate.h b/state_mainstate/include/states/mainstate.h
index 03c75d9..5f04a84 100644
--- a/state_mainstate/include/states/mainstate.h
+++ b/state_mainstate/include/states/mainstate.h
@@ -9,17 +9,14 @@
#include <cglm/cglm.h>
-#define WORLD_HEIGHT 32
-#define WORLD_WIDTH 32
-#define WORLD_LENGTH 32
-#define WORLD_SIZE (WORLD_HEIGHT * WORLD_LENGTH * WORLD_WIDTH)
+#include <worldgen.h>
typedef struct mainstate_state {
/* Resources */
Shader shaders[10];
RenderBatch terrain;
RenderObject objects[10];
- u8 world[WORLD_HEIGHT * WORLD_WIDTH * WORLD_LENGTH];
+ u8 world[WORLD_SIZE * CHUNK_SIZE];
i_ctx input_ctx;
binding_t input_bindings[10];
vec3 cam_dir;
diff --git a/state_mainstate/src/mainstate.c b/state_mainstate/src/mainstate.c
index a5c7053..fc3a2a8 100644
--- a/state_mainstate/src/mainstate.c
+++ b/state_mainstate/src/mainstate.c
@@ -6,13 +6,12 @@
#include <daw/state.h>
#include <daw/window.h>
#include <glad/gl.h>
-#include <worldgen.h>
#include <crate.h>
#define FOV_ORTHO 1
#ifdef FOV_ORTHO
-#define FOV_MAX 85
+#define FOV_MAX 145
#define FOV_MIN 5
#define FOV_INC 5
#else
@@ -113,28 +112,42 @@ void move_cam_up_stop(mainstate_state *s) { ACCELERATE( 0, -SPEED(s),
void move_cam_dwn(mainstate_state *s) { ACCELERATE( 0, -SPEED(s), 0); }
void move_cam_dwn_stop(mainstate_state *s) { ACCELERATE( 0, +SPEED(s), 0); }
+void window_resize_callback_ui(ivec3* dst, ivec2 src) {
+ // Map the resolution 1:1
+ glm_ivec2_copy(src, *dst);
+ // Alternatively, scale down the buffer to 1:4
+ //glm_ivec2_divs(src, 4, *dst);
+}
+
void window_resize_callback(ivec3* dst, ivec2 src) {
// Map the resolution 1:1
glm_ivec2_copy(src, *dst);
+ // Alternatively, Supersampling (not working??)
+ //glm_ivec2_scale(src, 2, *dst);
// Alternatively, scale down the buffer to 1:4
//glm_ivec2_divs(src, 4, *dst);
}
Camera UI_Camera;
+void perspective_update_callback_ui(void *restrict w, Camera *restrict dst, void *s, ivec2 src) {
+ mainstate_state *state = s;
+ r_perspective_ortho(dst, 15, src);
+ state->objects[3].texture = ((Window *restrict)w)->render_targets->buffer[1];
+}
-void perspective_update_callback(Camera* dst, void *s, ivec2 src) {
+void perspective_update_callback(void *restrict _ /* unused */, Camera* dst, void *s, ivec2 src) {
mainstate_state *state = s;
#ifdef FOV_ORTHO
r_perspective_ortho(dst, (float)state->fov, src);
#else
- r_perspective(&state->c, (float)state->fov, windowsize);
+ r_perspective(dst, (float)state->fov, src);
#endif
}
void perspective_update(mainstate_state *s) {
ivec2 windowsize;
window_get_size(&windowsize);
- //extern Instance* p;
+
#ifdef FOV_ORTHO
r_perspective_ortho(&s->c, (float)s->fov, windowsize);
#else
@@ -143,7 +156,7 @@ void perspective_update(mainstate_state *s) {
}
void fov_increment(mainstate_state *s) {
- if (s->fov >= FOV_MAX) {
+ if (s->fov + FOV_INC >= FOV_MAX) {
s->fov = FOV_MAX;
} else {
s->fov = s->fov + FOV_INC;
@@ -153,7 +166,7 @@ void fov_increment(mainstate_state *s) {
}
void fov_decrement(mainstate_state *s) {
- if (s->fov <= FOV_MIN) {
+ if (s->fov - FOV_INC <= FOV_MIN) {
s->fov = FOV_MIN;
} else {
s->fov = s->fov - FOV_INC;
@@ -248,13 +261,13 @@ void mainstate_init(Window *restrict w, mainstate_state *state, void* arg) {
/// Setup the camera
// Set the position (it is zero initialized)
- glm_vec3_copy((vec3){WORLD_WIDTH / 2.f, WORLD_HEIGHT / 4.f + 4.f, WORLD_LENGTH / 2.f}, state->c.pos);
+ glm_vec3_copy((vec3){CHUNK_WIDTH / 2.f, CHUNK_HEIGHT / 4.f + 4.f, CHUNK_LENGTH / 2.f}, state->c.pos);
// Copy to the desired position
glm_vec3_copy(state->c.pos, state->cam_pos);
// Field of view
- state->fov = FOV_MIN + 2 * FOV_INC;
+ state->fov = FOV_MIN + FOV_INC;
// Set the viewing angle of the camera -- the direction is subtracted from the
// position.
@@ -316,13 +329,23 @@ void mainstate_init(Window *restrict w, mainstate_state *state, void* arg) {
exit(EXIT_FAILURE);
}
- gen_terrain(state->world, WORLD_HEIGHT/2, WORLD_LENGTH, WORLD_WIDTH);
- for (isize i = 0; i < WORLD_SIZE; i++) {
+ gen_terrain(state->world);
+ for (isize i = 0; i < WORLD_SIZE * CHUNK_SIZE; i++) {
if (state->world[i] == BLOCK_none) continue;
- const isize y = i / (WORLD_LENGTH * WORLD_WIDTH); // height
- const isize z = (i - (WORLD_LENGTH * WORLD_WIDTH * y)) / WORLD_WIDTH; // length
- const isize x = i % WORLD_WIDTH; // width
+ const isize chunk_idx = i / CHUNK_SIZE;
+ const isize local_idx = i % CHUNK_SIZE;
+ const isize local_x = local_idx % CHUNK_WIDTH;
+ const isize local_y = local_idx / (CHUNK_LENGTH * CHUNK_WIDTH);
+ const isize local_z = (local_idx - (CHUNK_LENGTH * CHUNK_WIDTH * local_y)) / CHUNK_WIDTH;
+
+ const isize chunk_x = chunk_idx % WORLD_WIDTH;
+ const isize chunk_z = chunk_idx / WORLD_WIDTH;
+
+ const isize y = local_y; // height
+ const isize z = local_z + chunk_z * CHUNK_LENGTH; // length
+ const isize x = local_x + chunk_x * CHUNK_WIDTH; // width
+
Transform t = {
.position = {(float)x, (float)y, (float)z},
};
@@ -408,17 +431,17 @@ void mainstate_init(Window *restrict w, mainstate_state *state, void* arg) {
// There's a strange duality between using functions to change render_targets,
// and manipulating the datastructures directly.
window_init_renderstack(w, 2, sizeof(t) / sizeof(t[0]), p, t);
- w->render_targets->camera_reset_callback[0] = &perspective_update_callback;
- w->render_targets->framebuffer_size_callback[0] = &window_resize_callback;
+ w->render_targets->camera_reset_callback[0] = &perspective_update_callback_ui;
+ w->render_targets->framebuffer_size_callback[0] = &window_resize_callback_ui;
w->render_targets->camera_reset_callback[1] = &perspective_update_callback;
w->render_targets->framebuffer_size_callback[1] = &window_resize_callback;
+
r_set_camera(w->render_targets, 0, &UI_Camera);
- //r_set_camera(w->render_targets, 0, &state->c);
r_set_camera(w->render_targets, 1, &state->c);
- // Fokin illegal, the texturename referenced here should in theory change on
- // every window/framebbuffer resize where we tear it down and create a new
- // one..???
+ // Remember to keep this texture up-to date when resizing! A caveat I'd rather
+ // have implemented in the engine s.t. I don't need to think about it here.
+ // I guess it is soon time to define a "scene" structure for DAW.
state->objects[3] = RenderObject_new(
// Shader
get_asset(&state->resources, MyFullscreenShader),
@@ -427,10 +450,10 @@ void mainstate_init(Window *restrict w, mainstate_state *state, void* arg) {
// Vertices
shaderbuf_quad_fullscreen,
sizeof(shaderbuf_quad_fullscreen) / sizeof(ShaderBuffer)
- );
+ );
}
-void* mainstate_free(mainstate_state *state) {
+void* mainstate_free(mainstate_state *_ /* unused */) {
i_ctx_pop();
return NULL;
}
@@ -445,11 +468,20 @@ StateType mainstate_update(Window *restrict w, mainstate_state *state, f64 dt) {
r_clear_buffer(w->context, w->render_targets, 1);
// Order really shouldn't matter
- draw_model(w, 1, &state->terrain.renderobj, (vec4){0,0,0,1});
+ draw_model(w, 1, &state->terrain.renderobj, (vec4){0, 0, 0, 1});
// Location should, however
// Draw UI by their screen XY coordinates, Z is the depth/layering
- draw_model(w, 0, &state->objects[3], (vec4){0.0,0.0,0.0,1});
- draw_model(w, 0, &state->objects[2], (vec4){-0.5,0.5,0.0,1});
+ draw_model(w, 0, &state->objects[3], (vec4){0.0, 0.0, 0.0, 1});
+
+ {
+ // Anchor top left
+ const vec2 padding = {240, 240};
+ const float window_width = w->windowsize[0];
+ const float window_height = w->windowsize[1];
+ const float anchor_left = -((window_width - padding[0]) / window_width);
+ const float anchor_top = ((window_height - padding[1]) / window_height);
+ draw_model(w, 0, &state->objects[2], (vec4){anchor_left, anchor_top, 0.0, 1});
+ }
// Move the camera
// ... all of this should be easily selectable in the engine
diff --git a/state_mainstate/src/worldgen.c b/state_mainstate/src/worldgen.c
index 0155fc6..6e5b9c1 100644
--- a/state_mainstate/src/worldgen.c
+++ b/state_mainstate/src/worldgen.c
@@ -1,43 +1,100 @@
#include <stdlib.h>
+#include <cglm/ivec3.h>
#include <worldgen.h>
-void gen_terrain(u8 *world, usize height, usize length, usize width) {
+// Store the xyz position given an index
+static void global_position(ivec3 *pos, usize idx) {
+ const isize chunk_idx = idx / CHUNK_SIZE;
+ const isize local_idx = idx % CHUNK_SIZE;
+ const isize local_x = local_idx % CHUNK_WIDTH;
+ const isize local_y = local_idx / (CHUNK_LENGTH * CHUNK_WIDTH);
+ const isize local_z = (local_idx - (CHUNK_LENGTH * CHUNK_WIDTH * local_y)) / CHUNK_WIDTH;
+
+ const isize chunk_x = chunk_idx % WORLD_WIDTH;
+ const isize chunk_z = chunk_idx / WORLD_WIDTH;
+
+ const isize y = local_y; // height
+ const isize z = local_z + chunk_z * CHUNK_LENGTH; // length
+ const isize x = local_x + chunk_x * CHUNK_WIDTH; // width
+
+ *pos[0] = x;
+ *pos[1] = y;
+ *pos[2] = z;
+}
+
+// Return the index from xyz position
+static usize global_idx(ivec3 pos) {
+ int x = pos[0];
+ int y = pos[1];
+ int z = pos[2];
+
+ usize chunk_x = x / CHUNK_WIDTH;
+ usize chunk_z = z / CHUNK_LENGTH;
+ usize chunk_idx = chunk_z * WORLD_WIDTH + chunk_x;
+
+ usize local_x = x % CHUNK_WIDTH;
+ usize local_y = y;
+ usize local_z = z % CHUNK_LENGTH;
+ usize local_idx = local_y * CHUNK_LENGTH * CHUNK_WIDTH
+ + local_z * CHUNK_WIDTH
+ + local_x;
+
+ return chunk_idx * CHUNK_SIZE + local_idx;
+}
+
+// Chunks are laid out in worldspace as [c1, ..., cN]
+static void gen_chunk(u8 *chunk, usize z, usize x) {
+ // Flat chunks
+ for (usize yy = 0; yy < CHUNK_HEIGHT / 4; yy++) {
+ for (usize zz = 0; zz < CHUNK_LENGTH; zz++) {
+ for (usize xx = 0; xx < CHUNK_WIDTH; xx++) {
+ chunk[yy * CHUNK_LENGTH * CHUNK_WIDTH
+ + zz * CHUNK_WIDTH
+ + xx] = BLOCK_grass;
+ }
+ }
+ }
+}
+
+void gen_terrain(u8 *world) {
if (world == NULL) {
- world = calloc(width * length * height, sizeof(u8));
+ world = calloc(WORLD_SIZE * CHUNK_SIZE, sizeof(u8));
+ }
+
+ for (usize z = 0; z < WORLD_WIDTH; z++) {
+ for (usize x = 0; x < WORLD_LENGTH; x++) {
+ gen_chunk(&world[
+ z * WORLD_LENGTH * CHUNK_SIZE
+ + x * CHUNK_SIZE
+ ], z, x);
+ }
}
// y: height
// z: depth/length
// x: width
- // This is pretty cache unfriendly
- for (usize y = 0; y < height / 2; y++) {
- for (usize z = 0; z < length; z++) {
- for (usize x = 0; x < width; x++) {
- world[y * width * length
- + z * width
- + x] = BLOCK_grass;
- }
- }
- }
-
+ // "house"
for (usize y = 0; y < 4; y++) {
- for (usize z = 0; z < 8; z++) {
- for (usize x = 0; x < 8; x++) {
- if (z > 0 && z < 7 && x > 0 && x < 7) continue;
- world[((height / 2 + 1) + y) * width * length
- + (z + (length / 2 - 4)) * width
- + (x + (width / 2 - 4))] = BLOCK_rock;
+ for (usize z = 0; z < 7; z++) {
+ for (usize x = 0; x < 9; x++) {
+ if (z > 0 && z < 6 && x > 0 && x < 8) continue;
+ ivec3 pos = { CHUNK_WIDTH * WORLD_WIDTH / 2 + x - 4
+ , ((CHUNK_HEIGHT / 4) + y)
+ , CHUNK_LENGTH * WORLD_LENGTH / 2 + z - 4
+ };
+ world[global_idx(pos)] = BLOCK_rock;
}
}
}
// Doorway
- world[(height / 2 + 1) * width * length
- + (length / 2) * width
- + (width / 2 - 4)] = BLOCK_none;
- world[((height / 2 + 1) + 1) * width * length
- + (length / 2) * width
- + (width / 2 - 4)] = BLOCK_none;
+ ivec3 pos = { CHUNK_WIDTH * WORLD_WIDTH / 2
+ , (CHUNK_HEIGHT / 4)
+ , CHUNK_LENGTH * WORLD_LENGTH / 2 + 2
+ };
+ world[global_idx(pos)] = BLOCK_none;
+ pos[1]++;
+ world[global_idx(pos)] = BLOCK_none;
}