vertex arrays and display lists

Hello, all.
In my programm I used display lists. First of all I built display list:

void Render::BuildGLList()
{
//here I have collection of objects, each of them
//draws itself
}

//for example, FaceSet - one type of objects to draw
//I cannot use simply GL_QUADS or something
//like this, because faces in the set can
//be different, for example one face with 3
//vertices, the other with 4 or 5
void FaceSet::Draw()
{
//   each object has its color 
   glMaterialfv(GL_FRONT, GL_DIFFUSE, .....);
   glMaterialfv(GL_FRONT, GL_AMBIENT, .....);
   glMaterialfv(GL_FRONT, GL_SPECULAR, .....);
   glMaterialfv(GL_FRONT, GL_EMISSION, .....);

  for(int i = 0; i < numPols; ++i)
  {
     glBegin(GL_POLYGON);
     for(int j = 0, j < polDesc[i].size(); ++j)
     {
    //     here calls to glVertex
     }
     glEnd();
  }
}

After that, I simply call glCallList and I can draw scene from different viewpoints etc - it works not too slow. But It takes a lot of time to built display list and re-build it if scene is modified. So, I want to use gl vertex arrays.

1.Problem.
Due to RedBook glVertexPointer etc are not compiled in display list and executed immideatly.
2.
I tried to modify FaceSet::Draw method to use vertex arrays, now it works very fast, but… I have problem with glMaterialfv calls - my objects are not lit in a right way, they are very strange.

What should I do? I want to use vertex arrays, because display list’s building is VERY FAST with them.

Right, glVertexPointer is not compiled into display lists, but that’s fine. The drawing calls sourcing the vertex array data like glDrawArray and glDrawElements will send the vertex data from the arrays into the display list. From then on the display list is static, glVertexPointer will not have an effect on later glCallList(s).

But this won’t help much in your case because GL_POLYGON is not an independent primitive like GL_TRIANGLES or GL_QUADS and you need one drawing call per polygon, (or could use the glMultiDrawArrays extension).

Your loop could look like this:

glVertexPointer(all_your_polygons_vertices);
int first = 0;
for(int i = 0; i < numPols; ++i)
{
    int count = polDesc[i].size();
    glDrawArrays(GL_POLYGON, first, count);
    first += count;
}

If you have a lot of consecutive polygons with 3 or 4 vertices you should group them into GL_TRIANGLES and GL_QUADS. That would need some simple while-loops over the polDesc[i].size.
If you have a lot of display list rebuilding going on, you should go to vertex arrays and use vertex buffer objects (VBO) to increase performance.

To 2.) Make sure your normals are correct. You haven’t mentioned them.
Vertex arrays require the attributes per vertex! That is one normal per polygon won’t work. You need to replicate them for each vertex.

To 1)Hello. I think, I can tesselate all my polygons and work with triangle mesh.

To 2) Yes , I know - normal should be specified for each vertex. But can I use vertex arrays with glMaterial etc. ?

1.) If you do that, you might want to put your vertices into a vertex pool and use indexing drawing calls like glDrawElements and glDrawRangeElements.
A mesh of GL_TRIANGLES normally has vertices shared between multiple triangles. Using indexed drawing reduces the size of the vertex arrays and allows the hardware to reuse recently transformed vertices. Both will speed up your drawing.
Don’t build GL_TRIANGLES batches with a huge amount of vertices. Most implementations digest many batches with less than 65536 vertices (unsigned short indices!) faster than one big batch with millions of them.

You could also start remeshing the individual triangles into long triangle strips for drawing.

2.) glMaterial is not connected to how you sent geometry to OpenGL. If you haven’t enabled GL_COLOR_MATERIAL all glMaterial calls should work just fine.

Ok, thank you!