Using glDrawElements does not draw my .obj file

Posted by Hallik on Stack Overflow See other posts from Stack Overflow or by Hallik
Published on 2011-01-16T05:33:28Z Indexed on 2011/01/16 6:53 UTC
Read the original article Hit count: 274

Filed under:
|

I am trying to correctly import an .OBJ file from 3ds Max. I got this working using glBegin() & glEnd() from a previous question on here, but had really poor performance obviously, so I am trying to use glDrawElements now.

I am importing a chessboard, its game pieces, etc. The board, each game piece, and each square on the board is stored in a struct GroupObject. The way I store the data is like this:

struct Vertex
{
    float position[3];
    float texCoord[2];
    float normal[3];
    float tangent[4];
    float bitangent[3];
};

struct Material
{
    float ambient[4];
    float diffuse[4];
    float specular[4];
    float shininess;        // [0 = min shininess, 1 = max shininess]
    float alpha;            // [0 = fully transparent, 1 = fully opaque]

    std::string name;
    std::string colorMapFilename;
    std::string bumpMapFilename;

   std::vector<int> indices;
   int id;
  };

 //A chess piece or square
 struct GroupObject
 {
     std::vector<Material *> materials;
     std::string    objectName;
     std::string    groupName;
     int      index;
 };

All vertices are triangles, so there are always 3 points. When I am looping through the faces f section in the obj file, I store the v0, v1, & v2 in the Material->indices. (I am doing v[0-2] - 1 to account for obj files being 1-based and my vectors being 0-based.

So when I get to the render method, I am trying to loop through every object, which loops through every material attached to that object. I set the material information and try and use glDrawElements. However, the screen is black. I was able to draw the model just fine when I looped through each distinct material with all the indices associated with that material, and it drew the model fine. This time around, so I can use the stencil buffer for selecting GroupObjects, I changed up the loop, but the screen is black.

Here is my render loop. The only thing I changed was the for loop(s) so they go through each object, and each material in the object in turn.

void GLEngine::drawModel()

{

 glEnable(GL_BLEND);
 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

 // Vertex arrays setup
 glEnableClientState( GL_VERTEX_ARRAY );
 glVertexPointer(3, GL_FLOAT, model.getVertexSize(), model.getVertexBuffer()->position);

 glEnableClientState( GL_NORMAL_ARRAY );
 glNormalPointer(GL_FLOAT, model.getVertexSize(), model.getVertexBuffer()->normal);

 glClientActiveTexture( GL_TEXTURE0 );
 glEnableClientState( GL_TEXTURE_COORD_ARRAY );
 glTexCoordPointer(2, GL_FLOAT, model.getVertexSize(), model.getVertexBuffer()->texCoord);

glUseProgram(blinnPhongShader);

objects = model.getObjects();
// Loop through objects...
for( int i=0 ; i < objects.size(); i++ ) 
{
   ModelOBJ::GroupObject *object = objects[i];

   // Loop through materials used by object...
   for( int j=0 ; j<object->materials.size() ; j++ ) 
   {
      ModelOBJ::Material *pMaterial = object->materials[j];

      glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, pMaterial->ambient);
      glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, pMaterial->diffuse);
      glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, pMaterial->specular);
      glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, pMaterial->shininess * 128.0f);

     // Draw faces, letting OpenGL loop through them
     glDrawElements( GL_TRIANGLES, pMaterial->indices.size(), GL_UNSIGNED_INT, &pMaterial->indices );
   }

 }

  if (model.hasNormals())
       glDisableClientState(GL_NORMAL_ARRAY);

  if (model.hasTextureCoords())
  {
      glClientActiveTexture(GL_TEXTURE0);
      glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  }

  if (model.hasPositions())
      glDisableClientState(GL_VERTEX_ARRAY);

 glBindTexture(GL_TEXTURE_2D, 0);
  glUseProgram(0);
 glDisable(GL_BLEND);

}

I don't know what I am missing that's important. If it's also helpful, here is where I read a 'f' face line and store the info in the obj importer in the pMaterial->indices.

 else if (sscanf(buffer, "%d/%d/%d", &v[0], &vt[0], &vn[0]) == 3) // v/vt/vn
        {
            fscanf(pFile, "%d/%d/%d", &v[1], &vt[1], &vn[1]);
            fscanf(pFile, "%d/%d/%d", &v[2], &vt[2], &vn[2]);

            v[0] = (v[0] < 0) ? v[0] + numVertices - 1 : v[0] - 1;
            v[1] = (v[1] < 0) ? v[1] + numVertices - 1 : v[1] - 1;
            v[2] = (v[2] < 0) ? v[2] + numVertices - 1 : v[2] - 1;

currentMaterial->indices.push_back(v[0]);
currentMaterial->indices.push_back(v[1]);
currentMaterial->indices.push_back(v[2]);

Again, this worked drawing it all together only separated by materials, so I haven't changed code anywhere else except added the indices to the materials within objects, and the loop in the draw method. Before everything was showing up black, now with the setup as above, I am getting an unhandled exception write violation on the glDrawElements line. I did a breakpoint there, and there are over 600 elements in the pMaterial->indices array, so it's not empty, it has indices to use.

When I set the glDrawElements like this, it gives me the black screen but no errors

glDrawElements( GL_TRIANGLES, pMaterial->indices.size(), GL_UNSIGNED_INT, &pMaterial->indices[0] );

I have also tried adding this when I loop through the faces on import

if ( currentMaterial->startIndex == -1 )
    currentMaterial->startIndex = v[0];

currentMaterial->triangleCount++;

And when drawing...

//in draw method
glDrawElements( GL_TRIANGLES, pMaterial->triangleCount * 3, GL_UNSIGNED_INT, model.getIndexBuffer() + pMaterial->startIndex );

© Stack Overflow or respective owner

Related posts about c++

Related posts about opengl