Проблемы с glDrawArrays - PullRequest
1 голос
/ 22 мая 2019

Я пытаюсь переделать программу на glDrawArray . If i use just glVertex3f everything is fine and if i use glDrawArrays` для тех же значений вершин, у меня есть несколько случайных линий в дополнение к рисунку.

с glDrawArrays with DrawArrays

ususal glVertex3f как должно выглядеть ususal glVertex3f as it should look like

И в 50% я получаю ошибку

pgl.glDrawArrays(pgl.GL_TRIANGLE_STRIP, 0, array_size)

OSError: исключение: чтение нарушения доступа 0x0CF52000

код (пастин)

import pyglet
import pyglet.gl as pgl
from pyglet.window import key
import math
import json
import time


win = pyglet.window.Window(1300, 1000, resizable=True)

global_time = time.time()
frame_counter = 0

WINDOW = 1000
tr = 96
tr_temp = 90
INCREMENT = 5
transparant = False
xRotation = -70
zRotation = -30
yRotation = 180
zoom = 1
x = -180
y = 70
z = 0
light = False

param = 0
t_prev = -5
start_loop = False
run_l = False
Texture = False
texture_obj = None
lamp1 = False
lamp2 = False
lamp3 = False

data = {}

with open('PycharmProjects/untitled/data.json') as fp:
    data = json.load(fp)
    transparant = data['transparant']
    xRotation = data['xRotation']
    yRotation = data['yRotation']
    zRotation = data['zRotation']
    zoom = data['zoom']
    x = data['x']
    y = data['y']
    z = data['z']
    light = data['light']
    param = data['param']
    t_prev = data['t_prev']
    start_loop = data['start_loop']
    run_l = data['run_l']
    Texture = data['Texture']
    lamp1 = data['lamp1']
    lamp2 = data['lamp2']
    lamp3 = data['lamp3']
    tr = data['tr']


def writeToJSONFile(path, filename, data):
    filePathName = path + '.json'
    with open(filePathName, 'w') as fp:
        json.dump(data,fp)


def run_loop(dt):
    on_draw()


def draw_figure():
    global texture_obj
    angle = 0
    t = 0
    x = y = z = 0
    a = 50
    b = 100
    array_size = 0
    array = []


    if Texture:
        if texture_obj == None:
            texture_obj = pyglet.image.load("PycharmProjects/untitled/test1_texture.bmp").get_texture()
        pgl.glBindTexture(pgl.GL_TEXTURE_2D, texture_obj.id)
        pgl.glEnable(pgl.GL_TEXTURE_2D)
        # pgl.glTexParameterf(pgl.GL_TEXTURE_2D, pgl.GL_TEXTURE_WRAP_T, pgl.GL_REPEAT)
        # pgl.glTexParameterf(pgl.GL_TEXTURE_2D, pgl.GL_TEXTURE_MAG_FILTER, pgl.GL_NEAREST)
        # #
        #
        # pgl.glTexEnvi(pgl.GL_TEXTURE_ENV, pgl.GL_TEXTURE_ENV_MODE, pgl.GL_REPLACE)

    else:
        pgl.glDisable(pgl.GL_TEXTURE_2D)

    if not transparant:
        pgl.glPolygonMode(pgl.GL_FRONT_AND_BACK, pgl.GL_FILL)
    else:
        pgl.glPolygonMode(pgl.GL_FRONT_AND_BACK, pgl.GL_LINE)
    pgl.glBegin(pgl.GL_TRIANGLE_STRIP)
    for i in range(0, tr + 1):
        pgl.glColor3ub(0, 0, 0)
        if i >= 1:
            t1 = a1
            t2 = a2
            t3 = a3
        u = math.cos(i * 2 * math.pi / tr)
        v = math.sin(i * 2 * math.pi / tr)
        a1 = x + a * u
        a2 = y + b * v
        a3 = z + 8
        if Texture:
            pgl.glTexCoord2f(u * 0.5 + 0.5, v * 0.5 + 0.5)
        pgl.glVertex3f(a1, a2, a3)
        if i >= 1:
            pgl.glNormal3f((b2 - t2) * (a3 - b3) - (b3 - t3) * (a2 - b2), (b3 - t3) * (a1 - b1) - (b1 - t1) * (a3 - b3),
                           (b1 - t1) * (a2 - b2) - (b2 - t2) * (a1 - b1))
        b1 = x
        b2 = y
        b3 = z + 8
        if Texture:
            pgl.glTexCoord2f(0.5, 0.5)
        pgl.glVertex3f(b1, b2, b3)
    pgl.glEnd()
    for j in range(1, 27):
        pgl.glBegin(pgl.GL_TRIANGLE_STRIP)
        pgl.glColor3ub(0, 0, 0)
        x1 = a * math.cos(0)
        y1 = b * math.sin(0)
        a1 = x1 * math.cos(t * math.pi / 360) + y1 * math.sin(t * math.pi / 360)
        a2 = - x1 * math.sin(t * math.pi / 360) + y1 * math.cos(t * math.pi / 360)
        a3 = z + j * 8
        if Texture:
            pgl.glTexCoord2f(0.0, 0.0)
        a01 = a1
        a02 = a2
        a03 = a3
        print(a1,a2,a3)
        array.extend([a1,a2,a3])
        array_size += 3
        # pgl.glVertex3f(a1, a2, a3)
        b1 = x1 * math.cos((t + 16) * math.pi / 360) + y1 * math.sin((t + 16) * math.pi / 360)
        b2 = - x1 * math.sin((t + 16) * math.pi / 360) + y1 * math.cos((t + 16) * math.pi / 360)
        b3 = z + j * 8 + 8
        u = math.cos((t + 16) * math.pi / 360) + math.sin((t + 16) * math.pi / 360)
        v = (j - 1) / 26
        if Texture:
            pgl.glTexCoord2f(0.0, 0.0)
        array.extend([b1,b2,b3])
        print(b1,b2,b3)
        array_size += 3
        # pgl.glVertex3f(b1, b2, b3)
        b01 = b1
        b02 = b2
        b03 = b3
        for i in range(1, tr):
            pgl.glColor3ub(0, 0, 0)
            x1 = a * math.cos(i * 2 * math.pi / tr)
            y1 = b * math.sin(i * 2 * math.pi / tr)
            t1 = a1
            t2 = a2
            t3 = a3
            a1 = x1 * math.cos(t * math.pi / 360) + y1 * math.sin(t * math.pi / 360)
            a2 = - x1 * math.sin(t * math.pi / 360) + y1 * math.cos(t * math.pi / 360)
            a3 = z + j * 8
            pgl.glNormal3f((b2 - t2) * (a3 - b3) - (b3 - t3) * (a2 - b2), (b3 - t3) * (a1 - b1) - (b1 - t1) * (a3 - b3),
                           (b1 - t1) * (a2 - b2) - (b2 - t2) * (a1 - b1))
            v = math.cos(t * math.pi / 360) + math.sin(t * math.pi / 360)
            if Texture:
                pgl.glTexCoord2f((i - 1) / tr, (26 - j) / 26)
            array.extend([a1,a2,a3])
            print(a1,a2,a3)
            array_size += 3
            # pgl.glVertex3f(a1, a2, a3)
            x1 = a * math.cos(i * 2 * math.pi / tr)
            y1 = b * math.sin(i * 2 * math.pi / tr)
            b1 = x1 * math.cos((t + 16) * math.pi / 360) + y1 * math.sin((t + 16) * math.pi / 360)
            b2 = - x1 * math.sin((t + 16) * math.pi / 360) + y1 * math.cos((t + 16) * math.pi / 360)
            b3 = z + j * 8 + 8
            v = math.cos((t + 16) * math.pi / 360) + math.sin((t + 16) * math.pi / 360)
            if Texture:
                pgl.glTexCoord2f((i - 1) / tr, (25 - j) / 26)
            array.extend([b1,b2,b3])
            print(b1,b2,b3)
            array_size += 3
            # pgl.glVertex3f(b1, b2, b3)
        print(a01,a02,a03)
        array.extend([a01,a02,a03])
        array_size += 3
        # pgl.glVertex3f(a01, a02, a03)
        print(b01,b02,b03)
        array.extend([b01,b02,b03])
        array_size += 3
        # pgl.glVertex3f(b01, b02, b03)
        t = t + 16
        pgl.glEnd()
    pgl.glBegin(pgl.GL_TRIANGLE_STRIP)
    t = 416
    z = z + 144
    angle = angle + t
    for i in range(0, tr + 1):
        pgl.glColor3ub(0, 0, 0)
        u = math.cos(i * 2 * math.pi / tr)
        v = math.sin(i * 2 * math.pi / tr)
        x1 = x + a * u
        y1 = y + b * v
        x2 = x1 * math.cos(t * math.pi / 360) + y1 * math.sin(t * math.pi / 360)
        y2 = - x1 * math.sin(t * math.pi / 360) + y1 * math.cos(t * math.pi / 360)
        if i >= 1:
            t1 = a1
            t2 = a2
            t3 = a3
        a1 = x2
        a2 = y2
        a3 = z + 72
        if Texture:
            pgl.glTexCoord2f(u * 0.5 + 0.5, v * 0.5 + 0.5)
        pgl.glVertex3f(a1, a2, a3)
        if i >= 1:
            pgl.glNormal3f((b2 - t2) * (a3 - b3) - (b3 - t3) * (a2 - b2), (b3 - t3) * (a1 - b1) - (b1 - t1) * (a3 - b3),
                           (b1 - t1) * (a2 - b2) - (b2 - t2) * (a1 - b1))
        b1 = x
        b2 = y
        b3 = z + 72
        if Texture:
            pgl.glTexCoord2f(0.5, 0.5)
        pgl.glVertex3f(b1, b2, b3)
        angle = angle + i
    pgl.glEnd()
    pgl.glEnableClientState(pgl.GL_VERTEX_ARRAY)
    data = (pgl.GLfloat * len(array))(*array)
    pgl.glVertexPointer(3, pgl.GL_FLOAT, 0, data)
    pgl.glDrawArrays(pgl.GL_TRIANGLE_STRIP, 0, array_size)
    pgl.glDisableClientState(pgl.GL_VERTEX_ARRAY)



@win.event
def on_draw():
    global x, y, z, start_loop, run_l, param, t_prev, zRotation,frame_counter
    start_time = time.time()

    pgl.glClearColor(0.0, 0.0, 0.0, 0.0)
    pgl.glEnable(pgl.GL_DEPTH_TEST)
    if light:
        pgl.glEnable(pgl.GL_LIGHTING)
        pgl.glLightModelf(pgl.GL_LIGHT_MODEL_TWO_SIDE, pgl.GL_FALSE)
        pgl.glEnable(pgl.GL_NORMALIZE)
    else:
        pgl.glDisable(pgl.GL_LIGHTING)
        pgl.glDisable(pgl.GL_NORMALIZE)
    pgl.glClear(pgl.GL_COLOR_BUFFER_BIT | pgl.GL_DEPTH_BUFFER_BIT)

    pgl.glLoadIdentity()
    pgl.glViewport(0, 0, 1300, 1000)
    pgl.glMatrixMode(pgl.GL_PROJECTION)
    pgl.glLoadIdentity()
    pgl.glOrtho(-1300 / 4, 1300 / 4, -1000 / 4, 1000 / 4, -400, 600)
    pgl.glMatrixMode(pgl.GL_MODELVIEW)
    pgl.glLoadIdentity()

    if light:
        material_diffuse = [1.0, 1.0, 1.0, 1.0]
        pgl.glMaterialfv(pgl.GL_FRONT_AND_BACK, pgl.GL_DIFFUSE,
                         (pgl.GLfloat * len(material_diffuse))(*material_diffuse))

        if lamp1:
            light5_diffuse = [1.0, 0.0, 0.0];

            light5_position = [0, 0, -1.0, 0];

            pgl.glEnable(pgl.GL_LIGHT5);

            pgl.glLightfv(pgl.GL_LIGHT5, pgl.GL_DIFFUSE, (pgl.GLfloat * len(light5_diffuse))(*light5_diffuse));

            pgl.glLightfv(pgl.GL_LIGHT5, pgl.GL_POSITION, (pgl.GLfloat * len(light5_position))(*light5_position));

            pgl.glLightf(pgl.GL_LIGHT5, pgl.GL_CONSTANT_ATTENUATION, 0.0);

            pgl.glLightf(pgl.GL_LIGHT5, pgl.GL_LINEAR_ATTENUATION, 0.4);

            pgl.glLightf(pgl.GL_LIGHT5, pgl.GL_QUADRATIC_ATTENUATION, 0.8);
        else:
            pgl.glDisable(pgl.GL_LIGHT5);


        if lamp2:
            light6_diffuse = [0.0, 1.0, 0.0];

            light6_position = [1, 0.5, -1.0, 0];

            pgl.glEnable(pgl.GL_LIGHT6);

            pgl.glLightfv(pgl.GL_LIGHT6, pgl.GL_DIFFUSE, (pgl.GLfloat * len(light6_diffuse))(*light6_diffuse));

            pgl.glLightfv(pgl.GL_LIGHT6, pgl.GL_POSITION, (pgl.GLfloat * len(light6_position))(*light6_position));

            pgl.glLightf(pgl.GL_LIGHT6, pgl.GL_CONSTANT_ATTENUATION, 0.0);

            pgl.glLightf(pgl.GL_LIGHT6, pgl.GL_LINEAR_ATTENUATION, 0.4);

            pgl.glLightf(pgl.GL_LIGHT6, pgl.GL_QUADRATIC_ATTENUATION, 0.8);
        else:
            pgl.glDisable(pgl.GL_LIGHT6);


        if lamp3:
            light7_diffuse = [0.0, 0.0, 1.0];

            light7_position = [0.5 * math.cos(4 * math.pi / 3), 0.5 * math.sin(4 * math.pi / 3), 1.0, 0];

            pgl.glEnable(pgl.GL_LIGHT7);

            pgl.glLightfv(pgl.GL_LIGHT7, pgl.GL_DIFFUSE, (pgl.GLfloat * len(light7_diffuse))(*light7_diffuse));

            pgl.glLightfv(pgl.GL_LIGHT7, pgl.GL_POSITION, (pgl.GLfloat * len(light7_position))(*light7_position));

            pgl.glLightf(pgl.GL_LIGHT7, pgl.GL_CONSTANT_ATTENUATION, 0.0);

            pgl.glLightf(pgl.GL_LIGHT7, pgl.GL_LINEAR_ATTENUATION, 0.4);

            pgl.glLightf(pgl.GL_LIGHT7, pgl.GL_QUADRATIC_ATTENUATION, 0.8);
        else:
            pgl.glDisable(pgl.GL_LIGHT7);

    pgl.glPolygonMode(pgl.GL_FRONT_AND_BACK, pgl.GL_FILL)
    pgl.glPushMatrix()
    pgl.glTranslatef(x, y, z)
    pgl.glRotatef(xRotation, 1, 0, 0)
    pgl.glRotatef(yRotation, 0, 1, 0)
    pgl.glRotatef(zRotation, 0, 0, 1)
    pgl.glScalef(zoom, zoom, zoom)

    draw_figure()

    if start_loop:
        start_loop = False
        run_l = True
        x = ((1 - (param / 100)) ** 3) * (-180) + 3 * (param / 100) * ((1 - (param / 100)) ** 2) * (100) + 3 * (
                    (param / 100) ** 2) * (
                    1 - (param / 100)) * (0) + ((param / 100) ** 3) * (200)
        y = ((1 - (param / 100)) ** 3) * 70 + 3 * (param / 100) * ((1 - (param / 100)) ** 2) * (140) + 3 * (
                    (param / 100) ** 2) * (
                    1 - (param / 100)) * (140) + ((param / 100) ** 3) * (
                70)
        z = ((1 - (param / 100)) ** 3) * 0 + 3 * (param / 100) * ((1 - (param / 100)) ** 2) * (100) + 3 * (
                    (param / 100) ** 2) * (
                    1 - (param / 100)) * (100) + ((param / 100) ** 3) * (
                0)

    elif run_l:
        if param < 100 and param > t_prev:
            zRotation += INCREMENT
            param = param + 1
            t_prev = t_prev + 1
            if (param == 100):
                t_prev = 105
            x = ((1 - (param / 100)) ** 3) * (-180) + 3 * (param / 100) * ((1 - (param / 100)) ** 2) * (100) + 3 * (
                        (param / 100) ** 2) * (1 - (param / 100)) * (0) + ((param / 100) ** 3) * (200)
            y = ((1 - (param / 100)) ** 3) * 70 + 3 * (param / 100) * ((1 - (param / 100)) ** 2) * (140) + 3 * (
                        (param / 100) ** 2) * (1 - (param / 100)) * (140) + ((param / 100) ** 3) * (
                    70)
            z = ((1 - (param / 100)) ** 3) * 0 + 3 * (param / 100) * ((1 - (param / 100)) ** 2) * (100) + 3 * (
                        (param / 100) ** 2) * (1 - (param / 100)) * (100) + ((param / 100) ** 3) * (
                    0)
        if param > 0 and param < t_prev:
            zRotation -= INCREMENT
            param = param - 1
            t_prev = t_prev - 1
            if (param == 0):
                t_prev = -5
            x = ((1 - (param / 100)) ** 3) * (-180) + 3 * (param / 100) * ((1 - (param / 100)) ** 2) * (100) + 3 * (
                    (param / 100) ** 2) * (1 - (param / 100)) * (0) + ((param / 100) ** 3) * (200)
            y = ((1 - (param / 100)) ** 3) * 70 + 3 * (param / 100) * ((1 - (param / 100)) ** 2) * (140) + 3 * (
                    (param / 100) ** 2) * (1 - (param / 100)) * (140) + ((param / 100) ** 3) * (
                    70)
            z = ((1 - (param / 100)) ** 3) * 0 + 3 * (param / 100) * ((1 - (param / 100)) ** 2) * (100) + 3 * (
                    (param / 100) ** 2) * (1 - (param / 100)) * (100) + ((param / 100) ** 3) * (
                    0)

    frame_counter +=1
    # print("FPS: ", 1.0 / (time.time() - start_time))
    pgl.glPopMatrix()


@win.event
def on_text_motion(motion):
    global xRotation, yRotation, INCREMENT
    if motion == key.UP:
        xRotation -= INCREMENT
    elif motion == key.DOWN:
        xRotation += INCREMENT
    elif motion == key.LEFT:
        yRotation -= INCREMENT
    elif motion == key.RIGHT:
        yRotation += INCREMENT


@win.event
def on_key_press(symbol, modifiers):
    global transparant, data, tr, x, y, z, INCREMENT, zRotation, light, t, start_loop, run_l, Texture, tr_temp
    global xRotation, yRotation, zRotation,zoom, t_prev, texture_obj, lamp1, lamp2, lamp3, global_time, frame_counter
    if symbol == key.T and not transparant:
        transparant = True
    elif symbol == key.T and transparant:
        transparant = False
    elif symbol == key.W:
        x += 2.5
    elif symbol == key.S:
        x -= 2.5
    elif symbol == key.A:
        y -= 2.5
    elif symbol == key.D:
        y += 2.5
    elif symbol == key.Q:
        z -= 2.5
    elif symbol == key.E:
        z += 2.5
    elif symbol == key.L:
        light = not light
        lamp1 = True
        lamp2 = True
        lamp3 = True
    elif symbol == key.Z:
        zRotation += INCREMENT
    elif symbol == key.X:
        zRotation -= INCREMENT
    elif symbol == key.ESCAPE:
        path = 'PycharmProjects/untitled/data'
        fileName = 'data'
        data['transparant'] = transparant
        data['xRotation'] = xRotation
        data['yRotation'] = yRotation
        data['zRotation'] = zRotation
        data['zoom'] = zoom
        data['x'] = x
        data['y'] = y
        data['z'] = z
        data['light'] = light
        data['param'] = param
        data['t_prev'] = t_prev
        data['start_loop'] = start_loop
        data['run_l'] = run_l
        data['Texture'] = Texture
        data['lamp1'] = lamp1
        data['lamp2'] = lamp2
        data['lamp3'] = lamp3
        data['tr'] = tr
        data['tr_temp'] = tr_temp
        writeToJSONFile(path, fileName, data)
        pyglet.app.exit()
    elif symbol == key.P:
        tr += 5
    elif symbol == key.O:
        if tr > 6:
            tr -= 5
    elif symbol == key.SPACE:
        if not run_l:
            tr_temp = tr
            tr = 6
            start_loop = True
        else:
            run_l = False
            tr = tr_temp
    elif symbol == key.M:
        print("pressed")
        Texture = not Texture
    elif symbol == key._1:
        lamp1 = not lamp1
    elif symbol == key._2:
        lamp2 = not lamp2
    elif symbol == key._3:
        lamp3 = not lamp3
    elif symbol == key.F:
        print("FPS: ", frame_counter / (time.time() - global_time))
        frame_counter = 0
        global_time = time.time()



@win.event
def on_mouse_scroll(x, y, scroll_x, scroll_y):
    global zoom
    if scroll_y < 0:
        zoom += 0.1
    elif scroll_y > 0 and zoom - 0.1 > 0:
        zoom -= 0.1


@win.event
def on_mouse_press(x, y, button, modifiers):
    if button == pyglet.window.mouse.LEFT:
        print(x, y)


pyglet.clock.schedule_interval(run_loop, 0.1)
pyglet.app.run()

(для первого запуска отключите чтение из файла json, затем после первого закрытия с помощью esc программа прочитает сохраненные параметры)

Неисправности в draw_figure

1 Ответ

2 голосов
/ 22 мая 2019

Основная проблема заключается в том, что GL_TRIANGLE_STRIP не может быть произвольно подключен:

1      3      5
 +-----+-----+
 | \   | \   |
 |   \ |  \  |
 +-----+-----+
0      2      4


7      9      11
 +-----+-----+
 | \   | \   |
 |   \ |  \  |
 +-----+-----+
6      8      10

Если вышеперечисленные полосы соединяются напрямую, это приведет к образованию треугольников 4 - 5 - 6 и 5 - 6 -7, которые не нужны.

Но этого можно избежать простым трюком. Вы должны добавить дубликаты вершин. Обратите внимание, если 2 точки треугольника равны, площадь треугольника равна нулю.
Если бы вершины 5 и 6 были бы добавлены дважды, то полосы соединяются треугольниками 4 - 5 - 5, 5 - 5 - 6, 5 - 6 - 6 и 6 - 6 - 7. Каждый из этих треугольников не имеет размера.

Рекомендую хранить координаты вершин и атрибуты в списках:

vertex = []
color = []
normal = []
textcoord = []

Определить функцию, которая extend s списки по координатам и атрибутам:

def add_vertex(v, c, t, n):
    global vertex, color, normal, textcoord
    vertex.extend(v)
    color.extend(c)
    textcoord.extend(t)
    normal.extend(n)

Определите функцию, которая дублирует последние координаты и атрибуты в списке, которая может использоваться для объединения треугольных полос:

def repeat_vertex():
    add_vertex(vertex[-3:], color[-3:], textcoord[-2:], normal[-3:])

Определите еще одну функцию, которая строит фигуру (рисунок). Функция должна определять все атрибуты (цвет, координаты текстуры и вектор нормали), независимо от того, используются ли они позже:

def construct_figure():
    angle = 0
    t = 0
    x = y = z = 0
    a = 50
    b = 100

    for i in range(0, tr + 1):
        if i >= 1:
            t1, t2, t3 = a1, a2, a3
        u, v = math.cos(i * 2 * math.pi / tr), math.sin(i * 2 * math.pi / tr)
        a1, a2, a3 = x + a * u, y + b * v, z + 8
        add_vertex([a1, a2, a3],
            [u * 0.5 + 0.5, 0, v * 0.5 + 0.5],
            [u * 0.5 + 0.5, v * 0.5 + 0.5],
            [0, 0, -1])

        b1, b2, b3 = x, y, z + 8
        add_vertex([b1, b2, b3], [0.5, 0, 0.5], [0.5, 0.5], normal[-3:])
    repeat_vertex()

    for j in range(1, 27):
        x1, y1 = a * math.cos(0), b * math.sin(0)
        a1 = x1 * math.cos(t * math.pi / 360) + y1 * math.sin(t * math.pi / 360)
        a2 = - x1 * math.sin(t * math.pi / 360) + y1 * math.cos(t * math.pi / 360)
        a3 = z + j * 8
        a01, a02, a03 = a1, a2, a3
        add_vertex([a1, a2, a3], [0, 0, 0], [0, 0], normal[-3:])
        repeat_vertex()

        b1 = x1 * math.cos((t + 16) * math.pi / 360) + y1 * math.sin((t + 16) * math.pi / 360)
        b2 = - x1 * math.sin((t + 16) * math.pi / 360) + y1 * math.cos((t + 16) * math.pi / 360)
        b3 = z + j * 8 + 8
        u = math.cos((t + 16) * math.pi / 360) + math.sin((t + 16) * math.pi / 360)
        v = (j - 1) / 26
        add_vertex([b1, b2, b3], color[-3:], [0, 0], normal[-3:])

        b01, b02, b03 = b1, b2, b3
        for i in range(1, tr):
            x1 = a * math.cos(i * 2 * math.pi / tr)
            y1 = b * math.sin(i * 2 * math.pi / tr)
            t1, t2, t3 = a1, a2, a3
            a1 = x1 * math.cos(t * math.pi / 360) + y1 * math.sin(t * math.pi / 360)
            a2 = - x1 * math.sin(t * math.pi / 360) + y1 * math.cos(t * math.pi / 360)
            a3 = z + j * 8
            v = math.cos(t * math.pi / 360) + math.sin(t * math.pi / 360)
            add_vertex([a1, a2, a3],
                [math.cos(i * 2 * math.pi / tr)*0.5 + 0.5, j/27, math.sin(i * 2 * math.pi / tr)*0.5 + 0.5],
                [(i - 1) / tr, (26 - j) / 26],
                [(b2 - t2) * (a3 - b3) - (b3 - t3) * (a2 - b2), (b3 - t3) * (a1 - b1) - (b1 - t1) * (a3 - b3),
                 (b1 - t1) * (a2 - b2) - (b2 - t2) * (a1 - b1)])

            x1 = a * math.cos(i * 2 * math.pi / tr)
            y1 = b * math.sin(i * 2 * math.pi / tr)
            b1 = x1 * math.cos((t + 16) * math.pi / 360) + y1 * math.sin((t + 16) * math.pi / 360)
            b2 = - x1 * math.sin((t + 16) * math.pi / 360) + y1 * math.cos((t + 16) * math.pi / 360)
            b3 = z + j * 8 + 8
            v = math.cos((t + 16) * math.pi / 360) + math.sin((t + 16) * math.pi / 360)
            add_vertex([b1, b2, b3], color[-3:], [(i - 1) / tr, (25 - j) / 26], normal[-3:])

        add_vertex([a01, a02, a03], color[-3:], textcoord[-2:], normal[-3:])
        add_vertex([b01, b02, b03], color[-3:], textcoord[-2:], normal[-3:])
        t = t + 16
        repeat_vertex()

    t = 416
    z = z + 144
    angle = angle + t
    for i in range(0, tr + 1):
        u, v = math.cos(i * 2 * math.pi / tr), math.sin(i * 2 * math.pi / tr)
        x1, y1 = x + a * u, y + b * v
        x2 = x1 * math.cos(t * math.pi / 360) + y1 * math.sin(t * math.pi / 360)
        y2 = - x1 * math.sin(t * math.pi / 360) + y1 * math.cos(t * math.pi / 360)
        if i >= 1:
            t1, t2, t3 = a1, a2, a3
        a1, a2, a3 = x2, y2, z + 72
        add_vertex([a1, a2, a3],
            [u * 0.5 + 0.5, 1, v * 0.5 + 0.5],
            [u * 0.5 + 0.5, v * 0.5 + 0.5],
            [0, 0, 1])
        if i == 0:
            repeat_vertex()

        b1, b2, b3 = x, y, z +72
        add_vertex([b1, b2, b3], [0.5, 1, 0.5], [0.5, 0.5], normal[-3:])
        angle = angle + i
    repeat_vertex()

Теперь форму можно нарисовать с помощью glBegin / glEnd секвенций или glDrawArrays:

draw_array = True # False

def draw_figure():

    # [...]

    if not draw_array:

        pgl.glBegin(pgl.GL_TRIANGLE_STRIP)
        for i in range(len(vertex)//3):
            if Texture:
                pgl.glTexCoord2f(textcoord[i*2], textcoord[i*2+1])
            else:
                pgl.glColor3f(color[i*3], color[i*3+1], color[i*3+2])
            pgl.glNormal3f(normal[i*3], normal[i*3+1], normal[i*3+2])
            pgl.glVertex3f(vertex[i*3], vertex[i*3+1], vertex[i*3+2])
        pgl.glEnd()

    else:
        pgl.glEnableClientState(pgl.GL_VERTEX_ARRAY)
        data = (pgl.GLfloat * len(vertex))(*vertex)
        pgl.glVertexPointer(3, pgl.GL_FLOAT, 0, data)
        pgl.glDrawArrays(pgl.GL_TRIANGLE_STRIP, 0, len(vertex) // 3)
        pgl.glDisableClientState(pgl.GL_VERTEX_ARRAY)

Форма может быть построена в начале приложения:

construct_figure()
pyglet.clock.schedule_interval(run_loop, 0.1)
pyglet.app.run()

...