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