diff --git a/include/animation.h b/include/animation.h index 10a42bc..c676240 100644 --- a/include/animation.h +++ b/include/animation.h @@ -4,9 +4,11 @@ #include #include "util.h" -#include "render_object.h" +//#include "render_object.h" +struct render_object; + struct node_animation { render_object* ro; diff --git a/include/entity.h b/include/entity.h index 7a9731b..7b7b6a7 100644 --- a/include/entity.h +++ b/include/entity.h @@ -7,25 +7,16 @@ #include "render_object.h" -struct render_objects -{ - render_object* objs; - uint count; -}; - -// NOTE: an entity is the basic unit of the high level renderer interface struct entity { - // NOTE: glm::mat4 combines translation, scale, and rotation in a 4x4 - // transform matrix. This is the equivalent of the 'model' matrix in - // the model, view, projection matrix composition glm::mat4 world_transform; // TODO: should be a pointer into a global array of mesh_info(s) or // mesh_groups stored on the render_state object meMeshGroup mesh_group; - render_objects render_objs; + render_object* render_objs; + uint ro_count; }; bool entInit(entity& e, const char* model_path); diff --git a/include/mesh.h b/include/mesh.h index 9f5a72e..01b82f1 100644 --- a/include/mesh.h +++ b/include/mesh.h @@ -15,10 +15,11 @@ struct meMeshInfo { glm::mat4 model_transform; + // NOTE: vertices, normals, and tex_coords have the same count uint num_vertices; glm::vec3* vertices; glm::vec3* normals; - glm::vec3* texture_coords; // NOTE: using vec3 to stay aligned with other props + glm::vec3* texture_coords; // NOTE: stay aligned with other buffers uint num_indices; uint* indices; util_image diffuse_texture; @@ -27,9 +28,10 @@ struct meMeshInfo struct meMeshGroup { - bool use_normals; - uint num_meshes; + // TODO: this should be one big allocation since the mesh doesn't change + // while running meMeshInfo** meshes; + uint num_meshes; }; diff --git a/include/render_object.h b/include/render_object.h index ab1033a..c4449fb 100644 --- a/include/render_object.h +++ b/include/render_object.h @@ -4,6 +4,8 @@ #include #include +#include "mesh.h" + struct render_object { @@ -16,8 +18,10 @@ struct render_object GLuint index_buffer_id; }; +bool roInit(meMeshInfo* mi_in, render_object& ro_out); + // TODO: make use of glIsBuffer/glDeleteBuffers -void roFree(render_object* ro); +void roFree(render_object& ro); // TODO: implement me! -void roDraw(render_object* ro); +void roDraw(render_object& ro); diff --git a/src/entity.cpp b/src/entity.cpp index 6652393..6804d7d 100644 --- a/src/entity.cpp +++ b/src/entity.cpp @@ -1,17 +1,16 @@ +#include + #include #include "dumbLog.h" #include "entity.h" +#include "util.h" // forward declarations bool loadMeshIntoGL(entity& e); -#if 0 -bool initEntityROs(entity& e); -bool convertMeshInfo(meMeshInfo* mesh, render_object* ro, bool use_normals, bool use_texture); -#endif // interface @@ -23,22 +22,14 @@ entInit(entity& e, const char* model_path) entScale(e, glm::vec3(1.0)); entSetWorldPosition(e, glm::vec3(0, 0, 0)); - if (meLoadFromFile(e.mesh_group, model_path) - && loadMeshIntoGL(e)) + if (meLoadFromFile(e.mesh_group, model_path)) { -#if 0 - initEntityRG(e, shader, e.mesh_group.use_normals); - - if (!initEntityROs(e)) - goto cleanup; -#endif - } else { - goto cleanup; + e.ro_count = e.mesh_group.num_meshes; + e.render_objs = UTIL_ALLOC(e.ro_count, render_object); + if (loadMeshIntoGL(e)) + return true; } - return true; - -cleanup: entFree(e); return false; } @@ -48,8 +39,12 @@ entFree(entity& e) { meFreeMeshGroup(e.mesh_group); - for (uint i = 0; i < e.render_objs.count; i++) - roFree(&e.render_objs.objs[i]); + for (uint i = 0; i < e.ro_count; i++) + roFree(e.render_objs[i]); + + utilSafeFree(e.render_objs); + e.render_objs = nullptr; + e.ro_count = 0; } void @@ -78,125 +73,19 @@ entScale(entity& e, glm::vec3 v) bool loadMeshIntoGL(entity& e) { - LOG(Error) << "TODO: redo GL init for new render_object\n"; - return false; -} - -#if 0 -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*); -} -#endif - -#if 0 -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); + for (uint i = 0; i < e.mesh_group.num_meshes; i++) { + assert(e.render_objs != nullptr); + render_object ro = e.render_objs[i]; + meMeshInfo* mi = e.mesh_group.meshes[i]; + assert(mi != nullptr); + + if (!roInit(mi, ro)) { + LOG(Error) << "Error initializing render objects\n"; + entFree(e); 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; } -#endif - -#if 0 -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; -} -#endif diff --git a/src/mesh.cpp b/src/mesh.cpp index bb6e406..9ba3ae7 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -20,6 +20,7 @@ void freeMesh(meMeshInfo* mesh); inline glm::vec3 copyVector(aiVector3D v_in, glm::vec3& v_out); meMeshInfo* copyMeshInfo(const aiScene* scene, aiMesh* mesh); bool loadDiffuseTexture(const aiScene* scene, aiMesh* mesh, meMeshInfo* mi); +bool validateScene(const aiScene* scene, const char* filepath); // interface @@ -40,19 +41,11 @@ meLoadFromFile(meMeshGroup& mesh_group, const char* filepath) LOG(Info) << "Loading file: " << filepath << "\n"; const aiScene* scene = aiImportFile(filepath, aiProcessPreset_TargetRealtime_MaxQuality); - if (!scene) { - LOG(Error) << "Error loading file: " << filepath << "\n"; + if (!validateScene(scene, filepath)) return false; - } - - if (scene->mNumMeshes < 1) { - LOG(Error) << "Scene contains no meshes\n"; - return false; - } mesh_group.num_meshes = scene->mNumMeshes; mesh_group.meshes = UTIL_ALLOC(mesh_group.num_meshes, meMeshInfo*); - mesh_group.use_normals = scene->mMeshes[0]->HasNormals(); for (uint i = 0; i < scene->mNumMeshes; i++) { aiMesh* mesh = scene->mMeshes[i]; @@ -81,6 +74,8 @@ meFreeMeshGroup(meMeshGroup& mesh_group) freeMesh(mesh_group.meshes[i]); utilSafeFree(mesh_group.meshes); + mesh_group.num_meshes = 0; + mesh_group.meshes = nullptr; } void @@ -198,3 +193,24 @@ copyMeshInfo(const aiScene* scene, aiMesh* mesh) return mi; } + +bool +validateScene(const aiScene* scene, const char* filepath) +{ + if (!scene) { + LOG(Error) << "Error loading file: " << filepath << "\n"; + return false; + } + + if (scene->mNumMeshes < 1) { + LOG(Error) << "Scene contains no meshes\n"; + return false; + } + + if (!scene->mMeshes[0]->HasNormals()) { + LOG(Error) << "Mesh doesn't have normals\n"; + return false; + } + + return true; +} diff --git a/src/render_object.cpp b/src/render_object.cpp index 736f003..2fc50e3 100644 --- a/src/render_object.cpp +++ b/src/render_object.cpp @@ -3,8 +3,71 @@ #include "render_object.h" +// forward declarations + +bool initGLFloatBuffer(glm::vec3* buffer, uint count, GLuint& buffer_id); +bool initGLIndexBuffer(uint* buffer, uint num_indices, GLuint& buffer_id); + + +// interface + +bool +roInit(meMeshInfo* mi_in, render_object& ro_out) +{ + if (initGLFloatBuffer(mi_in->vertices, + mi_in->num_vertices, + ro_out.vertex_buffer_id) && + initGLFloatBuffer(mi_in->normals, + mi_in->num_vertices, + ro_out.normal_buffer_id) && + initGLFloatBuffer(mi_in->texture_coords, + mi_in->num_vertices, + ro_out.uv_buffer_id) && + initGLIndexBuffer(mi_in->indices, + mi_in->num_indices, + ro_out.index_buffer_id)) + { + return true; + } + + LOG(Error) << "Failed to initialize render_object\n"; + roFree(ro_out); + return false; +} + void -roFree(render_object* ro) +roFree(render_object& ro) { LOG(Debug) << "TODO: release GL buffers from render_object\n"; } + + +// internal + +bool +initGLFloatBuffer(glm::vec3* buffer, uint count, GLuint& buffer_id) +{ + glGenBuffers(1, &buffer_id); + glBindBuffer(GL_ARRAY_BUFFER, buffer_id); + glBufferData(GL_ARRAY_BUFFER, + count * sizeof(GLfloat), + buffer, + GL_STATIC_DRAW); + + // TODO: check for errors after buffering + return true; +} + +bool +initGLIndexBuffer(uint* buffer, uint num_indices, GLuint& buffer_id) +{ + glGenBuffers(1, &buffer_id); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer_id); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, + num_indices * sizeof(uint), + buffer, + GL_STATIC_DRAW); + + // TODO: check for errors after buffering + return true; +}