#include "Density.h" #include "Polygoniser.h" #include #include #include #include #include #include #include #include #include #include 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));} // ! https://learnopengl.com/#!PBR/Lighting static const char* vertex_shader_text = "#version 130\n" "uniform mat4 MVP;\n" "in vec3 vPos;\n" "in vec3 vNorm;\n" "out vec3 normal;\n" "void main()\n" "{\n" " gl_Position = MVP * vec4(vPos, 1.0);\n" " normal = normalize(vNorm);\n" "}\n"; static const char* fragment_shader_text = "#version 130\n" "in vec3 normal;\n" "out vec4 color;\n" "void main()\n" "{\n" " color = normal.y * vec4(1.0, 0.95, 0.9, 1.0);\n" "}\n"; static void error_callback(int error, const char* description) { fprintf(stderr, "Error: %s\n", description); } static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) { if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) glfwSetWindowShouldClose(window, GLFW_TRUE); } void checkShader(GLuint vertexShader, const std::string &name) { GLint status; glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &status); if (status == GL_FALSE) { std::cout << "Shader '" << name << "' compiled with an error(s):" << std::endl; char buffer[512]; int l; glGetShaderInfoLog(vertexShader, 512, &l, buffer); buffer[l] = 0; std::cout << buffer << std::endl; } } void checkProgam(GLuint vertexShader, const std::string &name) { GLint status; glGetProgramiv(vertexShader, GL_LINK_STATUS, &status); if (status == GL_FALSE) { std::cout << "Program '" << name << "' failed with an error(s):" << std::endl; char buffer[512]; int l; glGetProgramInfoLog(vertexShader, 512, &l, buffer); buffer[l] = 0; std::cout << buffer << std::endl; } } void calculateNormals(const std::vector &vtx, std::vector &tri, std::vector &normals) { normals.clear(); normals.resize(vtx.size(), glm::vec3(0)); for (size_t i = 0; i < tri.size(); i++) { int a = tri[i].x, b = tri[i].y, c = tri[i].z; glm::vec3 faceNormal = normalize( glm::cross(vtx[b] - vtx[a], vtx[c] - vtx[a])); normals[a] += faceNormal; normals[b] += faceNormal; normals[c] += faceNormal; } for (size_t i = 0; i < normals.size(); i++) normals[i] = glm::normalize(normals[i]); } void moveToMean(std::vector &vtx) { glm::vec3 mean(0); for (size_t i = 0; i < vtx.size(); i++) { mean += vtx[i]; } mean *= glm::vec3(1.f / vtx.size()); for (size_t i = 0; i < vtx.size(); i++) { vtx[i] -= mean; } } void smooth(std::vector &vtx, const std::vector &tri) { std::vector cogs(vtx.size(), glm::vec3(0.f)); std::vector valence(vtx.size(), 0); for (size_t iTri = 0; iTri < tri.size(); iTri++) { const glm::uvec3 &idx = tri[iTri]; for (size_t iE = 0; iE < 3; iE++) { valence[idx[iE]] += 2; cogs[idx[iE]] += vtx[idx[(iE + 1) % 3]]; cogs[idx[iE]] += vtx[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); */ for (size_t i = 0; i < vtx.size(); i++) { // vtx[i] = vtx[i] * glm::vec3(0.8) // + cogs[i] * glm::vec3(0.2f / valence[i]); vtx[i] = cogs[i] * glm::vec3(1.f / valence[i]); } } void saveAttrib(std::ostream &out, const char *prefix, std::vector &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, std::vector &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 std::vector &tris, size_t attribs) { for (size_t i = 0; i < tris.size(); i++) { out << "f"; for (size_t j = 0; j < 3; j++) { int v = tris[i][j] + 1; out << " " << v; if (attribs > 1) out << "/" << v; if (attribs > 2) out << "/" << v; out << " "; } out << "\n"; } } void calculateEdges(const std::vector &vtx, std::vector &tri, std::vector &edges) { edges.clear(); } int main(void) { std::srand(123); Density density; density.addRandomImpacts(1000, 0.2, 0.01, 0.005, 0.2, 4096); //density.saveCrossSection("density.png", 512); Polygonizer polygonizer(density); polygonizer.polygonize(0.2, 1. / 20.); moveToMean(polygonizer.vertices); { std::ofstream out("stage1.obj"); saveAttrib(out, "v ", polygonizer.vertices); saveFaces(out, polygonizer.triangles, 1); } smooth(polygonizer.vertices, polygonizer.triangles); { std::ofstream out("stage2.obj"); saveAttrib(out, "v ", polygonizer.vertices); saveFaces(out, polygonizer.triangles, 1); } std::vector normals; calculateNormals(polygonizer.vertices, polygonizer.triangles, normals); { std::ofstream out("stage3.obj"); saveAttrib(out, "v ", polygonizer.vertices); saveAttrib(out, "vn ", normals); saveFaces(out, polygonizer.triangles, 2); } std::vector edges; std::cout << "Vertices: " << polygonizer.vertices.size() << std::endl; std::cout << "Triangles: " << polygonizer.triangles.size() << std::endl; GLFWwindow* window; GLuint vertex_array, vertex_buffer, index_buffer, normal_buffer, vertex_shader, fragment_shader, program; GLint mvp_location, vpos_location, vnorm_location; glfwSetErrorCallback(error_callback); if (!glfwInit()) exit(EXIT_FAILURE); // glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); //glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_COMPAT_PROFILE); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1); window = glfwCreateWindow(640, 480, "Simple example", NULL, NULL); if (!window) { glfwTerminate(); exit(EXIT_FAILURE); } glfwSetKeyCallback(window, key_callback); glfwMakeContextCurrent(window); gladLoadGLLoader((GLADloadproc) glfwGetProcAddress); glfwSwapInterval(1); std::cout << "OpenGL version: " << glGetString(GL_VERSION) << std::endl; std::cout << "GLSL version: " << glGetString(GL_SHADING_LANGUAGE_VERSION) << std::endl; std::cout << "Vendor: " << glGetString(GL_VENDOR) << std::endl; std::cout << "Renderer: " << glGetString(GL_RENDERER) << std::endl; // NOTE: OpenGL error checks have been omitted for brevity // glGenBuffers(1, &vertex_buffer); // glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer); // glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); GLCK(glGenVertexArrays(1, &vertex_array)) GLCK(glBindVertexArray(vertex_array)) GLCK(glGenBuffers(1, &vertex_buffer)) GLCK(glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer)) GLCK( glBufferData(GL_ARRAY_BUFFER, polygonizer.vertices.size() * sizeof(glm::vec3), polygonizer.vertices.data(), GL_STATIC_DRAW)) GLCK(glGenBuffers(1, &index_buffer)) GLCK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer)) GLCK( glBufferData(GL_ELEMENT_ARRAY_BUFFER, polygonizer.triangles.size() * sizeof(glm::uvec3), polygonizer.triangles.data(), GL_STATIC_DRAW)) GLCK(glGenBuffers(1, &normal_buffer)) GLCK(glBindBuffer(GL_ARRAY_BUFFER, normal_buffer)) GLCK( glBufferData(GL_ARRAY_BUFFER, normals.size() * sizeof(glm::vec3), normals.data(), GL_STATIC_DRAW)) GLCK(vertex_shader = glCreateShader(GL_VERTEX_SHADER)) GLCK(glShaderSource(vertex_shader, 1, &vertex_shader_text, NULL)) GLCK(glCompileShader(vertex_shader)) checkShader(vertex_shader, "vertex"); GLCK(fragment_shader = glCreateShader(GL_FRAGMENT_SHADER)) GLCK(glShaderSource(fragment_shader, 1, &fragment_shader_text, NULL)) GLCK(glCompileShader(fragment_shader)) checkShader(fragment_shader, "fragment"); GLCK(program = glCreateProgram()) GLCK(glAttachShader(program, vertex_shader)) GLCK(glAttachShader(program, fragment_shader)) GLCK(glLinkProgram(program)) checkProgam(program, "program"); GLCK(mvp_location = glGetUniformLocation(program, "MVP")) std::cout << mvp_location << std::endl; GLCK(vpos_location = glGetAttribLocation(program, "vPos")) std::cout << vpos_location << std::endl; GLCK(vnorm_location = glGetAttribLocation(program, "vNorm")) std::cout << vnorm_location << std::endl; GLCK(glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer)) glEnableVertexAttribArray(vpos_location); GLCK( glVertexAttribPointer(vpos_location, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0)) if (vnorm_location >= 0) { GLCK(glBindBuffer(GL_ARRAY_BUFFER, normal_buffer)) GLCK(glEnableVertexAttribArray(vnorm_location)) GLCK( glVertexAttribPointer(vnorm_location, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0)) } ImGui_ImplGlfwGL3_Init(window, true); while (!glfwWindowShouldClose(window)) { glfwPollEvents(); ImGui_ImplGlfwGL3_NewFrame(); { static float f = 0.0f; static float resolution = 0.1f; ImGui::Text("Hello, world!"); if (ImGui::Button("Wireframe")) glPolygonMode( GL_FRONT_AND_BACK, GL_LINE); if (ImGui::Button("Fill")) glPolygonMode( GL_FRONT_AND_BACK, GL_FILL); ImGui::InputFloat("Resolution", &resolution); ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); } int width, height; glm::mat4 m(1.0f), p, mvp(2); glfwGetFramebufferSize(window, &width, &height); float ratio = width / (float) height; glViewport(0, 0, width, height); glClear(GL_COLOR_BUFFER_BIT); m = glm::rotate(m, (float) glfwGetTime(), glm::vec3(0.f, 0.f, 1.f)); //m = glm::translate(m, glm::vec3(-1.f)); //glm::translate(mvp, glm::vec3((float) glfwGetTime())); p = glm::ortho(-1.f, 1.f, -1.f, 1.f); mvp = p * m; GLCK(glUseProgram(program)) GLCK( glUniformMatrix4fv(mvp_location, 1, GL_FALSE, (const GLfloat*) &mvp)) // Draw the triangles ! GLCK(glBindVertexArray(vertex_array)) glDrawElements( GL_TRIANGLES, polygonizer.triangles.size() * 3, GL_UNSIGNED_INT, (void*) 0); //GLCK(glDrawArrays( GL_TRIANGLES, 0, polygonizer.triangles.size() * 3)) ImGui::Render(); glfwSwapBuffers(window); } glfwDestroyWindow(window); ImGui_ImplGlfwGL3_Shutdown(); glfwTerminate(); }