From 1ddf594d15f31f1502eeb18f0f0c8039799fff01 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Tue, 10 May 2016 18:24:28 +0200 Subject: [PATCH 1/4] Added support for indexed mesh data --- src/models.c | 21 +++++++++++++++++---- src/raylib.h | 7 +++++-- src/rlgl.c | 39 ++++++++++++++++++++++++++++----------- 3 files changed, 50 insertions(+), 17 deletions(-) diff --git a/src/models.c b/src/models.c index 7d24e383e..411501796 100644 --- a/src/models.c +++ b/src/models.c @@ -553,7 +553,7 @@ Model LoadModel(const char *fileName) if (model.mesh.vertexCount == 0) TraceLog(WARNING, "Model could not be loaded"); else { - rlglLoadMesh(&model.mesh); // Upload vertex data to GPU + rlglLoadMesh(&model.mesh); // Upload vertex data to GPU model.transform = MatrixIdentity(); model.material = LoadDefaultMaterial(); @@ -567,7 +567,9 @@ Model LoadModelEx(Mesh data) { Model model = { 0 }; - rlglLoadMesh(&data); // Upload vertex data to GPU + model.mesh = data; + + rlglLoadMesh(&model.mesh); // Upload vertex data to GPU model.transform = MatrixIdentity(); model.material = LoadDefaultMaterial(); @@ -693,12 +695,13 @@ Model LoadCubicmap(Image cubicmap) void UnloadModel(Model model) { // Unload mesh data - free(model.mesh.vertices); - free(model.mesh.texcoords); + if (model.mesh.vertices != NULL) free(model.mesh.vertices); + if (model.mesh.texcoords != NULL) free(model.mesh.texcoords); if (model.mesh.normals != NULL) free(model.mesh.normals); if (model.mesh.colors != NULL) free(model.mesh.colors); if (model.mesh.tangents != NULL) free(model.mesh.tangents); if (model.mesh.texcoords2 != NULL) free(model.mesh.texcoords2); + if (model.mesh.indices != NULL) free(model.mesh.indices); TraceLog(INFO, "Unloaded model data from RAM (CPU)"); @@ -708,8 +711,11 @@ void UnloadModel(Model model) rlDeleteBuffers(model.mesh.vboId[3]); // colors rlDeleteBuffers(model.mesh.vboId[4]); // tangents rlDeleteBuffers(model.mesh.vboId[5]); // texcoords2 + rlDeleteBuffers(model.mesh.vboId[6]); // indices rlDeleteVertexArrays(model.mesh.vaoId); + + UnloadMaterial(model.material); } // Load material data (from file) @@ -743,6 +749,13 @@ Material LoadDefaultMaterial(void) return material; } +void UnloadMaterial(Material material) +{ + rlDeleteTextures(material.texDiffuse.id); + rlDeleteTextures(material.texNormal.id); + rlDeleteTextures(material.texSpecular.id); +} + // Link a texture to a model void SetModelTexture(Model *model, Texture2D texture) { diff --git a/src/raylib.h b/src/raylib.h index 1258bffc7..054633256 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -368,18 +368,20 @@ typedef struct BoundingBox { // Vertex data definning a mesh typedef struct Mesh { - int vertexCount; // num vertices + int vertexCount; // number of vertices stored in arrays float *vertices; // vertex position (XYZ - 3 components per vertex) (shader-location = 0) float *texcoords; // vertex texture coordinates (UV - 2 components per vertex) (shader-location = 1) float *texcoords2; // vertex second texture coordinates (useful for lightmaps) (shader-location = 5) float *normals; // vertex normals (XYZ - 3 components per vertex) (shader-location = 2) float *tangents; // vertex tangents (XYZ - 3 components per vertex) (shader-location = 4) unsigned char *colors; // vertex colors (RGBA - 4 components per vertex) (shader-location = 3) + unsigned short *indices; // vertex indices (in case vertex data comes indexed) + int trianglesCount; // number of triangles to draw BoundingBox bounds; // mesh limits defined by min and max points unsigned int vaoId; // OpenGL Vertex Array Object id - unsigned int vboId[6]; // OpenGL Vertex Buffer Objects id (6 types of vertex data) + unsigned int vboId[7]; // OpenGL Vertex Buffer Objects id (7 types of vertex data) } Mesh; // Shader type (generic shader) @@ -813,6 +815,7 @@ void SetModelTexture(Model *model, Texture2D texture); // Link a textur Material LoadMaterial(const char *fileName); // Load material data (from file) Material LoadDefaultMaterial(void); // Load default material (uses default models shader) +void UnloadMaterial(Material material); // Unload material textures from VRAM void DrawModel(Model model, Vector3 position, float scale, Color tint); // Draw a model (with texture if set) void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model with extended parameters diff --git a/src/rlgl.c b/src/rlgl.c index 33f12debc..8364c4f1e 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -783,16 +783,16 @@ void rlDisableDepthTest(void) // Unload texture from GPU memory void rlDeleteTextures(unsigned int id) { - glDeleteTextures(1, &id); + if (id != 0) glDeleteTextures(1, &id); } // Unload render texture from GPU memory void rlDeleteRenderTextures(RenderTexture2D target) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - glDeleteFramebuffers(1, &target.id); - glDeleteTextures(1, &target.texture.id); - glDeleteTextures(1, &target.depth.id); + if (target.id != 0) glDeleteFramebuffers(1, &target.id); + if (target.texture.id != 0) glDeleteTextures(1, &target.texture.id); + if (target.depth.id != 0) glDeleteTextures(1, &target.depth.id); #endif } @@ -800,7 +800,7 @@ void rlDeleteRenderTextures(RenderTexture2D target) void rlDeleteShader(unsigned int id) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - glDeleteProgram(id); + if (id != 0) glDeleteProgram(id); #endif } @@ -810,7 +810,7 @@ void rlDeleteVertexArrays(unsigned int id) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) if (vaoSupported) { - glDeleteVertexArrays(1, &id); + if (id != 0) glDeleteVertexArrays(1, &id); TraceLog(INFO, "[VAO ID %i] Unloaded model data from VRAM (GPU)", id); } #endif @@ -1204,10 +1204,13 @@ void rlglDrawEx(Mesh mesh, Material material, Matrix transform, bool wires) glVertexAttribPointer(material.shader.texcoord2Loc, 2, GL_FLOAT, 0, 0, 0); glEnableVertexAttribArray(material.shader.texcoord2Loc); } + + if (mesh.indices != NULL) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, quadsBuffer[3]); } // Draw call! - glDrawArrays(GL_TRIANGLES, 0, mesh.vertexCount); + if (mesh.indices != NULL) glDrawElements(GL_TRIANGLES, mesh.trianglesCount*3, GL_UNSIGNED_SHORT, 0); // Indexed vertices draw + else glDrawArrays(GL_TRIANGLES, 0, mesh.vertexCount); if (material.texNormal.id != 0) { @@ -1225,7 +1228,11 @@ void rlglDrawEx(Mesh mesh, Material material, Matrix transform, bool wires) glBindTexture(GL_TEXTURE_2D, 0); // Unbind textures if (vaoSupported) glBindVertexArray(0); // Unbind VAO - else glBindBuffer(GL_ARRAY_BUFFER, 0); // Unbind VBOs + else + { + glBindBuffer(GL_ARRAY_BUFFER, 0); // Unbind VBOs + if (mesh.indices != NULL) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + } glUseProgram(0); // Unbind shader program #endif @@ -1682,11 +1689,12 @@ void rlglLoadMesh(Mesh *mesh) mesh->vboId[3] = 0; // Vertex colors VBO mesh->vboId[4] = 0; // Vertex tangents VBO mesh->vboId[5] = 0; // Vertex texcoords2 VBO + mesh->vboId[6] = 0; // Vertex indices VBO #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) GLuint vaoId = 0; // Vertex Array Objects (VAO) - GLuint vboId[6]; // Vertex Buffer Objects (VBOs) + GLuint vboId[7]; // Vertex Buffer Objects (VBOs) if (vaoSupported) { @@ -1775,12 +1783,21 @@ void rlglLoadMesh(Mesh *mesh) glDisableVertexAttribArray(5); } + if (mesh->indices != NULL) + { + glGenBuffers(1, &vboId[6]); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboId[6]); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned short)*mesh->trianglesCount*3, mesh->indices, GL_STATIC_DRAW); + } + + mesh->vboId[0] = vboId[0]; // Vertex position VBO mesh->vboId[1] = vboId[1]; // Texcoords VBO mesh->vboId[2] = vboId[2]; // Normals VBO mesh->vboId[3] = vboId[3]; // Colors VBO mesh->vboId[4] = vboId[4]; // Tangents VBO mesh->vboId[5] = vboId[5]; // Texcoords2 VBO + mesh->vboId[6] = vboId[6]; // Indices VBO if (vaoSupported) { @@ -2733,9 +2750,9 @@ static void DrawDefaultBuffers(void) // NOTE: The final parameter tells the GPU the offset in bytes from the start of the index buffer to the location of the first index to process #if defined(GRAPHICS_API_OPENGL_33) - glDrawElements(GL_TRIANGLES, numIndicesToProcess, GL_UNSIGNED_INT, (GLvoid*) (sizeof(GLuint) * indicesOffset)); + glDrawElements(GL_TRIANGLES, numIndicesToProcess, GL_UNSIGNED_INT, (GLvoid *)(sizeof(GLuint)*indicesOffset)); #elif defined(GRAPHICS_API_OPENGL_ES2) - glDrawElements(GL_TRIANGLES, numIndicesToProcess, GL_UNSIGNED_SHORT, (GLvoid*) (sizeof(GLushort) * indicesOffset)); + glDrawElements(GL_TRIANGLES, numIndicesToProcess, GL_UNSIGNED_SHORT, (GLvoid *)(sizeof(GLushort)*indicesOffset)); #endif //GLenum err; //if ((err = glGetError()) != GL_NO_ERROR) TraceLog(INFO, "OpenGL error: %i", (int)err); //GL_INVALID_ENUM! From aee5d9a39026d7cff2536806c1f10e25ccc57dcc Mon Sep 17 00:00:00 2001 From: raysan5 Date: Tue, 10 May 2016 19:24:05 +0200 Subject: [PATCH 2/4] Code tweak --- src/models.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/models.c b/src/models.c index 411501796..066b919ed 100644 --- a/src/models.c +++ b/src/models.c @@ -2019,7 +2019,7 @@ static Material LoadMTL(const char *fileName) char buffer[MAX_BUFFER_SIZE]; Vector3 color = { 1.0f, 1.0f, 1.0f }; - char *mapFileName; + char *mapFileName = NULL; FILE *mtlFile; From 5c112ff5425356a81920d907caf25a40c9ba71df Mon Sep 17 00:00:00 2001 From: raysan5 Date: Tue, 10 May 2016 19:24:25 +0200 Subject: [PATCH 3/4] Corrected tipo --- src/raylib.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/raylib.h b/src/raylib.h index 054633256..ecfce9fcf 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -376,7 +376,7 @@ typedef struct Mesh { float *tangents; // vertex tangents (XYZ - 3 components per vertex) (shader-location = 4) unsigned char *colors; // vertex colors (RGBA - 4 components per vertex) (shader-location = 3) unsigned short *indices; // vertex indices (in case vertex data comes indexed) - int trianglesCount; // number of triangles to draw + int triangleCount; // number of triangles to draw BoundingBox bounds; // mesh limits defined by min and max points From 6acfda599e5353b1c90bb11329ce50632851b1f5 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Tue, 10 May 2016 19:25:06 +0200 Subject: [PATCH 4/4] Support indexed mesh data on OpenGL 1.1 path Keep asking myself why I maintain this rendering path... -___- --- src/rlgl.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/rlgl.c b/src/rlgl.c index 8364c4f1e..3c0d9e796 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -1094,7 +1094,7 @@ void rlglDrawEx(Mesh mesh, Material material, Matrix transform, bool wires) glEnableClientState(GL_VERTEX_ARRAY); // Enable vertex array glEnableClientState(GL_TEXTURE_COORD_ARRAY); // Enable texture coords array if (mesh.normals != NULL) glEnableClientState(GL_NORMAL_ARRAY); // Enable normals array - if (mesh.colors != NULL) glEnableClientState(GL_COLOR_ARRAY); // Enable colors array + if (mesh.colors != NULL) glEnableClientState(GL_COLOR_ARRAY); // Enable colors array glVertexPointer(3, GL_FLOAT, 0, mesh.vertices); // Pointer to vertex coords array glTexCoordPointer(2, GL_FLOAT, 0, mesh.texcoords); // Pointer to texture coords array @@ -1104,7 +1104,9 @@ void rlglDrawEx(Mesh mesh, Material material, Matrix transform, bool wires) rlPushMatrix(); rlMultMatrixf(MatrixToFloat(transform)); rlColor4ub(material.colDiffuse.r, material.colDiffuse.g, material.colDiffuse.b, material.colDiffuse.a); - glDrawArrays(GL_TRIANGLES, 0, mesh.vertexCount); + + if (mesh.indices != NULL) glDrawElements(GL_TRIANGLES, mesh.triangleCount*3, GL_UNSIGNED_SHORT, mesh.indices); + else glDrawArrays(GL_TRIANGLES, 0, mesh.vertexCount); rlPopMatrix(); glDisableClientState(GL_VERTEX_ARRAY); // Disable vertex array @@ -1209,7 +1211,7 @@ void rlglDrawEx(Mesh mesh, Material material, Matrix transform, bool wires) } // Draw call! - if (mesh.indices != NULL) glDrawElements(GL_TRIANGLES, mesh.trianglesCount*3, GL_UNSIGNED_SHORT, 0); // Indexed vertices draw + if (mesh.indices != NULL) glDrawElements(GL_TRIANGLES, mesh.triangleCount*3, GL_UNSIGNED_SHORT, 0); // Indexed vertices draw else glDrawArrays(GL_TRIANGLES, 0, mesh.vertexCount); if (material.texNormal.id != 0) @@ -1787,7 +1789,7 @@ void rlglLoadMesh(Mesh *mesh) { glGenBuffers(1, &vboId[6]); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboId[6]); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned short)*mesh->trianglesCount*3, mesh->indices, GL_STATIC_DRAW); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned short)*mesh->triangleCount*3, mesh->indices, GL_STATIC_DRAW); }