Draw variable number of lines - PyOpenGL

1.7k views Asked by At

I want to create a function that user can call multiple times, say drawLine(x,y), and these all lines should be displayed at once(no replacement). I am new to PyOpenGL (and OpenGL) and I'm not sure how to go about doing this. As of now, I know how to draw a fixed number of lines using something like this :

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

Here, I can repeat the glBegin(GL_LINES) - glEnd() blocks multiple times to draw a fixed number of lines with fixed parameters. But how to do the variable line task?

In other words, I want to create a function, which upon being called with x and y coordinates, adds a line to the bunch of lines already being displayed on the screen. This function may be called multiple times according to user interaction. The only way I can think of adding lines is inserting glBegin-glEnd blocks in this main_loop function(shown in code above), but how to do that at runtime?

1

There are 1 answers

0
Rabbid76 On BEST ANSWER

You have to redraw the entire scene in every frame. Hence you need a list where you store the points for the lines.

Create a function which can draw a GL_LINE_STRIP. The argument to the function is a list of vertices:

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

Define an empty list for the verices:

line_vertices = []

Add a new point to the line by user interaction. For instnace when the mouse button is pressed:

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

Draw the line in the main application loop:

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

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

Minimal example:

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