Add textures

master
Elias Fleckenstein 2021-06-22 18:36:59 +02:00
parent 90063397fa
commit eea6a34554
35 changed files with 436 additions and 185 deletions

3
.gitmodules vendored
View 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

1
deps/stb vendored Submodule

@ -0,0 +1 @@
Subproject commit c9064e317699d2e495f36ba4f9ac037e88ee371a

View File

@ -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);
}

View File

@ -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;
}

View 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

View 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);

View 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

View 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});
}

View 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);

View File

@ -9,6 +9,12 @@
#include "network.h"
#include "scene.h"
#ifdef RELEASE
#define RESSOURCEPATH ""
#else
#define RESSOURCEPATH "../"
#endif
typedef struct Client
{
int fd;

View 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;

View 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)

View 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);

21
src/clientnode.c Normal file
View File

@ -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);
}
}

15
src/clientnode.h Normal file
View File

@ -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

View 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;

View 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);

View File

@ -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;

View File

@ -1,44 +1,123 @@
#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);
}

View 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;
Mesh *mesh_create(Vertex *vertices, GLsizei count);
void mesh_delete(Mesh *mesh);
void mesh_transform(Mesh *mesh);
void mesh_render(Mesh *mesh, ShaderProgram *prog);
struct Scene;
VertexBuffer vertexbuffer_create();
void vertexbuffer_set_texture(VertexBuffer *buffer, GLuint texture);
void vertexbuffer_add_vertex(VertexBuffer *buffer, Vertex *vertex);
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

View 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));
}

View 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

View 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)

View 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;
}
}

View 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

View 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);

View 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);
}

View 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};

61
src/texture.c Normal file
View File

@ -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);
}

9
src/texture.h Normal file
View File

@ -0,0 +1,9 @@
#ifndef _TEXTURE_H_
#define _TEXTURE_H_
#include <GL/glew.h>
#include <GL/gl.h>
GLuint get_texture(char *path);
#endif

View 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;

BIN
textures/dirt.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 676 B

BIN
textures/grass.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

BIN
textures/invalid.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

BIN
textures/stone.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 528 B