Guest User

Mesh.cpp

a guest
Jun 7th, 2014
303
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.87 KB | None | 0 0
  1. /*
  2.  
  3. Copyright 2011 Etay Meiri
  4.  
  5. This program is free software: you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation, either version 3 of the License, or
  8. (at your option) any later version.
  9.  
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program.  If not, see <http://www.gnu.org/licenses/>.
  17. */
  18.  
  19. #include <assert.h>
  20. #include "mesh.h"
  21. #include "OpenGLincludes.h"
  22. #include "Utils.h"
  23.  
  24. using namespace std;
  25.  
  26. #define POSITION_LOCATION 0
  27. #define TEX_COORD_LOCATION 1
  28. #define NORMAL_LOCATION 2
  29. #define WVP_LOCATION 3
  30. #define WORLD_LOCATION 7
  31.  
  32. Mesh::Mesh()
  33. {
  34.     m_VAO = 0;
  35.     ZERO_MEM(m_Buffers);
  36. }
  37.  
  38.  
  39. Mesh::~Mesh()
  40. {
  41.     Clear();
  42. }
  43.  
  44.  
  45. void Mesh::Clear()
  46. {
  47.     for (unsigned int i = 0; i < m_Textures.size(); i++) {
  48.         SAFE_DELETE(m_Textures[i]);
  49.     }
  50.  
  51.     if (m_Buffers[0] != 0) {
  52.         glDeleteBuffers(ARRAY_SIZE_IN_ELEMENTS(m_Buffers), m_Buffers);
  53.     }
  54.  
  55.     if (m_VAO != 0) {
  56.         glDeleteVertexArrays(1, &m_VAO);
  57.         m_VAO = 0;
  58.     }
  59. }
  60.  
  61.  
  62. bool Mesh::LoadMesh(const string& Filename)
  63. {
  64.     // Release the previously loaded mesh (if it exists)
  65.     Clear();
  66.  
  67.     // Create the VAO
  68.     glGenVertexArrays(1, &m_VAO);
  69.     glBindVertexArray(m_VAO);
  70.  
  71.     // Create the buffers for the vertices attributes
  72.     glGenBuffers(ARRAY_SIZE_IN_ELEMENTS(m_Buffers), m_Buffers);
  73.  
  74.     bool Ret = false;
  75.     Assimp::Importer Importer;
  76.  
  77.     const aiScene* pScene = Importer.ReadFile(Filename.c_str(), aiProcess_Triangulate | aiProcess_GenSmoothNormals | aiProcess_FlipUVs);
  78.  
  79.     if (pScene) {
  80.         Ret = InitFromScene(pScene, Filename);
  81.     }
  82.     else {
  83.         printf("Error parsing '%s': '%s'\n", Filename.c_str(), Importer.GetErrorString());
  84.     }
  85.  
  86.     // Make sure the VAO is not changed from the outside
  87.     glBindVertexArray(0);
  88.  
  89.     return Ret;
  90. }
  91.  
  92. bool Mesh::InitFromScene(const aiScene* pScene, const string& Filename)
  93. {
  94.     m_Entries.resize(pScene->mNumMeshes);
  95.     m_Textures.resize(pScene->mNumMaterials);
  96.  
  97.     vector<Vector3f> Positions;
  98.     vector<Vector3f> Normals;
  99.     vector<Vector2f> TexCoords;
  100.     vector<unsigned int> Indices;
  101.  
  102.     unsigned int NumVertices = 0;
  103.     unsigned int NumIndices = 0;
  104.  
  105.     // Count the number of vertices and indices
  106.     for (unsigned int i = 0; i < m_Entries.size(); i++) {
  107.         m_Entries[i].MaterialIndex = pScene->mMeshes[i]->mMaterialIndex;
  108.         m_Entries[i].NumIndices = pScene->mMeshes[i]->mNumFaces * 3;
  109.         m_Entries[i].BaseVertex = NumVertices;
  110.         m_Entries[i].BaseIndex = NumIndices;
  111.  
  112.         NumVertices += pScene->mMeshes[i]->mNumVertices;
  113.         NumIndices += m_Entries[i].NumIndices;
  114.     }
  115.  
  116.     // Reserve space in the vectors for the vertex attributes and indices
  117.     Positions.reserve(NumVertices);
  118.     Normals.reserve(NumVertices);
  119.     TexCoords.reserve(NumVertices);
  120.     Indices.reserve(NumIndices);
  121.  
  122.     // Initialize the meshes in the scene one by one
  123.     for (unsigned int i = 0; i < m_Entries.size(); i++) {
  124.         const aiMesh* paiMesh = pScene->mMeshes[i];
  125.         InitMesh(paiMesh, Positions, Normals, TexCoords, Indices);
  126.     }
  127.  
  128.     if (!InitMaterials(pScene, Filename)) {
  129.         return false;
  130.     }
  131.  
  132.     // Generate and populate the buffers with vertex attributes and the indices
  133.     glBindBuffer(GL_ARRAY_BUFFER, m_Buffers[POS_VB]);
  134.     glBufferData(GL_ARRAY_BUFFER, sizeof(Positions[0]) * Positions.size(), &Positions[0], GL_STATIC_DRAW);
  135.     glEnableVertexAttribArray(POSITION_LOCATION);
  136.     glVertexAttribPointer(POSITION_LOCATION, 3, GL_FLOAT, GL_FALSE, 0, 0);
  137.  
  138.     glBindBuffer(GL_ARRAY_BUFFER, m_Buffers[TEXCOORD_VB]);
  139.     glBufferData(GL_ARRAY_BUFFER, sizeof(TexCoords[0]) * TexCoords.size(), &TexCoords[0], GL_STATIC_DRAW);
  140.     glEnableVertexAttribArray(TEX_COORD_LOCATION);
  141.     glVertexAttribPointer(TEX_COORD_LOCATION, 2, GL_FLOAT, GL_FALSE, 0, 0);
  142.  
  143.     glBindBuffer(GL_ARRAY_BUFFER, m_Buffers[NORMAL_VB]);
  144.     glBufferData(GL_ARRAY_BUFFER, sizeof(Normals[0]) * Normals.size(), &Normals[0], GL_STATIC_DRAW);
  145.     glEnableVertexAttribArray(NORMAL_LOCATION);
  146.     glVertexAttribPointer(NORMAL_LOCATION, 3, GL_FLOAT, GL_FALSE, 0, 0);
  147.  
  148.     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_Buffers[INDEX_BUFFER]);
  149.     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Indices[0]) * Indices.size(), &Indices[0], GL_STATIC_DRAW);
  150.  
  151.     /*   glBindBuffer(GL_ARRAY_BUFFER, m_Buffers[WVP_MAT_VB]);
  152.  
  153.     for (unsigned int i = 0; i < 4 ; i++) {
  154.     glEnableVertexAttribArray(WVP_LOCATION + i);
  155.     glVertexAttribPointer(WVP_LOCATION + i, 4, GL_FLOAT, GL_FALSE, sizeof(Matrix4f), (const GLvoid*)(sizeof(GLfloat) * i * 4));
  156.     glVertexAttribDivisor(WVP_LOCATION + i, 1);
  157.     }
  158.  
  159.     glBindBuffer(GL_ARRAY_BUFFER, m_Buffers[WORLD_MAT_VB]);
  160.  
  161.     for (unsigned int i = 0; i < 4 ; i++) {
  162.     glEnableVertexAttribArray(WORLD_LOCATION + i);
  163.     glVertexAttribPointer(WORLD_LOCATION + i, 4, GL_FLOAT, GL_FALSE, sizeof(Matrix4f), (const GLvoid*)(sizeof(GLfloat) * i * 4));
  164.     glVertexAttribDivisor(WORLD_LOCATION + i, 1);
  165.     }*/
  166.  
  167.     return GLCheckError();
  168. }
  169.  
  170. void Mesh::InitMesh(const aiMesh* paiMesh,
  171.     vector<Vector3f>& Positions,
  172.     vector<Vector3f>& Normals,
  173.     vector<Vector2f>& TexCoords,
  174.     vector<unsigned int>& Indices)
  175. {
  176.     const aiVector3D Zero3D(0.0f, 0.0f, 0.0f);
  177.  
  178.     // Populate the vertex attribute vectors
  179.     for (unsigned int i = 0; i < paiMesh->mNumVertices; i++) {
  180.         const aiVector3D* pPos = &(paiMesh->mVertices[i]);
  181.         const aiVector3D* pNormal = &(paiMesh->mNormals[i]);
  182.         const aiVector3D* pTexCoord = paiMesh->HasTextureCoords(0) ? &(paiMesh->mTextureCoords[0][i]) : &Zero3D;
  183.  
  184.         Positions.push_back(Vector3f(pPos->x, pPos->y, pPos->z));
  185.         Normals.push_back(Vector3f(pNormal->x, pNormal->y, pNormal->z));
  186.         TexCoords.push_back(Vector2f(pTexCoord->x, pTexCoord->y));
  187.     }
  188.  
  189.     // Populate the index buffer
  190.     for (unsigned int i = 0; i < paiMesh->mNumFaces; i++) {
  191.         const aiFace& Face = paiMesh->mFaces[i];
  192.         assert(Face.mNumIndices == 3);
  193.         Indices.push_back(Face.mIndices[0]);
  194.         Indices.push_back(Face.mIndices[1]);
  195.         Indices.push_back(Face.mIndices[2]);
  196.     }
  197. }
  198.  
  199. bool Mesh::InitMaterials(const aiScene* pScene, const string& Filename)
  200. {
  201.     // Extract the directory part from the file name
  202.     string::size_type SlashIndex = Filename.find_last_of("/");
  203.     string Dir;
  204.  
  205.     if (SlashIndex == string::npos) {
  206.         Dir = ".";
  207.     }
  208.     else if (SlashIndex == 0) {
  209.         Dir = "/";
  210.     }
  211.     else {
  212.         Dir = Filename.substr(0, SlashIndex);
  213.     }
  214.  
  215.     bool Ret = true;
  216.  
  217.     // Initialize the materials
  218.     for (unsigned int i = 0; i < pScene->mNumMaterials; i++) {
  219.         const aiMaterial* pMaterial = pScene->mMaterials[i];
  220.  
  221.         m_Textures[i] = NULL;
  222.  
  223.         if (pMaterial->GetTextureCount(aiTextureType_DIFFUSE) > 0) {
  224.             aiString Path;
  225.  
  226.             if (pMaterial->GetTexture(aiTextureType_DIFFUSE, 0, &Path, NULL, NULL, NULL, NULL, NULL) == AI_SUCCESS) {
  227.                 string p(Path.data);
  228.  
  229.                 if (p.substr(0, 2) == ".\\") {
  230.                     p = p.substr(2, p.size() - 2);
  231.                 }
  232.  
  233.                 string FullPath = Dir + "/" + p;
  234.  
  235.                 m_Textures[i] = new Texture(GL_TEXTURE_2D, FullPath.c_str());
  236.  
  237.                 if (!m_Textures[i]->Load()) {
  238.                     printf("Error loading texture '%s'\n", FullPath.c_str());
  239.                     delete m_Textures[i];
  240.                     m_Textures[i] = NULL;
  241.                     Ret = false;
  242.                 }
  243.                 else {
  244.                     printf("Loaded texture '%s'\n", FullPath.c_str());
  245.                 }
  246.             }
  247.         }
  248.     }
  249.  
  250.     return Ret;
  251. }
  252.  
  253.  
  254. void Mesh::Render()
  255. {
  256.     glClearColor(0.0, 0.0, 0.0, 1.0);
  257.     glColor3f(1.0, 1.0, 1.0);
  258.     glBindVertexArray(m_VAO);
  259.  
  260.     for (unsigned int i = 0; i < m_Entries.size(); i++) {
  261.         const unsigned int MaterialIndex = m_Entries[i].MaterialIndex;
  262.  
  263.         assert(MaterialIndex < m_Textures.size());
  264.  
  265.         if (m_Textures[MaterialIndex]) {
  266.             m_Textures[MaterialIndex]->Bind(GL_TEXTURE0);
  267.         }
  268.  
  269.         glDrawElementsBaseVertex(GL_TRIANGLES,
  270.             m_Entries[i].NumIndices,
  271.             GL_UNSIGNED_INT,
  272.             (void*)(sizeof(unsigned int) * m_Entries[i].BaseIndex),
  273.             m_Entries[i].BaseVertex);
  274.     }
  275.  
  276.     // Make sure the VAO is not changed from the outside    
  277.     glBindVertexArray(0);
  278. }
  279.  
  280. void Mesh::Render(unsigned int NumInstances, const Matrix4f* WVPMats, const Matrix4f* WorldMats)
  281. {
  282.     glBindBuffer(GL_ARRAY_BUFFER, m_Buffers[WVP_MAT_VB]);
  283.     glBufferData(GL_ARRAY_BUFFER, sizeof(Matrix4f) * NumInstances, WVPMats, GL_DYNAMIC_DRAW);
  284.  
  285.     glBindBuffer(GL_ARRAY_BUFFER, m_Buffers[WORLD_MAT_VB]);
  286.     glBufferData(GL_ARRAY_BUFFER, sizeof(Matrix4f) * NumInstances, WorldMats, GL_DYNAMIC_DRAW);
  287.  
  288.     glBindVertexArray(m_VAO);
  289.  
  290.     for (unsigned int i = 0; i < m_Entries.size(); i++) {
  291.         const unsigned int MaterialIndex = m_Entries[i].MaterialIndex;
  292.  
  293.         assert(MaterialIndex < m_Textures.size());
  294.  
  295.         if (m_Textures[MaterialIndex]) {
  296.             m_Textures[MaterialIndex]->Bind(GL_TEXTURE0);
  297.         }
  298.  
  299.         glDrawElementsInstancedBaseVertex(GL_TRIANGLES,
  300.             m_Entries[i].NumIndices,
  301.             GL_UNSIGNED_INT,
  302.             (void*)(sizeof(unsigned int) * m_Entries[i].BaseIndex),
  303.             NumInstances,
  304.             m_Entries[i].BaseVertex);
  305.     }
  306.  
  307.     // Make sure the VAO is not changed from the outside    
  308.     glBindVertexArray(0);
  309. }
Advertisement
Add Comment
Please, Sign In to add comment