Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 8 of 8

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

  1. #1
    Junior Member Newbie
    Join Date
    Nov 2013
    Posts
    20

    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:
    Code :
    vertices = [ -0.8528478   4.046846   -1.,..,  -1.441251   -1.07833    10.85     ]
    or
    Code :
    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:
    Code :
    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:
    Code :
    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?

  2. #2
    Senior Member OpenGL Pro
    Join Date
    Jan 2012
    Location
    Australia
    Posts
    1,101
    probably not your error but
    Code :
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0) # reset

    should be
    Code :
     
    glBindBuffer(GL_ARRAY_BUFFER,0) # reset

    I can't see all you data but the vertices seem to be around an x value of -1 and your are translating another -10 - are you sure they are visible on the display?

  3. #3
    Junior Member Newbie
    Join Date
    Nov 2013
    Posts
    20
    Thanks for the help. They are seen on the display, because I displayed the same data (format) but without the VBO with the following code:
    Code :
    glEnableClientState(GL_VERTEX_ARRAY)
    glVertexPointer(3, GL_FLOAT, 0, vertices)
    glDrawArrays(GL_TRIANGLES, 0, len(vertices))
    glDisableClientState(GL_VERTEX_ARRAY)
    I tried replacing GL_ELEMENT_ARRAY_BUFFER with GL_ARRAY_BUFFER as suggested but it raised an error:
    Code :
    WindowsError: exception: access violation reading 0x0000000000000000
    Are you sure that it should be changed?

    I am using glOrtho() projection and as I understand to correctly display all the data you have to translate it away from you in z direction so all the data is put backward. Or am I wrong and I can remove this line?
    I have to say I think I solved the problem. The problem was in my model loader and its line is changed from:
    Code :
    vertices =  np.array(self.vertices)
    to
    Code :
    vertices =  np.array(self.vertices, dtype='float32')
    If I understand correctly as I use python 2.7.5 64bit and also (64-bit) numpy version (also 64-bit) the vertices data was numpy dtype='float64' and this data was displayed with GPU without VBO, but when I display vertices data using VBO the GPU did not display data correctly. From this I can deduce (correctly?) that (my or all) GPUs do not support VBOs with type 'float64'. Is any truth in this or am I totally wrong?

  4. #4
    Senior Member OpenGL Pro
    Join Date
    Jan 2012
    Location
    Australia
    Posts
    1,101
    I tried replacing GL_ELEMENT_ARRAY_BUFFER with GL_ARRAY_BUFFER as suggested but it raised an error:


    You should not get an error.

    Code :
     
    Code :
     glBindBuffer(GL_ARRAY_BUFFER, self.vbo_id)   
        glDrawArrays( GL_TRIANGLES, 
                      0, 
                      self.N_vertices )
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0) # reset

    This code binds the vertex buffer before the draw - which is correct; then bindings null to the element (index) buffer which does not hurt but does nothing since you are not using an element buffer.
    The code change I suggested is to bind null to the vertex buffer after your draw. This should not cause an error.

    glOrtho() projection and as I understand to correctly display all the data you have to translate it away from you in z direction

    In ortho projections there is no perspective so all objects appear the same size no matter how far they are along the camera z axis. The only reason to change the z value is let the depth buffer order the objects from nearest the camera to furtherest. Orth projections is often uses for 2D rendering like when you are writing a gui interface so all z-values are just set to 0.

    vertices data was numpy dtype='float64'
    Vertex buffers in OpenGL are 32-floats not 64-bit. (That is a slight lie - on some graphics cards it is possible to use 64-bit but with specialized calls). If you are supplying data in 64-bit you need to convert it before loading the vertex buffer.

  5. #5
    Junior Member Newbie
    Join Date
    Nov 2013
    Posts
    20
    You should not get an error.
    You are right. I tried once again and it is working. If I understand correctly you suggested to change the code:
    Code :
    glEnableClientState(GL_VERTEX_ARRAY)
    glVertexPointer(3, GL_FLOAT, 0, vertices)
    glBindBuffer(GL_ARRAY_BUFFER, self.vbo_id)
    glDrawArrays(GL_TRIANGLES, 0, len(vertices))
    glBindBuffer(GL_ARRAY_BUFFER, 0) # reset
    glDisableClientState(GL_VERTEX_ARRAY)
    to:
    Code :
    glEnableClientState(GL_VERTEX_ARRAY)
    glVertexPointer(3, GL_FLOAT, 0, None)
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.vbo_id)  
    glDrawArrays(GL_TRIANGLES, 0, self.N_vertices)
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0) # reset
    glDisableClientState(GL_VERTEX_ARRAY)
    I have to look what is best for my application GL_ELEMENT_ARRAY_BUFFER or GL_ARRAY_BUFFER. Can you give any practical guidelines about it?
    In ortho projections there is no perspective so all objects appear the same size no matter how far they are along the camera z axis. The only reason to change the z value is let the depth buffer order the objects from nearest the camera to furtherest. Orth projections is often uses for 2D rendering like when you are writing a gui interface so all z-values are just set to 0.
    Thanks for the warning. I was going trough some tutorials and they translated everything away from the camera if the camera was to close to the object and the object was not displayed properly. As I read the CAD softwares uses ortographic (parallel) projection and this is exactly what I need - no distortions in z direction
    Vertex buffers in OpenGL are 32-floats not 64-bit. (That is a slight lie - on some graphics cards it is possible to use 64-bit but with specialized calls). If you are supplying data in 64-bit you need to convert it before loading the vertex buffer.
    Thanks for clearing that out and confirming that I was thinking in the right direction
    I will just transform the datatype when assigning (saving) it to VBO (it's the easiest solution and I hope, I will not have to change it again in the future).

  6. #6
    Senior Member OpenGL Pro
    Join Date
    Jan 2012
    Location
    Australia
    Posts
    1,101
    I have to look what is best for my application GL_ELEMENT_ARRAY_BUFFER or GL_ARRAY_BUFFER. Can you give any practical guidelines about it?

    Element (index) buffers will usually save some space in the vertex buffer eg a quad would require 6 vertices with
    GL_ARRAY_BUFFER or 4 vertices and 6 indices with GL_ELEMENT_ARRAY_BUFFER . I don't believe you will see a performance difference since both can cache vertices equally well (or badly)

  7. #7
    Junior Member Newbie
    Join Date
    Nov 2013
    Posts
    20
    Thanks for the help and clear explanations. I would like to ask another question more related to OpenGL version(s) (than GL_ELEMENT_ARRAY_BUFFER or GL_ARRAY_BUFFER). The code I am working on runs w/o problems on:
    1. GL Version: 4.2.12217 Compatibility Profile Context 12.104.0.0, GL Renderer: AMD Radeon HD 6300M Series, GL Vendor: ATI Technologies Inc.
    2. GL Version: 4.4.0, GL Renderer: NVS 5400M/PCIe/SSE2, GL Vendor: NVIDIA Corporation

    but it returns an error when I try to run the code on integrated GPU:
    1. GL Version: 4.0.0 - Build 9.17.10.2843, GL Renderer: Intel(R) HD Graphics 4000, GL Vendor: Intel

    And the error:
    Code :
    Traceback (most recent call last):
      File "C:\...\visualization_engine_V6.py", line 120, in initializeGL
        self.geometry()
      File "C:\...\visualization_engine_V6.py", line 167, in geometry
        glEnable(GL_VERTEX_ARRAY)
      File "errorchecker.pyx", line 50, in OpenGL_accelerate.errorchecker._ErrorChecker.glCheckError (src\errorchecker.c:854)
    OpenGL.error.GLError: GLError(
    	err = 1280,
    	description = 'invalid enumerant',
    	baseOperation = glEnable,
    	cArguments = (GL_VERTEX_ARRAY,)
    )
    Traceback (most recent call last):
      File "C:\Users\Ales\Dropbox\python\src\visualization_engine\visualization_engine_V6.py", line 156, in paintGL
        glBindBuffer(GL_ARRAY_BUFFER, self.vbo_id)
    AttributeError: 'OpenGLWidget' object has no attribute 'vbo_id'
    It returns an error if I use GL_ELEMENT_ARRAY_BUFFER or GL_ARRAY_BUFFER calls. Can you point out where to look for the problem? The OpenGL versions are different...

    Isn't the case that, lets say, version 4.2 supports all the functions from the first version (1.0 or 0.1) to version 4.1 and the new added functions to version 4.2?
    And the code:
    Code :
            glEnableClientState(GL_VERTEX_ARRAY)
            glEnable(GL_VERTEX_ARRAY)
            #    generate a new VBO and get the associated vbo_id
            _id = 1
            self.vbo_id = glGenBuffers (_id)
            #    bind VBO in order to use
            glBindBuffer(GL_ARRAY_BUFFER, self.vbo_id)
            #    upload data to VBO
            vertices = model_loader.Model_loader(filename = "udarni_vzvod.stl").vertices
            self.N_vertices = len(vertices)
            #    data size in bytes
            self.dataSize = arrays.ArrayDatatype.arrayByteCount(vertices)
            glBufferData(GL_ARRAY_BUFFER, self.dataSize, vertices, GL_STATIC_DRAW)
            glBindBuffer(GL_ARRAY_BUFFER, self.vbo_id)
            glDisableClientState(GL_VERTEX_ARRAY)

  8. #8
    Junior Member Newbie
    Join Date
    Nov 2013
    Posts
    20
    I fixed the problem. The solution is to remove:
    Code :
    glEnable(GL_VERTEX_ARRAY)
    in the upper (main) code

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •