]> git.lizzy.rs Git - dragonblocks_alpha.git/blob - src/mapblock_meshgen.c
Add mapblock meshgen and mapgen
[dragonblocks_alpha.git] / src / mapblock_meshgen.c
1 #include <stdlib.h>
2 #include "mapblock_meshgen.h"
3
4 static struct
5 {
6         Map *map;
7         Scene *scene;
8         List queue;
9         pthread_mutex_t mtx;
10         pthread_t thread;
11         bool cancel;
12 } meshgen;
13
14 static Array make_vertices(MapBlock *block)
15 {
16         Array vertices = array_create(sizeof(GLfloat));
17
18         (void) block;
19
20         /*
21         ITERATE_MAPBLOCK {
22                 MapNode node = block->data[x][y][z];
23                 BlockDef *def = block->getDef();
24                 if (! def->drawable)
25                         continue;
26                 ivec3 bpos(x, y, z);
27                 vec3 pos_from_mesh_origin = vec3(bpos) - vec3(SIZE / 2 + 0.5);
28                 for (int facenr = 0; facenr < 6; facenr++) {
29                         ivec3 npos = bpos + face_dir[facenr];
30                         const Block *neighbor_own, *neighbor;
31                         neighbor_own = neighbor = getBlockNoEx(npos);
32                         if (! neighbor)
33                                 neighbor = map->getBlock(pos * SIZE + npos);
34                         if (neighbor && ! neighbor->getDef()->drawable)
35                                 any_drawable_block = true;
36                         if (! mesh_created_before)
37                                 neighbor = neighbor_own;
38                         if (! mesh_created_before && ! neighbor || neighbor && ! neighbor->getDef()->drawable) {
39                                 textures.push_back(def->tile_def.get(facenr));
40                                 for (int vertex_index = 0; vertex_index < 6; vertex_index++) {
41                                         for (int attribute_index = 0; attribute_index < 5; attribute_index++) {
42                                                 GLdouble value = box_vertices[facenr][vertex_index][attribute_index];
43                                                 switch (attribute_index) {
44                                                         case 0:
45                                                         value += pos_from_mesh_origin.x;
46                                                         break;
47                                                         case 1:
48                                                         value += pos_from_mesh_origin.y;
49                                                         break;
50                                                         case 2:
51                                                         value += pos_from_mesh_origin.z;
52                                                         break;
53                                                 }
54                                                 vertices.push_back(value);
55                                         }
56                                 }
57                         }
58                 }
59         }
60         */
61
62         return vertices;
63 }
64
65 static void *meshgen_thread(void *unused)
66 {
67         (void) unused;
68
69         while (! meshgen.cancel) {
70                 ListPair **lptr = &meshgen.queue.first;
71                 if (*lptr) {
72                         MapBlock *block = map_get_block(meshgen.map, *(v3s32 *)(*lptr)->key, false);
73
74                         pthread_mutex_lock(&meshgen.mtx);
75                         free((*lptr)->key);
76                         *lptr = (*lptr)->next;
77                         pthread_mutex_unlock(&meshgen.mtx);
78
79                         Array vertices = make_vertices(block);
80                         Mesh *mesh = NULL;
81
82                         if (vertices.siz > 0) {
83                                 mesh = mesh_create(vertices.ptr, vertices.siz);
84                                 free(vertices.ptr);
85                                 scene_add_mesh(meshgen.scene, mesh);
86                         }
87
88                         if (block->extra)
89                                 mesh->remove = true;
90
91                         block->extra = mesh;
92                 } else {
93                         sched_yield();
94                 }
95         }
96
97         return NULL;
98 }
99
100 static void enqueue_block(MapBlock *block)
101 {
102         v3s32 *posptr = malloc(sizeof(v3s32));
103         *posptr = block->pos;
104         pthread_mutex_lock(&meshgen.mtx);
105         if (! list_put(&meshgen.queue, posptr, NULL))
106                 free(posptr);
107         pthread_mutex_unlock(&meshgen.mtx);
108 }
109
110 static bool compare_positions(void *p1, void *p2)
111 {
112         v3s32 *pos1 = p1;
113         v3s32 *pos2 = p2;
114         return pos1->x == pos2->x && pos1->y == pos2->y && pos1->z == pos2->z;
115 }
116
117 void mapblock_meshgen_init(Map *map, Scene *scene)
118 {
119         meshgen.map = map;
120         meshgen.scene = scene;
121         meshgen.queue = list_create(&compare_positions);
122         pthread_mutex_init(&meshgen.mtx, NULL);
123         map->on_block_add = &enqueue_block;
124         map->on_block_change = &enqueue_block;
125         pthread_create(&meshgen.thread, NULL, &meshgen_thread, NULL);
126 }
127
128 void mapblock_meshgen_stop()
129 {
130         meshgen.cancel = true;
131         pthread_join(meshgen.thread, NULL);
132         pthread_mutex_destroy(&meshgen.mtx);
133         ITERATE_LIST(&meshgen.queue, pair) free(pair->key);
134         list_clear(&meshgen.queue);
135 }