COMMON = array.o binsearch.o list.o map.o signal.o util.o types.o
-SERVER = $(COMMON) server.o servercommands.o
-CLIENT = $(COMMON) client.o clientcommands.o mesh.o scene.o
+SERVER = $(COMMON) server.o servercommands.o mapgen.o
+CLIENT = $(COMMON) client.o clientcommands.o mesh.o scene.o mapblock_meshgen.o
LIBRARIES = -lpthread -lm
CLIENT_LIBRARIES = -lGL -lGLEW -lglfw
-FLAGS = -g
+FLAGS = -g -fmax-errors=4
ifdef RELEASE
FLAGS = -O3
#include <GL/gl.h>
#include <GLFW/glfw3.h>
#include "client.h"
+#include "mapblock_meshgen.h"
#include "signal.h"
#include "util.h"
glClear(GL_COLOR_BUFFER_BIT);
glClearColor(0.52941176470588, 0.8078431372549, 0.92156862745098, 1.0);
- mat4x4 view, proj;
-
- scene_render(client.scene, shader_program, view, proj);
+ scene_render(client.scene, shader_program);
glfwSwapBuffers(window);
glfwPollEvents();
client.name = NULL;
client.map = map_create();
client.scene = scene_create();
- //client.mapblock_meshgen = mapblock_meshgen_create();
+
+ mapblock_meshgen_init(client.map, client.scene);
pthread_t recv_thread;
pthread_create(&recv_thread, NULL, &reciever_thread, NULL);
if (client.name)
free(client.name);
+ mapblock_meshgen_stop();
+
map_delete(client.map);
scene_delete(client.scene);
- //mapblock_meshgen_delete(client.mapblock_meshgen);
pthread_mutex_destroy(&client.mtx);
}
#include "clientcommands.h"
#include "network.h"
#include "map.h"
-//#include "mapblock_meshgen.h"
#include "scene.h"
typedef struct Client
char *name;
Map *map;
Scene *scene;
- //MapblockMeshgen *mapblock_meshgen;
} Client;
void client_disconnect(bool send, const char *detail);
BinsearchResult res = binsearch(&pos.y, sector->blocks.ptr, sector->blocks.siz, &block_compare);
- if (res.success)
- return *get_block_ptr(sector, res.index);
- if (! create)
- return NULL;
+ MapBlock *block = NULL;
- MapBlock *block = allocate_block(pos);
+ if (res.success) {
+ block = *get_block_ptr(sector, res.index);
+ } else if (create) {
+ block = allocate_block(pos);
- MapNode air = map_node_create(NODE_AIR);
- ITERATE_MAPBLOCK block->data[x][y][z] = air;
+ if (map->on_block_create)
+ map->on_block_create(block);
- array_insert(§or->blocks, &block, res.index);
+ array_insert(§or->blocks, &block, res.index);
+ } else {
+ return NULL;
+ }
- return block;
+ return block->ready ? block : NULL;
}
void map_add_block(Map *map, MapBlock *block)
} else {
array_insert(§or->blocks, &block, res.index);
}
+ if (map->on_block_add)
+ map->on_block_add(block);
}
void map_clear_block(MapBlock *block, v3u8 init_state)
void map_set_node(Map *map, v3s32 pos, MapNode node)
{
v3u8 offset;
- MapBlock *block = map_get_block(map, map_node_to_block_pos(pos, &offset), true);
- MapNode *current_node = &block->data[offset.x][offset.y][offset.z];
- map_node_clear(current_node);
- *current_node = node;
+ MapBlock *block = map_get_block(map, map_node_to_block_pos(pos, &offset), false);
+ if (block) {
+ MapNode *current_node = &block->data[offset.x][offset.y][offset.z];
+ map_node_clear(current_node);
+ *current_node = node;
+ }
}
MapNode map_node_create(Node type)
{
MapNode data[16][16][16];
v3s32 pos;
+ bool ready;
void *extra;
} MapBlock;
u64 hash;
} MapSector;
+typedef void (*MapBlockCallback)(MapBlock *block);
+
typedef struct
{
Array sectors;
+ MapBlockCallback on_block_create;
+ MapBlockCallback on_block_add;
+ MapBlockCallback on_block_change;
} Map;
Map *map_create();
-static bool compare_positions(void *p1, void *p2)
+#include <stdlib.h>
+#include "mapblock_meshgen.h"
+
+static struct
{
- v3s32 *pos1 = p1;
- v3s32 *pos2 = p2;
- return pos1->x == pos2->x && pos1->y == pos2->y && pos->z == pos2->z;
-}
+ Map *map;
+ Scene *scene;
+ List queue;
+ pthread_mutex_t mtx;
+ pthread_t thread;
+ bool cancel;
+} meshgen;
-static void *mapblock_meshgen_thread(void *cliptr)
+static Array make_vertices(MapBlock *block)
{
- Client *client = cliptr;
+ Array vertices = array_create(sizeof(GLfloat));
- for ever {
- ListPair **lptr = &client->mapblock_meshgen_queue.first;
- if (*lptr) {
- MapBlock *block = map_get_block(client->map, *(v3s32 *)(*lptr)->key, false);
- Array vertices(sizeof(GLfloat));
-
- ITERATE_MAPBLOCK {
- MapNode node = block->data[x][y][z];
- BlockDef *def = block->getDef();
- if (! def->drawable)
- continue;
- ivec3 bpos(x, y, z);
- vec3 pos_from_mesh_origin = vec3(bpos) - vec3(SIZE / 2 + 0.5);
- for (int facenr = 0; facenr < 6; facenr++) {
- ivec3 npos = bpos + face_dir[facenr];
- const Block *neighbor_own, *neighbor;
- neighbor_own = neighbor = getBlockNoEx(npos);
- if (! neighbor)
- neighbor = map->getBlock(pos * SIZE + npos);
- if (neighbor && ! neighbor->getDef()->drawable)
- any_drawable_block = true;
- if (! mesh_created_before)
- neighbor = neighbor_own;
- if (! mesh_created_before && ! neighbor || neighbor && ! neighbor->getDef()->drawable) {
- textures.push_back(def->tile_def.get(facenr));
- for (int vertex_index = 0; vertex_index < 6; vertex_index++) {
- for (int attribute_index = 0; attribute_index < 5; attribute_index++) {
- GLdouble value = box_vertices[facenr][vertex_index][attribute_index];
- switch (attribute_index) {
- case 0:
- value += pos_from_mesh_origin.x;
- break;
- case 1:
- value += pos_from_mesh_origin.y;
- break;
- case 2:
- value += pos_from_mesh_origin.z;
- break;
- }
- vertices.push_back(value);
- }
+ (void) block;
+
+ /*
+ ITERATE_MAPBLOCK {
+ MapNode node = block->data[x][y][z];
+ BlockDef *def = block->getDef();
+ if (! def->drawable)
+ continue;
+ ivec3 bpos(x, y, z);
+ vec3 pos_from_mesh_origin = vec3(bpos) - vec3(SIZE / 2 + 0.5);
+ for (int facenr = 0; facenr < 6; facenr++) {
+ ivec3 npos = bpos + face_dir[facenr];
+ const Block *neighbor_own, *neighbor;
+ neighbor_own = neighbor = getBlockNoEx(npos);
+ if (! neighbor)
+ neighbor = map->getBlock(pos * SIZE + npos);
+ if (neighbor && ! neighbor->getDef()->drawable)
+ any_drawable_block = true;
+ if (! mesh_created_before)
+ neighbor = neighbor_own;
+ if (! mesh_created_before && ! neighbor || neighbor && ! neighbor->getDef()->drawable) {
+ textures.push_back(def->tile_def.get(facenr));
+ for (int vertex_index = 0; vertex_index < 6; vertex_index++) {
+ for (int attribute_index = 0; attribute_index < 5; attribute_index++) {
+ GLdouble value = box_vertices[facenr][vertex_index][attribute_index];
+ switch (attribute_index) {
+ case 0:
+ value += pos_from_mesh_origin.x;
+ break;
+ case 1:
+ value += pos_from_mesh_origin.y;
+ break;
+ case 2:
+ value += pos_from_mesh_origin.z;
+ break;
}
+ vertices.push_back(value);
}
}
}
+ }
+ }
+ */
- client_create_mesh(client, create_mesh(vertices.ptr, vertices.siz));
- pthread_mutex_lock(client->mapblock_meshgen_mtx);
+ return vertices;
+}
+
+static void *meshgen_thread(void *unused)
+{
+ (void) unused;
+
+ while (! meshgen.cancel) {
+ ListPair **lptr = &meshgen.queue.first;
+ if (*lptr) {
+ MapBlock *block = map_get_block(meshgen.map, *(v3s32 *)(*lptr)->key, false);
+
+ pthread_mutex_lock(&meshgen.mtx);
+ free((*lptr)->key);
*lptr = (*lptr)->next;
- pthread_mutex_unlock(client->mapblock_meshgen_mtx);
+ pthread_mutex_unlock(&meshgen.mtx);
+
+ Array vertices = make_vertices(block);
+ Mesh *mesh = NULL;
+
+ if (vertices.siz > 0) {
+ mesh = mesh_create(vertices.ptr, vertices.siz);
+ free(vertices.ptr);
+ scene_add_mesh(meshgen.scene, mesh);
+ }
+
+ if (block->extra)
+ mesh->remove = true;
+
+ block->extra = mesh;
} else {
sched_yield();
}
}
+
+ return NULL;
}
-void client_mapblock_changed(Client *client, v3s32 pos)
+static void enqueue_block(MapBlock *block)
{
v3s32 *posptr = malloc(sizeof(v3s32));
- *posptr = pos;
- pthread_mutex_lock(client->mapblock_meshgen_mtx);
- if (! list_put(&client->mapblock_meshgen_queue, posptr, NULL))
+ *posptr = block->pos;
+ pthread_mutex_lock(&meshgen.mtx);
+ if (! list_put(&meshgen.queue, posptr, NULL))
free(posptr);
- pthread_mutex_unlock(client->mapblock_meshgen_mtx);
+ pthread_mutex_unlock(&meshgen.mtx);
+}
+
+static bool compare_positions(void *p1, void *p2)
+{
+ v3s32 *pos1 = p1;
+ v3s32 *pos2 = p2;
+ return pos1->x == pos2->x && pos1->y == pos2->y && pos1->z == pos2->z;
+}
+
+void mapblock_meshgen_init(Map *map, Scene *scene)
+{
+ meshgen.map = map;
+ meshgen.scene = scene;
+ meshgen.queue = list_create(&compare_positions);
+ pthread_mutex_init(&meshgen.mtx, NULL);
+ map->on_block_add = &enqueue_block;
+ map->on_block_change = &enqueue_block;
+ pthread_create(&meshgen.thread, NULL, &meshgen_thread, NULL);
+}
+
+void mapblock_meshgen_stop()
+{
+ meshgen.cancel = true;
+ pthread_join(meshgen.thread, NULL);
+ pthread_mutex_destroy(&meshgen.mtx);
+ ITERATE_LIST(&meshgen.queue, pair) free(pair->key);
+ list_clear(&meshgen.queue);
}
#ifndef _MAPBLOCK_MESHGEN_H_
#define _MAPBLOCK_MESHGEN_H_
-typedef struct
-{
- pthread_mutex_t mtx;
-} MapblockMeshgen;
-
+#include "map.h"
+#include "scene.h"
+void mapblock_meshgen_init(Map *map, Scene *scene);
+void mapblock_meshgen_stop();
#endif
--- /dev/null
+#include <stdlib.h>
+#include "mapgen.h"
+
+// mapgen prototype
+static void generate_block(MapBlock *block)
+{
+ if (block->pos.y < 0 && rand() % 2 == 0) {
+ ITERATE_MAPBLOCK {
+ block->data[x][y][z] = map_node_create(rand() % 4 + 1);
+ }
+ }
+ block->ready = true;
+}
+
+void mapgen_init(Map *map)
+{
+ map->on_block_create = &generate_block;
+}
--- /dev/null
+#ifndef _MAPGEN_H_
+#define _MAPGEN_H_
+
+#include "map.h"
+
+void mapgen_init(Map *map);
+
+#endif
#include <GL/glew.h>
#include <GL/gl.h>
#include <linmath.h/linmath.h>
+#include <stdbool.h>
typedef struct
{
float angle;
mat4x4 transform;
GLuint VAO, VBO;
+ bool remove;
} Mesh;
Mesh *mesh_create(const GLvoid *vertices, GLsizei size);
void mesh_delete(Mesh *mesh);
+void mesh_render(Mesh *mesh, int prog);
#endif
Scene *scene = malloc(sizeof(Scene));
scene->meshes = list_create(NULL),
pthread_mutex_init(&scene->mtx, NULL);
-
return scene;
}
void scene_add_mesh(Scene *scene, Mesh *mesh)
{
+ pthread_mutex_lock(&scene->mtx);
list_put(&scene->meshes, mesh, NULL);
+ pthread_mutex_unlock(&scene->mtx);
}
-void scene_remove_mesh(Scene *scene, Mesh *mesh)
+void scene_render(Scene *scene, int prog)
{
- pthread_mutex_lock(&scene->mtx);
- list_delete(&scene->meshes, mesh);
- pthread_mutex_unlock(&scene->mtx);
- mesh_delete(mesh);
+ for (ListPair **pairptr = &scene->meshes.first; *pairptr != NULL; ) {
+ ListPair *pair = *pairptr;
+ Mesh *mesh = pair->key;
+ if (mesh->remove) {
+ pthread_mutex_lock(&scene->mtx);
+ *pairptr = pair->next;
+ pthread_mutex_unlock(&scene->mtx);
+ free(pair);
+ mesh_delete(mesh);
+ } else {
+ mesh_render(mesh, prog);
+ pairptr = &pair->next;
+ }
+ }
}
-
void scene_add_mesh(Scene *scene, Mesh *mesh);
void scene_remove_mesh(Scene *scene, Mesh *mesh);
-void scene_render(Scene *scene, int prog, mat4x4 view, mat4x4 proj); // ToDo
+void scene_render(Scene *scene, int prog);
#endif
#include <unistd.h>
#include <errno.h>
#include <netdb.h>
+#include "mapgen.h"
#include "server.h"
#include "signal.h"
#include "util.h"
perror("fopen");
}
+ mapgen_init(server.map);
+
while (! interrupted)
server_accept_client();