From 06defeae26c28589e56d33308d437d87f2f4b681 Mon Sep 17 00:00:00 2001 From: Adrian Scripca Date: Sat, 23 Apr 2022 16:52:26 +0300 Subject: [PATCH] Added mesh --- src/CMakeLists.txt | 3 + src/mesh.cpp | 148 +++++++++++++++++++++++++++++++++++++++++++++ src/mesh.h | 52 ++++++++++++++++ src/shader.cpp | 8 +-- src/shader.h | 3 +- 5 files changed, 207 insertions(+), 7 deletions(-) create mode 100644 src/mesh.cpp create mode 100644 src/mesh.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3be11bb..fd7ef6b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -2,6 +2,7 @@ set(HEADERS ${HEADERS} ${CMAKE_CURRENT_SOURCE_DIR}/colour.h ${CMAKE_CURRENT_SOURCE_DIR}/fbo.h + ${CMAKE_CURRENT_SOURCE_DIR}/mesh.h ${CMAKE_CURRENT_SOURCE_DIR}/peripherals.h ${CMAKE_CURRENT_SOURCE_DIR}/peripherals_glfw.h ${CMAKE_CURRENT_SOURCE_DIR}/shader.h @@ -9,9 +10,11 @@ set(HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/texture_generator.h PARENT_SCOPE ) + set(SOURCE ${SOURCE} ${CMAKE_CURRENT_SOURCE_DIR}/fbo.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/mesh.cpp ${CMAKE_CURRENT_SOURCE_DIR}/peripherals_glfw.cpp ${CMAKE_CURRENT_SOURCE_DIR}/shader.cpp ${CMAKE_CURRENT_SOURCE_DIR}/texture.cpp diff --git a/src/mesh.cpp b/src/mesh.cpp new file mode 100644 index 0000000..f99494b --- /dev/null +++ b/src/mesh.cpp @@ -0,0 +1,148 @@ +#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) { + + if (vbo_data != nullptr) + delete[] vbo_data; + + vbo_data = new float[componentsInVertex() * facets.size() * 3]; + vbo_size_in_elements = facets.size() * 3; + } + + // fill in buffer + int i = 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; + } + } + + 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 \ No newline at end of file diff --git a/src/mesh.h b/src/mesh.h new file mode 100644 index 0000000..1c2c42f --- /dev/null +++ b/src/mesh.h @@ -0,0 +1,52 @@ +#pragma once + +#include "defines.h" +#include "glm/glm.hpp" +#include + +BEGIN_NAMESPACE + +struct vertex { + glm::vec3 position; + glm::vec3 normal; +}; + +struct facet { + union { + struct { + size_t a, b, c; + }; + size_t vertices[3]; + }; + glm::vec3 normal; + glm::vec2 text_coords[3]; +}; + +struct edge { + size_t from; + size_t to; +}; + +struct mesh { + mesh(); + ~mesh(); + + std::vector vertices; + std::vector facets; + std::vector edges; + + void render(bool flat_shaded); + void merge(mesh &mesh); + void copy(mesh &mesh); + + bool initialized = false; + GLuint vbo_id = 0; + GLuint vao_id = 0; + float *vbo_data = nullptr; + int vbo_size_in_elements = 0; +}; + +void calculate_normals(mesh & mesh); +void flip_normals(mesh & mesh); + +END_NAMESPACE \ No newline at end of file diff --git a/src/shader.cpp b/src/shader.cpp index 4dfaad8..991595d 100644 --- a/src/shader.cpp +++ b/src/shader.cpp @@ -1,7 +1,5 @@ #include "shader.h" -#include #include -#include BEGIN_NAMESPACE @@ -68,10 +66,10 @@ void shader::unuse() const { } int shader::getUniform(const char *uniformName) { - if (uniformCache.count(uniformName) == 0) { - uniformCache[uniformName] = glGetUniformLocation(program_id, uniformName); + if (uniform_cache.count(uniformName) == 0) { + uniform_cache[uniformName] = glGetUniformLocation(program_id, uniformName); } - return uniformCache[uniformName]; + return uniform_cache[uniformName]; } void shader::setMatrix3Uniform(float *matrix, const char *uniformName) { diff --git a/src/shader.h b/src/shader.h index 539489f..13d7598 100644 --- a/src/shader.h +++ b/src/shader.h @@ -7,7 +7,6 @@ BEGIN_NAMESPACE class shader { public: - shader(const char *vs_content, const char *ps_content); virtual ~shader(); @@ -27,7 +26,7 @@ public: private: GLuint program_id; GLuint shader_ids[2]; - std::map uniformCache; + std::map uniform_cache; };