(PyOpenGL) Vertex Buffer Objects

Hier werden alle anderen GUI-Toolkits sowie Spezial-Toolkits wie Spiele-Engines behandelt.
Antworten
Barcellona
User
Beiträge: 74
Registriert: Dienstag 25. Mai 2010, 12:10

Hallo zusammen,

ich kämpfe mich gerade durch ein Buch zu OpenGL 3.0 und komme bei einem Beispiel nicht weiter.
Die Beispiel sind im Buch in C++-Code geschrieben und ich versuche sie in Python durchzuführen.

Und zwar soll ein Punkt durch erstellen eines Vertex Buffer Objects gezeichnet werden.

Hier ein Ausschnitt des Codes:

Code: Alles auswählen

import pygame
#from sys import exit
import sys

from OpenGL.GL import *
from OpenGL.GLU import *



screen = (800,600)

pygame.init()
surface = pygame.display.set_mode(screen, pygame.OPENGL|pygame.DOUBLEBUF, 16)
pygame.display.set_caption("Hallo Welt!")

...

# VERTEX BUFFER OBJECTS
    vbo_vertex=[[0,0,-2]]
    
    m_vertexBuffer=GLuint(0) # init the Buffer in Python!
    glGenBuffers(1, m_vertexBuffer) # generate a buffer for the vertices
    glBindBuffer(GL_ARRAY_BUFFER, m_vertexBuffer) #bind the vertex buffer
    glBufferData(GL_ARRAY_BUFFER, sys.getsizeof(vbo_vertex), vbo_vertex[0], GL_STATIC_DRAW)
    
    glBindBuffer(GL_ARRAY_BUFFER, m_vertexBuffer) #bind the vertex buffer
    glVertexPointer(3, GL_FLOAT, 0, BUFFER_OFFSET(0))
    
    glEnableClientState(GL_VERTEX_ARRAY) # enable Vertex Array
    glDrawArrays(GL_POINTS, 0, 1) # draw a single point
    glDisableClientState(GL_VERTEX_ARRAY) # disable the Vertex Array
    
    pygame.display.flip()
Probleme machen mir vor allem glGenBuffer und glBufferData.
glGenBuffer nimmt in dem Beispiel 2 Parameter - Anzahl der zu erstellenden Buffer und einen Pointer auf einen Array, der die Buffer-Namen speichert.
PyOpenGL gibt mir allerdings den Fehler, das glGenBuffer nur 1 Parameter nimmt :?
Bei glBufferData kommt es auch zu einem Fehler, der 2.Parameter soll die Byte-Größe des Vertex-Array sein...

Weiß jemand, was ich ändern muss?
Oder hat jemand ein bisschen Beispiel-Code in PyOpenGL der funktioniert?
BlackJack

@Barcellona: Ohne jetzt nachgeschaut zu haben, denke ich die `glGenBuffers()`-Frage kann man mit gesundem Menschenverstand lösen. Das in C dort die Anzahl und ein Array übergeben werden muss, liegt ja daran, dass in C die Arrays nicht "wissen" wie lang sie sind. Bei der Übergabe ist das nicht mehr als eine Adresse im Speicher ab der die Array-Elemente liegen. Wenn C-Arrays bei der Python-API für diese Bibliotheken mit Listen ersetzt werden, braucht man die Länge nicht mehr extra übergeben, denn Python-Listen kennen ihre eigene Länge. Also wird dort wahrscheinlich nur die Liste als Argument nötig sein.
Barcellona
User
Beiträge: 74
Registriert: Dienstag 25. Mai 2010, 12:10

Hmm, danke für die Antwort. Aber ich glaube, dass das so nicht ganz stimmt hier.

Das 1-Argument das glGenBuffers() haben will ist nämlich 'n' - die Anzahl der Buffer-Namen, die erstellt werden soll.
Es fliegt also das 2. Argument im Vergleich zu C++ raus, der Name der Liste, die diese Namen speichert.
Und das verstehe ich nicht...
Hab' bisher auch noch keine Lösung ergoogeln können :(
glBufferData, klappt ja auch noch nicht.
BlackJack

Okay, jetzt denke ich dass es Zeit für ein minimales "lauffähiges" Codebeispiel und die exakte Fehlermeldung wird.
Barcellona
User
Beiträge: 74
Registriert: Dienstag 25. Mai 2010, 12:10

Code bisher:

Code: Alles auswählen

import pygame
#from sys import exit
import sys

from OpenGL.GL import *
from OpenGL.GLU import *



screen = (800,600)

pygame.init()
surface = pygame.display.set_mode(screen, pygame.OPENGL|pygame.DOUBLEBUF, 16)
pygame.display.set_caption("Hallo Welt!")


def reshape((width,height)):
    glViewport(0, 0, width, height) # Bereich in dem gezeichnet wird
    glMatrixMode(GL_PROJECTION) #deprecated in OpenGL 3.0
    glLoadIdentity() # deprecated
    gluPerspective(60, 1.0*width/height, 0.1, 1000.0) # deprecated
    glMatrixMode(GL_MODELVIEW) # deprecated

def init():
    glEnable(GL_DEPTH_TEST) #enables depth testing 
    glClearColor(1.0, 1.0, 1.0, 1.0) # Hintergrundfarbe (r,g,,b,alpha)
    reshape(screen)
    global quad_angle
    quad_angle=0

def get_event():

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            exit()

def draw():
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT) #clears the screen

    glLoadIdentity()  #deprecated / veraltet in OpenGL 3.0
                            # reset the model matrix by loading the identity matrix
    gluLookAt(0, 0, 6, 0, 0, -100, 0, 1 ,0) # Ausrichtung der Kamera # deprecated
                 # Koordinaten der Kamera(x,y,z); wohin wird geblickt? (x,y,z), wo ist oben? (x,y,z)
    
    # Move left 1.5 units and into the screen 6.0 units
    glTranslatef(-1.5, 0.0, -6.0)
    
     # Rotate the quad on the X-axis
    glRotatef(quad_angle, 1.0, 0.0, 0.0) # (angle in degrees, x, y, z)
    
    # Drawing in IMMEDIATE MODE => deprecated in OpenGL 3.0
    glBegin(GL_QUADS) # Viereck
    glColor(0, 0, 1.0)  # Farbe (r,g,b) each with 0.0 = none and 1.0 = full
    
    glVertex3f(1, -1, -1)  # oben links
    glVertex3f(1, -1, 1)   # oben rechts
    glVertex3f(-1, -1, 1)  # unten rechts
    glVertex3f(-1, -1, -1) # unten links
    
    glVertex3f(1, 1, -1)  #5
    glVertex3f(-1, 1, -1) # 8
    glVertex3f(-1, 1, 1)  # 7
    glVertex3f(1, 1, 1)   # 6
    
    glVertex3f(1, -1, -1)  # 1
    glVertex3f(1, 1, -1)   # 5
    glVertex3f(1, 1, 1)  # 6
    glVertex3f(1, -1, 1) # 2
    
    # vorne
    #glVertex3f(1, -1, -1)   # 2
    #glVertex3f(1, 1, 1)  # 6
    #glVertex3f(-1, 1, 1)  # 7
   # glVertex3f(-1, -1, 1) # 3
   
   # glVertex3f(-1, -1, 1) #3
   # glVertex3f(-1, 1, 1)  # 7
   # glVertex3f(-1, 1, -1) # 8
   # glVertex3f(-1, -1, -1) #4

    glEnd()   
    
     # VERTEX ARRAYS
    
    myarray=[[-2,-2,0,2,-2,0,0,2,0]] # [] for each figure
    mycolors=[[0.5,1,0.2,1,1,0,0,1,1]] # [] for each figure 
    
    glEnableClientState(GL_COLOR_ARRAY) # enable Vertex Array
    glColorPointer(3, GL_FLOAT, 0, mycolors[0])
    
    glEnableClientState(GL_VERTEX_ARRAY) # enable Vertex Array
    glVertexPointer(3, GL_FLOAT, 0, myarray[0]) # tell OpenGL where the vertices are
    glDrawArrays(GL_TRIANGLES, 0, 3) # draw(what?, starting index, number of elements to draw)
    glDisableClientState(GL_VERTEX_ARRAY) # disable the Vertex Array
    
    glDisableClientState(GL_COLOR_ARRAY) # disable the Vertex Array
  
    
    
    # VERTEX BUFFER OBJECTS
    vbo_vertex=[[0,0,-2]]
    
    #m_vertexBuffer=GLuint(0) # init the Buffer in Python!
    m_vertexBuffer=glGenBuffers(1)#m_vertexBuffer) # generate a buffer for the vertices
    glBindBuffer(GL_ARRAY_BUFFER, m_vertexBuffer) #bind the vertex buffer
    glBufferData(GL_ARRAY_BUFFER, sys.getsizeof(vbo_vertex), vbo_vertex[0], GL_STATIC_DRAW) 
    
    glBindBuffer(GL_ARRAY_BUFFER, m_vertexBuffer) #bind the vertex buffer
    glVertexPointer(3, GL_FLOAT, 0, BUFFER_OFFSET(0))
    
    glEnableClientState(GL_VERTEX_ARRAY) # enable Vertex Array
    glDrawArrays(GL_POINTS, 0, 1) # draw a single point
    glDisableClientState(GL_VERTEX_ARRAY) # disable the Vertex Array
    # funktioniert noch nicht
    
    pygame.display.flip()

def main():
    init()
    maxfps = 100
    clock = pygame.time.Clock()
    while True:
        clock.tick(maxfps)
        draw()
        get_event()
        
        global quad_angle
        quad_angle -= 0.15

if __name__ == "__main__":
    main()

Die Fehlermeldung ist: NotImplementedError: Haven't implemented type-inference for lists yet # aus der Zeile glBufferData

Jemand eine Idee?

PS: http://ruby-opengl.rubyforge.org/tutori ... er_objects Diese Seite behandelt den Vorgang in Ruby
BlackJack

Naja, anscheinend kann man dort (noch) keine Liste übergeben, sondern muss irgend etwas anderes nehmen was als Array durchgeht. Für Listen ist das anscheinend noch nicht implementiert.

In der PyOpenGL-Doku im Dokument PyOpenGL for OpenGL Programmers stehen im Abschnitt "Array Handling" noch eine Menge anderer Typen. Das Ruby-Beispiel scheint den Weg über Zeichenketten zu gehen. Auf Python übertragen wäre das also mit dem `struct`-Modul machbar. Ich würde wahrscheinlich `numpy`-Arrays verwenden, wenn das als Abhängigkeit okay ist, oder `ctypes`-Arrays, wenn es bei der Standardbibliothek bleiben soll.
Barcellona
User
Beiträge: 74
Registriert: Dienstag 25. Mai 2010, 12:10

http://ltslashgt.com/2007/08/31/vertex- ... -pyopengl/

Scheint wohl so zu gehen, bekomme aber bisher auch einen Fehler für den NumPy-Array.
"dtype" scheint falsch zu sein. :?
BlackJack

@Barcellona: Ich denke mal Du musst immer auch ein wenig darauf achten für welches PyOpenGL das geschrieben ist. Der Blog-Eintrag ist vielleicht noch für 2.x!?
Barcellona
User
Beiträge: 74
Registriert: Dienstag 25. Mai 2010, 12:10

Code: Alles auswählen

    NineFloats= c_float * 10
    vbo_vertex=[]
    vbo_vertex.append(NineFloats(-1,-0.5,-2,1,-0.5,-2,0,0.5,-2))

    #m_vertexBuffer=GLuint(0) # init the Buffer in Python!
    m_vertexBuffer=glGenBuffers(1)#m_vertexBuffer) # generate a buffer for the vertices
    glBindBuffer(GL_ARRAY_BUFFER, m_vertexBuffer) #bind the vertex buffer
    glBufferData(GL_ARRAY_BUFFER, vbo_vertex[0], GL_STATIC_DRAW) 
          #sys.getsizeof(vbo_vertex),
    #glBindBuffer(GL_ARRAY_BUFFER, m_vertexBuffer) #bind the vertex buffer
    glVertexPointer(3, GL_FLOAT, 0, 0)
                                               # BUFFER_OFFSET(0)
    glEnableClientState(GL_VERTEX_ARRAY) # enable Vertex Array
  #  glDrawArrays(GL_POINTS, 0, 1) # draw a single point
    glDrawArrays(GL_TRIANGLES,0,3) # draw a triangle
    glDisableClientState(GL_VERTEX_ARRAY) # disable the Vertex Array
    # funktioniert noch nicht
Hab' jetzt alle Fehlermeldungen rausbekommen, aber das malen klappt noch nicht.
Habe es auf ein Dreieck geändert, erscheint aber nicht auf dem Schirm.
Aber wenigstens keine Fehlermeldungen durch den Code.
Sieht jemand noch was fehlt, damit es gezeichnet wird?
Benutzeravatar
veers
User
Beiträge: 1219
Registriert: Mittwoch 28. Februar 2007, 20:01
Wohnort: Zürich (CH)
Kontaktdaten:

NineFloats= c_float * 10?
glBufferData(GL_ARRAY_BUFFER, vbo_vertex[0], GL_STATIC_DRAW) , bist du dir sicher das du da vbo_vertex[0] meinst?

Code: Alles auswählen

class VboModel(object):
    def __init__(self, path):
        with open(path, "rb") as f:
            data = f.read()
        self.size = len(data)/4
        self.vboid = c.c_ulong()
        glGenBuffers(2, c.pointer(self.vboid))
        glBindBuffer(GL_ARRAY_BUFFER, self.vboid)
        glBufferData(GL_ARRAY_BUFFER, len(data), data, GL_STATIC_DRAW)
        print self.size*4

    def draw(self):
        #glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT)
        glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT)
        glBindBuffer(GL_ARRAY_BUFFER, self.vboid)
        glEnableClientState(GL_VERTEX_ARRAY)
        glVertexPointer(3, GL_FLOAT, 0, 0)
        glDrawArrays(GL_TRIANGLES, 0, self.size)
        glBindBuffer(GL_ARRAY_BUFFER, 0)
        glPopClientAttrib()
So habe ich das mal mit Pyglet gemacht.

http://www.pyglet.org/doc/api/pyglet.gr ... odule.html ist aber eine schönere Abstraktion für VBO.

Gruss,
Jonas
[url=http://29a.ch/]My Website - 29a.ch[/url]
"If privacy is outlawed, only outlaws will have privacy." - Phil Zimmermann
Barcellona
User
Beiträge: 74
Registriert: Dienstag 25. Mai 2010, 12:10

veers hat geschrieben:NineFloats= c_float * 10?
Ok, c_float * 9 :mrgreen: Vorher hiess der Array TenFloats (zu meiner Verteidigung :P )

vbo_vertex[0] müsste denk' ich richtig sein. Hab' doch den NineFloats-Array in eine Liste geschoben...
oder ist da was falsch?
Antworten