From ef5be632fe777e8303cb2fba6be95e0e4aa0fc85 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Fri, 17 Dec 2021 20:55:38 +0100 Subject: [PATCH] REVIEWED: `ExportMesh()` #2220 --- examples/models/models_mesh_generation.c | 118 ++++++++++++----------- src/rmodels.c | 41 +++++--- 2 files changed, 90 insertions(+), 69 deletions(-) diff --git a/examples/models/models_mesh_generation.c b/examples/models/models_mesh_generation.c index 095aad827..7213f58d9 100644 --- a/examples/models/models_mesh_generation.c +++ b/examples/models/models_mesh_generation.c @@ -5,64 +5,15 @@ * This example has been created using raylib 1.8 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * -* Copyright (c) 2017 Ramon Santamaria (Ray San) +* Copyright (c) 2017-2021 Ramon Santamaria (@raysan5) * ********************************************************************************************/ #include "raylib.h" -#define NUM_MODELS 9 // Parametric 3d shapes to generate +#define NUM_MODELS 9 // Parametric 3d shapes to generate -void AllocateMeshData(Mesh* mesh, int triangleCount) -{ - mesh->vertexCount = triangleCount * 3; - mesh->triangleCount = triangleCount; - - mesh->vertices = (float*)MemAlloc(mesh->vertexCount * 3 * sizeof(float)); - mesh->texcoords = (float*)MemAlloc(mesh->vertexCount * 2 * sizeof(float)); - mesh->normals = (float*)MemAlloc(mesh->vertexCount * 3 * sizeof(float)); -} - -// generate a simple triangle mesh from code -Mesh MakeMesh() -{ - Mesh mesh = { 0 }; - AllocateMeshData(&mesh, 1); - - // vertex at the origin - mesh.vertices[0] = 0; - mesh.vertices[1] = 0; - mesh.vertices[2] = 0; - mesh.normals[0] = 0; - mesh.normals[1] = 1; - mesh.normals[2] = 0; - mesh.texcoords[0] = 0; - mesh.texcoords[1] = 0; - - // vertex at 1,0,2 - mesh.vertices[3] = 1; - mesh.vertices[4] = 0; - mesh.vertices[5] = 2; - mesh.normals[3] = 0; - mesh.normals[4] = 1; - mesh.normals[5] = 0; - mesh.texcoords[2] = 0.5f; - mesh.texcoords[3] = 1.0f; - - // vertex at 2,0,0 - mesh.vertices[6] = 2; - mesh.vertices[7] = 0; - mesh.vertices[8] = 0; - mesh.normals[6] = 0; - mesh.normals[7] = 1; - mesh.normals[8] = 0; - mesh.texcoords[4] = 1; - mesh.texcoords[5] =0; - - UploadMesh(&mesh, false); - - return mesh; -} +static Mesh GenMeshCustom(void); // Generate a simple triangle mesh from code int main(void) { @@ -88,7 +39,18 @@ int main(void) models[5] = LoadModelFromMesh(GenMeshTorus(0.25f, 4.0f, 16, 32)); models[6] = LoadModelFromMesh(GenMeshKnot(1.0f, 2.0f, 16, 128)); models[7] = LoadModelFromMesh(GenMeshPoly(5, 2.0f)); - models[8] = LoadModelFromMesh(MakeMesh()); + models[8] = LoadModelFromMesh(GenMeshCustom()); + + // Generated meshes could be exported as .obj files + //ExportMesh(models[0].meshes[0], "plane.obj"); + //ExportMesh(models[1].meshes[0], "cube.obj"); + //ExportMesh(models[2].meshes[0], "sphere.obj"); + //ExportMesh(models[3].meshes[0], "hemisphere.obj"); + //ExportMesh(models[4].meshes[0], "cylinder.obj"); + //ExportMesh(models[5].meshes[0], "torus.obj"); + //ExportMesh(models[6].meshes[0], "knot.obj"); + //ExportMesh(models[7].meshes[0], "poly.obj"); + //ExportMesh(models[8].meshes[0], "custom.obj"); // Set checked texture as default diffuse component for all models material for (int i = 0; i < NUM_MODELS; i++) models[i].materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = texture; @@ -157,7 +119,7 @@ int main(void) case 5: DrawText("TORUS", 680, 10, 20, DARKBLUE); break; case 6: DrawText("KNOT", 680, 10, 20, DARKBLUE); break; case 7: DrawText("POLY", 680, 10, 20, DARKBLUE); break; - case 8: DrawText("Parametric(custom)", 580, 10, 20, DARKBLUE); break; + case 8: DrawText("Custom (triangle)", 580, 10, 20, DARKBLUE); break; default: break; } @@ -176,4 +138,50 @@ int main(void) //-------------------------------------------------------------------------------------- return 0; -} \ No newline at end of file +} + +// Generate a simple triangle mesh from code +static Mesh GenMeshCustom(void) +{ + Mesh mesh = { 0 }; + mesh.triangleCount = 1; + mesh.vertexCount = mesh.triangleCount*3; + mesh.vertices = (float *)MemAlloc(mesh.vertexCount*3*sizeof(float)); // 3 vertices, 3 coordinates each (x, y, z) + mesh.texcoords = (float *)MemAlloc(mesh.vertexCount*2*sizeof(float)); // 3 vertices, 2 coordinates each (x, y) + mesh.normals = (float *)MemAlloc(mesh.vertexCount*3*sizeof(float)); // 3 vertices, 3 coordinates each (x, y, z) + + // Vertex at (0, 0, 0) + mesh.vertices[0] = 0; + mesh.vertices[1] = 0; + mesh.vertices[2] = 0; + mesh.normals[0] = 0; + mesh.normals[1] = 1; + mesh.normals[2] = 0; + mesh.texcoords[0] = 0; + mesh.texcoords[1] = 0; + + // Vertex at (1, 0, 2) + mesh.vertices[3] = 1; + mesh.vertices[4] = 0; + mesh.vertices[5] = 2; + mesh.normals[3] = 0; + mesh.normals[4] = 1; + mesh.normals[5] = 0; + mesh.texcoords[2] = 0.5f; + mesh.texcoords[3] = 1.0f; + + // Vertex at (2, 0, 0) + mesh.vertices[6] = 2; + mesh.vertices[7] = 0; + mesh.vertices[8] = 0; + mesh.normals[6] = 0; + mesh.normals[7] = 1; + mesh.normals[8] = 0; + mesh.texcoords[4] = 1; + mesh.texcoords[5] =0; + + // Upload mesh data from CPU (RAM) to GPU (VRAM) memory + UploadMesh(&mesh, false); + + return mesh; +} diff --git a/src/rmodels.c b/src/rmodels.c index 06da90486..212d5a06d 100644 --- a/src/rmodels.c +++ b/src/rmodels.c @@ -1649,13 +1649,13 @@ bool ExportMesh(Mesh mesh, const char *fileName) if (IsFileExtension(fileName, ".obj")) { // Estimated data size, it should be enough... - int dataSize = mesh.vertexCount/3*(int)strlen("v 0000.00f 0000.00f 0000.00f") + - mesh.vertexCount/2*(int)strlen("vt 0.000f 0.00f") + - mesh.vertexCount/3*(int)strlen("vn 0.000f 0.00f 0.00f") + - mesh.triangleCount/3*(int)strlen("f 00000/00000/00000 00000/00000/00000 00000/00000/00000"); + int dataSize = mesh.vertexCount*(int)strlen("v 0000.00f 0000.00f 0000.00f") + + mesh.vertexCount*(int)strlen("vt 0.000f 0.00f") + + mesh.vertexCount*(int)strlen("vn 0.000f 0.00f 0.00f") + + mesh.triangleCount*(int)strlen("f 00000/00000/00000 00000/00000/00000 00000/00000/00000"); // NOTE: Text data buffer size is estimated considering mesh data size - char *txtData = (char *)RL_CALLOC(dataSize + 2000, sizeof(char)); + char *txtData = (char *)RL_CALLOC(dataSize*2 + 2000, sizeof(char)); int byteCount = 0; byteCount += sprintf(txtData + byteCount, "# //////////////////////////////////////////////////////////////////////////////////\n"); @@ -1665,7 +1665,7 @@ bool ExportMesh(Mesh mesh, const char *fileName) byteCount += sprintf(txtData + byteCount, "# // more info and bugs-report: github.com/raysan5/raylib //\n"); byteCount += sprintf(txtData + byteCount, "# // feedback and support: ray[at]raylib.com //\n"); byteCount += sprintf(txtData + byteCount, "# // //\n"); - byteCount += sprintf(txtData + byteCount, "# // Copyright (c) 2018 Ramon Santamaria (@raysan5) //\n"); + byteCount += sprintf(txtData + byteCount, "# // Copyright (c) 2018-2021 Ramon Santamaria (@raysan5) //\n"); byteCount += sprintf(txtData + byteCount, "# // //\n"); byteCount += sprintf(txtData + byteCount, "# //////////////////////////////////////////////////////////////////////////////////\n\n"); byteCount += sprintf(txtData + byteCount, "# Vertex Count: %i\n", mesh.vertexCount); @@ -1688,9 +1688,22 @@ bool ExportMesh(Mesh mesh, const char *fileName) byteCount += sprintf(txtData + byteCount, "vn %.3f %.3f %.3f\n", mesh.normals[v], mesh.normals[v + 1], mesh.normals[v + 2]); } - for (int i = 0; i < mesh.triangleCount; i++) + if (mesh.indices != NULL) { - byteCount += sprintf(txtData + byteCount, "f %i/%i/%i %i/%i/%i %i/%i/%i\n", i, i, i, i + 1, i + 1, i + 1, i + 2, i + 2, i + 2); + for (int i = 0, v = 0; i < mesh.triangleCount; i++, v += 3) + { + byteCount += sprintf(txtData + byteCount, "f %i/%i/%i %i/%i/%i %i/%i/%i\n", + mesh.indices[v] + 1, mesh.indices[v] + 1, mesh.indices[v] + 1, + mesh.indices[v + 1] + 1, mesh.indices[v + 1] + 1, mesh.indices[v + 1] + 1, + mesh.indices[v + 2] + 1, mesh.indices[v + 2] + 1, mesh.indices[v + 2] + 1); + } + } + else + { + for (int i = 0, v = 1; i < mesh.triangleCount; i++, v += 3) + { + byteCount += sprintf(txtData + byteCount, "f %i/%i/%i %i/%i/%i %i/%i/%i\n", v, v, v, v + 1, v + 1, v + 1, v + 2, v + 2, v + 2); + } } byteCount += sprintf(txtData + byteCount, "\n"); @@ -2252,14 +2265,14 @@ Mesh GenMeshCube(float width, float height, float length) int k = 0; // Indices can be initialized right now - for (int i = 0; i < 36; i+=6) + for (int i = 0; i < 36; i += 6) { mesh.indices[i] = 4*k; - mesh.indices[i+1] = 4*k+1; - mesh.indices[i+2] = 4*k+2; - mesh.indices[i+3] = 4*k; - mesh.indices[i+4] = 4*k+2; - mesh.indices[i+5] = 4*k+3; + mesh.indices[i + 1] = 4*k + 1; + mesh.indices[i + 2] = 4*k + 2; + mesh.indices[i + 3] = 4*k; + mesh.indices[i + 4] = 4*k + 2; + mesh.indices[i + 5] = 4*k + 3; k++; }