#include "mesh.h" BEGIN_NAMESPACE constexpr char *BUFFER_OFFSET(int i) { return (char *) NULL + i * sizeof(float); } constexpr int componentsInVertex() { return 3 + 3 + 2; // position, normal, uv } constexpr int sizeOfVertexInBytes() { return componentsInVertex() * sizeof(float); } mesh::mesh() { } mesh::~mesh() { if (initialized) { glDeleteVertexArrays(1, &vao_id); glDeleteBuffers(1, &vbo_id); } } void mesh::render(bool flat_shaded) { if (!initialized) { glGenVertexArrays(1, &vao_id); glGenBuffers(1, &vbo_id); initialized = true; } // construct data if ((facets.size() * 3) > vbo_size_in_elements) { delete[] vbo_data; vbo_data = new float[componentsInVertex() * facets.size() * 3]; vbo_size_in_elements = facets.size() * 3; } // fill in buffer size_t i = 0; size_t face_index = 0; for (auto& f: facets) { for (int j = 0; j < 3; j++) { vbo_data[i++] = vertices[f.vertices[j]].position.x; vbo_data[i++] = vertices[f.vertices[j]].position.y; vbo_data[i++] = vertices[f.vertices[j]].position.z; if (flat_shaded) { vbo_data[i++] = f.normal.x; vbo_data[i++] = f.normal.y; vbo_data[i++] = f.normal.z; } else { vbo_data[i++] = vertices[f.vertices[j]].normal.x; vbo_data[i++] = vertices[f.vertices[j]].normal.y; vbo_data[i++] = vertices[f.vertices[j]].normal.z; } vbo_data[i++] = f.text_coords[j].x; vbo_data[i++] = f.text_coords[j].y; } face_index++; } glBindVertexArray(vao_id); glBindBuffer(GL_ARRAY_BUFFER, vbo_id); glBufferData(GL_ARRAY_BUFFER, sizeOfVertexInBytes() * facets.size() * 3, vbo_data, GL_DYNAMIC_DRAW); glEnableVertexAttribArray(0); // vertices on stream 0 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeOfVertexInBytes(), BUFFER_OFFSET(0)); glEnableVertexAttribArray(1); // normals on stream 1 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeOfVertexInBytes(), BUFFER_OFFSET(3)); glEnableVertexAttribArray(2); // text coords on stream 2 glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeOfVertexInBytes(), BUFFER_OFFSET(6)); glDrawArrays(GL_TRIANGLES, 0, facets.size() * 3); glDisableVertexAttribArray(2); glDisableVertexAttribArray(1); glDisableVertexAttribArray(0); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); } void mesh::merge(mesh& mesh) { vertices.reserve(vertices.size() + mesh.vertices.size()); vertices.insert(vertices.end(), mesh.vertices.begin(), mesh.vertices.end()); auto original_facet_count = facets.size(); facets.reserve(facets.size() + mesh.facets.size()); for (auto& f: mesh.facets) { facet new_f = f; new_f.a += original_facet_count; new_f.b += original_facet_count; new_f.c += original_facet_count; facets.push_back(new_f); } size_t original_edge_count = edges.size(); edges.reserve(edges.size() + mesh.edges.size()); for (auto& e: mesh.edges) { edge new_edge = e; new_edge.from += original_edge_count; new_edge.to += original_edge_count; edges.push_back(new_edge); } } void mesh::copy(mesh& mesh) { vertices = mesh.vertices; facets = mesh.facets; edges = mesh.edges; } void calculate_normals(mesh& mesh) { for (auto& vertex: mesh.vertices) vertex.normal = glm::vec3(0); for (auto& facet: mesh.facets) { glm::vec3 a = mesh.vertices[facet.b].position - mesh.vertices[facet.a].position; glm::vec3 b = mesh.vertices[facet.c].position - mesh.vertices[facet.a].position; facet.normal = cross(a, b); if (length(facet.normal) > 0.00001) { facet.normal = normalize(facet.normal); } mesh.vertices[facet.a].normal += facet.normal; mesh.vertices[facet.b].normal += facet.normal; mesh.vertices[facet.c].normal += facet.normal; } for (auto& vertex: mesh.vertices) vertex.normal = normalize(vertex.normal); } void flip_normals(mesh& mesh) { for (auto& vertex: mesh.vertices) vertex.normal = -vertex.normal; for (auto& facet: mesh.facets) facet.normal = -facet.normal; } END_NAMESPACE