简体   繁体   中英

How to generate a plane using GL_TRIANGLES?

Is there an algorithm that could be used to generate a plane using the GL_TRIANGLES primitive type?

Here's my current function:

Mesh* Mesh::CreateMeshPlane(vec2 bottomleft, ivec2 numvertices, vec2 worldsize){

int numVerts = numvertices.x * numvertices.y;

float xStep = worldsize.x / (numvertices.x - 1);
float yStep = worldsize.y / (numvertices.y - 1);

VertexFormat* verts = new VertexFormat[numVerts];

for (int y = 0; y < numvertices.y; y++)
{
    for (int x = 0; x < numvertices.x; x++)
    {           
        verts[x + (y * numvertices.x)].pos.x = bottomleft.x + (xStep * x);
        verts[x + (y * numvertices.x)].pos.y = bottomleft.y + (yStep * y);
        verts[x + (y * numvertices.x)].pos.z = 0;
    }
}

Mesh* pMesh = new Mesh();
pMesh->Init(verts, numVerts, indices, 6, GL_STATIC_DRAW);

glPointSize(10.0f);
pMesh->m_PrimitiveType = GL_POINTS;

delete[] verts;

return pMesh;}

I'm just unsure how to implement indices into the for loop to be able to know which points to draw.

What I think I need to know:

Each square will be made up of 2 triangles, each square requiring 6 indices

Currently I'm drawing from the bottom left

I need to know how many squares I'll have from the numbers passed in

Maybe something like this:

int width = 4;
int length = 6;
int height = 1;

std::vector<float> planeVertices;

for (int x = 0; x < width - 1; x++) {
    for (int z = 0; z < length - 1; z++) {
        planeVertices.push_back(x);
        planeVertices.push_back(height);
        planeVertices.push_back(z);

        planeVertices.push_back(x);
        planeVertices.push_back(height);
        planeVertices.push_back(z + 1);

        planeVertices.push_back(x + 1);
        planeVertices.push_back(height);
        planeVertices.push_back(z + 1);


        planeVertices.push_back(x);
        planeVertices.push_back(height);
        planeVertices.push_back(z);

        planeVertices.push_back(x + 1);
        planeVertices.push_back(height);
        planeVertices.push_back(z);

        planeVertices.push_back(x + 1);
        planeVertices.push_back(height);
        planeVertices.push_back(z + 1);
    }
}

...

unsigned int VBO, VAO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);

glBindVertexArray(VAO);

glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, planeVertices.size() * sizeof(float), planeVertices.data(), GL_STATIC_DRAW);

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), 0);
glEnableVertexAttribArray(0);

...

glDrawArrays(GL_TRIANGLES, 0, (width - 1) * (length - 1) * 6);

This code creates an std::vector<float> and adds the plane vertices to it. The nested for loops add two triangles for every unit of the plane (so with width as 4 and length as 6 the plane will be 4 units by 6 units, and will be made of 6 * 4 * 2 = 48 triangles). The height of the plane is set by the height variable. This only generates flat planes, but a simple transformation lets you rotate and scale this as you need.

WARNING: this code is untested.

Just to close this question here's how I did it:

Mesh* Mesh::CreateMeshPlane(vec3 bottomleft, ivec2 numvertices, vec2 
worldsize, vec2 texturerepetition)
{
    int numVerts = numvertices.x * numvertices.y;
    int numFaces = (numvertices.x - 1) * (numvertices.y - 1);
    int numIndices = numFaces * 6;

    float xStep = worldsize.x / (numvertices.x - 1);
    float yStep = worldsize.y / (numvertices.y - 1);
    float zStep = worldsize.y / (numvertices.y - 1);

    float uStep = texturerepetition.x / (numvertices.x - 1);
    float vStep = texturerepetition.y / (numvertices.y - 1);

    VertexFormat* verts = new VertexFormat[numVerts];
    unsigned int* indices = new unsigned int[numIndices];

    for (int y = 0; y < numvertices.y; y++)
    {
        for (int x = 0; x < numvertices.x; x++)
        {
            verts[x + (y * numvertices.x)].pos.x = bottomleft.x + (xStep * x);
            verts[x + (y * numvertices.x)].pos.y = bottomleft.y;
            verts[x + (y * numvertices.x)].pos.z = bottomleft.z + (zStep * y);

            verts[y * numvertices.x + x].uv.x = uStep * x;
            verts[y * numvertices.x + x].uv.y = vStep * y;
        }
    }

    int offset = 0;

    for (int i = 0; i < numIndices; i++)
    {
        // The bottom left index of the current face
        // + the offset to snap back when we hit the edge
        unsigned int cornerIndex = i/6 + offset;

        // If we reach the edge we increase the offset so that it goes to the next bottom left
        if ((cornerIndex + 1)%numvertices.x == 0)
        {
            offset++;
            cornerIndex++; // Adding new offset to the bottom left
        }

        // First triangle
        indices[i] = (unsigned int)cornerIndex;
        i++;
        indices[i] = (unsigned int)cornerIndex + numvertices.x;
        i++;
        indices[i] = (unsigned int)cornerIndex + numvertices.x + 1;
        i++;

        // Second triangle
        indices[i] = (unsigned int)cornerIndex;
        i++;
        indices[i] = (unsigned int)cornerIndex + numvertices.x + 1;
        i++;
        indices[i] = (unsigned int)cornerIndex + 1;
    }

    //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

    Mesh* pMesh = new Mesh();
    pMesh->Init(verts, numVerts, indices, numIndices, GL_STATIC_DRAW);

    delete[] verts;

    return pMesh;
}

Workflow: 1. Calculating number of faces I need, then the number of indices 2. Creating an offset that is added to the cornerIndex when we realize we hit the edge of the vertex array (by using modulus numvertices.y) 3. Doing simple math to draw corners in correct order based on the cornerIndex

Notes: 1. Im drawing using GL_TRIANGLES as the primitive type 2. Drawing from bottom left to top right 3. cornerIndex therefore is the bottom left of the current square we're drawing on

Hope someone can find this helpful!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM