Colby Ray
Colby Ray

Reputation: 135

Drawing Primitives with Pyglet

I'm new to pyglet and opengl and I can't get GL_LINES to work. GL_POINTS is ok. i keep getting this error: ValueError: Can only assign sequence of same size. It obviously seems as if I'm defining the wrong number of vertices but the count seems right to me and i don't know how to fix it.

@window.event
def on_draw():
    glClear(GL_COLOR_BUFFER_BIT)

    howmany=i=2
    coords=[];colors=[]
    while i>0:
        x=random.randint(0,window.width)
        y=random.randint(0,window.height)
        x2=random.randint(0,window.width)
        y2=random.randint(0,window.height)
        coords.append(x); coords.append(y); coords.append(x2); coords.append(y2)
        #c=(random.randint(0,255),random.randint(0,255),random.randint(0,255))
        #c2=(random.randint(0,255),random.randint(0,255),random.randint(0,255))
        #for cx in c: colors.append(cx)
        #for cx in c2: colors.append(cx)
        i=i-1

    coords=tuple(coords)
    colors=tuple(colors)
    vertex_list=pyglet.graphics.vertex_list(howmany,('v2i', coords))#,('c3B', colors))
    vertex_list.draw(pyglet.gl.GL_LINES)

Upvotes: 2

Views: 4982

Answers (1)

Torxed
Torxed

Reputation: 23480

I will go a head and optemize your code while solving your problem if that's fine.
Rendering primetives one-by-one will be extremely taxing on the system because you'll do logical operations while trying to render each logical operation which might cause glitches in the drawing process.

There for, i'd consider trying to finish your logical operations as quickly as possible and throw a collective lump of data to the graphic card, and to do this you need to use something called batched rendering.

@window.event
def on_draw():
    main_batch = pyglet.graphics.Batch()
    glClear(GL_COLOR_BUFFER_BIT)

    # for is less likely to get stuck than while
    for i in range(2):
        x = random.randint(0,window.width)
        y = random.randint(0,window.height)
        dest_x = random.randint(0,window.width)
        dest_y = random.randint(0,window.height)

        main_batch.add(2, gl.GL_LINES, None,
                            ('v2f', (x, y, dest_x, dest_y)),
                            ('c3B', (255, 0, 0, 0, 255, 0)) #c3B is a gradient (0,0,0, 255,255,255) combo
                                                            # this gradient will be per line, not end to end.
                        )
    main_batch.draw()

What probably confused you is the 2 in v2i and how color and the number of lines are related. See howmany in your example will be the definition of how many end-point there are in cords, not how how many lines you got.

Meaning, if you have 2 lines, that's 4 endpoints, because each line will have a starting and end cordinate. The solution would be to do howmany*2 because there's always a fixed ammount of positions in a 2D line.

However, the problem with this is that you're also assining a color to each line, meaning the length of the colors list must match the length of the cords list in a particular manner, because they'll be directly related to each other.

So in my above example, I will add one line at a time as a single object with a given color to the batch, it's slightly less effective but will work as a demonstration. And i'll render the batch once i've added two lines.

If you want to do the same operation but wiht 2 lines, you'd do something like:

main_batch.add(4, gl.GL_LINES, None,
                            ('v2i', (100,100, 120,100,   # start -> end
                                     120,100, 120,150))  # start -> end
                        )

Now that's 4 sa in x,y -> x,y -> x,y -> x,y, 4 corindates.
Now I left out the color in this code block just to show you how to add a multi-cord vertex line. This code will default to a white line and will be renderable.

Either you can do:

 glColor3f(1, 0, 0) # Produces a red line
 main_batch.draw()

To change the color of that 4 cord line, or.. You could define the color cords while creating the line. c3B basically means 3 colors per "definition" aka your standard RGB value. But you will need one RGB definition per x,y coordinate. So it will look something like this:

main_batch.add(4, gl.GL_LINES, None,
                            ('v2i', (100,100, 120,100,   # start -> end
                                     120,100, 120,150)),  # start -> end

                             ('c3B', (0,0,0, 255,255,255,
                                      0,0,0, 255,255,255))
                        )

This creates two connecting lines, each individual line with a black to white gradient and adds the "shape" to a batch and renders the entire batch in one go.
The next shape of lines you create you can add to the same batch and render two lines in the same iteration.

To make this more compact and convert it back to how you originally set up your lists:

cords = (100,100, 120,100, 120,100, 120,150)
howmany = len(cords) / 2 # How many lines, not cordinates

colors = (0,0,0, 255,255,255)*howmany
main_batch.add(howmany, gl.GL_LINES, None, ('v2i', cords), ('c3B', colors))

Upvotes: 4

Related Questions