如何正确填充顶点数组

时间:2016-01-19 23:22:51

标签: c++ opengl vertex triangulation vertex-array-object

我对如何填充顶点数组以使其正确绘制感到困惑。我正在使用的OpenGL代码是:

float vertices[size];
//Here I have a method to populate the array with my values from a 2D matrix

glGenVertexArrays(1, &vaoID[0]); // Create our Vertex Array Object
glBindVertexArray(vaoID[0]); // Bind our Vertex Array Object so we can use it

glGenBuffers(1, vboID); // Generate our Vertex Buffer Object
glBindBuffer(GL_ARRAY_BUFFER, vboID[0]); // Bind our Vertex Buffer Object
glBufferData(GL_ARRAY_BUFFER, (size) * sizeof(GLfloat), vertices, GL_STATIC_DRAW); // Set the size and data of our VBO and set it to STATIC_DRAW

glVertexAttribPointer((GLuint)0, 3, GL_FLOAT, GL_FALSE, 0, 0); // Set up our vertex attributes pointer
glEnableVertexAttribArray(0); // Disable our Vertex Array Object
glBindVertexArray(0); // Disable our Vertex Buffer Object

glBindVertexArray(vaoID[0]); // Bind our Vertex Array Object
glDrawArrays(GL_TRIANGLES, 0, size/3); // Draw
glBindVertexArray(0); // Unbind our Vertex Array Object

希望图像更容易理解。在图像' A'左边的3x3矩阵显示了当我绘制三角形时我目前得到的东西,右边的矩阵是我想要实现的。

目前,当我创建要绘制的顶点数组时,我会按照图像' B'中显示的顺序填充它。我在沿着一行工作时向数组添加值,然后逐步向下并重复。例如:

vertexArray[0] = matrixElement[0].x  
vertexArray[1] = matrixElement[0].y  
vertexArray[2] = matrixElement[0].z  
vertexArray[3] = matrixElement[1].x  
vertexArray[4] = matrixElement[1].y  
vertexArray[5] = matrixElement[1].z  

这个输入到vertexArray的顺序给出了可以在图像中看到的结果,其中创建了错误的三角形。

我的问题是:填充顶点数组的合理方法是什么,其顺序是在一个大的顶点矩阵上创建三角形,其方式类似于图像中的右手图表' A& #39;

Image of issue

3 个答案:

答案 0 :(得分:2)

您正在使用GL_TRIANGLESglDrawArrays(),因此您需要为所需的每个三角形附加3个顶点:

// first vertex
vertexArray.push_back( matrixElement[0].x );
vertexArray.push_back( matrixElement[0].y );
vertexArray.push_back( matrixElement[0].z );

// second vertex
vertexArray.push_back( matrixElement[3].x );
vertexArray.push_back( matrixElement[3].y );
vertexArray.push_back( matrixElement[3].z );

// third vertex
vertexArray.push_back( matrixElement[1].x );
vertexArray.push_back( matrixElement[1].y );
vertexArray.push_back( matrixElement[1].z );
...

答案 1 :(得分:2)

如果你想避免任何冗余,并用一个绘制调用绘制整个网格,一个选项是使用以下组合:

  • GL_TRIANGLE_STRIP作为原始类型。
  • 索引图。
  • 原始重启(需要OpenGL 3.1或更高版本)。

需要原始重启功能,因为您无法使用单个三角形条轻松表示此网格。使用草图中的编号,您可以使用这两个索引序列来描述具有两个三角形条带的拓扑:

0 3 1 4 2 5
3 6 4 7 5 8

设置和启用原语重启可以通过以下调用完成:

glEnable(GL_PRIMITIVE_RESTART);
glPrimitiveRestartIndex(0xFFFF);

您可以选择索引,但是公共策略(以及OpenGL ES中唯一支持的选项)是使用最大可能值,如果使用GLushort作为索引类型,则使用0xFFFF。

启用原始重启后,"特殊" index然后将启动一个新的三角形条带。因此,上面的两个三角形条带现在可以通过单个索引序列给出:

0 3 1 4 2 5 0xFFFF 3 6 4 7 5 8

您应该能够找到大量示例来说明如何设置索引缓冲区(您可以通过使用GL_ELEMENT_ARRAY_BUFFER来识别它们),因此我将跳过该部分。然后绘制调用:

glDrawElements(GL_TRIANGLE_STRIP, 0, 13, GL_UNSIGNED_SHORT, 0);

其中13是使用的索引数。

有使用原始重启的替代方法:

  • 使用重复的顶点。在原始重启被广泛使用之前,这是一个常见的技巧。我不会再推荐它了。仅作说明,本例中的索引序列为:

    0 3 1 4 2 5 5 3 3 6 4 7 5 8
    

    两个重复的索引将导致退化(0像素)三角形,"连接"两个三角形条。

  • 使用glMultiDrawElements()通过一次绘制调用绘制多个三角形条带。

答案 2 :(得分:1)

对于您要找的内容,GL_TRIANGLE_STRIPGL_TRIANGLES更好。有关如何排列顶点的示例,请参阅here