Pyopengl тесселящие полигоны

У меня есть полигоны в виде:

[(1,2), (2,4), (3,4), (5,6)]

Мне нужно тесселяция, чтобы нарисовать их, но ягодица слишком сложна. Opengl не может обрабатывать выпуклые многоугольники.

Я думаю, что мне нужно что-то вроде:

http://www.math.uiuc.edu/~gfrancis/illimath/windows/aszgard_mini/pylibs/OpenGLContext/scenegraph/polygontessellator.py

Но я не понимаю, как его использовать. Кто-нибудь может дать мне наглядный пример?

Он должен использовать Pyopengl, поскольку он должен интегрироваться с другим проектом (Pygame и т. Д. Не будет работать)

В качестве альтернативы, есть ли способ объединения триеш из массива строк?

1 ответ

На самом деле я работаю над тем же для рендеринга векторной графики в Python! Собирая этот пример кода, я нашел этот ресурс полезным для понимания gluTesselator (хотя эта ссылка не использует python). Ниже приведен пример кода, который визуализирует вогнутый многоугольник с двумя отверстиями (еще одно потенциальное ограничение необработанного OpenGL без GLU), который не имеет ни одного из пользовательских классов, которые я обычно использую, и использует (медленный и ужасный) немедленный режим для простоты. Функция триангуляции содержит соответствующий код для создания gluTesselator.

from OpenGL.GLU import *
from OpenGL.GL import *
from pygame.locals import *
import pygame
import sys

def triangulate(polygon, holes=[]):
    """
    Returns a list of triangles.
    Uses the GLU Tesselator functions!
    """
    vertices = []
    def edgeFlagCallback(param1, param2): pass
    def beginCallback(param=None):
        vertices = []
    def vertexCallback(vertex, otherData=None):
        vertices.append(vertex[:2])
    def combineCallback(vertex, neighbors, neighborWeights, out=None):
        out = vertex
        return out
    def endCallback(data=None): pass

    tess = gluNewTess()
    gluTessProperty(tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD)
    gluTessCallback(tess, GLU_TESS_EDGE_FLAG_DATA, edgeFlagCallback)#forces triangulation of polygons (i.e. GL_TRIANGLES) rather than returning triangle fans or strips
    gluTessCallback(tess, GLU_TESS_BEGIN, beginCallback)
    gluTessCallback(tess, GLU_TESS_VERTEX, vertexCallback)
    gluTessCallback(tess, GLU_TESS_COMBINE, combineCallback)
    gluTessCallback(tess, GLU_TESS_END, endCallback)
    gluTessBeginPolygon(tess, 0)

    #first handle the main polygon
    gluTessBeginContour(tess)
    for point in polygon:
        point3d = (point[0], point[1], 0)
        gluTessVertex(tess, point3d, point3d)
    gluTessEndContour(tess)

    #then handle each of the holes, if applicable
    if holes != []:
        for hole in holes:
            gluTessBeginContour(tess)
            for point in hole:
                point3d = (point[0], point[1], 0)
                gluTessVertex(tess, point3d, point3d)
            gluTessEndContour(tess)

    gluTessEndPolygon(tess)
    gluDeleteTess(tess)
    return vertices

if __name__ == "__main__":
    width, height = 550, 400
    pygame.init()
    pygame.display.set_mode((width, height), DOUBLEBUF|OPENGL)
    pygame.display.set_caption("Tesselation Demo")
    clock = pygame.time.Clock()
    glClear(GL_COLOR_BUFFER_BIT)
    glClear(GL_DEPTH_BUFFER_BIT)
    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    glOrtho(0, width, height, 0, -1, 1)#flipped so top-left = (0, 0)!
    glMatrixMode(GL_MODELVIEW)
    glLoadIdentity()

    #define the polygon and some holes
    polygon = [(0, 0), (550, 0), (550, 400), (275, 200), (0, 400)]
    hole1 = [(10, 10), (10, 100), (100, 100), (100, 10)]
    hole2 = [(300, 50), (350, 100), (400, 50), (350, 200)]
    holes = [hole1, hole2]
    vertices = triangulate(polygon, holes=holes)

    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()

        glColor(1, 0, 0)
        glBegin(GL_TRIANGLES)
        for vertex in vertices:
            glVertex(*vertex)
        glEnd()

        pygame.display.flip()
        clock.tick_busy_loop(60)

Вывод приведенного выше кода должен выглядеть следующим образом: введите описание изображения здесь

Также, как примечание, вы можете использовать pygame с pyopengl, как показано в примере кода выше. Однако я лично предпочитаю использовать pysdl2 для предоставления окна для моего приложения, а не pygame, который основан на более старом sdl 1.2 и кажется заброшенным. Я использую только Pygame в приведенном выше примере, так как в демоверсии работать с ним более лаконично.

Другие вопросы по тегам