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};
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 = {
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)) {
}
}
+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;
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
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);
}
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
});
}
-static void render()
+static void render(f64 dtime)
{
glEnable(GL_DEPTH_TEST);
glEnable(GL_ALPHA_TEST);
glFrontFace(GL_CCW);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- scene_render();
+ scene_render(dtime);
glDisable(GL_CULL_FACE);
sky_render();
debug_menu_update_daylight();
debug_menu_update_sun_angle();
- render();
+ render(dtime);
glfwSwapBuffers(window.handle);
glfwPollEvents();
// render scene
glBindFramebuffer(GL_FRAMEBUFFER, FBOs[0]);
- render();
+ render(0.0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// blit AA-buffer into no-AA buffer
obj->frustum_culling = false;
obj->current_face = NULL;
obj->faces = array_create(sizeof(ObjectFace));
+ obj->on_render = NULL;
+ obj->extra = NULL;
return obj;
}
#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;
Array vertices;
} ObjectFace;
-typedef struct
+typedef struct Object
{
v3f32 pos, rot, scale;
f32 angle;
aabb3f32 box;
ObjectFace *current_face;
Array faces;
+ void (*on_render)(struct Object *obj, f64 dtime);
+ void *extra;
} Object;
Object *object_create();
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
pthread_mutex_unlock(&scene.mtx);
}
-void scene_render()
+void scene_render(f64 dtime)
{
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic"
free(pair);
object_delete(obj);
} else {
- object_render(obj);
+ object_render(obj, dtime);
pairptr = &pair->next;
}
}
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);