text: #include "Mesh.h"
  
  Mesh::Mesh(std::vector<Vertex> vertices, std::vector<unsigned int> indices, std::vector<std::shared_ptr<Texture>> m_Textures)
  {
      std::cout << "[Mesh] creating mesh" << std::endl;
      this->vertices = vertices;
      this->indices = indices;
      this->m_Textures = m_Textures;
  
      setupMesh();
  }
  
  Mesh::~Mesh() {
      std::cout << "[Mesh] destroying" << std::endl;
      vertices.clear();
      indices.clear();
      m_Textures.clear();
  
      glDeleteVertexArrays(1, &VAO);
      unsigned int arrays[2] = { VBO, EBO };
      glDeleteBuffers(2, arrays);
  }
  
  void Mesh::setupMesh()
  {
      glGenVertexArrays(1, &VAO);
      glGenBuffers(1, &VBO);
      glGenBuffers(1, &EBO);
  
      glBindVertexArray(VAO);
      glBindBuffer(GL_ARRAY_BUFFER, VBO);
  
      glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), &vertices[0], GL_STATIC_DRAW);
  
      glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
      glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int),
          &indices[0], GL_STATIC_DRAW);
  
      // vertex positions
      glEnableVertexAttribArray(0);
      glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0);
      // vertex normals
      glEnableVertexAttribArray(1);
      glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, Normal));
      // vertex texture coords
      glEnableVertexAttribArray(2);
      glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, TexCoords));
  
      glEnableVertexAttribArray(3);
      glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, Tangent));
  
      glEnableVertexAttribArray(4);
      glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, Bitangent));
  
      glBindVertexArray(0);
  }
  
  
  void Mesh::Render(std::shared_ptr<Shader> shader)
  {
      unsigned int diffuseNr = 1;
      unsigned int specularNr = 1;
      unsigned int normalNr = 1;
      for (unsigned int i = 0; i < m_Textures.size(); i++)
      {
          glActiveTexture(GL_TEXTURE0 + i); // activate proper texture unit before binding
          // retrieve texture number (the N in diffuse_textureN)
          std::string number;
          std::string name = m_Textures[i]->type;
          if (name == "texture_diffuse")
              number = std::to_string(diffuseNr++);
          else if (name == "texture_specular")
              number = std::to_string(specularNr++);
          else if (name == "texture_normal")
              number = std::to_string(normalNr++);
  
          shader->setInt((name + number).c_str(), i);
          glBindTexture(GL_TEXTURE_2D, m_Textures[i]->id);
      }
      glActiveTexture(GL_TEXTURE0);
  
      // draw mesh
      glBindVertexArray(VAO);
      glDrawElements(GL_TRIANGLES, (GLsizei)indices.size(), GL_UNSIGNED_INT, 0);
      glBindVertexArray(0);
  
      for (unsigned int i = 0; i < m_Textures.size(); i++) {
          glActiveTexture(GL_TEXTURE0 + i);
          glBindTexture(GL_TEXTURE_2D, 0);
      }
  }