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!