How to make a rectangular grid of triangles?

I’m using OpenGL, GLFW and GLEW to create a simulation of water waves for a school project. I’m using a textured grid and will manipulate said grid in the vertex shader.

I tried to create the grid by adapting the GeometryGenerator class in Frank Luna’s book “Introduction to 3D Game Programming”. I created the function but it gives me an odd scalene triangle instead of the grid.
I have attempted multiple of my own fixes and forums to no success.

Can anyone suggest a fix or a different function which would work better?

Here are the relevant snippets of code:

struct vertex
    {
        GLfloat x, y, z;
        GLfloat u, v;
    };

struct index
{
    GLuint a, b, c;
};

struct MeshData
{
    std::vector<vertex> Vertices;
    std::vector<index> Indices;
    //std::vector<GLuint> Indices;
};
void CreateGrid(float width, float depth, int m, int n, MeshData& meshData)
{
    int vertexCount = m*n;
    int faceCount   = (m-1)*(n-1)*2;
    // Create the vertices.

    float halfWidth = 0.5f*width;
    float halfDepth = 0.5f*depth;

    float dx = width / (n-1);
    float dz = depth / (m-1);

    float du = 1.0f / (n-1);
    float dv = 1.0f / (m-1);


    meshData.Vertices.resize(vertexCount);
    for(GLfloat i = 0.0f; i < m; ++i)
    {
        GLfloat z = halfDepth - i*dz;
        for(GLfloat j = 0.0f; j < n; ++j)
        {
            //code
            GLfloat x = -halfWidth + j*dx;

            meshData.Vertices[i*n+j].x = x;
            meshData.Vertices[i*n+j].y = 0.0f;
            meshData.Vertices[i*n+j].z = z;

            meshData.Vertices[i*n+j].u = j*du;
            meshData.Vertices[i*n+j].v = i*dv;

            //vertex temp = {x, 0.0f, z, j*du, i*dv};
            //meshData.Vertices.push_back(temp);
        }
    }
    //indices
    meshData.Indices.resize(faceCount);

    GLuint offset = 0;
    for(GLuint i = 0; i < m-1; ++i)
    {
        for(GLuint j = 0; j < n-1; ++j)
        {               
            //offset = x * m;
            index temp = 
            {
                i*n+j,
                i*n+j+1,
                (i+1)*n+j
            };

            index temp_2 = 
            {
                (i+1)*n+j,
                i*n+j+1,
                (i+1)*n+j+1
            };

            meshData.Indices.push_back(temp);
            meshData.Indices.push_back(temp_2);
        }
    }
}

Also passing the data to the VAO.


#pragma region "object_initialization"
    // Set the object data (buffers, vertex attributes)

    MeshData grid;

    CreateGrid(30, 20, 2.0f, 3.0f, grid);

    // Setup plane VAO
    GLuint planeVAO, planeVBO, planeEBO;
    glGenVertexArrays(1, &planeVAO);

    glGenBuffers(1, &planeVBO);
    glGenBuffers(1, &planeEBO);
    glBindVertexArray(planeVAO);

    glBindBuffer(GL_ARRAY_BUFFER, planeVBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertex) * grid.Vertices.size(), &grid.Vertices, GL_STATIC_DRAW);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, planeEBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(index) * grid.Indices.size(), &grid.Indices, GL_STATIC_DRAW);


    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (GLvoid*)0);
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
    glBindVertexArray(0);

    // Load textures
    GLuint floorTexture = loadTexture("C://path to.../brushwater.png");
    #pragma endregion

Here is the rendering code:

while(!glfwWindowShouldClose(window))
    {
        // Set frame time
        GLfloat currentFrame = glfwGetTime();
        deltaTime = currentFrame - lastFrame;
        lastFrame = currentFrame;

        // Check and call events
        glfwPollEvents();
        Do_Movement();

        // Clear the colorbuffer
        glClearColor(0.2f, 0.2f, 0.2f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);    

        // Draw objects
        shader.Use(); 
        glm::mat4 model;
        glm::mat4 view = camera.GetViewMatrix();
        glm::mat4 projection = glm::perspective(camera.Zoom, (float)screenWidth/(float)screenHeight, 0.1f, 100.0f);
        glUniformMatrix4fv(glGetUniformLocation(shader.Program, "view"), 1, GL_FALSE, glm::value_ptr(view));
        glUniformMatrix4fv(glGetUniformLocation(shader.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
        // Floor
        glBindVertexArray(planeVAO);
        glBindTexture(GL_TEXTURE_2D, floorTexture);
        model = glm::mat4();
        glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
        glDrawArrays(GL_TRIANGLES, 0, 3*grid.Indices.size());
        glBindVertexArray(0);               


        // Swap the buffers
        glfwSwapBuffers(window);
    }

My outputs now are textured scalene triangles.
Thanks in advanced for reading it though, and thanks for your help!

there is NO WAY to render lines of a grid if you use:
glDrawArrays(GL_TRIANGLES, …);
because GL_TRIANGLES ONLY generates triangles, if you pass only 2 points, it will rener nothing

you have to use GL_LINES (or GL_LINE_LOOP) as rendering mode in the draw call if you want to render lines

ps: shouldnt it be

glBufferData(GL_ARRAY_BUFFER, sizeof(vertex) * grid.Vertices.size(), &grid.Vertices.data(), GL_STATIC_DRAW);

rather than

glBufferData(GL_ARRAY_BUFFER, sizeof(vertex) * grid.Vertices.size(), &grid.Vertices, GL_STATIC_DRAW);

?