Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I am trying to write my own OBJ importer and renderer in OpenGL (yes, I know, reinventing the wheel) and I found a problem that I don't knwo how to handle.

In an OBJ file faces are defined by a list of indices that refers to the vertices IDs that belongs to that face (and the same for texture coordinates IDs), an example of a face could be:

f 2411/905 2414/906 2913/1463

which would mean that this face is created by vertices 2411, 2414, 3913 and texture coordinates IDs 905, 906, 1463. And this leads to different index buffers, if I am not mistaken...

Now the question is, having both a buffer of vertices and a buffer of texture coordinates, how can I use both "at the same time", if I am only able to bing one index buffer and the indices to be used for a particular face are different for vertices and texture coordinates? Is there any trick to bind two index buffers, one for vertices and another one for texture coordinates?

And finally, just to give some code of what I've tried and that obviously doesn't work because I am binding two different GL_ELEMENT_ARRAY_BUFFER_ARB before drawing..., so it ends up with random texture coodinates.

// TEXTURE VBO
glBindBufferARB(GL_ARRAY_BUFFER_ARB, texCoordBuffer);
glTexCoordPointer(2, GL_FLOAT, 0, 0);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);

glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, texIndicesBuffer);         
glIndexPointer(GL_INT, 0, 0);

// GEOMETRY VBO
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vertexBuffer);
glVertexPointer(3, GL_FLOAT, 0, 0);
glEnableClientState(GL_VERTEX_ARRAY);

glBindBufferARB(GL_ARRAY_BUFFER_ARB, normalBuffer);
glNormalPointer(GL_FLOAT, 0, 0);
glEnableClientState(GL_NORMAL_ARRAY);                                   

glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, indicesBuffer);
glIndexPointer(GL_INT, 0, 0);

// Bind texture and draw...
share|improve this question
    
I asked a similar question here –  bobobobo Jan 6 '13 at 4:53
    
Asked and answered. –  Nicol Bolas Jan 6 '13 at 7:45
    
Thanks @bobobobo and Nicol, I couldn't find these questions before. Looks we've all been there :) –  Dan Jan 6 '13 at 11:16

2 Answers 2

up vote 6 down vote accepted

You cannot use separate index buffers in the way you intend to. But since you are writing your own importer, you can very well reorganise the in-memory data so that both the position and texture information are indexed the same way. This possibly means duplicating information in the process, but that cost must be put in regard to the overall bandwidth gain provided by the use of index buffers.

The recently released book OpenGL Insights has a chapter about how to do this efficiently: Indexing Multiple Vertex Arrays, by Arnaud Masserann. Even if you do not have the book or the article, the author provides the full source code on GitHub.

share|improve this answer
    
Thanks Sam! Reorganising the data was one of the solutions I was thinking of, but I thought there might be an easier way to get around this. It looked to me too complicated for just an OBJ importer... ;) –  Dan Jan 4 '13 at 10:51
    
Also - glIndexPointer does not do what you think it does. opengl.org/sdk/docs/man2/xhtml/glIndexPointer.xml –  Jimmy Shelter Jan 4 '13 at 12:23
1  
@Dan Unfortunately, an OBJ importer is fairly complicated :( –  Luke B. Jan 4 '13 at 13:12
    
@Sam I finally got it working, reorganising the UV coordinates array in order to match the vertex index array as you suggested. Thanks! –  Dan Jan 4 '13 at 15:22

What you have to do is "dupe up the data".

Say for (a contrived) example you have a square, but for some reason all 4 points of the square use the same normal:

v 0 0 0
v 1 0 0
v 1 1 0
v 0 1 0

vn 0 0 1

f 1//1 2//1 3//1
f 1//1 3//1 4//1

Great! Now what do you do?

When you're building your vertex array, you just duplicate vn 4 times. So your vertex array would contain:

struct Vertex{
  Vector3f pos, norm ;
}  ;

vector<Vertex> verts(4) ;
verts[0] = Vertex( Vector3f( 0, 0, 0 ), Vector3f( 0, 0, 1 ) ) 
verts[1] = Vertex( Vector3f( 1, 0, 0 ), Vector3f( 0, 0, 1 ) ) 
verts[2] = Vertex( Vector3f( 1, 1, 0 ), Vector3f( 0, 0, 1 ) ) 

verts[3] = Vertex( Vector3f( 0, 0, 0 ), Vector3f( 0, 0, 1 ) ) 
verts[4] = Vertex( Vector3f( 1, 1, 0 ), Vector3f( 0, 0, 1 ) ) 
verts[5] = Vertex( Vector3f( 0, 1, 0 ), Vector3f( 0, 0, 1 ) ) 

So you see, the normal Vector3f( 0,0,1 ) has got to be duplicated all over the place. If you use an index buffer, you can reduce this to 4 verts. But that's the best you can do with a situation like this.

share|improve this answer
    
Thanks @bobobobo, this is similar to what I ended up doing. I basically reordered the array of UVs in order to match the order of the vertices. In the case of having vertices with multiple UVs, I duplicated that vertex, adding an extra vertex in the list of vertices and assigning to it its original UV. –  Dan Jan 6 '13 at 11:13

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.