Question

I have a custom file format that has all the needed information for a 3D mesh (exported from 3ds Max). I've extracted the data for vertices, vertex indices and normals.

I pass to OpenGL the vertex data, vertex indices and normals data and I render the mesh with a call to glDrawElements(GL_TRIANGLES,...)

Everything looks right but the normals. The problem is that the normals have different indices. And because OpenGL can use only one index buffer, it uses that index buffer for both the vertices and the normals.

I would be really grateful if you could suggest me how to go about that problem.

Important thing to note is that the vertex/normal data is not "sorted" and therefore I am unable to use the functionality of glDrawArrays(GL_TRIANGLES,...) - the mesh doesn't render correctly.

Is there a way/algorithm that I can use to sort the data so the mesh can be drawn correctly with glDrawArrays(GL_TRIANGLES,..) ? But even if there is an algorithm, there is one more problem - I will have to duplicate some vertices (because my vertex buffer consists of unique vertices - for example if you have cube my buffer will only have 8 vertices) and I am not sure how to do that.

Was it helpful?

Solution 2

I managed to do it without passing index buffer to OpenGL with glDrawArrays(GL_TRIANGLES,..) What I did is the following: Fill a vertex array, vertex indices array, normals array and normals indices array. Then I created new vertex and normal arrays with sorted data and passed them to OpenGL.

for i = 0; i < vertexIndices.size(); ++i
    newVertexArray[i] = oldVertexArray[vertexIndices[i]];

for i = 0; i < normalsIndices.size(); ++i
    newNormalsArray[i] = oldNormalsArray[normalsIndices[i]];

I optimized it a bit, without filling indices arrays at all. But the optimization depends on the way the programmer is reading the mesh data.

OTHER TIPS

File types that use separate indices for vertices and normals do not match to the OpenGL vertex model very directly. As you noticed, OpenGL uses a single set of indices.

What you need to do is create an OpenGL vertex for each unique (vertex index, normal index) pair in your input. That takes a little work, but is not terribly difficult, particularly if you use available data structures. A STL map works well for this, with the (vertex index, normal index) pair as the key. I'm not going to provide full C++ code, but I can sketch it out.

Let's say you have already read your vertices into some kind of array/vector data structure inVertices, where the coordinates for vertex with index vertexIdx are stored in inVertices[vertexIdx]. Same thing for the normals, where the normal vector with index normalIdx is stored in inNormals[normalIdx].

Now you get to read a list of triangles, with each corner of each triangle given by both a vertexIdx and a normalIdx. We'll build a new combinedVertices array/vector that contains both vertex and normal coordinates, plus a new combinedIndices index list. Pseudo code:

nextCombinedIdx = 0
indexMap = empty
loop over triangles in input file
    loop over 3 corners of triangle
        read vertexIdx and normalIdx for the corner
        if indexMap.contains(key(vertexIdx, normalIdx)) then
            combinedIdx = indexMap.get(key(vertexIdx, normalIdx))
        else
            combinedIdx = nextCombinedIdx
            indexMap.add(key(vertexIdx, normalIdx), combinedIdx)
            nextCombinedIdx = nextCombinedIdx + 1
            combinedVertices.add(inVertices[vertexIdx], inNormals[normalIdx])
        end if
        combinedIndices.add(combinedIdx)
    end loop
end loop
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top