0

Trying to modify this OpenGL and GLKit tutorial at raywenderlich.com, I am trying to render a cube from a wavefront obj file, without the per vertex color information and with surface normals. But the thing that is rendered looks nothing like a cube.

"(Not a) Cube"

For parsing an obj file I have a method (createDrawable) that goes through the obj and saves the info into a struct (Drawable) that contains four things: vertex buffer, index buffer, number of faces in the object and the transform matrix of the object. (Here are the header, .m file and the .obj file.)

- (Drawable)createDrawable: (NSString *)objFileName {
    ......
    ......

    // Parsed obj and put info in vertexData and indices arrays.

    Drawable _drawable;

    _drawable.numFaces = numFaces;

    glGenBuffers(1, &_drawable.vertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, _drawable.vertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData) * numFaces * 8, vertexData, GL_STATIC_DRAW);

    glGenBuffers(1, &_drawable.indexBuffer);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _drawable.indexBuffer);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices) * numFaces * 3, indices, GL_STATIC_DRAW);

    _drawable.matrix = GLKMatrix4Identity;
    _drawable.matrix = GLKMatrix4Translate(_drawable.matrix, 0.0f, 0.0f, 10.0f);

    return _drawable;
}

For rendering I am using another method (renderDrawable) that binds an object's buffers, sets pointers to them and then renders using glDrawElements(..).

- (void) renderDrawable: (Drawable)object {
    glBindBuffer(GL_ARRAY_BUFFER, object.vertexBuffer);
    glEnableVertexAttribArray(GLKVertexAttribPosition);        
    glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 0, (const GLvoid *) 0);
    glEnableVertexAttribArray(GLKVertexAttribTexCoord1);
    glVertexAttribPointer(GLKVertexAttribTexCoord1, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid *) 3);
    glEnableVertexAttribArray(GLKVertexAttribNormal);
    glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 0, (const GLvoid *) 5);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, object.indexBuffer);
    glDrawElements(GL_LINES, sizeof(object.indexBuffer) * 3 * object.numFaces, GL_UNSIGNED_BYTE, (const GLvoid *) object.indexBuffer);
}

I think I am doing something wrong with the buffers (part of createDrawable shown here and renderDrawable, in the .m file), but I just can't figure out what it is.

Brad Larson
  • 170,088
  • 45
  • 397
  • 571
KK.
  • 783
  • 8
  • 20

2 Answers2

1

I think you problem is that you pass GL_LINES to glDrawElements() instead of GL_TRIANGLES.

Tobias Schlegel
  • 3,970
  • 18
  • 22
  • No. Actually when passing GL_TRIANGLES, nothing comes up on the screen. I was just fed up and randomly making tweaks when I noticed that passing GL_LINES makes at least 'something' come up. (Ideally, the overall shape should be the same, I think) – KK. May 30 '12 at 10:45
  • No, the shape will be completeley different, because GL_LINES takes two vertices per line and GL_TRIANGLES three vertices per polygon. – Tobias Schlegel May 30 '12 at 10:58
  • Ok. I didn't know that. It means that nothing is drawn on screen when I am using GL_TRIANGLES. – KK. May 30 '12 at 11:01
1

I think that the "stride" param in glVertexArrayPointer should be set to 8 * sizeof(float) for instance (size of a single vertex)

glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (const GLvoid *) 5);

when stride is 0 - that means attribs are stored in a continous way... but you have interleaved attribs so you must provide some more info to OpenGL.

Another issue: what is the sizeof(vertexData) * numFaces * 8... I think is should be: sizeof(vertexData) * numFaces * 3

And for index buffer: sizeof(indices) * numFaces * 3 - I think it should be sizeof(int) * numFaces * 3

int - type for indices, but you have GL_BYTE (that means that you can have only 256 different indices!)

when rendering: glDrawArrays - you have index buffer bound, so set the last param to NULL

fen
  • 9,835
  • 5
  • 34
  • 57
  • `sizeof(vertexData) * numFaces * 8` meant providing the size of the whole vertexData array. It actually should have been `sizeof(vertexData) * numFaces * 8 * 3`, because there should be 3 vertices per face, and there are 8 float values (3V, 2T and 3N) per vertex. Using the latter makes more faces visible, though not for a cube. Also, I have changed the type of indices to uint. – KK. May 30 '12 at 11:12
  • yes yes... I wrote that answer to quickly and there were some errors :) Hope this helped – fen May 30 '12 at 19:18
  • Of course it helped. It helped me take a fresh look at things. Thanks for helping. – KK. Jun 01 '12 at 16:23