Add textures
parent
90063397fa
commit
eea6a34554
|
@ -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
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Subproject commit c9064e317699d2e495f36ba4f9ac037e88ee371a
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
130
src/blockmesh.c
130
src/blockmesh.c
|
@ -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});
|
||||
}
|
||||
|
|
18
src/client.c
18
src/client.c
|
@ -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);
|
||||
|
|
|
@ -9,6 +9,12 @@
|
|||
#include "network.h"
|
||||
#include "scene.h"
|
||||
|
||||
#ifdef RELEASE
|
||||
#define RESSOURCEPATH ""
|
||||
#else
|
||||
#define RESSOURCEPATH "../"
|
||||
#endif
|
||||
|
||||
typedef struct Client
|
||||
{
|
||||
int fd;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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
|
17
src/list.c
17
src/list.c
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
158
src/mesh.c
158
src/mesh.c
|
@ -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);
|
||||
}
|
||||
|
|
46
src/mesh.h
46
src/mesh.h
|
@ -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
|
||||
|
|
15
src/node.c
15
src/node.c
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
24
src/scene.c
24
src/scene.c
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
#ifndef _TEXTURE_H_
|
||||
#define _TEXTURE_H_
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include <GL/gl.h>
|
||||
|
||||
GLuint get_texture(char *path);
|
||||
|
||||
#endif
|
|
@ -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;
|
||||
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 676 B |
Binary file not shown.
After Width: | Height: | Size: 6.4 KiB |
Binary file not shown.
After Width: | Height: | Size: 5.9 KiB |
Binary file not shown.
After Width: | Height: | Size: 528 B |
Loading…
Reference in New Issue