A small OpenGL 3+ renderer and game engine
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

164 lines
4.1 KiB

#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;
}