diff --git a/src/chunk.c b/src/chunk.c index 19d4a4a..33a313a 100644 --- a/src/chunk.c +++ b/src/chunk.c @@ -35,9 +35,11 @@ #include "tesselator.h" #include "chunk.h" #include "channel.h" +#include "utils.h" struct chunk chunks[CHUNKS_PER_DIM * CHUNKS_PER_DIM]; +HashTable chunk_block_queue; struct channel chunk_work_queue; struct channel chunk_result_queue; @@ -51,7 +53,7 @@ struct chunk_result_packet { struct chunk* chunk; int max_height; struct tesselator tesselator; - uint32_t minimap_data[CHUNK_SIZE * CHUNK_SIZE]; + uint32_t* minimap_data; }; struct chunk_render_call { @@ -73,6 +75,7 @@ void chunk_init() { channel_create(&chunk_work_queue, sizeof(struct chunk_work_packet), CHUNKS_PER_DIM * CHUNKS_PER_DIM); channel_create(&chunk_result_queue, sizeof(struct chunk_result_packet), CHUNKS_PER_DIM * CHUNKS_PER_DIM); + ht_setup(&chunk_block_queue, sizeof(struct chunk*), sizeof(struct chunk_result_packet), 64); int chunk_enabled_cores = min(max(window_cpucores() / 2, 1), CHUNK_WORKERS_MAX); log_info("%i cores enabled for chunk generation", chunk_enabled_cores); @@ -178,6 +181,7 @@ void* chunk_generate(void* data) { struct chunk_result_packet result; result.chunk = work.chunk; + result.minimap_data = malloc(CHUNK_SIZE * CHUNK_SIZE * sizeof(uint32_t)); tesselator_create(&result.tesselator, VERTEX_INT, 0); uint32_t blocks_count; @@ -557,9 +561,7 @@ void chunk_generate_naive(struct libvxl_block* blocks, int count, uint32_t* soli int y = map_size_y - 1 - key_getz(blk->position); int z = key_gety(blk->position); - if(*max_height < y) { - *max_height = y; - } + *max_height = max(*max_height, y); uint32_t col = blk->color; int r = blue(col); @@ -727,25 +729,38 @@ void chunk_generate_naive(struct libvxl_block* blocks, int count, uint32_t* soli void chunk_update_all() { size_t drain = channel_size(&chunk_result_queue); - for(size_t k = 0; k < drain; k++) { - struct chunk_result_packet result; - channel_await(&chunk_result_queue, &result); + if(drain > 0) { + struct chunk_result_packet results[drain]; - if(!result.chunk->created) { - glx_displaylist_create(&result.chunk->display_list, true, false); - result.chunk->created = true; + for(size_t k = 0; k < drain; k++) { + channel_await(&chunk_result_queue, results + k); + results[k].chunk->updated = false; } - result.chunk->last_update = window_time(); - result.chunk->max_height = result.max_height; + struct chunk_result_packet* result = results + drain - 1; + + for(size_t k = 0; k < drain; k++, result--) { + if(!result->chunk->updated) { + result->chunk->updated = true; + + if(!result->chunk->created) { + glx_displaylist_create(&result->chunk->display_list, true, false); + result->chunk->created = true; + } + + result->chunk->max_height = result->max_height; + + tesselator_glx(&result->tesselator, &result->chunk->display_list); - tesselator_glx(&result.tesselator, &result.chunk->display_list); - tesselator_free(&result.tesselator); + glBindTexture(GL_TEXTURE_2D, texture_minimap.texture_id); + glTexSubImage2D(GL_TEXTURE_2D, 0, result->chunk->x * CHUNK_SIZE, result->chunk->y * CHUNK_SIZE, + CHUNK_SIZE, CHUNK_SIZE, GL_RGBA, GL_UNSIGNED_BYTE, result->minimap_data); + glBindTexture(GL_TEXTURE_2D, 0); + } - glBindTexture(GL_TEXTURE_2D, texture_minimap.texture_id); - glTexSubImage2D(GL_TEXTURE_2D, 0, result.chunk->x * CHUNK_SIZE, result.chunk->y * CHUNK_SIZE, CHUNK_SIZE, - CHUNK_SIZE, GL_RGBA, GL_UNSIGNED_BYTE, result.minimap_data); - glBindTexture(GL_TEXTURE_2D, 0); + tesselator_free(&result->tesselator); + free(result->minimap_data); + } } } @@ -763,10 +778,23 @@ void chunk_rebuild_all() { } void chunk_block_update(int x, int y, int z) { - channel_put(&chunk_work_queue, - &(struct chunk_work_packet) { - .chunk = chunks + (x / CHUNK_SIZE) + (z / CHUNK_SIZE) * CHUNKS_PER_DIM, - .chunk_x = x / CHUNK_SIZE, - .chunk_y = z / CHUNK_SIZE, - }); + struct chunk* c = chunks + (x / CHUNK_SIZE) + (z / CHUNK_SIZE) * CHUNKS_PER_DIM; + + ht_insert(&chunk_block_queue, &c, + &(struct chunk_work_packet) { + .chunk = c, + .chunk_x = c->x, + .chunk_y = c->y, + }); +} + +static bool iterate_chunk_updates(void* key, void* value, void* user) { + channel_put(&chunk_work_queue, value); + + return true; +} + +void chunk_queue_blocks() { + ht_iterate(&chunk_block_queue, NULL, iterate_chunk_updates); + ht_clear(&chunk_block_queue); } diff --git a/src/chunk.h b/src/chunk.h index 878c961..79f09e0 100644 --- a/src/chunk.h +++ b/src/chunk.h @@ -34,7 +34,7 @@ extern struct chunk { struct glx_displaylist display_list; int max_height; - float last_update; + bool updated; bool created; int x, y; } chunks[CHUNKS_PER_DIM * CHUNKS_PER_DIM]; @@ -51,5 +51,6 @@ void chunk_generate_naive(struct libvxl_block* blocks, int count, uint32_t* soli int* max_height, int ao); void chunk_rebuild_all(void); void chunk_draw_visible(void); +void chunk_queue_blocks(); #endif diff --git a/src/map.c b/src/map.c index 09d43fe..2ff652a 100644 --- a/src/map.c +++ b/src/map.c @@ -37,6 +37,7 @@ #include "minheap.h" #include "tesselator.h" #include "utils.h" +#include "config.h" uint8_t* map_heights; int map_size_x = 512; @@ -518,14 +519,17 @@ void map_set(int x, int y, int z, unsigned int color) { chunk_block_update(x + 1, y, z); if(z < map_size_z - 1 && z_off == CHUNK_SIZE - 1) chunk_block_update(x, y, z + 1); - if(x > 0 && z > 0 && x_off == 0 && z_off == 0) - chunk_block_update(x - 1, y, z - 1); - if(x < map_size_x - 1 && z < map_size_z - 1 && x_off == CHUNK_SIZE - 1 && z_off == CHUNK_SIZE - 1) - chunk_block_update(x + 1, y, z + 1); - if(x > 0 && z < map_size_z - 1 && x_off == 0 && z_off == CHUNK_SIZE - 1) - chunk_block_update(x - 1, y, z + 1); - if(x < map_size_x - 1 && z > 0 && x_off == CHUNK_SIZE - 1 && z_off == 0) - chunk_block_update(x + 1, y, z - 1); + + if(settings.ambient_occlusion) { + if(x > 0 && z > 0 && x_off == 0 && z_off == 0) + chunk_block_update(x - 1, y, z - 1); + if(x < map_size_x - 1 && z < map_size_z - 1 && x_off == CHUNK_SIZE - 1 && z_off == CHUNK_SIZE - 1) + chunk_block_update(x + 1, y, z + 1); + if(x > 0 && z < map_size_z - 1 && x_off == 0 && z_off == CHUNK_SIZE - 1) + chunk_block_update(x - 1, y, z + 1); + if(x < map_size_x - 1 && z > 0 && x_off == CHUNK_SIZE - 1 && z_off == 0) + chunk_block_update(x + 1, y, z - 1); + } if(x == 0) chunk_block_update(map_size_x - 1, y, z); diff --git a/src/network.c b/src/network.c index 87b6db9..6f67f32 100644 --- a/src/network.c +++ b/src/network.c @@ -1090,6 +1090,9 @@ int network_update() { } } } + + chunk_queue_blocks(); + return 1; } diff --git a/src/utils.c b/src/utils.c index 120c69a..0c96133 100644 --- a/src/utils.c +++ b/src/utils.c @@ -64,3 +64,12 @@ size_t int_hash(void* raw_key, size_t key_size) { x = (x >> 16) ^ x; return x; } + +void ht_iterate(HashTable* ht, void* user, bool (*callback)(void* key, void* value, void* user)) { + for(size_t chain = 0; chain < ht->capacity; chain++) { + HTNode* node = ht->nodes[chain]; + + while(node && callback(node->key, node->value, user)) + node = node->next; + } +} diff --git a/src/utils.h b/src/utils.h index 1773103..4d74c0e 100644 --- a/src/utils.h +++ b/src/utils.h @@ -22,9 +22,12 @@ #include +#include "hashtable.h" + int base64_decode(char* data, int len); int int_cmp(void* first_key, void* second_key, size_t key_size); size_t int_hash(void* raw_key, size_t key_size); +void ht_iterate(HashTable* ht, void* user, bool (*callback)(void* key, void* value, void* user)); #endif