问题描述
我想创建一个用户可以多次调用的函数,例如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()