绘制可变数量的线-PyOpenGL

问题描述

我想创建一个用户可以多次调用函数,例如drawLine(x,y),并且所有这些行应一次显示(不能替换)。我是PyOpenGL(和OpenGL)的新手,我不确定该怎么做。到目前为止,我知道如何使用类似这样的方法绘制固定数量的线:

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()

在这里,我可以重复glBegin(GL_LInes)-glEnd()块多次,以绘制具有固定参数的固定数量的线。但是如何执行可变行任务?

换句话说, 我想创建一个函数,在使用x和y坐标调用函数时,会将一条线添加到已经在屏幕上显示的那一行线中。根据用户交互,可以多次调用功能。我唯一想到添加行的方法是在此main_loop函数中插入glBegin-glEnd块(如上面的代码所示),但是如何在运行时做到这一点?

解决方法

您必须在每帧中重新绘制整个场景。因此,您需要一个列表,在其中存储线的点。

创建一个可以绘制GL_LINE_STRIP的函数。该函数的参数是一个顶点列表:

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))

在主应用程序循环中画线:

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

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

最小示例:

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,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],-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()