#include <dragonstd/tree.h>
+#include <getline.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include "client/camera.h"
#include "client/client_config.h"
#include "client/frustum.h"
+#include "client/opengl.h"
#include "client/model.h"
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
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)
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)
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);
}
{
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;
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
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;
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];
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,
fclose(file);
array_clr(&stack);
+ transform_node(model->root);
return model;
}
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);
}
{
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;
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);
}
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];
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);
}