vertex arrays and OBJ format

Started by
7 comments, last by Bakura 17 years, 5 months ago
Hi! I'm new here :) and I've just made my first REALLY REALLY simple obj loader, however, I'm having trouble. I'm using JOGL just so you know. I'm storing my mesh data in these: private FloatBuffer m_vertices; private FloatBuffer m_texCoords; private FloatBuffer m_normals; private IntBuffer m_faces; I've successfully rendered a cube however I'm having trouble with normals. I store like this in the indices buffer(m_faces): [nx1, ny1, nz1, vx1, vy1, vz1, nx2, ny2, nyz2, vx1...] Which is the correct order? :D [n,v,t]? am I even in the correct order? :P Also, can someone post a nice cube OBJ file... currently I'm using: http://www.scs.fsu.edu/~burkardt/data/obj/cube.obj with made up texture indicenumbers.. :) here is my render func: // Enable Pointers gl.glEnableClientState(GL.GL_VERTEX_ARRAY); // Enable Vertex Arrays gl.glVertexPointer(3, GL.GL_FLOAT, 0, m_vertices); gl.glEnableClientState(GL.GL_NORMAL_ARRAY); // Enable Normal Arrays gl.glNormalPointer(GL.GL_FLOAT, 0, m_normals); gl.glEnableClientState(GL.GL_TEXTURE_COORD_ARRAY); // Enable Texture Arrays gl.glTexCoordPointer(2, GL.GL_FLOAT, 0, m_texCoords); // Render // Draw All Of The Triangles At Once gl.glDrawElements(GL.GL_TRIANGLES, m_nrOfFaces, GL.GL_UNSIGNED_INT, m_faces); // Disable Pointers // Disable Vertex Arrays gl.glDisableClientState(GL.GL_VERTEX_ARRAY); gl.glDisableClientState(GL.GL_NORMAL_ARRAY); gl.glDisableClientState(GL.GL_TEXTURE_COORD_ARRAY); (yeah I know it's supposed to be m_nrOfFaces*3 but I've made my reader increasing m_nrOfFaces *3 :) ) Well the lighting on my cube looks like crap because my normals are somehow strange... anyone know how to store the index array correctly with texture, normal and vertex? [Edited by - Elrinth on October 21, 2006 4:06:25 PM]
Advertisement
Quote:Original post by Elrinth
(yeah I know it's supposed to be m_nrOfFaces*3 but I've made my reader increasing m_nrOfFaces *3 :) )

Bad move. Now your code says one thing and does another. Either change the name to m_nrOfVertices, or put the 3* at the call site instead.

Anyway, have you correctly flatterend the different arrays into arrays with common index? The object you presented should, when correctly parsed for OpenGL, contain 24 vertices. 8 corners of the cube, but each corner must be duplicated 3 times, since each shared corner can have 3 different normals.

as I've said, the cube is drawn correctly... however the normals aren't.

and yeah.. I should probably rename that var to m_facesX3 or something.. because that's what it is. ;)
A correctly drawn cube can just as well mean that you onlt read the vertices and normals, and then use the vertex indices to draw it. Of course the cubes shape will look correct then. But I was asking if you correctly flatterned the arrays. Since there are two index arrays in the object file, one for vertices and one for normals, something OpenGL doesn't like, you have to make a single index array and adapt the vertex and normal arrays to that index array. Have you done that?

Are both your vertex and normal arrays all 24 elements large? An element being a 3-component vertex or normal.
nope....
my vertex array is 8*3
my normal array is 6*3
my indice array is 12*3*2

I'm not sure how I'm supposed to correctly make my normal array 24 elements large and still have the same content.
I'm not familiar on how I flatteren something, what does it mean to do it?

How should I store the loaded points for using a fast drawing method... and which is this fast drawing method (if not gldrawelements).

[Edited by - Elrinth on October 23, 2006 6:41:49 AM]
The problem with importing OBJ, as well as many other file formats, into vertex arrays suitable for OpenGL's vertex array mechanism is that OpenGL accepts only a single index array, but uses this index array to index all arrays at the same time. The data you have uses separate index arrays for each array type. These does not play well with OpenGL. In fact, you can't use them at all (not counting immediate mode rendering).

For example, look at the first triangle. It uses vertex index 1, 7 and 5, but normal index 2, 2 and 2. Different indices for vertices and normals. What you have to do is transform the vertex, normal and index arrays so that each face uses the same index to index both the vertex and normal arrays.

An easy way that does not take advantage of shared vertices is to simply loop through all faces and copy the indexed vertices and normals to another array. That gives you a non-indexed vertex array you can draw with glDrawArrays.

A cube is a very bad example of an indexed vertex array. In fact, it is the worse case scenario for an indexed vertex array. Indexed vertex arrays are good for models with shared vertices, but a cube generally don't have any shared vertices.
I have exactly the same problem... I'm making my first ASE loader. The only solution which works was to load all the vertex, all the normals, and all the indices into different vectors (m_vVertices, m_vNormales, m_vIndices). With the Immediate Mode, it worked without any problem, but with vertex buffer objects or vertex arrays, problem because a lot of vertices are shared among some faces ! The only solution I found was to create another array of vertices, like that :

tabVertices = new float [m_iNumFaces * m_iNumPoints * 3];

for (int i = 0 ; i < m_iNumFaces ; ++i)
{
tabVertices [9 * i] = m_vVertices [m_vFaces .indexVertices [0]].x;
tabVertices [9 * i + 1] = m_vVertices [m_vFaces .indexVertices [0]].y;
tabVertices [9 * i + 2] = m_vVertices [m_vFaces .indexVertices [0]].z;

tabVertices [9 * i + 3] = m_vVertices [m_vFaces .indexVertices [1]].x;
tabVertices [9 * i + 4] = m_vVertices [m_vFaces .indexVertices [1]].y;
tabVertices [9 * i + 5] = m_vVertices [m_vFaces .indexVertices [1]].z;

tabVertices [9 * i + 6] = m_vVertices [m_vFaces .indexVertices [2]].x;
tabVertices [9 * i + 7] = m_vVertices [m_vFaces .indexVertices [2]].y;
tabVertices [9 * i + 8] = m_vVertices [m_vFaces .indexVertices [2]].z;
}

And use glDrawArrays instead of glDrawElements. But I think it's not a good solution because the model has around 59 000 vertices and 61 000 faces, so because each vertices have three coordinates, it makes 177 000 numbers. But with this method, my new array of vertices has 61000 * 9 = 549 000 numbers... It makes a lot more !

So is there a better solution than duplicate all the vertices... And if I understand well, glDrawElements is usual only when drawing without normals and texture coordinates (or if it's not, why ?).
I agree with Brother Bob, Im using 3 seperate arrays(verts normals and uvs.) just use the index array to build the three arrays and use glDrawArrays(). once you get this working switch to Vertex Buffer Objects.
Yes now I'm using VBO with three arrays and glDrawArrays, but I have to always create a new array for the vertices and an array for the textures, in order to have the same order,...

It's long to create a new array, for some models I have to create an new array of 150 000 floats :/.

This topic is closed to new replies.

Advertisement