我应该使用哪个OpenGL基本体绘制三角剖分?

时间:2019-03-10 09:57:50

标签: python opengl triangulation

我有以下图像:

enter image description here

我能够像以下那样进行三角剖分: enter image description here

我使用python的triangle库做到了。我的三角剖分结果存储在一个dict对象中,该对象如下所示:

>>> triangulation["vertices"]
array([[ 23.        , 282.        ],
       [ 24.        , 254.        ],
       [ 30.        , 239.        ],
       [ 43.        , 219.        ],
       [ 60.        , 204.        ], ...  And so on ...



>>> triangulation["triangles"]
array([[ 89, 106, 105],
       [ 99,  35,  86],
       [110,  68,  87],
       [ 47,  66,  83],
       [ 72,  82,  74], ...  And so on ...

现在,我想使用OpenGL扭曲并将此纹理绘制为网格。我想知道应该使用哪个原语?我认为TRIANGLE_STRIP是正确的解决方案,但这是一个复杂的三角剖分,很明显,仅一个TRIANGLE_STRIP是不够的。

1 个答案:

答案 0 :(得分:4)

您有2个数组。第一个数组包含二维顶点坐标,第二个数组包含索引。
您必须使用glDrawElements来绘制第二个数组中包含的三角形图元。索引指的是第一数组对应的顶点坐标。

首先,您需要为顶点坐标创建一个浮点缓冲区,并为索引创建一个积分缓冲区。最简单的方法是使用NumPy将嵌套列表或数组转换为数组缓冲区。

假设您有一个vertices数组,其格式为 [[x0,y0],[x1,y1],[x2,y2],...] 和以{em> [[a0,b0,c0],[a1,b1,c1],[a2,b2,c2],...] 形式的indices数组,然后缓冲区可以这样创建:

import numpy as np

vertex_array = np.array(vertices, dtype=np.float32)

no_of_indices = len(indices) * 3
index_array = np.array(indices, dtype=np.uint32)

使用ctypes代替NumPy可以完成相同的操作。但是然后必须分别以 [x0,y0,x1,y1,x2,y2,...] 的形式 [a0,b0 ,c0,a1,b1,c1,a2,b2,c2,...]

vertex_array = (ctypes.c_float * len(flat_vertices))(*flat_vertices)

no_of_indices = len(flat_indices) * 3
index_array = (ctypes.c_uint32 * no_of_indices)(*flat_indices)

创建一个顶点数组对象。参见Vertex Specification

vao = glGenVertexArrays(1)
glBindVertexArray(vao)

ibo = glGenBuffers(1)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo)
glBufferData(GL_ELEMENT_ARRAY_BUFFER, index_array, GL_STATIC_DRAW)

vbo = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, vbo)
glBufferData(GL_ARRAY_BUFFER, vertex_array, GL_STATIC_DRAW)

glVertexAttribPointer(0, 2, GL_FLOAT, False, 0, None)
glEnableVertexAttribArray(0)

glBindBuffer(GL_ARRAY_BUFFER, 0)
glBindVertexArray(0)

如果要绘制三角形图元,则只需绑定顶点数组对象并调用glDrawElements

glBindVertexArray(vao)
glDrawElements(GL_TRIANGLES, no_of_indices, GL_UNSIGNED_INT, None)

关于评论:

  

[...]我已经知道如何通过先使用glTexCoord2f然后使用glVertex3f来对平面进行纹理化,但是并没有弄清楚如何使用vao来实现。

最简单的方法是创建一个单独的纹理坐标数组。假设您具有格式为[[u0,v0],[u1,v1],[u2,v2],...]的纹理坐标texAttr。 生成缓冲区很简单:

texAttr_array = np.array(texAttr, dtype=np.float32)

如果有着色器程序,则必须添加纹理坐标属性:

例如

layout (location = 0) in vec2 vertex;
layout (location = 1) in vec2 texAttr;

并定义通用顶点属性数据的数组。

vao = glGenVertexArrays(1)
glBindVertexArray(vao)

# [...] index buffer

vbo = glGenBuffers(2)
glBindBuffer(GL_ARRAY_BUFFER, vbo[0])
glBufferData(GL_ARRAY_BUFFER, vertex_array, GL_STATIC_DRAW)
glBindBuffer(GL_ARRAY_BUFFER, vbo[1])
glBufferData(GL_ARRAY_BUFFER, texAttr_array, GL_STATIC_DRAW)

glVertexAttribPointer(0, 2, GL_FLOAT, False, 0, None)
glEnableVertexAttribArray(0)
glVertexAttribPointer(1, 2, GL_FLOAT, False, 0, None)
glEnableVertexAttribArray(1)

glBindBuffer(GL_ARRAY_BUFFER, 0)
glBindVertexArray(0)

如果使用兼容性配置文件和固定功能属性,则必须指定glTexCoordPointer并启用客户端状态GL_TEXTURE_COORD_ARRAY
注意,客户端状态GL_VERTEX_ARRAYglVertexPointer映射到顶点属性0。请参见What are the Attribute locations for fixed function pipeline in OpenGL 4.0++ core profile?

vao = glGenVertexArrays(1)
glBindVertexArray(vao)

# [...] index buffer

vbo = glGenBuffers(2)
glBindBuffer(GL_ARRAY_BUFFER, vbo[0])
glBufferData(GL_ARRAY_BUFFER, vertex_array, GL_STATIC_DRAW)
glBindBuffer(GL_ARRAY_BUFFER, vbo[1])
glBufferData(GL_ARRAY_BUFFER, texAttr_array, GL_STATIC_DRAW)

glVertexPointer(2, GL_FLOAT, 0, None)
glEnableClientState(GL_VERTEX_ARRAY)
glTexCoordPointer(2, GL_FLOAT, 0, None)
glEnableClientState(GL_TEXTURE_COORD_ARRAY)

glBindBuffer(GL_ARRAY_BUFFER, 0)
glBindVertexArray(0)

请注意,如果您不使用着色器,则必须通过

启用二维纹理
glEnable(GL_TEXTURE_2D)

关于评论:

  

我想逐个替换顶点[...]

可以用glBufferSubData更改单个顶点坐标,其中第二个参数是顶点坐标的字节偏移量。坐标i的偏移量应为4*2*i(4是浮点数的大小,以字节为单位,每个坐标包含2个分量 x y )。

相关问题