0

enter image description here

I create a .obj loader that reads from a mesh file that was created in blender 2.66 and loads the data into a std::vector that is passed to Opengl as a VBO. None of the vertices in the mesh file have a position of (0,0,0). So what could be a possible reason that the mesh is getting that extra vertex in the center? As the original mesh is just a triangulated plane with only four vertices.

struct Vertex
{
    //Position
    GLfloat m_X;
    GLfloat m_Y;
    GLfloat m_Z;

    //Normal
    GLfloat m_NX;
    GLfloat m_NY;
    GLfloat m_NZ;

    //TexCoords
    GLfloat m_U;
    GLfloat m_V;
};

void Mesh::loadMesh(std::string Filename)
{
  ...

    const unsigned int PositionAttribute = 0;
    const unsigned int NormalAttribute   = 1;
    const unsigned int TexCoordAttribute = 2;

    //Create a new VBO and use the variable id to store the VBO id
    glGenBuffers(1, &MeshVBO);

    //make the new VBO active
    glBindBuffer(GL_ARRAY_BUFFER, MeshVBO);

    //Pass the Mesh's vertex data into the VBO to be transferred to super fast Video RAM
    glBufferData(GL_ARRAY_BUFFER, m_Vertices.size() * sizeof(Vertex), &m_Vertices[0], GL_STATIC_DRAW);

    glEnableVertexAttribArray(PositionAttribute);
    glEnableVertexAttribArray(NormalAttribute);
    glEnableVertexAttribArray(TexCoordAttribute);

    //specifies the location and data of an array of vertex
    glVertexAttribPointer(PositionAttribute, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)0);
    glVertexAttribPointer(NormalAttribute, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)(sizeof(GLfloat) * 3)); //12 byte offset
    glVertexAttribPointer(TexCoordAttribute, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)(sizeof(GLfloat) * 6)); //24 byte offset

    //make the new VBO active
    glBindBuffer(GL_ARRAY_BUFFER, MeshVBO);

    glGenBuffers(1, &MeshIBO);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, MeshIBO);

    glBufferData(GL_ELEMENT_ARRAY_BUFFER, (sizeof(GLushort) * m_IndexList.size()), &m_IndexList[0], GL_STATIC_DRAW); 

    //Cleanup
    delete[] m_VertexArray;
    delete[] m_Indices;
    m_VertexArray = NULL;
    m_Indices = NULL;

    return Success;
}

void Mesh::drawMesh()
{
    glDrawElements(GL_POINTS, (GLsizei)m_IndexList.size() + 1, GL_UNSIGNED_SHORT, 0);
}

Plane.obj

# Blender v2.66 (sub 1) OBJ File: ''
# www.blender.org
mtllib plane.mtl
o Plane
v 0.622129 -0.622129 0.000000
v -0.622129 -0.622129 0.000000
v 0.622129 0.622129 -0.000000
v -0.622129 0.622129 -0.000000
vn 1.000000 0.000000 0.000000
usemtl None
s off
f 2//1 1//1 3//1
f 4//1 2//1 3//1
genpfault
  • 51,148
  • 11
  • 85
  • 139
  • 8
    Probably the `+ 1` in the second argument of `glDrawElements()`. Looks like you explicitly render one more point than you have. – Reto Koradi Sep 30 '14 at 05:25
  • Could you post the mesh file that is generated? You can also tell if that's where the problem is coming from if there are more than 4 vertices specified. Though I agree with @Reto Koradi that its the +1 – Daniel Sep 30 '14 at 11:59
  • @RetoKoradi Removing the "+1" from gldrawelements() removes the lower right-hand vertex from the mesh. Is it possible that my vector is not passing the indices properly somehow? The indices checked in debug match that of the file. – thatguyoverthere Sep 30 '14 at 20:20
  • @Daniel I included the file in the post that is generated by blender. – thatguyoverthere Sep 30 '14 at 20:21
  • 1
    Be aware that the indices in an OBJ file are 1-based, while OpenGL uses 0-based indices. So when you read the file, you'll need to subtract 1 from each index. If you want to support the full OBJ format, indices can also be negative, which means that they are relative to the last read vertex. – Reto Koradi Sep 30 '14 at 20:24
  • @RetoKoradi Thanks a ton, subtraction did the trick. I wasn't aware of the OBJ file indices being 1-based. Where may I ask did you come across that info. I don't remember that being in the .obj file Wikipedia page. – thatguyoverthere Sep 30 '14 at 21:16
  • @RetoKoradi you should make an answer so we can upvote you, and so OP can set it as the accepted answer :) – Daniel Oct 01 '14 at 04:37
  • The wikipedia page says "A valid vertex index starts from 1". @Daniel: Thanks, I was going to. Done now. – Reto Koradi Oct 01 '14 at 05:10

1 Answers1

4

Your main problem is that indices in OBJ files are 1-based, while OpenGL uses 0-based indices. This means that you will have to subtract 1 from the indices you read from the OBJ file. This is most conveniently done right after you read the indices in your parsing code, because most programming languages and APIs use 0-based indices.

If you want to be able to read a wider selection of OBJ files, you will also have to handle negative index values in the input file. This doesn't seem to be used as commonly, and you may be able to skip this if the files come from a well controlled source (e.g. you always generate them yourself with the same software). If present, negative indices are relative to the end of the vertices read so far. E.g. index -1 is the latest vertex read, -2 the second latest, etc.

In the posted code, you added 1 to the number of available indices in the draw call:

glDrawElements(GL_POINTS, (GLsizei)m_IndexList.size() + 1, GL_UNSIGNED_SHORT, 0);

I suspect that you might have done this to compensate for the wrong index values. Once you have the correct index values, you should remove the + 1.

For more detailed documentation of the OBJ format, the Wikipedia page (http://en.wikipedia.org/wiki/Wavefront_.obj_file) contains a good overview. The most detailed and thorough definition I ever found is here: http://www.martinreddy.net/gfx/3d/OBJ.spec. The OBJ format can contain fairly advanced features, like NURBS. If you write your own parser and renderer, you will probably want to settle for a subset. Otherwise you'll be busy for quite some time.

If you want more in-depth information about how to render meshes from OBJ files efficiently, here are a few more of my related answers to earlier questions:

Community
  • 1
  • 1
Reto Koradi
  • 53,228
  • 8
  • 93
  • 133