From e16915428c09eff1677ecfad321d7e9cc0f7ad33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gero=20M=C3=BCller?= Date: Fri, 3 Nov 2017 09:22:38 +1000 Subject: [PATCH] extract Mesh and GLMesh --- src/Application.cpp | 212 +++++++-------------------------- src/Application.h | 15 +-- src/Mesh.cpp | 278 +++++++++++++++++++++++++++----------------- src/Mesh.h | 54 +++++---- src/Polygoniser.cpp | 32 ++--- src/Polygoniser.h | 5 +- src/SkyBox.cpp | 29 ++--- src/gl.h | 121 +++++++++++++++++++ src/types.h | 1 + 9 files changed, 409 insertions(+), 338 deletions(-) create mode 100644 src/gl.h diff --git a/src/Application.cpp b/src/Application.cpp index 3f0c48f..3c4b8c7 100644 --- a/src/Application.cpp +++ b/src/Application.cpp @@ -2,8 +2,7 @@ #include "Mesh.h" #include "Shader.h" -#include -#include +#include "gl.h" #include #include @@ -27,30 +26,6 @@ using glm::uvec3; using std::map; using std::vector; -static bool glck(const char* call) { - int err = glGetError(); - if (err == 0) { - return true; - } else { - switch (err) { - case GL_INVALID_VALUE: - printf("GL_INVALID_VALUE: %s\n", call); - break; - case GL_INVALID_ENUM: - printf("GL_INVALID_ENUM: %s\n", call); - break; - case GL_INVALID_OPERATION: - printf("GL_INVALID_OPERATION: %s\n", call); - break; - default: - printf("UNKNOWN Error: %s\n", call); - } - return false; - } -} - -#define GLCK(a) {a; assert(glck(#a));} - static void error_callback(int error, const char* description) { fprintf(stderr, "Error: %s\n", description); } @@ -80,12 +55,11 @@ static void char_callback(GLFWwindow* window, unsigned int c) { Application::Application() : window(0), density(), densityIsolevel(0.2), polygonizer(density, densityIsolevel), textureSize(512), texturemapper(density, - textureSize), programId(0), vPositionLoc(-1), vTexCoordLoc(-1), vNormalLoc( - -1), meteoridCount(1000), meteroidMinRadius(0.005), meteroidMaxRadius( - 0.2), meteroidSizeExponent(2048), densityFrequency(2), densityOctave( - 2), densityScale(1.0f), resolution(0.1), smoothMesh(true), viewDistance( - 3.0f), fpsMode(false), meshUploadRequest(false), textureUploadRequest( - false) { + textureSize), programId(0), meteoridCount(1000), meteroidMinRadius( + 0.005), meteroidMaxRadius(0.2), meteroidSizeExponent(2048), densityFrequency( + 2), densityOctave(2), densityScale(1.0f), resolution(0.1), smoothMesh( + true), viewDistance(3.0f), fpsMode(false), meshUploadRequest( + false), textureUploadRequest(false) { init(); } @@ -145,31 +119,20 @@ void Application::init() { ImGui_ImplGlfwGL3_Init(window, false); - GLCK(glGenVertexArrays(1, &vertexArrayId)) - GLCK(glGenBuffers(1, &vPositionId)) - GLCK(glGenBuffers(1, &vTexCoordId)) - GLCK(glGenBuffers(1, &vNormalId)) - GLCK(glGenBuffers(1, &indexBufferId)) - GLCK(glGenTextures(1, &tAlbedoId)) GLCK(glGenTextures(1, &tNormalId)) GLCK(glGenTextures(1, &tRoughnessId)) GLCK(glGenTextures(1, &tMetalicId)) loadShader(); - updateVertexArrayObject(); + glMesh.create(); + glMesh.update(vPositionLoc, vNormalLoc, vTexCoordLoc); generateAsteroid(); } void Application::shutdown() { ImGui_ImplGlfwGL3_Shutdown(); - GLCK(glDeleteBuffers(1, &vPositionId)) - GLCK(glDeleteBuffers(1, &vTexCoordId)) - GLCK(glDeleteBuffers(1, &vNormalId)) - GLCK(glDeleteBuffers(1, &indexBufferId)) - GLCK(glDeleteVertexArrays(1, &vertexArrayId)) - glfwDestroyWindow(window); glfwTerminate(); } @@ -217,15 +180,16 @@ void Application::toogleFpsMode() { void Application::generateAsteroid() { if (meshProgress.begin("Random Impacts", 1)) { - //if (density.getImpacts().size() == 0) - density.addRandomImpacts(1000, densityIsolevel, 0.01, 0.005, 0.2, 256); + if (density.getImpacts().size() == 0) + density.addRandomImpacts(1000, densityIsolevel, 0.01, 0.005, 0.2, + 256); //density.saveCrossSection("density.png", 512); } polygonizer.polygonize(resolution, meshProgress); if (smoothMesh && meshProgress.begin("Smooth", 1)) { - smooth(polygonizer.vertices, polygonizer.indices); + polygonizer.mesh.smooth(); // { // std::ofstream out("stage2.obj"); // saveAttrib(out, "v ", polygonizer.vertices); @@ -233,72 +197,40 @@ void Application::generateAsteroid() { // } } - uvec4v_t edges; - if (meshProgress.begin("Find Edges", 1)) { - findEdges(polygonizer.vertices, polygonizer.indices, edges); - } - uvec3v_t adjacents; - if (meshProgress.begin("Find Adjacent", 1)) { - findAdjacent(edges, polygonizer.indices.size(), adjacents); - } - vec3v_t faceNormals; - calculateFaceNormals(polygonizer.vertices, polygonizer.indices, - faceNormals); - - vec3v_t positions; - uvec3v_t indices; - uintv_t patches; - - createPatches(polygonizer.vertices, polygonizer.indices, faceNormals, - adjacents, positions, indices, patches, 0.9); - { - std::ofstream out("stage1.obj"); - saveAttrib(out, "v ", positions); - saveFaces(out, indices, 1); + if (meshProgress.begin("Generate Edges", 1)) { + polygonizer.mesh.generateEdges(); } - if (meshProgress.begin("Calculate Vertex Normals", 1)) { - calculateVertexNormals(polygonizer.vertices, polygonizer.indices, - normals); -// { -// std::ofstream out("stage3.obj"); -// saveAttrib(out, "v ", polygonizer.vertices); -// saveAttrib(out, "vn ", normals); -// saveFaces(out, polygonizer.indices, 2); -// } - + if (meshProgress.begin("Generate Adjacent", 1)) { + polygonizer.mesh.generateAdjacent(); } - std::cout << "Vertices: " << polygonizer.vertices.size() << std::endl; - std::cout << "Triangles: " << polygonizer.indices.size() << std::endl; + if (meshProgress.begin("Generate Face Normals", 1)) { + polygonizer.mesh.generateFaceNormals(); + } + + if (meshProgress.begin("Generate Vertex Normals", 1)) { + polygonizer.mesh.generateNormals(); + } + + if (meshProgress.begin("Generate Patched", 1)) { + mesh = polygonizer.mesh.createPatched(0.9); + } + + if (meshProgress.begin("Save Patched", 1)) { + mesh.save("patched.obj"); + } if (meshProgress.begin("Map Textures", 1)) { - texturemapper.map(polygonizer.vertices, normals, polygonizer.indices); + texturemapper.map(mesh.positions, mesh.normals, mesh.indices); } if (meshProgress.begin("Move To Mean", 1)) { - moveToMean(texturemapper.vertices); - -// { -// std::ofstream out("stage4.obj"); -// saveAttrib(out, "v ", texturemapper.vertices); -// saveAttrib(out, "vn ", texturemapper.normals); -// saveAttrib(out, "vt ", texturemapper.texcoords); -// saveFaces(out, texturemapper.indices, 3); -// } - + mesh.moveToMean(); } if (meshProgress.begin("Save", 4)) { - std::ofstream out("asteroid.obj"); - saveAttrib(out, "v ", texturemapper.vertices); - meshProgress.advance(); - saveAttrib(out, "vn ", texturemapper.normals); - meshProgress.advance(); - saveAttrib(out, "vt ", texturemapper.texcoords); - meshProgress.advance(); - saveFaces(out, texturemapper.indices, 3); - meshProgress.advance(); + mesh.save("final.obj"); } meshProgress.finish(); @@ -310,40 +242,6 @@ void Application::generateAsteroid() { } -bool Application::bindVertexAttrib(GLuint id, GLint loc, GLuint size) { - if (loc < 0) - return false; - GLCK(glBindBuffer(GL_ARRAY_BUFFER, id)) - GLCK(glEnableVertexAttribArray(loc)) - GLCK(glVertexAttribPointer(loc, // attribute - size,// size - GL_FLOAT,// type - GL_FALSE,// normalized? - 0,// stride - (void* ) 0// array buffer offset - )) - return true; -} - -void Application::updateVertexArrayObject() { - GLCK(glBindVertexArray(vertexArrayId)) - - if (vPositionLoc >= 0) - GLCK(glDisableVertexAttribArray(vPositionLoc)) - if (vNormalLoc >= 0) - GLCK(glDisableVertexAttribArray(vNormalLoc)) - if (vTexCoordLoc >= 0) - GLCK(glDisableVertexAttribArray(vTexCoordLoc)) - - bindVertexAttrib(vPositionId, vPositionLoc, 3); - bindVertexAttrib(vNormalId, vNormalLoc, 3); - bindVertexAttrib(vTexCoordId, vTexCoordLoc, 2); - - GLCK(glBindVertexArray(0)) -} - - - void Application::loadShader() { if (programId >= 0) GLCK(glDeleteProgram(programId)) @@ -365,29 +263,6 @@ void Application::loadShader() { GLCK(tMetalicLoc = glGetAttribLocation(programId, "tMetalic")) } -void Application::uploadMesh() { - printf("upload mesh\n"); - GLCK(glBindVertexArray(vertexArrayId)) - - GLCK(glBindBuffer(GL_ARRAY_BUFFER, vPositionId)) - GLCK( - glBufferData(GL_ARRAY_BUFFER, texturemapper.vertices.size() * sizeof(vec3), texturemapper.vertices.data(), GL_STATIC_DRAW)) - - GLCK(glBindBuffer(GL_ARRAY_BUFFER, vTexCoordId)) - GLCK( - glBufferData(GL_ARRAY_BUFFER, texturemapper.texcoords.size() * sizeof(glm::vec2), texturemapper.texcoords.data(), GL_STATIC_DRAW)) - - GLCK(glBindBuffer(GL_ARRAY_BUFFER, vNormalId)) - GLCK( - glBufferData(GL_ARRAY_BUFFER, texturemapper.normals.size() * sizeof(vec3), texturemapper.normals.data(), GL_STATIC_DRAW)) - - GLCK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferId)) - GLCK( - glBufferData(GL_ELEMENT_ARRAY_BUFFER, texturemapper.indices.size() * sizeof(uvec3), texturemapper.indices.data(), GL_STATIC_DRAW)) - - GLCK(glBindVertexArray(0)) -} - void Application::uploadTexture() { printf("upload texture\n"); glBindTexture(GL_TEXTURE_2D, tAlbedoId); @@ -399,11 +274,11 @@ void Application::uploadTexture() { } void Application::renderMesh() { - GLCK(glBindVertexArray(vertexArrayId)) - GLCK( - glDrawElements(GL_TRIANGLES, texturemapper.indices.size() * 3, GL_UNSIGNED_INT, (void* ) 0)) - GLCK(glBindVertexArray(0)) + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LESS); + glEnable(GL_CULL_FACE); + glMesh.render(); } void Application::prepareShader() { @@ -507,8 +382,8 @@ void Application::prepareShader() { void Application::gui() { ImGui::Begin("Mesh Generation"); - ImGui::Text("Vertices: %lu, Triangles: %lu", polygonizer.vertices.size(), - polygonizer.indices.size()); + ImGui::Text("Vertices: %lu, Triangles: %lu", mesh.positions.size(), + mesh.indices.size()); //ImGui::InputFloat("Resolution", &resolution); ImGui::SliderFloat("Resolution", &resolution, 0.1, 0.001, "%.3f", 0.1); if (ImGui::SliderFloat("Frequency", &densityFrequency, 1, 10, "%.0f", 1)) @@ -546,7 +421,7 @@ void Application::gui() { ImGui::Begin("Rendering"); if (ImGui::Button("Reload Shader")) { loadShader(); - updateVertexArrayObject(); + glMesh.update(vPositionLoc, vNormalLoc, vTexCoordLoc); } if (ImGui::Button("Wireframe")) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); @@ -574,12 +449,9 @@ void Application::run() { glViewport(0, 0, width, height); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_LESS); - glEnable(GL_CULL_FACE); if (meshUploadRequest) { - uploadMesh(); + glMesh.upload(mesh); meshUploadRequest = false; } if (textureUploadRequest) { diff --git a/src/Application.h b/src/Application.h index 6c8efa7..8eaca8f 100644 --- a/src/Application.h +++ b/src/Application.h @@ -4,6 +4,7 @@ #include "Polygoniser.h" #include "TextureMapper.h" #include "ProgressMonitor.h" +#include "gl.h" #include #include @@ -23,18 +24,14 @@ class Application { float textureSize; TextureMapper texturemapper; - unsigned int vertexArrayId, vPositionId, vTexCoordId, vNormalId, - indexBufferId, programId, tAlbedoId, tNormalId, tRoughnessId, - tMetalicId; + int vPositionLoc, vTexCoordLoc, vNormalLoc; + unsigned int programId, tAlbedoId, tNormalId, tRoughnessId, tMetalicId; int MVPloc, Vloc, Mloc, MVloc, LightPosition_worldspaceloc; - int vPositionLoc, vTexCoordLoc, vNormalLoc, tAlbedoLoc, tNormalLoc, - tRoughnessLoc, tMetalicLoc; + int tAlbedoLoc, tNormalLoc, tRoughnessLoc, tMetalicLoc; - vec3v_t vertices; - vec3v_t normals; - vec2v_t texcoords; - uvec3v_t indices; + Mesh mesh; + GLMesh glMesh; size_t meteoridCount; float meteroidMinRadius; diff --git a/src/Mesh.cpp b/src/Mesh.cpp index 5d278f5..8069d25 100644 --- a/src/Mesh.cpp +++ b/src/Mesh.cpp @@ -1,10 +1,12 @@ #include "Mesh.h" +#include "gl.h" #include #include #include #include +#include using namespace std; using namespace glm; @@ -12,11 +14,59 @@ using namespace glm; static const uvec3::value_type InvalidIndex = numeric_limits::max(); -void calculateVertexNormals(const vec3v_t &positions, uvec3v_t &indices, - vec3v_t &normals) { +Mesh::Mesh() { + +} +Mesh::Mesh(Mesh &other) { + positions = other.positions; + normals = other.normals; + texcoords = other.texcoords; + + faceNormals = other.faceNormals; + indices = other.indices; + patches = other.patches; + edges = other.edges; + + adjacents = other.adjacents; + tangents = other.tangents; + bitangents = other.bitangents; +} + +Mesh::Mesh(Mesh &&other) { + positions.swap(other.positions); + normals.swap(other.normals); + texcoords.swap(other.texcoords); + + faceNormals.swap(other.faceNormals); + indices.swap(other.indices); + patches.swap(other.patches); + edges.swap(other.edges); + + adjacents.swap(other.adjacents); + tangents.swap(other.tangents); + bitangents.swap(other.bitangents); +} + +Mesh& Mesh::operator=(Mesh &&other) { + positions.swap(other.positions); + normals.swap(other.normals); + texcoords.swap(other.texcoords); + + faceNormals.swap(other.faceNormals); + indices.swap(other.indices); + patches.swap(other.patches); + edges.swap(other.edges); + + adjacents.swap(other.adjacents); + tangents.swap(other.tangents); + bitangents.swap(other.bitangents); + return *this; +} + +void Mesh::generateNormals() { normals.clear(); normals.resize(positions.size(), vec3(0)); - #pragma omp parallel for +#pragma omp parallel for for (size_t i = 0; i < indices.size(); i++) { int a = indices[i].x, b = indices[i].y, c = indices[i].z; vec3 faceNormal = normalize( @@ -31,99 +81,19 @@ void calculateVertexNormals(const vec3v_t &positions, uvec3v_t &indices, } -void calculateFaceNormals(const vec3v_t &positions, uvec3v_t &indices, - vec3v_t &normals) { - normals.clear(); - normals.resize(indices.size(), vec3(uninitialize)); - #pragma omp parallel for +void Mesh::generateFaceNormals() { + faceNormals.clear(); + faceNormals.resize(indices.size(), vec3(uninitialize)); +#pragma omp parallel for for (size_t i = 0; i < indices.size(); i++) { int a = indices[i].x, b = indices[i].y, c = indices[i].z; - normals[i] = normalize( + faceNormals[i] = normalize( cross(positions[b] - positions[a], positions[c] - positions[a])); } } -void moveToMean(vec3v_t &positions) { - vec3 mean(0); - for (size_t i = 0; i < positions.size(); i++) { - mean += positions[i]; - } - mean *= vec3(1.f / positions.size()); - for (size_t i = 0; i < positions.size(); i++) { - positions[i] -= mean; - } -} - -void smooth(vec3v_t &positions, const uvec3v_t &indices) { - vec3v_t cogs(positions.size(), vec3(0.f)); - vector valence(positions.size(), 0); - - for (size_t iTri = 0; iTri < indices.size(); iTri++) { - const uvec3 &idx = indices[iTri]; - for (size_t iE = 0; iE < 3; iE++) { - valence[idx[iE]] += 2; - cogs[idx[iE]] += positions[idx[(iE + 1) % 3]]; - cogs[idx[iE]] += positions[idx[(iE + 2) % 3]]; - } - } - /* - for (v_it = mesh.vertices_begin(); v_it != v_end; ++v_it) { - cog[0] = cog[1] = cog[2] = valence = 0.0; - - for (vv_it = mesh.vv_iter(*v_it); vv_it.is_valid(); ++vv_it) { - cog += mesh.point(*vv_it); - ++valence; - } - cogs.push_back(cog / valence); - } - for (v_it = mesh.vertices_begin(), cog_it = cogs.begin(); v_it != v_end; - ++v_it, ++cog_it) - if (!mesh.is_boundary(*v_it)) - mesh.set_point(*v_it, *cog_it); - - */ - #pragma omp parallel for - for (size_t i = 0; i < positions.size(); i++) { -// vtx[i] = vtx[i] * vec3(0.8) -// + cogs[i] * vec3(0.2f / valence[i]); - positions[i] = cogs[i] * vec3(1.f / valence[i]); - } -} - -void saveAttrib(std::ostream &out, const char *prefix, vec3v_t &elements) { - for (size_t i = 0; i < elements.size(); i++) { - out << prefix << elements[i].x << " " << elements[i].y << " " - << elements[i].z << "\n"; - } -} - -void saveAttrib(std::ostream &out, const char *prefix, vec2v_t &elements) { - for (size_t i = 0; i < elements.size(); i++) { - out << prefix << elements[i].x << " " << elements[i].y << "\n"; - } -} - -void saveFaces(std::ostream &out, const uvec3v_t &incdices, size_t attribs) { - for (size_t i = 0; i < incdices.size(); i++) { - out << "f"; - - for (size_t j = 0; j < 3; j++) { - int v = incdices[i][j] + 1; - out << " " << v; - if (attribs > 1) - out << "/" << v; - if (attribs > 2) - out << "/" << v; - out << " "; - } - - out << "\n"; - } -} - -void findEdges(const vec3v_t &positions, const uvec3v_t &indices, - uvec4v_t &edges) { +void Mesh::generateEdges() { edges.clear(); map, uint32_t> edgeMap; for (size_t iTri = 0; iTri < indices.size(); iTri++) { @@ -145,8 +115,7 @@ void findEdges(const vec3v_t &positions, const uvec3v_t &indices, } } -void computeTangentBasis(vec3v_t & positions, vec2v_t & texcoords, - vec3v_t & normals, vec3v_t & tangents, vec3v_t & bitangents) { +void Mesh::generateTangentBasis() { for (size_t i = 0; i < positions.size(); i += 3) { @@ -185,9 +154,8 @@ void computeTangentBasis(vec3v_t & positions, vec2v_t & texcoords, } } -void findAdjacent(const uvec4v_t &edges, size_t nFaces, uvec3v_t &adjacents) { - printf("findAdjacent: %lu\n", nFaces); - adjacents.resize(nFaces, uvec3(InvalidIndex)); +void Mesh::generateAdjacent() { + adjacents.resize(indices.size(), uvec3(InvalidIndex)); for (size_t i = 0; i < edges.size(); i++) { int a = edges[i].z; int b = edges[i].w; @@ -209,14 +177,93 @@ void findAdjacent(const uvec4v_t &edges, size_t nFaces, uvec3v_t &adjacents) { } } -void createPatches(const vec3v_t &positions, const uvec3v_t &indices, - const vec3v_t &faceNormals, const uvec3v_t &adjacents, - vec3v_t &oPositions, uvec3v_t &oIndices, uintv_t &patches, - float threshold) { +void Mesh::moveToMean() { + vec3 mean(0); + for (size_t i = 0; i < positions.size(); i++) { + mean += positions[i]; + } + mean *= vec3(1.f / positions.size()); + for (size_t i = 0; i < positions.size(); i++) { + positions[i] -= mean; + } +} + +void Mesh::smooth() { + if (positions.size() == 0 || indices.size() == 0) + return; + + vec3v_t cogs(positions.size(), vec3(0.f)); + vector valence(positions.size(), 0); + + for (size_t iTri = 0; iTri < indices.size(); iTri++) { + const uvec3 &idx = indices[iTri]; + for (size_t iE = 0; iE < 3; iE++) { + valence[idx[iE]] += 2; + cogs[idx[iE]] += positions[idx[(iE + 1) % 3]]; + cogs[idx[iE]] += positions[idx[(iE + 2) % 3]]; + } + } + /* + for (v_it = mesh.vertices_begin(); v_it != v_end; ++v_it) { + cog[0] = cog[1] = cog[2] = valence = 0.0; + + for (vv_it = mesh.vv_iter(*v_it); vv_it.is_valid(); ++vv_it) { + cog += mesh.point(*vv_it); + ++valence; + } + cogs.push_back(cog / valence); + } + for (v_it = mesh.vertices_begin(), cog_it = cogs.begin(); v_it != v_end; + ++v_it, ++cog_it) + if (!mesh.is_boundary(*v_it)) + mesh.set_point(*v_it, *cog_it); + + */ +#pragma omp parallel for + for (size_t i = 0; i < positions.size(); i++) { +// vtx[i] = vtx[i] * vec3(0.8) +// + cogs[i] * vec3(0.2f / valence[i]); + positions[i] = cogs[i] * vec3(1.f / valence[i]); + } +} + +void Mesh::saveAttrib(std::ostream &out, const char *prefix, + const vec3v_t &elements) const { + for (size_t i = 0; i < elements.size(); i++) { + out << prefix << elements[i].x << " " << elements[i].y << " " + << elements[i].z << "\n"; + } +} + +void Mesh::saveAttrib(std::ostream &out, const char *prefix, + const vec2v_t &elements) const { + for (size_t i = 0; i < elements.size(); i++) { + out << prefix << elements[i].x << " " << elements[i].y << "\n"; + } +} + +void Mesh::saveFaces(std::ostream &out, const uvec3v_t &incdices, + size_t attribs) const { + for (size_t i = 0; i < incdices.size(); i++) { + out << "f"; + + for (size_t j = 0; j < 3; j++) { + int v = incdices[i][j] + 1; + out << " " << v; + if (attribs > 1) + out << "/" << v; + if (attribs > 2) + out << "/" << v; + out << " "; + } + + out << "\n"; + } +} + +Mesh Mesh::createPatched(float threshold) const { assert(adjacents.size() == indices.size()); - patches.clear(); - oPositions.clear(); - oIndices.clear(); + Mesh mesh; vector processed(indices.size(), false); for (size_t i = 0; i < indices.size(); i++) { @@ -251,18 +298,39 @@ void createPatches(const vec3v_t &positions, const uvec3v_t &indices, for (size_t k = 0; k < 3; k++) { auto it = vertexMap.find(idx[k]); if (it == vertexMap.end()) { - uint32_t newIdx = oPositions.size(); - oPositions.push_back(positions[idx[k]]); + uint32_t newIdx = mesh.positions.size(); + mesh.positions.push_back(positions[idx[k]]); + if (normals.size()) + mesh.normals.push_back(normals[idx[k]]); vertexMap[idx[k]] = newIdx; idx[k] = newIdx; } else { idx[k] = it->second; } } - oIndices.push_back(idx); + mesh.indices.push_back(idx); } printf("\n"); } - + return mesh; +} + +void Mesh::save(std::ostream &out) const { + size_t nAttribs = 1; + saveAttrib(out, "v ", positions); + if (normals.size()) { + nAttribs++; + saveAttrib(out, "vn ", normals); + } + if (texcoords.size()) { + nAttribs++; + saveAttrib(out, "vt ", texcoords); + } + saveFaces(out, indices, nAttribs); +} + +void Mesh::save(std::string filename) const { + std::ofstream out(filename.c_str()); + save(out); } diff --git a/src/Mesh.h b/src/Mesh.h index 1cc4083..fc94e7c 100644 --- a/src/Mesh.h +++ b/src/Mesh.h @@ -5,31 +5,43 @@ #include #include -void calculateVertexNormals(const vec3v_t &positions, uvec3v_t &indices, - vec3v_t &normals); -void calculateFaceNormals(const vec3v_t &positions, uvec3v_t &indices, - vec3v_t &normals); -void findEdges(const vec3v_t &positions, const uvec3v_t &indices, - uvec4v_t &edges); -//void createPatches(const vec3v_t &positions, const uvec3v_t &indices, -// const uvec4v_t &edges, vec3v_t &oPositions, uvec3v_t &oIndices, -// uvec4v_t &oEdges, uintv_t &patches, float threshold); +struct Mesh { + vec3v_t positions; + vec3v_t normals; + vec2v_t texcoords; -void moveToMean(vec3v_t &positions); + vec3v_t faceNormals; + uvec3v_t indices; + uintv_t patches; + uvec4v_t edges; + uvec3v_t adjacents; + vec3v_t tangents; + vec3v_t bitangents; -void smooth(vec3v_t &positions, const uvec3v_t &indices); + Mesh(); + Mesh(Mesh &other); + Mesh(Mesh &&other); -void saveAttrib(std::ostream &out, const char *prefix, vec3v_t &elements); + Mesh& operator=(Mesh&&); -void saveAttrib(std::ostream &out, const char *prefix, vec2v_t &elements); + void generateNormals(); + void generateTangentBasis(); -void saveFaces(std::ostream &out, const uvec3v_t &indicess, size_t attributes); + void generateAdjacent(); + void generateFaceNormals(); + void generateEdges(); -void findAdjacent(const uvec4v_t &edges, size_t nFaces, uvec3v_t &adjacents); + void moveToMean(); + void smooth(); -void computeTangentBasis(vec3v_t & vertices, vec2v_t & texcoords, - vec3v_t & normals, vec3v_t & tangents, vec3v_t & bitangents); -void createPatches(const vec3v_t &positions, const uvec3v_t &indices, - const vec3v_t &faceNormals, const uvec3v_t &adjacents, - vec3v_t &oPositions, uvec3v_t &oIndices, uintv_t &patches, - float threshold); + Mesh createPatched(float threshold) const; + + void saveAttrib(std::ostream &out, const char *prefix, + const vec3v_t &elements) const; + void saveAttrib(std::ostream &out, const char *prefix, + const vec2v_t &elements) const; + void saveFaces(std::ostream &out, const uvec3v_t &indicess, + size_t attributes) const; + void save(std::ostream &out) const; + void save(std::string filename) const; +}; diff --git a/src/Polygoniser.cpp b/src/Polygoniser.cpp index ffe6a47..be0d248 100644 --- a/src/Polygoniser.cpp +++ b/src/Polygoniser.cpp @@ -114,7 +114,7 @@ void Polygonizer::polygonize(const vec3 &lower, const vec3 &upper, for (int iTri = 0; iTri < nTris; iTri++) { vec3 *ps = tris[iTri].p; - // skip degenerate vertices + // skip degenerate positions if (all(epsilonEqual(ps[0], ps[1], 1e-8f)) || all(epsilonEqual(ps[0], ps[2], 1e-8f)) || all(epsilonEqual(ps[2], ps[1], 1e-8f))) @@ -128,8 +128,8 @@ void Polygonizer::polygonize(const vec3 &lower, const vec3 &upper, if (vit != vertexLookup.end()) { idc[k] = vit->second; } else { - idc[k] = vertices.size(); - vertices.push_back(p); + idc[k] = positions.size(); + positions.push_back(p); vertexLookup[p] = idc[k]; } } @@ -142,7 +142,7 @@ void Polygonizer::polygonize(const vec3 &lower, const vec3 &upper, void Polygonizer::polygonize(float resolution) { vertexLookup.clear(); - vertices.clear(); + positions.clear(); indices.clear(); const float isocellSize = 1.f / isocells; @@ -187,11 +187,11 @@ void Polygonizer::calculateLayer(std::vector &layer, float resolution, void Polygonizer::polygonize(float resolution, ProgressMonitor &progress) { vertexLookup.clear(); - vertices.clear(); - indices.clear(); + mesh.positions.clear(); + mesh.indices.clear(); - vertices.reserve(pow(1. / resolution, 2) * 8); - indices.reserve(pow(1. / resolution, 2) * 8); + mesh.positions.reserve(pow(1. / resolution, 2) * 8); + mesh.indices.reserve(pow(1. / resolution, 2) * 8); size_t nSteps = 1.f / resolution; size_t nSamples = nSteps + 1; @@ -258,7 +258,7 @@ void Polygonizer::polygonize(float resolution, ProgressMonitor &progress) { for (int iTri = 0; iTri < nTris; iTri++) { vec3 *ps = tris[iTri].p; - // skip degenerate vertices + // skip degenerate positions if (all(epsilonEqual(ps[0], ps[1], 1e-8f)) || all(epsilonEqual(ps[0], ps[2], 1e-8f)) || all(epsilonEqual(ps[2], ps[1], 1e-8f))) @@ -272,12 +272,12 @@ void Polygonizer::polygonize(float resolution, ProgressMonitor &progress) { if (vit != vertexLookup.end()) { idc[k] = vit->second; } else { - idc[k] = vertices.size(); - vertices.push_back(p); + idc[k] = mesh.positions.size(); + mesh.positions.push_back(p); vertexLookup[p] = idc[k]; } } - indices.push_back(idc); + mesh.indices.push_back(idc); } } } @@ -287,7 +287,7 @@ void Polygonizer::polygonize(float resolution, ProgressMonitor &progress) { //void Polygonizer::polygonize(float resolution) { // vertexLookup.clear(); -// vertices.clear(); +// positions.clear(); // indices.clear(); // // size_t nSteps = 1.f / resolution; @@ -329,7 +329,7 @@ void Polygonizer::polygonize(float resolution, ProgressMonitor &progress) { // for (int iTri = 0; iTri < nTris; iTri++) { // vec3 *ps = tris[iTri].p; // -// // skip degenerate vertices +// // skip degenerate positions // if (all(epsilonEqual(ps[0], ps[1], 1e-8f)) // || all(epsilonEqual(ps[0], ps[2], 1e-8f)) // || all(epsilonEqual(ps[2], ps[1], 1e-8f))) @@ -343,8 +343,8 @@ void Polygonizer::polygonize(float resolution, ProgressMonitor &progress) { // if (vit != vertexLookup.end()) { // idc[k] = vit->second; // } else { -// idc[k] = vertices.size(); -// vertices.push_back(p); +// idc[k] = positions.size(); +// positions.push_back(p); // vertexLookup[p] = idc[k]; // } // } diff --git a/src/Polygoniser.h b/src/Polygoniser.h index de4d98e..34c4fcc 100644 --- a/src/Polygoniser.h +++ b/src/Polygoniser.h @@ -3,7 +3,7 @@ #include #include -#include "types.h" +#include "Mesh.h" #include "Density.h" #include "ProgressMonitor.h" @@ -47,8 +47,7 @@ class Polygonizer { void calculateLayer(std::vector &layer, float resolution, size_t nSamples, float z); public: - vec3v_t vertices; - uvec3v_t indices; + Mesh mesh; std::map vertexLookup; diff --git a/src/SkyBox.cpp b/src/SkyBox.cpp index 722ba0c..9e0fa25 100644 --- a/src/SkyBox.cpp +++ b/src/SkyBox.cpp @@ -6,7 +6,8 @@ using namespace std; -SkyBox::SkyBox() { +SkyBox::SkyBox() : + textureId(GL_INVALID_INDEX), programId(GL_INVALID_INDEX) { glGenTextures(1, &textureId); } @@ -55,19 +56,19 @@ void SkyBox::Render() { glCullFace(GL_FRONT); glDepthFunc(GL_LEQUAL); -/* - Pipeline p; - p.Scale(20.0f, 20.0f, 20.0f); - p.Rotate(0.0f, 0.0f, 0.0f); - p.WorldPos(m_pCamera->GetPos().x, m_pCamera->GetPos().y, - m_pCamera->GetPos().z); - p.SetCamera(m_pCamera->GetPos(), m_pCamera->GetTarget(), - m_pCamera->GetUp()); - p.SetPerspectiveProj(m_persProjInfo); - m_pSkyboxTechnique->SetWVP(p.GetWVPTrans()); - m_pCubemapTex->Bind(GL_TEXTURE0); - m_pMesh->Render(); -*/ + /* + Pipeline p; + p.Scale(20.0f, 20.0f, 20.0f); + p.Rotate(0.0f, 0.0f, 0.0f); + p.WorldPos(m_pCamera->GetPos().x, m_pCamera->GetPos().y, + m_pCamera->GetPos().z); + p.SetCamera(m_pCamera->GetPos(), m_pCamera->GetTarget(), + m_pCamera->GetUp()); + p.SetPerspectiveProj(m_persProjInfo); + m_pSkyboxTechnique->SetWVP(p.GetWVPTrans()); + m_pCubemapTex->Bind(GL_TEXTURE0); + m_pMesh->Render(); + */ glCullFace(OldCullFaceMode); glDepthFunc(OldDepthFuncMode); } diff --git a/src/gl.h b/src/gl.h new file mode 100644 index 0000000..6d06396 --- /dev/null +++ b/src/gl.h @@ -0,0 +1,121 @@ +#pragma once + +#include +#include + +#include "types.h" + +static bool glck(const char* call) { + int err = glGetError(); + if (err == 0) { + return true; + } else { + switch (err) { + case GL_INVALID_VALUE: + printf("GL_INVALID_VALUE: %s\n", call); + break; + case GL_INVALID_ENUM: + printf("GL_INVALID_ENUM: %s\n", call); + break; + case GL_INVALID_OPERATION: + printf("GL_INVALID_OPERATION: %s\n", call); + break; + default: + printf("UNKNOWN Error: %s\n", call); + } + return false; + } +} + +#define GLCK(a) {a; assert(glck(#a));} + +class GLMesh { + unsigned int vertexArrayId, vPositionId, vTexCoordId, vNormalId, + indexBufferId; + unsigned int indexCount; + +public: + + GLMesh() : + vertexArrayId(0), vPositionId(0), vTexCoordId(0), vNormalId(0), indexBufferId( + 0), indexCount(0) { + + } + + ~GLMesh() { + GLCK(glDeleteBuffers(1, &vPositionId)) + GLCK(glDeleteBuffers(1, &vTexCoordId)) + GLCK(glDeleteBuffers(1, &vNormalId)) + GLCK(glDeleteBuffers(1, &indexBufferId)) + GLCK(glDeleteVertexArrays(1, &vertexArrayId)) + } + + void create() { + GLCK(glGenVertexArrays(1, &vertexArrayId)) + GLCK(glGenBuffers(1, &vPositionId)) + GLCK(glGenBuffers(1, &vTexCoordId)) + GLCK(glGenBuffers(1, &vNormalId)) + GLCK(glGenBuffers(1, &indexBufferId)) + } + + void upload(const Mesh &mesh) { + printf("upload mesh\n"); + GLCK(glBindVertexArray(vertexArrayId)) + + GLCK(glBindBuffer(GL_ARRAY_BUFFER, vPositionId)) + GLCK( + glBufferData(GL_ARRAY_BUFFER, mesh.positions.size() * sizeof(glm::vec3), mesh.positions.data(), GL_STATIC_DRAW)) + + GLCK(glBindBuffer(GL_ARRAY_BUFFER, vTexCoordId)) + GLCK( + glBufferData(GL_ARRAY_BUFFER, mesh.texcoords.size() * sizeof(glm::vec2), mesh.texcoords.data(), GL_STATIC_DRAW)) + + GLCK(glBindBuffer(GL_ARRAY_BUFFER, vNormalId)) + GLCK( + glBufferData(GL_ARRAY_BUFFER, mesh.normals.size() * sizeof(glm::vec3), mesh.normals.data(), GL_STATIC_DRAW)) + + GLCK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferId)) + GLCK( + glBufferData(GL_ELEMENT_ARRAY_BUFFER, mesh.indices.size() * sizeof(glm::uvec3), mesh.indices.data(), GL_STATIC_DRAW)) + + GLCK(glBindVertexArray(0)) + + indexCount = mesh.indices.size() * 3; + } + + void render() { + GLCK(glBindVertexArray(vertexArrayId)) + GLCK( + glDrawElements(GL_TRIANGLES, indexCount, GL_UNSIGNED_INT, (void* ) 0)) + GLCK(glBindVertexArray(0)) + + } + + bool bindVertexAttrib(GLuint id, GLint loc, GLuint size) const { + if (loc < 0) { + GLCK(glDisableVertexAttribArray(loc)) + } else { + GLCK(glBindBuffer(GL_ARRAY_BUFFER, id)) + GLCK(glEnableVertexAttribArray(loc)) + GLCK(glVertexAttribPointer(loc, // attribute + size,// size + GL_FLOAT,// type + GL_FALSE,// normalized? + 0,// stride + (void* ) 0// array buffer offset + )) + } + return true; + } + + void update(int vPositionLoc, int vNormalLoc, int vTexCoordLoc) const { + GLCK(glBindVertexArray(vertexArrayId)) + + bindVertexAttrib(vPositionId, vPositionLoc, 3); + bindVertexAttrib(vNormalId, vNormalLoc, 3); + bindVertexAttrib(vTexCoordId, vTexCoordLoc, 2); + + GLCK(glBindVertexArray(0)) + } +}; + diff --git a/src/types.h b/src/types.h index 27cc5b0..cbcdbcd 100644 --- a/src/types.h +++ b/src/types.h @@ -3,6 +3,7 @@ #include "AlignedAllocator.h" #include #include +#include #include typedef glm::tvec4 ucvec4_t;