]> git.lizzy.rs Git - dragonblocks_alpha.git/blob - src/clientmap.c
Redesign map handling
[dragonblocks_alpha.git] / src / clientmap.c
1 #include <stdlib.h>
2 #include "clientmap.h"
3
4 static struct
5 {
6         List queue;
7         pthread_mutex_t mtx;
8         pthread_t thread;
9         bool cancel;
10 } meshgen;
11
12 static Client *client = NULL;
13
14 static v3f vpos[6][6] = {
15         {
16                 {-0.5f, -0.5f, -0.5f},
17                 {+0.5f, -0.5f, -0.5f},
18                 {+0.5f, +0.5f, -0.5f},
19                 {+0.5f, +0.5f, -0.5f},
20                 {-0.5f, +0.5f, -0.5f},
21                 {-0.5f, -0.5f, -0.5f},
22         },
23         {
24                 {-0.5f, -0.5f, +0.5f},
25                 {+0.5f, +0.5f, +0.5f},
26                 {+0.5f, -0.5f, +0.5f},
27                 {+0.5f, +0.5f, +0.5f},
28                 {-0.5f, -0.5f, +0.5f},
29                 {-0.5f, +0.5f, +0.5f},
30         },
31         {
32                 {-0.5f, +0.5f, +0.5f},
33                 {-0.5f, -0.5f, -0.5f},
34                 {-0.5f, +0.5f, -0.5f},
35                 {-0.5f, -0.5f, -0.5f},
36                 {-0.5f, +0.5f, +0.5f},
37                 {-0.5f, -0.5f, +0.5f},
38         },
39         {
40                 {+0.5f, +0.5f, +0.5f},
41                 {+0.5f, +0.5f, -0.5f},
42                 {+0.5f, -0.5f, -0.5f},
43                 {+0.5f, -0.5f, -0.5f},
44                 {+0.5f, -0.5f, +0.5f},
45                 {+0.5f, +0.5f, +0.5f},
46         },
47         {
48                 {-0.5f, -0.5f, -0.5f},
49                 {+0.5f, -0.5f, -0.5f},
50                 {+0.5f, -0.5f, +0.5f},
51                 {+0.5f, -0.5f, +0.5f},
52                 {-0.5f, -0.5f, +0.5f},
53                 {-0.5f, -0.5f, -0.5f},
54         },
55         {
56                 {-0.5f, +0.5f, -0.5f},
57                 {+0.5f, +0.5f, -0.5f},
58                 {+0.5f, +0.5f, +0.5f},
59                 {+0.5f, +0.5f, +0.5f},
60                 {-0.5f, +0.5f, +0.5f},
61                 {-0.5f, +0.5f, -0.5f},
62         },
63 };
64
65 static v3s8 fdir[6] = {
66         {+0, +0, -1},
67         {+0, +0, +1},
68         {-1, +0, +0},
69         {+1, +0, +0},
70         {+0, -1, +0},
71         {+0, +1, +0},
72 };
73
74 #define GNODDEF(block, x, y, z) node_definitions[block->data[x][y][z].type]
75 #define VALIDPOS(pos) (pos.x >= 0 && pos.x < 16 && pos.y >= 0 && pos.y < 16 && pos.z >= 0 && pos.z < 16)
76
77 static Array make_vertices(MapBlock *block)
78 {
79         Array vertices = array_create(sizeof(Vertex));
80
81         ITERATE_MAPBLOCK {
82                 NodeDefintion *def = &GNODDEF(block, x, y, z);
83                 if (def->visible) {
84                         v3u8 pos = {x, y, z};
85                         v3f offset = {x + 8.5f, y + 8.5f, z + 8.5f};
86                         v3f color = get_node_color(def);
87                         for (int f = 0; f < 6; f++) {
88                                 v3s8 *noff = &fdir[f];
89                                 v3s8 npos = {
90                                         pos.x + noff->x,
91                                         pos.y + noff->y,
92                                         pos.z + noff->z,
93                                 };
94                                 if (! VALIDPOS(npos) || ! GNODDEF(block, npos.x, npos.y, npos.z).visible) {
95                                         for (int v = 0; v < 6; v++) {
96                                                 Vertex vertex = {
97                                                         vpos[f][v].x + offset.x,
98                                                         vpos[f][v].y + offset.y,
99                                                         vpos[f][v].z + offset.z,
100                                                         color.x,
101                                                         color.y,
102                                                         color.z,
103                                                 };
104                                                 array_append(&vertices, &vertex);
105                                         }
106                                 }
107                         }
108                 }
109         }
110
111         return vertices;
112 }
113
114 #undef GNODDEF
115 #undef VALIDPOS
116
117 static void *meshgen_thread(void *unused)
118 {
119         (void) unused;
120
121         while (! meshgen.cancel) {
122                 ListPair **lptr = &meshgen.queue.first;
123                 if (*lptr) {
124                         pthread_mutex_lock(&meshgen.mtx);
125                         MapBlock *block = (*lptr)->key;
126                         block->state = MBS_READY;
127                         ListPair *next = (*lptr)->next;
128                         free(*lptr);
129                         *lptr = next;
130                         pthread_mutex_unlock(&meshgen.mtx);
131
132                         Array vertices = make_vertices(block);
133                         Mesh *mesh = NULL;
134
135                         if (vertices.siz > 0) {
136                                 mesh = mesh_create(vertices.ptr, vertices.siz);
137                                 mesh->pos = (v3f) {block->pos.x * 16.0f - 8.0f, block->pos.y * 16.0f - 8.0f, block->pos.z * 16.0f - 8.0f};
138                                 mesh_transform(mesh);
139                                 scene_add_mesh(client->scene, mesh);
140                         }
141
142                         if (block->extra)
143                                 ((Mesh *) block->extra)->remove = true;
144
145                         block->extra = mesh;
146                 } else {
147                         sched_yield();
148                 }
149         }
150
151         return NULL;
152 }
153
154 void clientmap_init(Client *cli)
155 {
156         client = cli;
157         meshgen.queue = list_create(NULL);
158         pthread_mutex_init(&meshgen.mtx, NULL);
159         pthread_create(&meshgen.thread, NULL, &meshgen_thread, NULL);
160 }
161
162 void clientmap_deinit()
163 {
164         meshgen.cancel = true;
165         pthread_join(meshgen.thread, NULL);
166         pthread_mutex_destroy(&meshgen.mtx);
167         list_clear(&meshgen.queue);
168 }
169
170 void clientmap_block_changed(MapBlock *block)
171 {
172         pthread_mutex_lock(&meshgen.mtx);
173         if (block->state != MBS_PROCESSING) {
174                 block->state = MBS_PROCESSING;
175                 list_put(&meshgen.queue, block, NULL);
176         }
177         pthread_mutex_unlock(&meshgen.mtx);
178 }