Search code examples
pythonopenglpyopengl

How to use glDrawArrays() with VBO - Vertex Buffer Object to display .stl geometry


I am working in Python with PyOpenGL bindings for OpenGL. I have a geometry data in .stl file and I read the file and create a data vertices that has the form:

vertices = [ -0.8528478   4.046846   -1.,..,  -1.441251   -1.07833    10.85     ]

or:

vertices = [[ -0.8528478   4.046846   -1.       ]
            [  5.244714    7.080829   -1.       ]
             ..., 
            [ -1.596363   -0.8316395  10.85     ]
            [ -1.441251   -1.07833    10.85     ]]

the data is the same in both cases, the difference is only in shape. I create the VBO with method geometry() from .stl file using model_loader:

def geometry(self):
    glEnable(GL_VERTEX_ARRAY)
    #    generate a new VBO and get the associated vbo_id
    id = 1
    #    bind VBO in order to use
    glBindBuffer(GL_ARRAY_BUFFER, self.vbo_id)
    #    upload data to VBO
    vertices = model_loader.Model_loader(filename = "body.stl").vertices
    self.N_vertices = len(vertices)
    #    data size in bytes
    dataSize = arrays.ArrayDatatype.arrayByteCount(vertices)
    print "dataSize =", dataSize
    glBufferData(GL_ARRAY_BUFFER, dataSize, vertices, GL_STATIC_DRAW)
    glBindBuffer(GL_ARRAY_BUFFER, self.vbo_id)

Drawing is done in method paintGL:

def paintGL(self):
    """
    display geometry
    """
    # Clear the screen
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    #    setup camera
    glMatrixMode(GL_MODELVIEW)
    glLoadMatrixf(self.camera.currentMatrix)
    glPushMatrix()      #we don't want each object to move the camera           
    glTranslatef(-10, 0, 0)
    #     light
    glLightfv(GL_LIGHT0, GL_POSITION, np.array([0.0, 100.0, -100.0]))
    glLightModeli( GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE )
    glColor4f(1, 1, 1, 1)
    glEnableClientState(GL_VERTEX_ARRAY)
    glVertexPointer(3, 
                    GL_FLOAT, 
                    0, 
                    0)
    glBindBuffer(GL_ARRAY_BUFFER, self.vbo_id)   
    glDrawArrays( GL_TRIANGLES, 
                  0, 
                  self.N_vertices )
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0) # reset
    glDisableClientState(GL_VERTEX_ARRAY)
    glPopMatrix() 

The problem is, that it only displays one point if I change to GL_POINTS and when GL_TRANGLES is used is doesn't display anything!

Before working with VBO I display the geometry only with the glDrawArrays() and the geometry was/is displayed without problems (no errors). But when trying to implement VBO it is not working. How can it be solved?


Solution

  • I have solved the problem. If anyone else will have similar problem, here is the solution. As I am using 64-bit version of python (including numpy). The vertices are type numpy.array() and were type (dtype) float64.

    I changed the line in the model loader from:

    self.vertices =  np.array(self.vertices)
    

    to:

    self.vertices =  np.array(self.vertices, dtype='float32')
    

    Based on that I would say that (older) GPU only support float32. Or do GPUs support float64? If anyone can clarify this it would be great.