Sign in to follow this  
VansFannel

vertex, normal and texcoordinate indices

Recommended Posts

VansFannel    101
Hello.

I have a question about glDrawElements and vertex, normal and texcoordinate indices.

If I have geometric vertex, vertex normals and texture vertices, each with its own indices.

Which of those indices may I use?

If I have this code:

glVertexAttribPointer(vertexHandle, 3, GL_FLOAT, GL_FALSE, 0,
(const GLvoid*) &teapotVertices[0]);
glVertexAttribPointer(normalHandle, 3, GL_FLOAT, GL_FALSE, 0,
(const GLvoid*) &teapotNormals[0]);
glVertexAttribPointer(textureCoordHandle, 2, GL_FLOAT, GL_FALSE, 0,
(const GLvoid*) &teapotTexCoords[0]);

glEnableVertexAttribArray(vertexHandle);
glEnableVertexAttribArray(normalHandle);
glEnableVertexAttribArray(textureCoordHandle);

glBindTexture(GL_TEXTURE_2D, thisTexture->mTextureID);
glUniformMatrix4fv(mvpMatrixHandle, 1, GL_FALSE,
(GLfloat*)&modelViewProjection.data[0] );
glDrawElements(GL_TRIANGLES, NUM_TEAPOT_OBJECT_INDEX, GL_UNSIGNED_SHORT,
(const GLvoid*) &teapotIndices[0]);

What should hold teapotIndices?

Thanks.

Share this post


Link to post
Share on other sites
karwosts    840
Quote:

If I have geometric vertex, vertex normals and texture vertices, each with its own indices.

Which of those indices may I use?


You can't use any of them as is.

You have to generate a new set of data and indices such that vertices, vertex normals, and texture vertices all have the same index. It's not a trivial operation.

If you search here for VBO and OBJ, you'll find that this exact question has been answered and discussed hundreds of times before. Or just use ASSIMP if you don't want to do it yourself.

Share this post


Link to post
Share on other sites
karwosts    840
Quote:
Original post by VansFannel
Thanks for your answer but, what should I do?


Quote:
Original post by karwosts
If you search here for VBO and OBJ, you'll find that this exact question has been answered and discussed hundreds of times before.


Search for "vbo obj" returns:

OBJ to indexed VBO - GameDev.Net Discussion Forums
VBO - Vertices, Indices, UVs in one VBO and their indices in ...
Rendering .OBJ Meshes using VBOs - GameDev.Net Discussion Forums
[solved]wavefront obj and vbo/ibo - GameDev.Net Discussion Forums
VBO Loading/Drawing C++ - GameDev.Net Discussion Forums
Opengl going immediate mode to buffered drawing - GameDev.Net ...

and that's just from the first 10 results.

Share this post


Link to post
Share on other sites
VansFannel    101

I am stupid, but I can't find what I'm looking for.

I'm very very very new on OpenGL ES 2.0 development.

I only want to know if I have to order them.

If have this:

f v1/vt1/vn1 v2/vt2/vn2 v3/vt3/vn3

I must use the following array:

v1/v2/v3 vt1/vt2/vt3 vn1/vn2/vn3

I want to use glDrawElements, so I need indices for its third parameter.

Thanks.

Share this post


Link to post
Share on other sites
wolfscaptain    200
The point is that while OBJ files relate to the glBegin/End way, they can't EVER work with newer methods.

Like I posted in the other two threads in this page (sigh...), you must "flatten" them to linear data.
You don't have to do it all the way if you don't need to, of course, since having indices helps the GPU work better with caching, but you need to fix shared data.

A 3D box is an excellent example of a model that must be flattened all the way.
With glBegin/End it could have 8 vertices, texcoords, and normals.
With anything newer it must have 24 of each.

The main difference between, say, the above cube and an actual model is that an actual model is continuous, while a box isn't. A real model usually wont have these "edges", it would be all roundish and in one piece.

This is why while the indices may be different, it is usually just to spare on file size by compacting many values into one.
An example to this would be a big 2D grid, where you might have 1000x1000 vertices and texcoords, but can get along just fine with 1 normal if you didn't edit normals.
In this case, you can just "add" the missing data and fix the indices. This way you will still have at the end a full list of indices, and a working model.

It's easier, however, to just go all the way and completely turn the model into linear data, so I suggest you to do that unless your world is very detailed and actually needs to be efficient.
You can always make it more efficient if you notice this is a bottleneck (remember, optimize when you NEED to, not when you WANT to).

Share this post


Link to post
Share on other sites
dpadam450    2357
A vertex that is at the same location is different if any of its attributes are different, they must be split. It isn't too hard to figure out if you can use one of those vertices, or you need to duplicate and give it new texcoords/normal.

Share this post


Link to post
Share on other sites
szecs    2990
Quote:
Original post by VansFannel
Sorry, I've forgotten to metion that I'm working with OpenGL ES 2.0 for Android.


The actual problem (linearizing the data) has nothing to do with this. Do you actually read the comments in this thread? I guess not...

Share this post


Link to post
Share on other sites
CableGuy    1335
Lets say you have a vertex attribute arrays called posArray,normalArray and uvArray. The way normal rendering works is by specifying a list of indices into these arrays that forms your primitives, so assuming you are rendering triangles and lets say your indices list is 0,1,2,3,4,5 then you got two triangles here
first one is 0,1,2 which means that it's position is posArray[0],posArray[1],posArray[2] it's normals are normalArray[0],normalArray[1],normalArray[2] and so on.
The problem lies if for example, you are given a triangle which has different indices for the different arrays for example 0,1,2 for position 7,100,2 for normals and so on. In this case you will have to duplicate you vertices.

Hope this clarifies a bit.

Share this post


Link to post
Share on other sites
V-man    813
It really isn't difficult to write the algorithm for duplicating the vertex and normals and texcoords.
If you have a line like
f 1/3/4 5/5/5 2/4/3

that is a triangle.
First, we must subtract by 1 so we get
f 0/2/3 4/4/4 1/3/2

now, let's do it

j=0;
k=0;
m=0;
for(i=0; i<3; i++)
{
new_vertexarray[k]=vertexarray[vertex_index[j]*3]; //X
new_vertexarray[k+1]=vertexarray[vertex_index[j]*3+1]; //Y
new_vertexarray[k+2]=vertexarray[vertex_index[j]*3+2]; //Z

new_normalarray[k]=normalarray[normal_index[j]*3]; //NX
new_normalarray[k+1]=normalarray[normal_index[j]*3+1]; //NY
new_normalarray[k+2]=normalarray[normal_index[j]*3+2]; //NZ

new_texcoordarray[m]=texcoordarray[tex_index[j]*2]; //S
new_texcoordarray[m+1]=texcoordarray[tex_index[j]*2+1]; //T
k+=3;
m+=2;
j++;
}


in the end, new_vertexarray would have to be of size 9 (3 vertex)
in the end, new_normalarray would have to be of size 9 (3 vertex)
in the end, new_texcoordarray would have to be of size 6 (3 vertex)

You also need a new_indexarray.
Needs to be size 3.
The values will start from 0 and go up.

I suggest you to think and write whatever algorithm you want. If you are not good with algorithms, forget about programming.

Share this post


Link to post
Share on other sites
VansFannel    101
I've tried this method and it doesn't work for me.

I'm trying to draw a cube and I'm getting a flat square.

These are my vertex and fragment shader:


static const char* vertexShader = "

attribute vec4 vertexPosition;

uniform mat4 modelViewProjectionMatrix;

void main()
{
gl_Position = modelViewProjectionMatrix * vertexPosition;
}
";

static const char* fragmentShader = "

precision mediump float;

void main()
{
gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);
}
";




[Edited by - VansFannel on December 10, 2010 5:59:40 AM]

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this