PDA

View Full Version : Problem with VBOs :)



OnTheRun
10-14-2004, 12:39 AM
Hi all,
I'm trying to get VBOs running. Right now I have an array with the model-data in it, which I pass to the following functions:

glEnableClientState(GL_VERTEX_ARRAY);

glGenBuffersARB(1, &buffer2);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffer2);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(data), data, GL_STATIC_DRAW_ARB);I'm drawing it with:


glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffer2);
glVertexPointer(3, GL_FLOAT, 0, 0);

glDrawArrays(GL_TRIANGLES, 0, 2880);This works pretty good right now.

So I thought about implementing the normals with a normal array, which I read out:

for(int i=0; i<numFaces; i++)
{
glNormal3f(normals[i].v[0], normals[i].v[1], normals[i].v[2]);
}As I was using glVertex3f these coordinates worked without problems, so I read the coordinates into a file, copied them by hand in an array called normalz and tried to do a normal-array with them:


glEnableClientState(GL_NORMAL_ARRAY);

glGenBuffersARB(1, &amp;norm);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, norm);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(normalz), normalz, GL_STATIC_DRAW_ARB);I tried to bind them with:

glBindBufferARB(GL_ARRAY_BUFFER_ARB, norm);
glNormalPointer(GL_FLOAT, 0, NULL);But now the object looks kindof weird. Some normals work, some don't.
Any hints what I'm doing wrong?

Thanks and greetings

Relic
10-14-2004, 02:47 AM
Originally posted by OnTheRun:

for(int i=0; i<numFaces; i++)
{
glNormal3f(normals[i].v[0], normals[i].v[1], normals[i].v[2]);
}For vertex arrays you need a normal per vertex, the above loop looks like normal per face.
(You know there is glNormal3fv? ;) )

OnTheRun
10-14-2004, 02:52 AM
Thank you for your answer.
Ok, I see now :)
The problem is, i'm taking the normals out of an .obj-file, made with maya, which describes each normal for a face.
For example:


vn -0.306219 0.895231 -0.323715
f 1//1 2//2 3//3The description of the .obj-format says:

f v1[/vt1][/vn1] v2[/vt2][/vn2] v3[/vt3][/vn3] ...

So the first face has the above normals for example. How do I get the normals per vertex?

CrazyButcher
10-14-2004, 12:50 PM
another problem you will bump into is, that you need to store all per vertex attribs in a single VBO, as you can bind only one at a time
one ARRAY and one ELEMENT_ARRAY buffer at a time.

so you would store your vertex data interleaved like
normal (x,y,z) pos (x,y,z)

To get normals per vertex you could run over all tris and add the normals to the vertex normals affected.

like
face (vertex a, vertex b, vertex c) : normal n
a.normal += n
b.normal += n
c.normal += n

then when you are finished you "normalize" all vertex normals.

This would make your object smooth, to get hard edges and smooth parts, you would need to create multiple vertices per edges, depending on if you want a hard edge.

Ikaruga
10-14-2004, 02:01 PM
The problem is (I'm willing to wager) that you are generating two buffer objects when you only need one. Remember conceptually buffer objects are just chunks of video memory. So what you should do is generate a buffer of a size equal to at least the sum of the sizes of vertices and normals. Then store them in that buffer in some format that gl*Pointer can handle (like VVVNNNVVVNNN or VVVVVVV...NNNNNN... or whatever) and set the pointers appropriately.

Then when you bind your buffer object and set your pointers, the call to glDrawElements will dereference the proper data and give you your nicely organized vertices!

Relic
10-14-2004, 09:59 PM
Originally posted by CrazyButcher:
another problem you will bump into is, that you need to store all per vertex attribs in a single VBO, as you can bind only one at a time
one ARRAY and one ELEMENT_ARRAY buffer at a time.

so you would store your vertex data interleaved like
normal (x,y,z) pos (x,y,z)
While storing the data interleaved in a single buffer is a good idea, it's wrong that you must put all the data in one array buffer. Unfortunately the spec has no nice example but it's possible to put each attribute into a separate vertex buffer object. That's nice if you have some static and some dynamic data. Group them into separate buffer objects.

The BindBuffer call just select a buffer, only the gl*Pointer calls associate buffers with attributes. It looks like this:

BindBufferARB(ARRAY_BUFFER_ARB, 1);
VertexPointer(4, FLOAT, 0, BUFFER_OFFSET(0));
BindBufferARB(ARRAY_BUFFER_ARB, 2);
ColorPointer(4, UNSIGNED_BYTE, 0, BUFFER_OFFSET(0));

CrazyButcher
10-15-2004, 12:44 AM
thanks Relic, wasnt aware of that, that opens some new possibilities to optimize =)