title: OpenGL Model/Texture rendering using VAO/VBO
body: <p>I am trying to render 3D models with textures using <a href="http://assimp.sourceforge.net/" rel="nofollow">Assimp</a>. The conversion goes perfect, all textures positions and what not gets loaded. I have tested the texture images by drawing them to the screen in 2D. 
  For some reason it does not render the textures to the model.
  I am a beginner in OpenGL so forgive me if i dont explain it right.
  The tutorial I have based the code on is from <a href="http://www.lighthouse3d.com/cg-topics/code-samples/importing-3d-models-with-assimp/" rel="nofollow">here</a>, but i stripped a big part since I have my own camera/movement system.</p>
  
  <p>The model renders like this: <a href="http://i.stack.imgur.com/5sK9K.png" rel="nofollow">http://i.stack.imgur.com/5sK9K.png</a></p>
  
  <p>whilest the texture in use looks like this: <a href="http://i.stack.imgur.com/sWGp7.jpg" rel="nofollow">http://i.stack.imgur.com/sWGp7.jpg</a></p>
  
  <p>The relevant rendering code is the following:</p>
  
  <p>Generating textures from data file:</p>
  
  <pre><code>int Mesh::LoadGLTextures(const aiScene* scene){
    if (scene-&gt;HasTextures()) return -1; //yes this is correct
    /* getTexture Filenames and Numb of Textures */
    for (unsigned int m = 0; m&lt;scene-&gt;mNumMaterials; m++){
      int texIndex = 0;
  
      aiReturn texFound;
      aiString path;  // filename
  
      while ((texFound = scene-&gt;mMaterials[m]-&gt;GetTexture(aiTextureType_DIFFUSE, texIndex, &amp;path)) == AI_SUCCESS){
          textureIdMap[path.data] = NULL; //fill map with textures, pointers still NULL yet
          texIndex++;
      }
    }
  
    int numTextures = textureIdMap.size();
    /* create and fill array with GL texture ids */
    GLuint* textureIds = new GLuint[numTextures];
  
    /* get iterator */
    std::map&lt;std::string, GLuint&gt;::iterator itr = textureIdMap.begin();
  
    std::string basepath = getBasePath(path);
  
    ALLEGRO_BITMAP *image;
    for (int i = 0; i&lt;numTextures; i++){
      std::string filename = (*itr).first;  // get filename
      (*itr).second = textureIds[i];    // save texture id for filename in map
      itr++;                                // next texture
  
      std::string fileloc = basepath + filename;  /* Loading of image */
      image = al_load_bitmap(fileloc.c_str());
  
      if (image) /* If no error occured: */{
          GLuint texId = al_get_opengl_texture(image);
  
          //glGenTextures(numTextures, &amp;textureIds[i]); /* Texture name generation */
          glBindTexture(GL_TEXTURE_2D, texId); /* Binding of texture name */
          //redefine standard texture values
          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); /* We will use linear
                                                                            interpolation for magnification filter */
          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); /* We will use linear
                                                                            interpolation for minifying filter */
          textureIdMap[filename] = texId;
      } else {
          /* Error occured */
          std::cout &lt;&lt; "Couldn't load Image: " &lt;&lt; fileloc.c_str() &lt;&lt; "\n";
      }
    }
  
    //Cleanup
    delete[] textureIds;
  
    //return success
    return true;
  }
  </code></pre>
  
  <p>Generating VBO/VAO:</p>
  
  <pre><code>void Mesh::genVAOsAndUniformBuffer(const aiScene *sc) {
    struct MyMesh aMesh;
    struct MyMaterial aMat;
    GLuint buffer;
  
    // For each mesh
    for (unsigned int n = 0; n &lt; sc-&gt;mNumMeshes; ++n){
      const aiMesh* mesh = sc-&gt;mMeshes[n];
  
      // create array with faces
      // have to convert from Assimp format to array
      unsigned int *faceArray;
      faceArray = (unsigned int *)malloc(sizeof(unsigned int) * mesh-&gt;mNumFaces * 3);
      unsigned int faceIndex = 0;
  
      for (unsigned int t = 0; t &lt; mesh-&gt;mNumFaces; ++t) {
          const aiFace* face = &amp;mesh-&gt;mFaces[t];
  
          memcpy(&amp;faceArray[faceIndex], face-&gt;mIndices, 3 * sizeof(unsigned int));
          faceIndex += 3;
      }
      aMesh.numFaces = sc-&gt;mMeshes[n]-&gt;mNumFaces;
  
      // generate Vertex Array for mesh
      glGenVertexArrays(1, &amp;(aMesh.vao));
      glBindVertexArray(aMesh.vao);
  
      // buffer for faces
      glGenBuffers(1, &amp;buffer);
      glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
      glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int) * mesh-&gt;mNumFaces * 3, faceArray, GL_STATIC_DRAW);
  
      // buffer for vertex positions
      if (mesh-&gt;HasPositions()) {
          glGenBuffers(1, &amp;buffer);
          glBindBuffer(GL_ARRAY_BUFFER, buffer);
          glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3 * mesh-&gt;mNumVertices, mesh-&gt;mVertices, GL_STATIC_DRAW);
          glEnableVertexAttribArray(vertexLoc);
          glVertexAttribPointer(vertexLoc, 3, GL_FLOAT, 0, 0, 0);
      }
  
      // buffer for vertex normals
      if (mesh-&gt;HasNormals()) {
          glGenBuffers(1, &amp;buffer);
          glBindBuffer(GL_ARRAY_BUFFER, buffer);
          glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3 * mesh-&gt;mNumVertices, mesh-&gt;mNormals, GL_STATIC_DRAW);
          glEnableVertexAttribArray(normalLoc);
          glVertexAttribPointer(normalLoc, 3, GL_FLOAT, 0, 0, 0);
      }
  
      // buffer for vertex texture coordinates
      if (mesh-&gt;HasTextureCoords(0)) {
          float *texCoords = (float *)malloc(sizeof(float) * 2 * mesh-&gt;mNumVertices);
          for (unsigned int k = 0; k &lt; mesh-&gt;mNumVertices; ++k) {
              texCoords[k * 2] = mesh-&gt;mTextureCoords[0][k].x;
              texCoords[k * 2 + 1] = mesh-&gt;mTextureCoords[0][k].y;
          }
  
          glGenBuffers(1, &amp;buffer);
          glEnableVertexAttribArray(texCoordLoc);
          glBindBuffer(GL_ARRAY_BUFFER, buffer);
  
          glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 2 * mesh-&gt;mNumVertices, texCoords, GL_STATIC_DRAW);
          glVertexAttribPointer(texCoordLoc, 2, GL_FLOAT, GL_FALSE, 0, 0);
      }
  
      // unbind buffers
      glBindVertexArray(0);
      glBindBuffer(GL_ARRAY_BUFFER, 0);
      glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
  
      // create material uniform buffer
      aiMaterial *mtl = sc-&gt;mMaterials[mesh-&gt;mMaterialIndex];
  
      aiString texPath;   //contains filename of texture
      if (AI_SUCCESS == mtl-&gt;GetTexture(aiTextureType_DIFFUSE, 0, &amp;texPath)){
          //bind texture
          unsigned int texId = textureIdMap[texPath.data];
          aMesh.texIndex = texId;
          aMat.texCount = 1;
      } else {
          aMat.texCount = 0;
      }
  
      float c[4];
      set_float4(c, 0.8f, 0.8f, 0.8f, 1.0f);
      aiColor4D diffuse;
      if (AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_DIFFUSE, &amp;diffuse))
          color4_to_float4(&amp;diffuse, c);
      memcpy(aMat.diffuse, c, sizeof(c));
  
      set_float4(c, 0.2f, 0.2f, 0.2f, 1.0f);
      aiColor4D ambient;
      if (AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_AMBIENT, &amp;ambient))
          color4_to_float4(&amp;ambient, c);
      memcpy(aMat.ambient, c, sizeof(c));
  
      set_float4(c, 0.0f, 0.0f, 0.0f, 1.0f);
      aiColor4D specular;
      if (AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_SPECULAR, &amp;specular))
          color4_to_float4(&amp;specular, c);
      memcpy(aMat.specular, c, sizeof(c));
  
      set_float4(c, 0.0f, 0.0f, 0.0f, 1.0f);
      aiColor4D emission;
      if (AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_EMISSIVE, &amp;emission))
          color4_to_float4(&amp;emission, c);
      memcpy(aMat.emissive, c, sizeof(c));
  
      float shininess = 0.0;
      unsigned int max;
      aiGetMaterialFloatArray(mtl, AI_MATKEY_SHININESS, &amp;shininess, &amp;max);
      aMat.shininess = shininess;
  
      glGenBuffers(1, &amp;(aMesh.uniformBlockIndex));
      glBindBuffer(GL_UNIFORM_BUFFER, aMesh.uniformBlockIndex);
      glBufferData(GL_UNIFORM_BUFFER, sizeof(aMat), (void *)(&amp;aMat), GL_STATIC_DRAW);
  
      myMeshes.push_back(aMesh);
    }
  }
  </code></pre>
  
  <p>Rendering model:</p>
  
  <pre><code>void Mesh::recursive_render(const aiScene *sc, const aiNode* nd){
    // draw all meshes assigned to this node
    for (unsigned int n = 0; n &lt; nd-&gt;mNumMeshes; ++n){
      glEnable(GL_TEXTURE_2D);
      glBindTexture(GL_TEXTURE_2D, myMeshes[nd-&gt;mMeshes[n]].texIndex);
  
      // bind VAO
      glBindVertexArray(myMeshes[nd-&gt;mMeshes[n]].vao);
  
      // draw
      glDrawElements(GL_TRIANGLES, myMeshes[nd-&gt;mMeshes[n]].numFaces * 3, GL_UNSIGNED_INT, 0);
    }
  
    // draw all children
    for (unsigned int n = 0; n &lt; nd-&gt;mNumChildren; ++n){
        recursive_render(sc, nd-&gt;mChildren[n]);
    }
  }
  </code></pre>
  
  <p>Any other relevant code parts can be found in my open github project <a href="https://github.com/kwek20/StrategyGame/tree/master/Strategy" rel="nofollow">https://github.com/kwek20/StrategyGame/tree/master/Strategy</a></p>
  
  <p>Mesh.cpp is relevant, as well as main.cpp and Camera.cpp.</p>
  
  <p>As far as I understaind I followed the guidelines well, created a VAO, created VBOs, added data and enabled the proper vertex array attriute tot render the scene with.</p>
  
  <p>I have checked all the data variables and everything is filled according to plan</p>
  
  <p>Could anyone here spot the mistake I have made and or explain it?
  Some links are typed weird because of the limit I have :(</p>