在OpenGL中创建一个网格

时间:2017-11-03 00:54:11

标签: c++ c++11 opengl grid stdvector

我需要使用OpenGL在xy平面中生成NxN分辨率网格。最终网格需要由三角形(GL_TRIANGLES)制作,所以它应该如下例所示:

 ^
 *   |  ----------
 *   |  |\ |\ |\ |
 *   |  | \| \| \|
 *   |  ----------
 *   |  |\ |\ |\ |
 * y |  | \| \| \|
 *   |  ----------
 *   |  |\ |\ |\ |
 *   |  | \| \| \|
 *   |  ----------
 *   |
 *   |-------------->
 *          x

请注意,我需要以顶点索引形式存储网格(通过参数给出结构)。

我的代码:

void generate_grid(
std::uint32_t N,
std::vector<glm::vec3>* vertices,
std::vector<glm::uvec3>* indices)
{
    for (int i = 0; i < N; i++) {
        glBegin(GL_TRIANGLES);
    for (int j = 0; j < N; j++) {
        int vertexNum = indices;  // Index for vertex j of face i.
        double[] vertexCoords = vertices[vertexNum];  // The vertex itself.
        glVertex3f(vertexCoords, 0);
    }
    glEnd();
} 

有什么建议吗?问候。

1 个答案:

答案 0 :(得分:2)

由于语言是C ++并且你使用的是std::vector,你应该更改函数签名并通过引用而不是指针传递参数。

void generate_grid(int N, std::vector<glm::vec3> &vertices, std::vector<glm::uvec3> &indices);

首先,你必须填充顶点数组。请注意,对于N*N字段,您需要(N+1)*(N+1)个顶点。其次,您必须为每个字段生成三角形索引,您必须生成2个三角形:

 float f(float x, float y)
{
    // use any curve function you want
    return sin(x*2.0f*3.141526f) * sin(y*2.0f*3.141526f) * 0.1f;
}

void generate_grid(int N, std::vector<glm::vec3> &vertices, std::vector<glm::uvec3> &indices)
{
    for (int j=0; j<=N; ++j) 
    {
        for (int i=0; i<=N; ++i)
        {
            float x = (float)i/(float)N;
            float y = (float)j/(float)N;
            float z = f(x, y);
            vertices.push_back(glm::vec3(x, y, z));
        }
    }

    for (int j=0; j<N; ++j) 
    {
        for (int i=0; i<N; ++i)
        {
            int row1 = j * (N+1);
            int row2 = (j+1) * (N+1);  

            // triangle 1
            indices.push_back(glm::uvec3(row1+i, row1+i+1, row2+i+1)); 

            // triangle 2
            indices.push_back(glm::uvec3(row1+i, row2+i+1, row2+i)); 
        }
    }
}

旧学校和弃用的方式来绘制这个,就像这样:

void draw_grid(const std::vector<glm::vec3> &vertices, const std::vector<glm::uvec3> &indices)
{
    glBegin(GL_TRIANGLES);
    for ( auto i : indices )
    {
        glVertex3fv(glm::value_ptr(vertices[i.x]));
        glVertex3fv(glm::value_ptr(vertices[i.y]));
        glVertex3fv(glm::value_ptr(vertices[i.z]));
    }
    glEnd();
}

绘制几何体的常用方法是创建Vertex Array Object

GLuint generate_vao(const std::vector<glm::vec3> &vertices, const std::vector<glm::uvec3> &indices)
{
    GLuint  vao;
    glGenVertexArrays( 1, &vao );
    glBindVertexArray( vao );

    GLuint vbo;
    glGenBuffers( 1, &vbo );
    glBindBuffer( GL_ARRAY_BUFFER, vbo );
    glBufferData( GL_ARRAY_BUFFER, vertices.size()*sizeof(glm::vec3), glm::value_ptr(vertices[0]), GL_STATIC_DRAW );
    glEnableVertexAttribArray( 0 );
    glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, 0, nullptr );

    GLuint ibo;
    glGenBuffers( 1, &ibo );
    glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, ibo );
    glBufferData( GL_ELEMENT_ARRAY_BUFFER, indices.size()*sizeof(glm::uvec3), glm::value_ptr(indices[0]), GL_STATIC_DRAW );

    glBindVertexArray( 0 );
    glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
    glBindBuffer( GL_ARRAY_BUFFER, 0 );

    return vao;
}


void draw_vao( GLuint vao, GLsizei n )
{  
    glBindVertexArray( vao );
    glDrawElements( GL_TRIANGLES, (GLsizei)n, GL_UNSIGNED_INT, NULL );
    glBindVertexArray( 0 );
}

std::vector<glm::vec3> vertices;
std::vector<glm::uvec3> indices;

GLuint vao = generate_vao( vertices, indices );
.....
draw_vao( vao, (GLsizei)indices.size()*3 );