]> git.lizzy.rs Git - dragonblocks_alpha.git/commitdiff
Add textures
authorElias Fleckenstein <eliasfleckenstein@web.de>
Tue, 22 Jun 2021 16:36:59 +0000 (18:36 +0200)
committerElias Fleckenstein <eliasfleckenstein@web.de>
Tue, 22 Jun 2021 16:36:59 +0000 (18:36 +0200)
35 files changed:
.gitmodules
deps/stb [new submodule]
shaders/fragment.glsl
shaders/vertex.glsl
src/Makefile
src/array.c
src/array.h
src/blockmesh.c
src/client.c
src/client.h
src/clientcommands.c
src/clientmap.c
src/clientmap.h
src/clientnode.c [new file with mode: 0644]
src/clientnode.h [new file with mode: 0644]
src/list.c
src/list.h
src/map.c
src/mesh.c
src/mesh.h
src/node.c
src/node.h
src/queue.c
src/scene.c
src/scene.h
src/server.c
src/servermap.c
src/signal.c
src/texture.c [new file with mode: 0644]
src/texture.h [new file with mode: 0644]
src/util.h
textures/dirt.png [new file with mode: 0644]
textures/grass.png [new file with mode: 0644]
textures/invalid.png [new file with mode: 0644]
textures/stone.png [new file with mode: 0644]

index b4172dbd829e111a7c41ecc275e9c17dbd517adb..6c23b94f7261fd3c697456f859eba60cca9a347d 100644 (file)
@@ -4,3 +4,6 @@
 [submodule "deps/perlin"]
        path = deps/perlin
        url = https://github.com/czinn/perlin
+[submodule "deps/stb"]
+       path = deps/stb
+       url = https://github.com/nothings/stb
diff --git a/deps/stb b/deps/stb
new file mode 160000 (submodule)
index 0000000..c9064e3
--- /dev/null
+++ b/deps/stb
@@ -0,0 +1 @@
+Subproject commit c9064e317699d2e495f36ba4f9ac037e88ee371a
index dd9cb004b788a5d0a19aacfa6dd216982d3c5846..98b37dbe2b516812e3a1013c950da53b43d736a4 100755 (executable)
@@ -1,10 +1,12 @@
 #version 330 core
 
-in vec3 fragmentColor;
+in vec2 fragmentTextureCoords;
 
 out vec4 outColor;
 
+uniform sampler2D texture0;
+
 void main()
 {
-       outColor = vec4(fragmentColor, 0.1);
+       outColor = texture(texture0, fragmentTextureCoords);
 }
index 16ebda3dc6cbd4154ae3b2678b27d87f9fe4d95d..58e743a9c4f7daea8cabf213c27e881745083a23 100755 (executable)
@@ -1,9 +1,9 @@
 #version 330 core
 
 layout(location = 0) in vec3 vertexPosition;
-layout(location = 1) in vec3 vertexColor;
+layout(location = 1) in vec2 vertexTextureCoords;
 
-out vec3 fragmentColor;
+out vec2 fragmentTextureCoords;
 
 uniform mat4 model;
 uniform mat4 view;
@@ -12,6 +12,6 @@ uniform mat4 projection;
 void main()
 {
     gl_Position = projection * view * model * vec4(vertexPosition, 1.0);
-    fragmentColor = vertexColor;
+    fragmentTextureCoords = vertexTextureCoords;
 }
 
index 07104c4100984dca8676fb45944fb1b2ffb0c85e..34e267c78934275aca5f884bb4da98ec0ec3aad7 100644 (file)
@@ -1,6 +1,6 @@
 COMMON = array.o list.o map.o signal.o util.o types.o node.o queue.o
 SERVER = $(COMMON) server.o servercommands.o servermap.o perlin.o facecache.o mapgen.o mapdb.o
-CLIENT = $(COMMON) client.o clientcommands.o clientmap.o mesh.o scene.o shaders.o blockmesh.o
+CLIENT = $(COMMON) client.o clientcommands.o clientmap.o clientnode.o mesh.o scene.o shaders.o blockmesh.o texture.o
 LIBRARIES = -lpthread -lm -lz
 FLAGS = -g -fmax-errors=4
 
index 1d648f23878f51aa3b14bc2c7d72bb939a08b148..b0bf747024939718ec2de51df02b5a0d606562ac 100644 (file)
@@ -47,6 +47,14 @@ void array_append(Array *array, void *elem)
        memcpy((char *) array->ptr + oldsiz * array->membsiz, elem, array->membsiz);
 }
 
+void array_copy(Array *array, void **ptr, size_t *count)
+{
+       *count = array->siz;
+       size_t size = array->siz * array->membsiz;
+       *ptr = malloc(size);
+       memcpy(*ptr, array->ptr, size);
+}
+
 ArraySearchResult array_search(Array *array, void *search)
 {
        assert(array->cmp);
index 3bb6256e3bcc35c7072841031f27e542c187745e..73c8b4b43200b63a94437b129905bd97008ca08c 100644 (file)
@@ -25,6 +25,7 @@ typedef struct
 Array array_create(size_t membsiz);
 void array_insert(Array *array, void *elem, size_t idx);
 void array_append(Array *array, void *elem);
+void array_copy(Array *array, void **ptr, size_t *count);
 ArraySearchResult array_search(Array *array, void *search);
 
 #endif
index af4675fddcab973153b6d93c236fbe2cdee721be..7ea1368a5d8919c3edbf539cb9c3299a29430af6 100644 (file)
@@ -1,53 +1,54 @@
 #include "blockmesh.h"
+#include "clientnode.h"
 
-static v3f vpos[6][6] = {
+Vertex cube_vertices[6][6] = {
        {
-               {-0.5f, -0.5f, -0.5f},
-               {+0.5f, -0.5f, -0.5f},
-               {+0.5f, +0.5f, -0.5f},
-               {+0.5f, +0.5f, -0.5f},
-               {-0.5f, +0.5f, -0.5f},
-               {-0.5f, -0.5f, -0.5f},
+               {-0.5, -0.5, -0.5, +0.0, +0.0},
+               {+0.5, -0.5, -0.5, +1.0, +0.0},
+               {+0.5, +0.5, -0.5, +1.0, +1.0},
+               {+0.5, +0.5, -0.5, +1.0, +1.0},
+               {-0.5, +0.5, -0.5, +0.0, +1.0},
+               {-0.5, -0.5, -0.5, +0.0, +0.0},
        },
        {
-               {-0.5f, -0.5f, +0.5f},
-               {+0.5f, +0.5f, +0.5f},
-               {+0.5f, -0.5f, +0.5f},
-               {+0.5f, +0.5f, +0.5f},
-               {-0.5f, -0.5f, +0.5f},
-               {-0.5f, +0.5f, +0.5f},
+               {-0.5, -0.5, +0.5, +0.0, +0.0},
+               {+0.5, +0.5, +0.5, +1.0, +1.0},
+               {+0.5, -0.5, +0.5, +1.0, +0.0},
+               {+0.5, +0.5, +0.5, +1.0, +1.0},
+               {-0.5, -0.5, +0.5, +0.0, +0.0},
+               {-0.5, +0.5, +0.5, +0.0, +1.0},
        },
        {
-               {-0.5f, +0.5f, +0.5f},
-               {-0.5f, -0.5f, -0.5f},
-               {-0.5f, +0.5f, -0.5f},
-               {-0.5f, -0.5f, -0.5f},
-               {-0.5f, +0.5f, +0.5f},
-               {-0.5f, -0.5f, +0.5f},
+               {-0.5, +0.5, +0.5, +1.0, +1.0},
+               {-0.5, -0.5, -0.5, +0.0, +0.0},
+               {-0.5, +0.5, -0.5, +0.0, +1.0},
+               {-0.5, -0.5, -0.5, +0.0, +0.0},
+               {-0.5, +0.5, +0.5, +1.0, +1.0},
+               {-0.5, -0.5, +0.5, +1.0, +0.0},
        },
        {
-               {+0.5f, +0.5f, +0.5f},
-               {+0.5f, +0.5f, -0.5f},
-               {+0.5f, -0.5f, -0.5f},
-               {+0.5f, -0.5f, -0.5f},
-               {+0.5f, -0.5f, +0.5f},
-               {+0.5f, +0.5f, +0.5f},
+               {+0.5, +0.5, +0.5, +1.0, +1.0},
+               {+0.5, +0.5, -0.5, +0.0, +1.0},
+               {+0.5, -0.5, -0.5, +0.0, +0.0},
+               {+0.5, -0.5, -0.5, +0.0, +0.0},
+               {+0.5, -0.5, +0.5, +1.0, +0.0},
+               {+0.5, +0.5, +0.5, +1.0, +1.0},
        },
        {
-               {-0.5f, -0.5f, -0.5f},
-               {+0.5f, -0.5f, -0.5f},
-               {+0.5f, -0.5f, +0.5f},
-               {+0.5f, -0.5f, +0.5f},
-               {-0.5f, -0.5f, +0.5f},
-               {-0.5f, -0.5f, -0.5f},
+               {-0.5, -0.5, -0.5, +0.0, +1.0},
+               {+0.5, -0.5, -0.5, +1.0, +1.0},
+               {+0.5, -0.5, +0.5, +1.0, +0.0},
+               {+0.5, -0.5, +0.5, +1.0, +0.0},
+               {-0.5, -0.5, +0.5, +0.0, +0.0},
+               {-0.5, -0.5, -0.5, +0.0, +1.0},
        },
        {
-               {-0.5f, +0.5f, -0.5f},
-               {+0.5f, +0.5f, -0.5f},
-               {+0.5f, +0.5f, +0.5f},
-               {+0.5f, +0.5f, +0.5f},
-               {-0.5f, +0.5f, +0.5f},
-               {-0.5f, +0.5f, -0.5f},
+               {-0.5, +0.5, -0.5, +0.0, +1.0},
+               {+0.5, +0.5, -0.5, +1.0, +1.0},
+               {+0.5, +0.5, +0.5, +1.0, +0.0},
+               {+0.5, +0.5, +0.5, +1.0, +0.0},
+               {-0.5, +0.5, +0.5, +0.0, +0.0},
+               {-0.5, +0.5, -0.5, +0.0, +1.0},
        },
 };
 
@@ -60,44 +61,41 @@ static v3s8 fdir[6] = {
        {+0, +1, +0},
 };
 
-#define GNODDEF(block, x, y, z) node_definitions[block->data[x][y][z].type]
+#define VISIBLE(block, x, y, z) node_definitions[block->data[x][y][z].type].visible
 #define VALIDPOS(pos) (pos.x >= 0 && pos.x < 16 && pos.y >= 0 && pos.y < 16 && pos.z >= 0 && pos.z < 16)
 
-static Array make_vertices(MapBlock *block)
+static VertexBuffer make_vertices(MapBlock *block)
 {
-       Array vertices = array_create(sizeof(Vertex));
+       VertexBuffer buffer = vertexbuffer_create();
 
        ITERATE_MAPBLOCK {
-               NodeDefintion *def = &GNODDEF(block, x, y, z);
-               if (def->visible) {
-                       v3u8 pos = {x, y, z};
+               if (VISIBLE(block, x, y, z)) {
                        v3f offset = {x + 8.5f, y + 8.5f, z + 8.5f};
-                       v3f color = get_node_color(def);
+
+                       vertexbuffer_set_texture(&buffer, client_node_definitions[block->data[x][y][z].type].texture);
+
                        for (int f = 0; f < 6; f++) {
-                               v3s8 *noff = &fdir[f];
                                v3s8 npos = {
-                                       pos.x + noff->x,
-                                       pos.y + noff->y,
-                                       pos.z + noff->z,
+                                       x + fdir[f].x,
+                                       y + fdir[f].y,
+                                       z + fdir[f].z,
                                };
-                               if (! VALIDPOS(npos) || ! GNODDEF(block, npos.x, npos.y, npos.z).visible) {
+
+                               if (! VALIDPOS(npos) || ! VISIBLE(block, npos.x, npos.y, npos.z)) {
                                        for (int v = 0; v < 6; v++) {
-                                               Vertex vertex = {
-                                                       vpos[f][v].x + offset.x,
-                                                       vpos[f][v].y + offset.y,
-                                                       vpos[f][v].z + offset.z,
-                                                       color.x,
-                                                       color.y,
-                                                       color.z,
-                                               };
-                                               array_append(&vertices, &vertex);
+                                               Vertex vertex = cube_vertices[f][v];
+                                               vertex.x += offset.x;
+                                               vertex.y += offset.y;
+                                               vertex.z += offset.z;
+
+                                               vertexbuffer_add_vertex(&buffer, &vertex);
                                        }
                                }
                        }
                }
        }
 
-       return vertices;
+       return buffer;
 }
 
 #undef GNODDEF
@@ -105,17 +103,7 @@ static Array make_vertices(MapBlock *block)
 
 void make_block_mesh(MapBlock *block, Scene *scene)
 {
-       Array vertices = make_vertices(block);
-       Mesh *mesh = NULL;
-
-       if (vertices.siz > 0) {
-               mesh = mesh_create(vertices.ptr, vertices.siz);
-               mesh->pos = (v3f) {block->pos.x * 16.0f - 8.0f, block->pos.y * 16.0f - 8.0f, block->pos.z * 16.0f - 8.0f};
-               mesh_transform(mesh);
-               scene_add_mesh(scene, mesh);
-       }
-
        if (block->extra)
-               ((Mesh *) block->extra)->remove = true;
-       block->extra = mesh;
+               ((MeshObject *) block->extra)->remove = true;
+       block->extra = meshobject_create(make_vertices(block), scene, (v3f) {block->pos.x * 16.0f - 8.0f, block->pos.y * 16.0f - 8.0f, block->pos.z * 16.0f - 8.0f});
 }
index 70d87277bd5e215560e34217e7272f69f5f88a0f..ebac21f75fa98995a41c784d9e0808cea8058e9c 100644 (file)
@@ -11,6 +11,7 @@
 #include <GLFW/glfw3.h>
 #include "client.h"
 #include "clientmap.h"
+#include "clientnode.h"
 #include "signal.h"
 #include "shaders.h"
 #include "util.h"
@@ -33,10 +34,8 @@ void client_disconnect(bool send, const char *detail)
 
 #include "network.c"
 
-static void *reciever_thread(void *unused)
+static void *reciever_thread(__attribute__((unused)) void *unused)
 {
-       (void) unused;
-
        handle_packets(&client);
 
        if (errno != EINTR)
@@ -83,20 +82,15 @@ static void client_loop()
 
        glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
 
-       const char *shader_path;
-
-#ifdef RELEASE
-       shader_path = "shaders";
-#else
-       shader_path = "../shaders";
-#endif
-
-       ShaderProgram *prog = create_shader_program(shader_path);
+       ShaderProgram *prog = create_shader_program(RESSOURCEPATH "shaders");
        if (! prog) {
                fprintf(stderr, "Failed to create shader program\n");
                return;
        }
 
+       init_client_node_definitions();
+       clientmap_start_meshgen();
+
        mat4x4 view, projection;
 
        update_view_matrix(prog, view);
index 7e93df1708fc86df807f89dfeeca9a7672e26943..7f02e421f17b7c84a9eb41bd579391ca20972f00 100644 (file)
@@ -9,6 +9,12 @@
 #include "network.h"
 #include "scene.h"
 
+#ifdef RELEASE
+       #define RESSOURCEPATH ""
+#else
+       #define RESSOURCEPATH "../"
+#endif
+
 typedef struct Client
 {
        int fd;
index cc586e9b33d1835ce7c59c13e178fe8549d1027f..d085627b138582ae3d3a65afd6edb6e3b2989177 100644 (file)
@@ -4,10 +4,8 @@
 #include "clientmap.h"
 #include "types.h"
 
-static bool disconnect_handler(Client *client, bool good)
+static bool disconnect_handler(__attribute__((unused)) Client *client, bool good)
 {
-       (void) client;
-
        if (good)
                client_disconnect(false, NULL);
        return true;
index 4f65239713b0fc5571b10d47bb96e35a20bb0009..8c8a62dc4e3c8dd0eb651600277ed831175bda44 100644 (file)
@@ -17,10 +17,8 @@ static void set_block_ready(void *block)
        ((MapBlock *) block)->state = MBS_READY;
 }
 
-static void *meshgen_thread(void *unused)
+static void *meshgen_thread(__attribute__((unused)) void *unused)
 {
-       (void) unused;
-
        while (! meshgen.cancel) {
                MapBlock *block;
                if ((block = dequeue_callback(meshgen.queue, &set_block_ready)))
@@ -36,13 +34,19 @@ void clientmap_init(Client *cli)
 {
        client = cli;
        meshgen.queue = create_queue();
+}
+
+void clientmap_start_meshgen()
+{
        pthread_create(&meshgen.thread, NULL, &meshgen_thread, NULL);
 }
 
 void clientmap_deinit()
 {
        meshgen.cancel = true;
-       pthread_join(meshgen.thread, NULL);
+       delete_queue(meshgen.queue);
+       if (meshgen.thread)
+               pthread_join(meshgen.thread, NULL);
 }
 
 void clientmap_block_changed(MapBlock *block)
index e46c374e6fb4b5bd54491d9d38483720c072c0ff..a56a7660ed7b9b3d92f16475f69ffe381ffdb4e2 100644 (file)
@@ -4,6 +4,7 @@
 #include "client.h"
 
 void clientmap_init(Client *cli);
+void clientmap_start_meshgen();
 void clientmap_deinit();
 
 void clientmap_block_changed(MapBlock *block);
diff --git a/src/clientnode.c b/src/clientnode.c
new file mode 100644 (file)
index 0000000..b82625a
--- /dev/null
@@ -0,0 +1,21 @@
+#include "client.h"
+#include "clientnode.h"
+#include "node.h"
+#include "texture.h"
+
+ClientNodeDefintion client_node_definitions[NODE_UNLOADED] = {
+       {RESSOURCEPATH "textures/invalid.png", 0},
+       {NULL, 0},
+       {RESSOURCEPATH "textures/grass.png", 0},
+       {RESSOURCEPATH "textures/dirt.png", 0},
+       {RESSOURCEPATH "textures/stone.png", 0},
+};
+
+void init_client_node_definitions()
+{
+       for (Node node = NODE_INVALID; node < NODE_UNLOADED; node++) {
+               ClientNodeDefintion *def = &client_node_definitions[node];
+               if (def->texture_path)
+                       def->texture = get_texture(def->texture_path);
+       }
+}
diff --git a/src/clientnode.h b/src/clientnode.h
new file mode 100644 (file)
index 0000000..e51616b
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef _CLIENTNODE_H_
+#define _CLIENTNODE_H_
+
+#include "node.h"
+
+typedef struct
+{
+       char *texture_path;
+       GLuint texture;
+} ClientNodeDefintion;
+
+extern ClientNodeDefintion client_node_definitions[];
+void init_client_node_definitions();
+
+#endif
index fa8af7078a34de049340f1e14471f2a526142f32..8734f4f03287dcc79441c0fee47ae455a866bd8d 100644 (file)
@@ -21,9 +21,16 @@ List list_create(ListComparator cmp)
 }
 
 void list_clear(List *list)
+{
+       list_clear_func(list, NULL, NULL);
+}
+
+void list_clear_func(List *list, void (*func)(void *key, void *value, void *arg), void *arg)
 {
        for (ListPair *pair = list->first; pair != NULL;) {
                ListPair *next = pair->next;
+               if (func)
+                       func(pair->key, pair->value, arg);
                free(pair);
                pair = next;
        }
@@ -50,6 +57,16 @@ bool list_put(List *list, void *key, void *value)
        return true;
 }
 
+void *list_get_cached(List *list, void *key, void *(*provider)(void *key))
+{
+       ListPair **pairptr;
+       for (pairptr = &list->first; *pairptr != NULL; pairptr = &(*pairptr)->next) {
+               if (list->cmp((*pairptr)->key, key))
+                       return (*pairptr)->value;
+       }
+       return (*pairptr = make_pair(key, provider(key)))->value;
+}
+
 void list_set(List *list, void *key, void *value)
 {
        ListPair **pairptr;
index 3097062716ab77b65a26f7b81d685e7f574d5afc..065100b2674651e957d62de9452652376bd88dc3 100644 (file)
@@ -25,8 +25,10 @@ bool list_compare_string(void *v1, void *v2);
 
 List list_create(ListComparator cmp);
 void list_clear(List *list);
+void list_clear_func(List *list, void (*func)(void *key, void *value, void *arg), void *arg);
 
 bool list_put(List *list, void *key, void *value);
+void *list_get_cached(List *list, void *key, void *(*provider)(void *key));
 void list_set(List *list, void *key, void *value);
 void *list_get(List *list, void *key);
 void *list_delete(List *list, void *key);
index d8bf4ef375b52a223ad4df8ef33f1df6b67a62f0..46c56728390e6e364da011258c150f55710175e3 100644 (file)
--- a/src/map.c
+++ b/src/map.c
@@ -7,8 +7,6 @@
 #include "map.h"
 #include "util.h"
 
-#define CMPBOUNDS(x) x == 0 ? 0 : x > 0 ? 1 : -1
-
 static s8 sector_compare(void *hash, void *sector)
 {
        s64 d = *((u64 *) hash) - (*(MapSector **) sector)->hash;
index 295e39c57f93093e03e0c672ac09351077633ad0..a9489d0e6971e6599b6c243ca652526f6bd96157 100644 (file)
+#include <assert.h>
 #include <stdlib.h>
 #include <stddef.h>
 #include "mesh.h"
+#include "scene.h"
 
-Mesh *mesh_create(Vertex *vertices, GLsizei count)
+VertexBuffer vertexbuffer_create()
 {
-       Mesh *mesh = malloc(sizeof(Mesh));
-       mesh->pos = (v3f) {0.0f, 0.0f, 0.0f};
-       mesh->rot = (v3f) {0.0f, 0.0f, 0.0f};
-       mesh->scale = (v3f) {1.0f, 1.0f, 1.0f};
-       mesh_transform(mesh);
-       mesh->angle = 0.0f;
-       mesh->VAO = 0;
-       mesh->VBO = 0;
-       mesh->remove = false;
-       mesh->vertices = vertices;
-       mesh->count = count;
-       return mesh;
+       return (VertexBuffer) {
+               .faces = array_create(sizeof(Face)),
+       };
+}
+
+void vertexbuffer_set_texture(VertexBuffer *buffer, GLuint texture)
+{
+       if (buffer->current && buffer->current->texture == texture)
+               return;
+       Face face = {
+               .texture = texture,
+               .vertices = array_create(sizeof(Vertex)),
+       };
+       array_append(&buffer->faces, &face);
+       buffer->current = &((Face *) buffer->faces.ptr)[buffer->faces.siz - 1];
+}
+
+void vertexbuffer_add_vertex(VertexBuffer *buffer, Vertex *vertex)
+{
+       array_append(&buffer->current->vertices, vertex);
+}
+
+static int qsort_compare_faces(const void *f1, const void *f2)
+{
+       return ((Face *) f1)->texture - ((Face *) f2)->texture;
+}
+
+static void add_mesh(Array *meshes, Array *vertices, GLuint texture)
+{
+       if (vertices->siz > 0) {
+               Mesh *mesh = malloc(sizeof(Mesh));
+               mesh->VAO = mesh->VBO = 0;
+               // the reason the vertices are not copied and then free'd like anything else is that the vertices will be deleted after the first render anyway
+               mesh->vertices = vertices->ptr;
+               mesh->vertices_count = vertices->siz;
+               mesh->texture = texture;
+
+               array_append(meshes, &mesh);
+       }
+
+       *vertices = array_create(sizeof(Vertex));
+}
+
+MeshObject *meshobject_create(VertexBuffer buffer, struct Scene *scene, v3f pos)
+{
+       if (buffer.faces.siz == 0)
+               return NULL;
+
+       MeshObject *obj = malloc(sizeof(MeshObject));
+       obj->remove = false;
+
+       obj->pos = pos;
+       obj->rot = (v3f) {0.0f, 0.0f, 0.0f};
+       obj->scale = (v3f) {1.0f, 1.0f, 1.0f};
+       obj->angle = 0.0f;
+       meshobject_transform(obj);
+
+       qsort(buffer.faces.ptr, buffer.faces.siz, sizeof(Face), &qsort_compare_faces);
+
+       Array meshes = array_create(sizeof(Mesh *));
+       Array vertices = array_create(sizeof(Vertex));
+       GLuint texture = 0;
+
+       for (size_t f = 0; f < buffer.faces.siz; f++) {
+               Face *face = &((Face *) buffer.faces.ptr)[f];
+
+               if (face->texture != texture) {
+                       add_mesh(&meshes, &vertices, texture);
+                       texture = face->texture;
+               }
+
+               for (size_t v = 0; v < face->vertices.siz; v++)
+                       array_append(&vertices, &((Vertex *) face->vertices.ptr)[v]);
+               free(face->vertices.ptr);
+       }
+       add_mesh(&meshes, &vertices, texture);
+       free(buffer.faces.ptr);
+
+       array_copy(&meshes, (void *) &obj->meshes, &obj->meshes_count);
+       free(meshes.ptr);
+
+       scene_add_object(scene, obj);
+
+       return obj;
 }
 
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wpedantic"
 
-void mesh_transform(Mesh *mesh)
+void meshobject_transform(MeshObject *obj)
 {
-       mat4x4_translate(mesh->transform, mesh->pos.x, mesh->pos.y, mesh->pos.z);
-       mat4x4_rotate(mesh->transform, mesh->transform, mesh->rot.x, mesh->rot.y, mesh->rot.z, mesh->angle);
-       mat4x4_scale_aniso(mesh->transform, mesh->transform, mesh->scale.x, mesh->scale.y, mesh->scale.z);
+       mat4x4_translate(obj->transform, obj->pos.x, obj->pos.y, obj->pos.z);
+       mat4x4_rotate(obj->transform, obj->transform, obj->rot.x, obj->rot.y, obj->rot.z, obj->angle);
+       mat4x4_scale_aniso(obj->transform, obj->transform, obj->scale.x, obj->scale.y, obj->scale.z);
 }
 
 #pragma GCC diagnostic pop
 
-void mesh_delete(Mesh *mesh)
+void meshobject_delete(MeshObject *obj)
 {
-       if (mesh->vertices)
-               free(mesh->vertices);
-       if (mesh->VAO)
-               glDeleteVertexArrays(1, &mesh->VAO);
-       if (mesh->VBO)
-               glDeleteBuffers(1, &mesh->VAO);
-       free(mesh);
+       for (size_t i = 0; i < obj->meshes_count; i++) {
+               Mesh *mesh = obj->meshes[i];
+
+               if (mesh->vertices)
+                       free(mesh->vertices);
+               if (mesh->VAO)
+                       glDeleteVertexArrays(1, &mesh->VAO);
+               if (mesh->VBO)
+                       glDeleteBuffers(1, &mesh->VAO);
+               free(mesh);
+       }
+       free(obj);
 }
 
 static void mesh_configure(Mesh *mesh)
@@ -49,13 +128,16 @@ static void mesh_configure(Mesh *mesh)
        glBindVertexArray(mesh->VAO);
        glBindBuffer(GL_ARRAY_BUFFER, mesh->VBO);
 
-       glBufferData(GL_ARRAY_BUFFER, mesh->count * sizeof(Vertex), mesh->vertices, GL_STATIC_DRAW);
+       glBufferData(GL_ARRAY_BUFFER, mesh->vertices_count * sizeof(Vertex), mesh->vertices, GL_STATIC_DRAW);
+
 
        glVertexAttribPointer(0, 3, GL_FLOAT, false, sizeof(Vertex), (GLvoid *) offsetof(Vertex, x));
        glEnableVertexAttribArray(0);
-       glVertexAttribPointer(1, 3, GL_FLOAT, false, sizeof(Vertex), (GLvoid *) offsetof(Vertex, r));
+
+       glVertexAttribPointer(1, 2, GL_FLOAT, false, sizeof(Vertex), (GLvoid *) offsetof(Vertex, s));
        glEnableVertexAttribArray(1);
 
+
        glBindBuffer(GL_ARRAY_BUFFER, 0);
        glBindVertexArray(0);
 
@@ -63,14 +145,24 @@ static void mesh_configure(Mesh *mesh)
        mesh->vertices = NULL;
 }
 
-void mesh_render(Mesh *mesh, ShaderProgram *prog)
+void meshobject_render(MeshObject *obj, ShaderProgram *prog)
 {
-       if (mesh->vertices)
-               mesh_configure(mesh);
+       glUniformMatrix4fv(prog->loc_model, 1, GL_FALSE, obj->transform[0]);
 
-       glUniformMatrix4fv(prog->loc_model, 1, GL_FALSE, mesh->transform[0]);
+       glActiveTexture(GL_TEXTURE0);
 
-       glBindVertexArray(mesh->VAO);
-       glDrawArrays(GL_TRIANGLES, 0, mesh->count);
+       for (size_t i = 0; i < obj->meshes_count; i++) {
+               Mesh *mesh = obj->meshes[i];
+
+               if (mesh->vertices)
+                       mesh_configure(mesh);
+
+               glBindTexture(GL_TEXTURE_2D, mesh->texture);
+               glBindVertexArray(mesh->VAO);
+
+               glDrawArrays(GL_TRIANGLES, 0, mesh->vertices_count);
+       }
+
+       glBindTexture(GL_TEXTURE_2D, 0);
        glBindVertexArray(0);
 }
index b5422ff093a1709d97b70d415be1189b29ffaec6..5726ba85538748b41921a051079d769b3736b40c 100644 (file)
@@ -5,29 +5,55 @@
 #include <GL/gl.h>
 #include <linmath.h/linmath.h>
 #include <stdbool.h>
+#include "array.h"
 #include "shaders.h"
 #include "types.h"
 
 typedef struct
 {
        GLfloat x, y, z;
-       GLfloat r, g, b;
-} __attribute__((packed, aligned(4))) Vertex;
+       GLfloat s, t;
+} __attribute__((packed)) Vertex;
+
+typedef struct
+{
+       GLuint texture;
+       Array vertices;
+} Face;
+
+typedef struct
+{
+       Face *current;
+       Array faces;
+} VertexBuffer;
+
+typedef struct
+{
+       GLuint VAO, VBO;
+       GLuint texture;
+       Vertex *vertices;
+       GLuint vertices_count;
+} Mesh;
 
 typedef struct
 {
        v3f pos, rot, scale;
        float angle;
        mat4x4 transform;
-       GLuint VAO, VBO;
        bool remove;
-       Vertex *vertices;
-       GLsizei count;
-} Mesh;
+       Mesh **meshes;
+       size_t meshes_count;
+} MeshObject;
+
+struct Scene;
+
+VertexBuffer vertexbuffer_create();
+void vertexbuffer_set_texture(VertexBuffer *buffer, GLuint texture);
+void vertexbuffer_add_vertex(VertexBuffer *buffer, Vertex *vertex);
 
-Mesh *mesh_create(Vertex *vertices, GLsizei count);
-void mesh_delete(Mesh *mesh);
-void mesh_transform(Mesh *mesh);
-void mesh_render(Mesh *mesh, ShaderProgram *prog);
+MeshObject *meshobject_create(VertexBuffer buffer, struct Scene *scene, v3f pos);
+void meshobject_delete(MeshObject *obj);
+void meshobject_transform(MeshObject *obj);
+void meshobject_render(MeshObject *obj, ShaderProgram *prog);
 
 #endif
index 161df5cc8d3a724297031c0ed6c3b445476cb7c0..8c7de65d133aa0b77cf1238f76b1c46e9557aa6c 100644 (file)
@@ -2,14 +2,9 @@
 #include "util.h"
 
 NodeDefintion node_definitions[NODE_UNLOADED] = {
-       {true,  false, "#991300", {0.0f, 0.0f, 0.0f}},
-       {false, false, "",        {0.0f, 0.0f, 0.0f}},
-       {true,  false, "#137822", {0.0f, 0.0f, 0.0f}},
-       {true,  false, "#6B3627", {0.0f, 0.0f, 0.0f}},
-       {true,  false, "#4F4F4F", {0.0f, 0.0f, 0.0f}},
+       {true},
+       {false},
+       {true},
+       {true},
+       {true},
 };
-
-v3f get_node_color(NodeDefintion *def)
-{
-       return def->color_initialized ? def->color : (def->color = html_to_v3f(def->color_str));
-}
index 06a8890334bb370dd7977261fb2a81d7dbe1f1e5..aef57e8dfc10a769f84f98d1d9bf39fcd78ab776 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef _NODE_H_
 #define _NODE_H_
 
+#include <stdbool.h>
 #include "types.h"
 
 typedef enum
@@ -16,13 +17,8 @@ typedef enum
 typedef struct
 {
        bool visible;
-       bool color_initialized;
-       const char *color_str;
-       v3f color;
 } NodeDefintion;
 
-v3f get_node_color(NodeDefintion *def);
-
 extern NodeDefintion node_definitions[];
 
 #endif
index 217909878a89233e72add4aa0bc865aa32fc34a2..05375d661e7fe9bd0ac2e9ff27baacf1521ba4e9 100644 (file)
@@ -13,6 +13,7 @@ void delete_queue(Queue *queue)
 {
        pthread_mutex_destroy(&queue->mtx);
        list_clear(&queue->list);
+       free(queue);
 }
 
 void enqueue(Queue *queue, void *elem)
index e100c5be79aff461936595f035b6927e0e5283ff..a753d13715fc5c9dd4d0828b2aea9f3bf0c6f076 100644 (file)
@@ -4,39 +4,43 @@
 Scene *scene_create()
 {
        Scene *scene = malloc(sizeof(Scene));
-       scene->meshes = list_create(NULL),
+       scene->objects = list_create(NULL),
        pthread_mutex_init(&scene->mtx, NULL);
        return scene;
 }
 
+static void list_delete_mesh(void *key, __attribute__((unused)) void *value, __attribute__((unused)) void *unused)
+{
+       meshobject_delete(key);
+}
+
 void scene_delete(Scene *scene)
 {
-       ITERATE_LIST(&scene->meshes, pair) mesh_delete(pair->key);
-       list_clear(&scene->meshes);
+       list_clear_func(&scene->objects, &list_delete_mesh, NULL);
        pthread_mutex_destroy(&scene->mtx);
        free(scene);
 }
 
-void scene_add_mesh(Scene *scene, Mesh *mesh)
+void scene_add_object(Scene *scene, MeshObject *obj)
 {
        pthread_mutex_lock(&scene->mtx);
-       list_put(&scene->meshes, mesh, NULL);
+       list_put(&scene->objects, obj, NULL);
        pthread_mutex_unlock(&scene->mtx);
 }
 
 void scene_render(Scene *scene, ShaderProgram *prog)
 {
-       for (ListPair **pairptr = &scene->meshes.first; *pairptr != NULL; ) {
+       for (ListPair **pairptr = &scene->objects.first; *pairptr != NULL; ) {
                ListPair *pair = *pairptr;
-               Mesh *mesh = pair->key;
-               if (mesh->remove) {
+               MeshObject *obj = pair->key;
+               if (obj->remove) {
                        pthread_mutex_lock(&scene->mtx);
                        *pairptr = pair->next;
                        pthread_mutex_unlock(&scene->mtx);
                        free(pair);
-                       mesh_delete(mesh);
+                       meshobject_delete(obj);
                } else {
-                       mesh_render(mesh, prog);
+                       meshobject_render(obj, prog);
                        pairptr = &pair->next;
                }
        }
index e8edd88a7cbc30fe77f91448f41a7846af33b861..465e86039e8cf32df59f6d3617a2528ea847cb9f 100644 (file)
@@ -6,17 +6,16 @@
 #include "mesh.h"
 #include "shaders.h"
 
-typedef struct
+typedef struct Scene
 {
-       List meshes;
+       List objects;
        pthread_mutex_t mtx;
 } Scene;
 
 Scene *scene_create();
 void scene_delete(Scene *scene);
 
-void scene_add_mesh(Scene *scene, Mesh *mesh);
-void scene_remove_mesh(Scene *scene, Mesh *mesh);
+void scene_add_object(Scene *scene, MeshObject *obj);
 void scene_render(Scene *scene, ShaderProgram *prog);
 
 #endif
index d6e3b6e4719d9da00f86b06a102300c5ef22edfd..a5377380960f3b338a98ab35bdc91dfcb8c287b0 100644 (file)
@@ -89,6 +89,11 @@ static void server_accept_client()
        printf("Connected %s\n", client->address);
 }
 
+static void list_disconnect_client(void *key, __attribute__((unused)) void *value, __attribute__((unused)) void *unused)
+{
+       server_disconnect_client(key, DISCO_NO_REMOVE | DISCO_NO_MESSAGE, "");
+}
+
 void server_start(int fd)
 {
        server.sockfd = fd;
@@ -108,8 +113,7 @@ void server_start(int fd)
        servermap_deinit();
 
        pthread_rwlock_wrlock(&server.clients_rwlck);
-       ITERATE_LIST(&server.clients, pair) server_disconnect_client(pair->key, DISCO_NO_REMOVE | DISCO_NO_MESSAGE, "");
-       list_clear(&server.clients);
+       list_clear_func(&server.clients, &list_disconnect_client, NULL);
        pthread_rwlock_unlock(&server.clients_rwlck);
        pthread_rwlock_wrlock(&server.players_rwlck);
        list_clear(&server.players);
index 83a0b5876ec616aac7709c01b4e47eb0b592924b..db2e7d85eb485b94f05ed2af0d392e8bef0d37bf 100644 (file)
@@ -24,6 +24,14 @@ static void initialize_block(MapBlock *block)
        block->state = MBS_MODIFIED;
 }
 
+static void reset_client_block(void *key, __attribute__((unused)) void *value, void *block)
+{
+       Client *client = list_get(&server->players, key);
+       if (client)
+               list_delete(&client->sent_blocks, block);
+       free(key);
+}
+
 static void reset_block(MapBlock *block)
 {
        MapBlockExtraData *extra = block->extra;
@@ -41,12 +49,7 @@ static void reset_block(MapBlock *block)
 
        save_block(servermap.db, block);
 
-       ITERATE_LIST(&extra->clients, pair) {
-               Client *client = list_get(&server->players, pair->key);
-               if (client)
-                       list_delete(&client->sent_blocks, block);
-               free(pair->key);
-       }
+       list_clear_func(&extra->clients, &reset_client_block, block);
        list_clear(&extra->clients);
 
        block->state = MBS_READY;
@@ -129,10 +132,8 @@ static void map_step()
        pthread_rwlock_unlock(&server->players_rwlck);
 }
 
-static void *map_thread(void *unused)
+static void *map_thread(__attribute__((unused)) void *unused)
 {
-       (void) unused;
-
        servermap.db = open_mapdb("map.sqlite");
 
        while (! servermap.cancel)
@@ -149,13 +150,17 @@ void servermap_init(Server *srv)
        pthread_create(&servermap.thread, NULL, &map_thread, NULL);
 }
 
+static void list_delete_extra_data(void *key, __attribute__((unused)) void *value, __attribute__((unused)) void *unused)
+{
+       free(key);
+}
+
 void servermap_delete_extra_data(void *ext)
 {
        MapBlockExtraData *extra = ext;
 
        if (extra) {
-               ITERATE_LIST(&extra->clients, pair) free(pair->key);
-               list_clear(&extra->clients);
+               list_clear_func(&extra->clients, &list_delete_extra_data, NULL);
                free(extra->data);
                free(extra);
        }
index 5c8c43551714e42f57d2003431b6e36ebb30f8a5..d9a8c846922bf5be589034df79fa0f62a1a4f212 100644 (file)
@@ -11,9 +11,8 @@ static void interrupt_handler(int sig)
        fprintf(stderr, "%s\n", strsignal(sig));
 }
 
-static void silent_handler(int sig)
+static void silent_handler(__attribute__((unused)) int sig)
 {
-       (void) sig;
 }
 
 static struct sigaction sigact_interrupt = {0};
diff --git a/src/texture.c b/src/texture.c
new file mode 100644 (file)
index 0000000..9f32b9e
--- /dev/null
@@ -0,0 +1,61 @@
+#define STB_IMAGE_IMPLEMENTATION
+#include <stb/stb_image.h>
+#include <stdbool.h>
+#include "list.h"
+#include "texture.h"
+
+static List textures;
+
+__attribute((constructor(101))) static void init_textures()
+{
+       stbi_set_flip_vertically_on_load(true);
+
+       textures = list_create(&list_compare_string);
+}
+
+static void list_delete_texture(__attribute__((unused)) void *key, void *value, __attribute__((unused)) void *unused)
+{
+       glDeleteTextures(1, value);
+       free(value);
+}
+
+__attribute((destructor)) static void delete_textures()
+{
+       list_clear_func(&textures, &list_delete_texture, NULL);
+}
+
+static void *create_texture(void *key)
+{
+       int width, height, channels;
+
+       unsigned char *data = stbi_load(key, &width, &height, &channels, 0);
+       if (! data) {
+               printf("Failed to load texture %s\n", (char *) key);
+               return 0;
+       }
+
+       GLuint *id = malloc(sizeof(GLuint));
+
+       glGenTextures(1, id);
+
+       glBindTexture(GL_TEXTURE_2D, *id);
+
+       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
+       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+       glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
+       glGenerateMipmap(GL_TEXTURE_2D);
+
+       stbi_image_free(data);
+
+       glBindTexture(GL_TEXTURE_2D, 0);
+
+       return id;
+}
+
+GLuint get_texture(char *path)
+{
+       return *(GLuint *)list_get_cached(&textures, path, &create_texture);
+}
diff --git a/src/texture.h b/src/texture.h
new file mode 100644 (file)
index 0000000..33198e3
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef _TEXTURE_H_
+#define _TEXTURE_H_
+
+#include <GL/glew.h>
+#include <GL/gl.h>
+
+GLuint get_texture(char *path);
+
+#endif
index f8387dc94d0fba9fe48e88be47894b980ce8aec2..9d76b7eee7dcbcf98acf5b459154cc8bb381182c 100644 (file)
@@ -7,6 +7,7 @@
 
 #define ever (;;)
 #define INBRACES(str) str ? "(" : "", str ? str : "", str ? ")" : ""
+#define CMPBOUNDS(x) x == 0 ? 0 : x > 0 ? 1 : -1
 
 extern const char *program_name;
 
diff --git a/textures/dirt.png b/textures/dirt.png
new file mode 100644 (file)
index 0000000..5cc6e86
Binary files /dev/null and b/textures/dirt.png differ
diff --git a/textures/grass.png b/textures/grass.png
new file mode 100644 (file)
index 0000000..d7e9d81
Binary files /dev/null and b/textures/grass.png differ
diff --git a/textures/invalid.png b/textures/invalid.png
new file mode 100644 (file)
index 0000000..c04d569
Binary files /dev/null and b/textures/invalid.png differ
diff --git a/textures/stone.png b/textures/stone.png
new file mode 100644 (file)
index 0000000..a641ceb
Binary files /dev/null and b/textures/stone.png differ