X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fclient%2Fmodel.c;h=7c1c1e2b6170e7a5da819538e7011fcbf373a19d;hb=5760d5e9de1a031e748953930cca31479a3809ef;hp=1d163c7b1a34c8b78a4a3bde116986626905370f;hpb=f931fe22ecf29461e2fc3fced222c1ee0d083ff9;p=dragonblocks_alpha.git diff --git a/src/client/model.c b/src/client/model.c index 1d163c7..7c1c1e2 100644 --- a/src/client/model.c +++ b/src/client/model.c @@ -1,10 +1,12 @@ #include +#include #include #include #include #include "client/camera.h" #include "client/client_config.h" #include "client/frustum.h" +#include "client/opengl.h" #include "client/model.h" typedef struct { @@ -13,10 +15,10 @@ typedef struct { } ModelBatchTexture; static List scene; -static pthread_rwlock_t lock_scene; +static List scene_new; +static pthread_mutex_t lock_scene_new; static GLint units; -// fixme: blending issues still occur static int cmp_batch_texture(const ModelBatchTexture *ta, const ModelBatchTexture *tb) { return @@ -54,20 +56,32 @@ static void render_node(ModelNode *node) if (!node->visible) return; + if (node->clockwise) { + glFrontFace(GL_CW); GL_DEBUG + } + for (size_t i = 0; i < node->meshes.siz; i++) { ModelMesh *mesh = &((ModelMesh *) node->meshes.ptr)[i]; - glUseProgram(mesh->shader->prog); - glUniformMatrix4fv(mesh->shader->loc_transform, 1, GL_FALSE, node->abs[0]); + if (!mesh->mesh) + continue; + + glUseProgram(mesh->shader->prog); GL_DEBUG + glUniformMatrix4fv(mesh->shader->loc_transform, 1, GL_FALSE, node->abs[0]); GL_DEBUG // bind textures - for (GLuint i = 0; i < mesh->num_textures; i++) - glBindTextureUnit(i, mesh->textures[i]); + for (GLuint i = 0; i < mesh->num_textures; i++) { + glBindTextureUnit(i, mesh->textures[i]); GL_DEBUG + } mesh_render(mesh->mesh); } - list_itr(&node->children, (void *) &render_node, NULL, NULL); + list_itr(&node->children, &render_node, NULL, NULL); + + if (node->clockwise) { + glFrontFace(GL_CCW); GL_DEBUG + } } static void free_node_meshes(ModelNode *node) @@ -79,7 +93,7 @@ static void free_node_meshes(ModelNode *node) free(mesh->mesh); } - list_clr(&node->children, (void *) &free_node_meshes, NULL, NULL); + list_clr(&node->children, &free_node_meshes, NULL, NULL); } static void delete_node(ModelNode *node) @@ -90,9 +104,11 @@ static void delete_node(ModelNode *node) if (mesh->textures) free(mesh->textures); } - list_clr(&node->children, (void *) &delete_node, NULL, NULL); + list_clr(&node->children, &delete_node, NULL, NULL); array_clr(&node->meshes); + if (node->name) + free(node->name); free(node); } @@ -115,44 +131,46 @@ static ModelNode *clone_node(ModelNode *original, ModelNode *parent) { ModelNode *node = malloc(sizeof *node); *node = *original; + if (original->name) + node->name = strdup(original->name); init_node(node, parent); array_cln(&node->meshes, &original->meshes); for (size_t i = 0; i < node->meshes.siz; i++) clone_mesh(&((ModelMesh *) node->meshes.ptr)[i]); - list_itr(&original->children, (void *) &clone_node, parent, NULL); + list_itr(&original->children, &clone_node, node, NULL); return node; } static int cmp_model(const Model *model, const f32 *distance) { - return f32_cmp(&model->distance, distance); + return -f32_cmp(&model->distance, distance); } static void render_model(Model *model) { - if (model->flags.wireframe) - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + if (model->callbacks.before_render) + model->callbacks.before_render(model); render_node(model->root); - if (model->flags.wireframe) - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + if (model->callbacks.after_render) + model->callbacks.after_render(model); } // step model help im stuck static void model_step(Model *model, Tree *transparent, f64 dtime) { + if (model->callbacks.step) + model->callbacks.step(model, dtime); + if (client_config.view_distance < (model->distance = sqrt( pow(model->root->pos.x - camera.eye[0], 2) + pow(model->root->pos.y - camera.eye[1], 2) + pow(model->root->pos.z - camera.eye[2], 2)))) return; - if (model->callbacks.step) - model->callbacks.step(model, dtime); - if (!model->root->visible) return; @@ -172,15 +190,19 @@ static void model_step(Model *model, Tree *transparent, f64 dtime) void model_init() { list_ini(&scene); - pthread_rwlock_init(&lock_scene, NULL); - glGetIntegerv(GL_MAX_TEXTURE_UNITS, &units); + list_ini(&scene_new); + + pthread_mutex_init(&lock_scene_new, NULL); + units = opengl_texture_batch_units(); } // ded void model_deinit() { list_clr(&scene, &model_delete, NULL, NULL); - pthread_rwlock_destroy(&lock_scene); + list_clr(&scene_new, &model_delete, NULL, NULL); + + pthread_mutex_destroy(&lock_scene_new); } // Model functions @@ -190,12 +212,14 @@ Model *model_create() Model *model = malloc(sizeof *model); model->root = model_node_create(NULL); model->extra = NULL; + model->replace = NULL; model->callbacks.step = NULL; + model->callbacks.before_render = NULL; + model->callbacks.after_render = NULL; model->callbacks.delete = NULL; model->flags.delete = - model->flags.wireframe = model->flags.frustum_culling = model->flags.transparent = 0; @@ -267,16 +291,15 @@ Model *model_load(const char *path, const char *textures_path, Mesh *cube, Model cursor += n; else fprintf(stderr, "[warning] invalid value for rot in model %s in line %d\n", path, count); + + node->rot = v3f32_scale(node->rot, M_PI / 180.0); } else if (strcmp(key, "scale") == 0) { if (sscanf(cursor, "%f %f %f %n", &node->scale.x, &node->scale.y, &node->scale.z, &n) == 3) cursor += n; else fprintf(stderr, "[warning] invalid value for scale in model %s in line %d\n", path, count); - } else if (strcmp(key, "angle") == 0) { - if (sscanf(cursor, "%f%n", &node->angle, &n) == 1) - cursor += n; - else - fprintf(stderr, "[warning] invalid value for angle in model %s in line %d\n", path, count); + } else if (strcmp(key, "clockwise") == 0) { + node->clockwise = 1; } else if (strcmp(key, "cube") == 0) { char texture[length + 1]; @@ -285,7 +308,7 @@ Model *model_load(const char *path, const char *textures_path, Mesh *cube, Model char filepath[strlen(textures_path) + 1 + strlen(texture) + 1]; sprintf(filepath, "%s/%s", textures_path, texture); - Texture *texture = texture_load_cubemap(filepath); + Texture *texture = texture_load_cubemap(filepath, false); model_node_add_mesh(node, &(ModelMesh) { .mesh = cube, @@ -313,6 +336,7 @@ Model *model_load(const char *path, const char *textures_path, Mesh *cube, Model fclose(file); array_clr(&stack); + transform_node(model->root); return model; } @@ -346,15 +370,16 @@ void model_get_bones(Model *model, ModelBoneMapping *mappings, size_t num_mappin name = cursor = strdup(mappings[i].name); ModelNode *node = model->root; - while ((tok = strtok_r(cursor, ".", &saveptr))) { - node = list_get(&node->children, tok, (void *) &cmp_node, NULL); + + while (node && (tok = strtok_r(cursor, ".", &saveptr))) { + node = list_get(&node->children, tok, &cmp_node, NULL); cursor = NULL; } if (node) *mappings[i].node = node; else - fprintf(stderr, "[warning] no such bone: %s\n", name); + fprintf(stderr, "[warning] no such bone: %s\n", mappings[i].name); free(name); } @@ -366,11 +391,11 @@ ModelNode *model_node_create(ModelNode *parent) { ModelNode *node = malloc(sizeof *node); node->name = NULL; - node->visible = true; + node->visible = 1; + node->clockwise = 0; node->pos = (v3f32) {0.0f, 0.0f, 0.0f}; node->rot = (v3f32) {0.0f, 0.0f, 0.0f}; node->scale = (v3f32) {1.0f, 1.0f, 1.0f}; - node->angle = 0.0f; array_ini(&node->meshes, sizeof(ModelMesh), 0); init_node(node, parent); return node; @@ -378,22 +403,22 @@ ModelNode *model_node_create(ModelNode *parent) void model_node_transform(ModelNode *node) { + mat4x4_identity(node->rel); + mat4x4_translate(node->rel, node->pos.x, node->pos.y, node->pos.z); - mat4x4_rotate(node->rel, node->rel, - node->rot.x, - node->rot.y, - node->rot.z, - node->angle); - mat4x4_scale_aniso(node->rel, node->rel, node->scale.x, node->scale.y, node->scale.z); + mat4x4_rotate_X(node->rel, node->rel, node->rot.x); + mat4x4_rotate_Y(node->rel, node->rel, node->rot.y); + mat4x4_rotate_Z(node->rel, node->rel, node->rot.z); + transform_node(node); } @@ -415,7 +440,7 @@ void model_node_add_batch(ModelNode *node, ModelBatch *batch) size_t num_meshes = ceil((double) batch->textures.siz / (double) units); array_grw(&node->meshes, num_meshes); - ModelMesh *meshes = node->meshes.ptr + node->meshes.siz - num_meshes; + ModelMesh *meshes = &((ModelMesh *) node->meshes.ptr)[node->meshes.siz - num_meshes]; for (size_t m = 0; m < num_meshes; m++) { ModelMesh *mesh = &meshes[m]; @@ -506,37 +531,40 @@ void model_batch_add_vertex(ModelBatch *batch, GLuint texture, const void *verte void model_scene_add(Model *model) { - pthread_rwlock_wrlock(&lock_scene); - list_apd(&scene, model); - pthread_rwlock_unlock(&lock_scene); + pthread_mutex_lock(&lock_scene_new); + list_apd(&scene_new, model); + pthread_mutex_unlock(&lock_scene_new); } void model_scene_render(f64 dtime) { + pthread_mutex_lock(&lock_scene_new); + if (scene_new.fst) { + *scene.end = scene_new.fst; + scene.end = scene_new.end; + + list_ini(&scene_new); + } + pthread_mutex_unlock(&lock_scene_new); + Tree transparent; tree_ini(&transparent); - pthread_rwlock_rdlock(&lock_scene); for (ListNode **node = &scene.fst; *node != NULL;) { Model *model = (*node)->dat; - pthread_rwlock_unlock(&lock_scene); if (model->flags.delete) { - model_delete(model); + if (model->replace) + (*node)->dat = model->replace; + else + list_nrm(&scene, node); - pthread_rwlock_wrlock(&lock_scene); - list_nrm(&scene, node); - pthread_rwlock_unlock(&lock_scene); - - pthread_rwlock_rdlock(&lock_scene); + model_delete(model); } else { - model_step(model, &transparent, dtime); - - pthread_rwlock_rdlock(&lock_scene); node = &(*node)->nxt; + model_step(model, &transparent, dtime); } } - pthread_rwlock_unlock(&lock_scene); tree_clr(&transparent, &render_model, NULL, NULL, TRAVERSION_INORDER); }