]> git.lizzy.rs Git - dragonblocks_alpha.git/blob - src/client/blockmesh.c
59b60c2aa47ebc9bc6ca5ee4d6166ea65ee6bff7
[dragonblocks_alpha.git] / src / client / blockmesh.c
1 #include "client/blockmesh.h"
2 #include "client/client_map.h"
3 #include "client/client_node.h"
4 #include "client/cube.h"
5
6 static v3s8 fdir[6] = {
7         {+0, +0, -1},
8         {+0, +0, +1},
9         {-1, +0, +0},
10         {+1, +0, +0},
11         {+0, -1, +0},
12         {+0, +1, +0},
13 };
14
15 static s32 half_block_size = MAPBLOCK_SIZE / 2;
16
17 static void make_vertices(Object *object, MapBlock *block, bool hide_edges)
18 {
19         object->visible = false;
20         v3s32 node_bp = {
21                 block->pos.x * MAPBLOCK_SIZE,
22                 block->pos.y * MAPBLOCK_SIZE,
23                 block->pos.z * MAPBLOCK_SIZE
24         };
25
26         ITERATE_MAPBLOCK {
27                 MapNode *node = &block->data[x][y][z];
28                 ClientNodeDefinition *def = &client_node_definitions[node->type];
29
30                 if (def->visibility != NV_NONE) {
31                         v3f32 offset = {
32                                 x - half_block_size - 0.5,
33                                 y - half_block_size - 0.5,
34                                 z - half_block_size - 0.5
35                         };
36
37                         for (int f = 0; f < 6; f++) {
38                                 v3s8 npos = {
39                                         x + fdir[f].x,
40                                         y + fdir[f].y,
41                                         z + fdir[f].z,
42                                 };
43
44                                 bool direct_neighbor = npos.x >= 0 && npos.x < MAPBLOCK_SIZE
45                                         && npos.y >= 0 && npos.y < MAPBLOCK_SIZE
46                                         && npos.z >= 0 && npos.z < MAPBLOCK_SIZE;
47
48                                 MapNode neighbor = direct_neighbor
49                                         ? block->data[npos.x][npos.y][npos.z]
50                                         : map_get_node(client_map.map, (v3s32) {npos.x + node_bp.x, npos.y + node_bp.y, npos.z + node_bp.z});
51
52                                 bool transparency_edge = def->visibility != NV_BLEND || neighbor.type != node->type;
53
54                                 bool render_node = def->visibility == NV_CLIP || (neighbor.type != NODE_UNLOADED
55                                         && client_node_definitions[neighbor.type].visibility != NV_SOLID
56                                         && transparency_edge);
57
58                                 object->visible = object->visible || render_node;
59
60                                 if (! hide_edges && ! direct_neighbor)
61                                         render_node = transparency_edge;
62
63                                 if (render_node) {
64                                         object->transparent = object->transparent || def->visibility == NV_BLEND;
65                                         object_set_texture(object, def->tiles.textures[f]);
66
67                                         for (int v = 0; v < 6; v++) {
68                                                 Vertex3D vertex = cube_vertices[f][v];
69                                                 vertex.position.x += offset.x;
70                                                 vertex.position.y += offset.y;
71                                                 vertex.position.z += offset.z;
72
73                                                 if (def->render)
74                                                         def->render((v3s32) {x + node_bp.x, y + node_bp.y, z + node_bp.z}, node, &vertex, f, v);
75
76                                                 object_add_vertex(object, &vertex);
77                                         }
78                                 }
79                         }
80                 }
81         }
82 }
83
84 static void animate_mapblock_mesh(Object *obj, f64 dtime)
85 {
86         obj->scale.x += dtime * 2.0;
87
88         if (obj->scale.x > 1.0f) {
89                 obj->scale.x = 1.0f;
90                 client_map_schedule_update_block_mesh(obj->extra);
91         }
92
93         obj->scale.z = obj->scale.y = obj->scale.x;
94
95         object_transform(obj);
96 }
97
98 void blockmesh_make(MapBlock *block)
99 {
100         MapBlockExtraData *extra = block->extra;
101
102         Object *obj = object_create();
103
104         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};
105         obj->scale = extra->obj ? extra->obj->scale : (v3f32) {0.1f, 0.1f, 0.1f};
106         obj->frustum_culling = true;
107         obj->box = (aabb3f32) {{-half_block_size - 1.0f, -half_block_size - 1.0f, -half_block_size - 1.0f}, {half_block_size + 1.0f, half_block_size + 1.0f, half_block_size + 1.0f}};
108         obj->on_render = (obj->scale.x == 1.0f) ? NULL : &animate_mapblock_mesh;
109         obj->extra = block;
110
111         make_vertices(obj, block, obj->scale.x == 1.0f);
112
113         if (! object_add_to_scene(obj)) {
114                 object_delete(obj);
115                 obj = NULL;
116         }
117
118         if (extra->obj)
119                 extra->obj->remove = true;
120
121         extra->obj = obj;
122 }