From 411b1eaaed3ce0e23a6e00837ebf54af11e38717 Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Wed, 29 Sep 2021 21:30:48 +0200 Subject: [PATCH] Add grow animation for newly created block meshes --- src/client/blockmesh.c | 33 ++++++++++++++++++++++++------- src/client/client_map.c | 44 ++++++++++++++++++++--------------------- src/client/client_map.h | 1 + src/client/game.c | 8 ++++---- src/client/object.c | 7 ++++++- src/client/object.h | 6 ++++-- src/client/scene.c | 4 ++-- src/client/scene.h | 2 +- 8 files changed, 66 insertions(+), 39 deletions(-) diff --git a/src/client/blockmesh.c b/src/client/blockmesh.c index 26ca2ba..f822092 100644 --- a/src/client/blockmesh.c +++ b/src/client/blockmesh.c @@ -14,7 +14,7 @@ static v3s8 fdir[6] = { static s32 half_block_size = MAPBLOCK_SIZE / 2; -static void make_vertices(Object *object, MapBlock *block) +static void make_vertices(Object *object, MapBlock *block, bool hide_edges) { v3s32 node_bp = {block->pos.x * MAPBLOCK_SIZE, block->pos.y * MAPBLOCK_SIZE, block->pos.z * MAPBLOCK_SIZE}; @@ -23,7 +23,7 @@ static void make_vertices(Object *object, MapBlock *block) ClientNodeDefintion *def = &client_node_definitions[node->type]; if (def->visibility != NV_NONE) { - v3f32 offset = {x + (f32) MAPBLOCK_SIZE / 2.0f, y + (f32) MAPBLOCK_SIZE / 2.0f, z + (f32) MAPBLOCK_SIZE / 2.0f}; + v3f32 offset = {x - half_block_size - 0.5, y - half_block_size - 0.5, z - half_block_size - 0.5}; for (int f = 0; f < 6; f++) { v3s8 npos = { @@ -36,9 +36,11 @@ static void make_vertices(Object *object, MapBlock *block) if (npos.x >= 0 && npos.x < MAPBLOCK_SIZE && npos.y >= 0 && npos.y < MAPBLOCK_SIZE && npos.z >= 0 && npos.z < MAPBLOCK_SIZE) neighbor = block->data[npos.x][npos.y][npos.z].type; - else { + else if (hide_edges) { MapNode nn = map_get_node(client_map.map, (v3s32) {npos.x + node_bp.x, npos.y + node_bp.y, npos.z + node_bp.z}); neighbor = nn.type; + } else { + neighbor = NODE_AIR; } if (neighbor != NODE_UNLOADED && client_node_definitions[neighbor].visibility != NV_SOLID && (def->visibility != NV_TRANSPARENT || neighbor != node->type)) { @@ -61,23 +63,40 @@ static void make_vertices(Object *object, MapBlock *block) } } +static void animate_mapblock_mesh(Object *obj, f64 dtime) +{ + obj->scale.x += dtime * 2.0; + + if (obj->scale.x > 1.0f) { + obj->scale.x = 1.0f; + client_map_schedule_update_block_mesh(obj->extra); + } + + obj->scale.z = obj->scale.y = obj->scale.x; + + object_transform(obj); +} + void blockmesh_make(MapBlock *block) { + MapBlockExtraData *extra = block->extra; + Object *obj = object_create(); - obj->pos = (v3f32) {block->pos.x * MAPBLOCK_SIZE - half_block_size, block->pos.y * MAPBLOCK_SIZE - half_block_size, block->pos.z * MAPBLOCK_SIZE - half_block_size}; + obj->pos = (v3f32) {block->pos.x * MAPBLOCK_SIZE + half_block_size + 0.5f, block->pos.y * MAPBLOCK_SIZE + half_block_size + 0.5f, block->pos.z * MAPBLOCK_SIZE + half_block_size + 0.5f}; + obj->scale = extra->obj ? extra->obj->scale : (v3f32) {0.1f, 0.1f, 0.1f}; obj->frustum_culling = false; obj->box = (aabb3f32) {{-half_block_size, -half_block_size, -half_block_size}, {half_block_size, half_block_size, half_block_size}}; + obj->on_render = (obj->scale.x == 1.0f) ? NULL : &animate_mapblock_mesh; + obj->extra = block; - make_vertices(obj, block); + make_vertices(obj, block, obj->scale.x == 1.0f); if (! object_add_to_scene(obj)) { object_delete(obj); obj = NULL; } - MapBlockExtraData *extra = block->extra; - if (extra->obj) extra->obj->remove = true; diff --git a/src/client/client_map.c b/src/client/client_map.c index ca1bfaf..6524573 100644 --- a/src/client/client_map.c +++ b/src/client/client_map.c @@ -42,21 +42,6 @@ static void *meshgen_thread(unused void *arg) return NULL; } -// enqueue mesh to block update queue -static void schedule_update_block_mesh(MapBlock *block) -{ - if (! block) - return; - - pthread_mutex_lock(&block->mtx); - MapBlockExtraData *extra = block->extra; - if (! extra->queue) { - extra->queue = true; - queue_enqueue(client_map.queue, block); - } - pthread_mutex_unlock(&block->mtx); -} - // sync functions // send block request command to server @@ -229,12 +214,27 @@ void client_map_block_received(MapBlock *block) extra->state = MBS_FRESH; pthread_mutex_unlock(&block->mtx); - schedule_update_block_mesh(block); + client_map_schedule_update_block_mesh(block); - schedule_update_block_mesh(map_get_block(client_map.map, (v3s32) {block->pos.x + 1, block->pos.y + 0, block->pos.z + 0}, false)); - schedule_update_block_mesh(map_get_block(client_map.map, (v3s32) {block->pos.x + 0, block->pos.y + 1, block->pos.z + 0}, false)); - schedule_update_block_mesh(map_get_block(client_map.map, (v3s32) {block->pos.x + 0, block->pos.y + 0, block->pos.z + 1}, false)); - schedule_update_block_mesh(map_get_block(client_map.map, (v3s32) {block->pos.x - 1, block->pos.y - 0, block->pos.z - 0}, false)); - schedule_update_block_mesh(map_get_block(client_map.map, (v3s32) {block->pos.x - 0, block->pos.y - 1, block->pos.z - 0}, false)); - schedule_update_block_mesh(map_get_block(client_map.map, (v3s32) {block->pos.x - 0, block->pos.y - 0, block->pos.z - 1}, false)); + client_map_schedule_update_block_mesh(map_get_block(client_map.map, (v3s32) {block->pos.x + 1, block->pos.y + 0, block->pos.z + 0}, false)); + client_map_schedule_update_block_mesh(map_get_block(client_map.map, (v3s32) {block->pos.x + 0, block->pos.y + 1, block->pos.z + 0}, false)); + client_map_schedule_update_block_mesh(map_get_block(client_map.map, (v3s32) {block->pos.x + 0, block->pos.y + 0, block->pos.z + 1}, false)); + client_map_schedule_update_block_mesh(map_get_block(client_map.map, (v3s32) {block->pos.x - 1, block->pos.y - 0, block->pos.z - 0}, false)); + client_map_schedule_update_block_mesh(map_get_block(client_map.map, (v3s32) {block->pos.x - 0, block->pos.y - 1, block->pos.z - 0}, false)); + client_map_schedule_update_block_mesh(map_get_block(client_map.map, (v3s32) {block->pos.x - 0, block->pos.y - 0, block->pos.z - 1}, false)); +} + +// enqueue block to mesh update queue +void client_map_schedule_update_block_mesh(MapBlock *block) +{ + if (! block) + return; + + pthread_mutex_lock(&block->mtx); + MapBlockExtraData *extra = block->extra; + if (! extra->queue) { + extra->queue = true; + queue_enqueue(client_map.queue, block); + } + pthread_mutex_unlock(&block->mtx); } diff --git a/src/client/client_map.h b/src/client/client_map.h index ce4056b..8f75da8 100644 --- a/src/client/client_map.h +++ b/src/client/client_map.h @@ -39,5 +39,6 @@ void client_map_set_simulation_distance(u32 simulation_distance); // update simu void client_map_start(); // start meshgen and sync threads void client_map_stop(); // stop meshgen and sync threads void client_map_block_received(MapBlock *block); // called when a block was actually recieved from server +void client_map_schedule_update_block_mesh(MapBlock *block); // enqueue block to mesh update queue #endif diff --git a/src/client/game.c b/src/client/game.c index 0f66bf0..0564dbf 100644 --- a/src/client/game.c +++ b/src/client/game.c @@ -39,7 +39,7 @@ static void crosshair_init() }); } -static void render() +static void render(f64 dtime) { glEnable(GL_DEPTH_TEST); glEnable(GL_ALPHA_TEST); @@ -53,7 +53,7 @@ static void render() glFrontFace(GL_CCW); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - scene_render(); + scene_render(dtime); glDisable(GL_CULL_FACE); sky_render(); @@ -90,7 +90,7 @@ static void game_loop(Client *client) debug_menu_update_daylight(); debug_menu_update_sun_angle(); - render(); + render(dtime); glfwSwapBuffers(window.handle); glfwPollEvents(); @@ -190,7 +190,7 @@ void take_screenshot() // render scene glBindFramebuffer(GL_FRAMEBUFFER, FBOs[0]); - render(); + render(0.0); glBindFramebuffer(GL_FRAMEBUFFER, 0); // blit AA-buffer into no-AA buffer diff --git a/src/client/object.c b/src/client/object.c index def0e4f..6dd4871 100644 --- a/src/client/object.c +++ b/src/client/object.c @@ -60,6 +60,8 @@ Object *object_create() obj->frustum_culling = false; obj->current_face = NULL; obj->faces = array_create(sizeof(ObjectFace)); + obj->on_render = NULL; + obj->extra = NULL; return obj; } @@ -204,8 +206,11 @@ static bool inside_frustum(aabb3f32 box, mat4x4 MVP) #pragma GCC diagnostic pop -void object_render(Object *obj) +void object_render(Object *obj, f64 dtime) { + if (obj->on_render) + obj->on_render(obj, dtime); + if (! obj->visible) return; diff --git a/src/client/object.h b/src/client/object.h index 9d06302..8c2fcdc 100644 --- a/src/client/object.h +++ b/src/client/object.h @@ -45,7 +45,7 @@ typedef struct Array vertices; } ObjectFace; -typedef struct +typedef struct Object { v3f32 pos, rot, scale; f32 angle; @@ -59,6 +59,8 @@ typedef struct aabb3f32 box; ObjectFace *current_face; Array faces; + void (*on_render)(struct Object *obj, f64 dtime); + void *extra; } Object; Object *object_create(); @@ -67,6 +69,6 @@ void object_set_texture(Object *obj, Texture *texture); void object_add_vertex(Object *obj, Vertex3D *vertex); bool object_add_to_scene(Object *obj); void object_transform(Object *obj); -void object_render(Object *obj); +void object_render(Object *obj, f64 dtime); #endif diff --git a/src/client/scene.c b/src/client/scene.c index 9d076ab..979bdcc 100644 --- a/src/client/scene.c +++ b/src/client/scene.c @@ -61,7 +61,7 @@ void scene_add_object(Object *obj) pthread_mutex_unlock(&scene.mtx); } -void scene_render() +void scene_render(f64 dtime) { #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wpedantic" @@ -91,7 +91,7 @@ void scene_render() free(pair); object_delete(obj); } else { - object_render(obj); + object_render(obj, dtime); pairptr = &pair->next; } } diff --git a/src/client/scene.h b/src/client/scene.h index 639dc9a..29013de 100644 --- a/src/client/scene.h +++ b/src/client/scene.h @@ -28,7 +28,7 @@ extern struct Scene bool scene_init(); void scene_deinit(); void scene_add_object(Object *obj); -void scene_render(); +void scene_render(f64 dtime); void scene_on_resize(int width, int height); GLuint scene_get_max_texture_units(); void scene_get_view_proj(mat4x4 target); -- 2.44.0