Dibujar un número variable de líneas - PyOpenGL

Sep 27 2020

Quiero crear una función que el usuario pueda llamar varias veces, digamos drawLine (x, y), y todas estas líneas deben mostrarse a la vez (sin reemplazo). Soy nuevo en PyOpenGL (y OpenGL) y no estoy seguro de cómo hacerlo. A partir de ahora, sé cómo dibujar un número fijo de líneas usando algo como esto:

def main_loop(window):
    while (
        glfw.get_key(window, glfw.KEY_ESCAPE) != glfw.PRESS and
        not glfw.window_should_close(window)
    ):
        glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT)
        glBegin(GL_LINES)
        glVertex2f(0.0,0.0)
        glVertex2f(1.0,1.0)
        glEnd()

        glfw.swap_buffers(window)
        glfw.poll_events()

Aquí, puedo repetir los bloques glBegin (GL_LINES) - glEnd () varias veces para dibujar un número fijo de líneas con parámetros fijos. Pero, ¿cómo se hace la tarea de la línea variable?

En otras palabras, quiero crear una función, que al ser llamada con las coordenadas xey, agrega una línea al grupo de líneas que ya se muestran en la pantalla. Esta función se puede llamar varias veces según la interacción del usuario. La única forma en que puedo pensar en agregar líneas es insertando bloques glBegin-glEnd en esta función main_loop (que se muestra en el código anterior), pero ¿cómo hacerlo en tiempo de ejecución?

Respuestas

1 Rabbid76 Sep 26 2020 at 23:50

Tienes que volver a dibujar toda la escena en cada fotograma. Por lo tanto, necesita una lista en la que almacene los puntos de las líneas.

Cree una función que pueda dibujar un GL_LINE_STRIP. El argumento de la función es una lista de vértices:

def draw_line(vertices):
    glBegin(GL_LINE_STRIP)
    for vertex in vertices:
        glVertex2f(*vertex)
    glEnd()

Defina una lista vacía para los verices:

line_vertices = []

Agregue un nuevo punto a la línea mediante la interacción del usuario. Por ejemplo, cuando se presiona el botón del mouse:

def onMouseButton(win, button, action, mods):
    global line_vertices
    
    if button == glfw.MOUSE_BUTTON_LEFT:
        if action == glfw.PRESS:
            line_vertices.append(glfw.get_cursor_pos(win))

Dibuja la línea en el bucle principal de la aplicación:

while not glfwWindowShouldClose(window):
    # [...]

    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
    draw_line(line_vertices + [glfw.get_cursor_pos(window)])  

Ejemplo mínimo:

import glfw
from glfw.GLFW import *
from OpenGL.GL import *

def draw_line(vertices):
    glBegin(GL_LINE_STRIP)
    for vertex in vertices:
        glVertex2f(*vertex)
    glEnd()

line_vertices = []

def onMouseButton(win, button, action, mods):
    global line_vertices
    
    if button == glfw.MOUSE_BUTTON_LEFT:
        if action == glfw.PRESS:
            line_vertices.append(glfw.get_cursor_pos(win))

glfw.init()
display_size = (640, 480)
window = glfw.create_window(*display_size, "OpenGL window", None, None)

glfw.make_context_current(window)
glfw.set_mouse_button_callback(window, onMouseButton)

glMatrixMode(GL_PROJECTION)
glLoadIdentity()
glOrtho(0, display_size[0], display_size[1], 0, -1, 1)

glMatrixMode(GL_MODELVIEW)
glLoadIdentity()

while not glfwWindowShouldClose(window):
    
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
    draw_line(line_vertices + [glfw.get_cursor_pos(window)])  

    glfwSwapBuffers(window)
    glfwPollEvents()

glfw.terminate()