#include "dumbLog.h" #include "entity.h" void initEntityRG(Entity& e, rg_shader_program& shader, bool use_normals); bool initEntityROs(Entity& e); bool convertMeshInfo(meMeshInfo* mesh, render_object* ro, bool use_normals, bool use_texture); bool entInit(Entity& e, const char* data_dir, rg_shader_program& shader) { e.world_transform = glm::mat4(1.0); entScale(e, e.scale); uint max_len = 256; // TODO: define max_len for property strings char full_path[max_len]; if (utilConcatPath(full_path, data_dir, e.model_filename, max_len)) { if (meLoadFromFile(e.mesh_group, data_dir, full_path)) { initEntityRG(e, shader, e.mesh_group.use_normals); entSetWorldPosition(e, e.translation.x, e.translation.y, e.translation.z); if (!initEntityROs(e)) goto cleanup; } else { goto cleanup; } } else { LOG(Error) << data_dir << " + " << e.model_filename << " is too long\n"; goto cleanup; } return true; cleanup: entFree(e); return false; } void entFree(Entity& e) { meFreeMeshGroup(e.mesh_group); rgFree(e.ren_group); } void entSetWorldPosition(Entity& e, float x, float y, float z) { e.world_transform[3][0] = e.translation.x = x; e.world_transform[3][1] = e.translation.y = y; e.world_transform[3][2] = e.translation.z = z; } void initEntityRG(Entity& e, rg_shader_program& shader, bool use_normals) { render_group* rg = UTIL_ALLOC(1, render_group); e.ren_group = rg; e.ren_group->shader = shader; rg->draw_indexed = true; rg->draw_mode = GL_TRIANGLES; rg->use_normals = use_normals; uint num_meshes = rg->num_objects = e.mesh_group.num_meshes; rg->render_objects = UTIL_ALLOC(num_meshes, render_object*); } bool initEntityROs(Entity& e) { render_group* rg = e.ren_group; for (uint i = 0; i < e.mesh_group.num_meshes; i++) { meMeshInfo* mesh = e.mesh_group.meshes[i]; uint buffer_len = mesh->num_vertices * 3; uint index_len = mesh->num_indices; render_object* ro = rgAllocateRenderObject(buffer_len, index_len); rg->render_objects[i] = ro; if (ro == nullptr) return false; if (!convertMeshInfo(mesh, ro, rg->use_normals, mesh->use_texture)) { rgFree(rg); return false; } if (mesh->use_texture) { ro->use_texture = true; if (!rgInitGLTexture(ro->tex_id, mesh->diffuse_texture)) { LOG(Error) << "Error initializing GL texture\n"; return false; } } } return true; } bool convertMeshInfo(meMeshInfo* mesh, render_object* ro, bool use_normals, bool use_texture) { uint vertex_buf_len = mesh->num_vertices * 3; GLfloat* vertex_buf = ro->vertex_buffer.buffer; GLfloat* normal_buf = ro->normal_buffer.buffer; GLfloat* uv_buf = ro->uv_buffer.buffer; uint* index_buf = ro->index_buffer.buffer; if (!vertex_buf || !normal_buf || !index_buf) return false; // dump vertices, colors, normals, and texture coords into render_group buffers uint vertex_index = 0; uint vertex_prop_index = 0; for (uint i = 0; i < vertex_buf_len; i++) { const glm::vec3& vertex = mesh->vertices[vertex_index]; switch (vertex_prop_index) { case 0: vertex_buf[i] = vertex.x; break; case 1: vertex_buf[i] = vertex.y; break; case 2: vertex_buf[i] = vertex.z; break; } if (use_normals) { const glm::vec3& normal = mesh->normals[vertex_index]; switch (vertex_prop_index) { case 0: normal_buf[i] = normal.x; break; case 1: normal_buf[i] = normal.y; break; case 2: normal_buf[i] = normal.z; break; } } if (use_texture) { const glm::vec3& uv = mesh->texture_coords[vertex_index]; switch (vertex_prop_index) { case 0: uv_buf[i] = uv.x; break; case 1: uv_buf[i] = uv.y; break; case 2: uv_buf[i] = uv.z; break; } } vertex_prop_index++; if (vertex_prop_index == 3) { vertex_prop_index = 0; vertex_index++; } } // dump indices for (uint i = 0; i < mesh->num_indices; i++) index_buf[i] = mesh->indices[i]; rgInitGLFloatBuffer(&ro->vertex_buffer, GL_DYNAMIC_DRAW, GL_ARRAY_BUFFER); if (use_normals) rgInitGLFloatBuffer(&ro->normal_buffer, GL_STATIC_DRAW, GL_ARRAY_BUFFER); if (use_texture) rgInitGLFloatBuffer(&ro->uv_buffer, GL_STATIC_DRAW, GL_ARRAY_BUFFER); rgInitGLIndexBuffer(&ro->index_buffer, GL_STATIC_DRAW, GL_ELEMENT_ARRAY_BUFFER); return true; }