1
votes

I am displaying a geometry (file format: .stl) with OpenGL (PyOpenGL and Python). Geometry data has the form and is assembled from triangles.

I save to VBO data of; vertices, normals and colors. As the normal is only defined per 3 vertices (triangle) and I define color vector for every vertex, the data in VBO has the form:

VBO = [v1x, v1y, v1z,...vNx, vNy, vNz,
       n1x, n1y, n1z,...nNx, nNy, nNz,
       R1, G1, B1,...RN, GN, BN]

In words; first I save all vertices, then I "append" (use of glBufferSubData) all normals (number of normals is 3-times less then number of vertices and vertice's colors) and then I append color vectors of each vertex (use of glBufferSubData). I would like to know if this is good idea, as I have problems painting each vertex in different color. The code for drawing is:

glPushMatrix()
glEnableClientState(GL_VERTEX_ARRAY)
glVertexPointer(3, 
                GL_FLOAT, 
                0, 
                None)
glEnableClientState(GL_COLOR_ARRAY)
glColorPointer(3,
               GL_UNSIGNED_BYTE,
               0,
               self.data_size_vertices+self.data_size_normals)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.vbo_id)     
glDrawArrays(GL_TRIANGLES,
             0,
             self.N_vertices)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0) # reset
glDisableClientState(GL_COLOR_ARRAY)
glDisableClientState(GL_VERTEX_ARRAY)
glPopMatrix()

I think I am having problems with glColorPointer(). Can someone point out the problem? I have also seen two more ways to save the data to VBO:

  1. create separate VBO for vertices, VBO for normals and VBO for colors
  2. one VBO but has the form: [v1, c1, v2, c2, v3, c3, n1, ....]

Is any of this two a better solution (more common in practice)? And do I have to assign a normal of triangle to each vertex although it is the same (for 3 vertices that define a triangle)? As I would like to get the display as shown below (left: current state, middle: plan, right: ideal - the point is the shading of surfaces), I would like to ask you to give me some directions about how to achieve this (using shaders). enter image description here

1
What is wrong with the image you get? The "current state" is what you should get from your code (ignoring the normals, as you currently do).derhass
@derhass OK. If I understand correctly I have to use glNormalPointer call to get the display similar to middle or right one? If I use glNormalPointer, do I have to use shaders or can this function be used without shaders and still get display like the middle or right one?lskrinjar

1 Answers

1
votes

You will have to duplicate the normal for each vertex. For OpenGL, a vertex is a set of attributes (like position, color, normal, texcoords, ...). A vertex is referenced by its index, so the i-th vertex will be composed of the i-th element of all enabled attribute arrays.

A common layout for vertex attributes is to interleave the attribs per vertex, like

v1x, v1y, v1z, n1x, n1y, n1z, R1, G1, B1, v2x, ...

That way, all data which is fetched for processing a single is local close to each other, increasing cache efficiency. You can use the stride parameter of the attrib pointers to set it up for such a layout.

The "current state" image looks to me like it should look when no normal array is enabled (and lighting still is enabled). The GL will then reuse the currently set normal vector for all vertices, resulting in the shading you see. Looking at the "ideal" image, I would conclude that the blue color is correct for the object, so I do not see what is wrong with your color array.