1 #include <dragonstd/tree.h>
5 #include "client/cube.h"
6 #include "client/gl_debug.h"
7 #include "client/mesh.h"
19 static v3s32 face_dir[6] = {
32 } __attribute__((packed)) LoadedVertex;
33 static VertexLayout loaded_layout = {
34 .attributes = (VertexAttribute[]) {
35 {GL_FLOAT, 3, sizeof(v3f32)}, // position
36 {GL_FLOAT, 3, sizeof(v3f32)}, // normal
37 {GL_FLOAT, 3, sizeof(v3f32)}, // color
40 .size = sizeof(LoadedVertex),
43 static int cmp_loaded_voxel(const LoadedVoxel *voxel, const v3s32 *pos)
45 return v3s32_cmp(&voxel->pos, pos);
48 static void render_loaded_voxel(LoadedVoxel *voxel, LoadedRenderArgs *args)
50 v3f32 pos = v3s32_to_f32(voxel->pos);
51 for (int f = 0; f < 6; f++) {
52 v3s32 neigh_pos = v3s32_add(voxel->pos, face_dir[f]);
53 if (tree_get(&args->voxels, &neigh_pos, &cmp_loaded_voxel, NULL))
56 for (int v = 0; v < 6; v++)
57 array_apd(&args->vertices, &(LoadedVertex) {
58 v3f32_add(cube_vertices[f][v].position, pos),
59 cube_vertices[f][v].normal,
65 void mesh_load(Mesh *mesh, const char *path)
67 mesh->layout = &loaded_layout;
68 mesh->vao = mesh->vbo = 0;
71 mesh->free_data = true;
73 LoadedRenderArgs args;
74 tree_ini(&args.voxels);
75 array_ini(&args.vertices, sizeof(LoadedVertex), 500);
77 FILE *file = fopen(path, "r");
79 fprintf(stderr, "[warning] failed to open mesh %s\n", path);
88 while ((length = getline(&line, &siz, file)) > 0) {
94 LoadedVoxel *voxel = malloc(sizeof *voxel);
97 if (sscanf(line, "%d %d %d %2x%2x%2x",
98 &voxel->pos.x, &voxel->pos.z, &voxel->pos.y,
99 &color.x, &color.y, &color.z) != 6) {
100 fprintf(stderr, "[warning] syntax error in mesh %s in line %d: %s\n",
106 voxel->color = (v3f32) {
107 (f32) color.x / 0xFF,
108 (f32) color.y / 0xFF,
109 (f32) color.z / 0xFF,
112 if (!tree_add(&args.voxels, &voxel->pos, voxel, &cmp_loaded_voxel, NULL)) {
113 fprintf(stderr, "[warning] more than one voxel at position (%d, %d, %d) in mesh %s in line %d\n",
114 voxel->pos.x, voxel->pos.y, voxel->pos.z, path, count);
124 tree_trv(&args.voxels, &render_loaded_voxel, &args, NULL, 0);
125 tree_clr(&args.voxels, &free, NULL, NULL, 0);
127 mesh->data = args.vertices.ptr;
128 mesh->count = args.vertices.siz;
131 // upload data to GPU (only done once)
132 void mesh_upload(Mesh *mesh)
134 glGenVertexArrays(1, &mesh->vao); GL_DEBUG
135 glGenBuffers(1, &mesh->vbo); GL_DEBUG
137 glBindVertexArray(mesh->vao); GL_DEBUG
138 glBindBuffer(GL_ARRAY_BUFFER, mesh->vbo); GL_DEBUG
140 glBufferData(GL_ARRAY_BUFFER, mesh->count * mesh->layout->size,
141 mesh->data, GL_STATIC_DRAW); GL_DEBUG
144 for (GLuint i = 0; i < mesh->layout->count; i++) {
145 VertexAttribute *attrib = &mesh->layout->attributes[i];
147 glVertexAttribPointer(i, attrib->length, attrib->type, GL_FALSE,
148 mesh->layout->size, (GLvoid *) offset); GL_DEBUG
149 glEnableVertexAttribArray(i); GL_DEBUG
151 offset += attrib->size;
154 glBindBuffer(GL_ARRAY_BUFFER, 0); GL_DEBUG
155 glBindVertexArray(0); GL_DEBUG
163 void mesh_render(Mesh *mesh)
169 glBindVertexArray(mesh->vao); GL_DEBUG
170 glDrawArrays(GL_TRIANGLES, 0, mesh->count); GL_DEBUG
173 void mesh_destroy(Mesh *mesh)
175 if (mesh->data && mesh->free_data)
179 glDeleteVertexArrays(1, &mesh->vao); GL_DEBUG
183 glDeleteBuffers(1, &mesh->vbo); GL_DEBUG
186 mesh->vao = mesh->vbo = 0;