update vertices and indices in OPENGL - c++

hi everyone I new to OPENGL and I want to update the vertices and indices when I translate the 3d object I make vertices vector and indices vector these vector hold all the data of the 3d object is this possible
the code I use :
// Create buffers/arrays
glGenVertexArrays(1, &this->VAO);
glGenBuffers(1, &this->VBO);
glGenBuffers(1, &this->EBO);
glBindVertexArray(this->VAO);
// Load data into vertex buffers
glBindBuffer(GL_ARRAY_BUFFER, this->VBO);
// A great thing about structs is that their memory layout is sequential for all its items.
// The effect is that we can simply pass a pointer to the struct and it translates perfectly to a glm::vec3/2 array which
// again translates to 3/2 floats which translates to a byte array.
glBufferData(GL_ARRAY_BUFFER,this->vertices.size() * sizeof(vertex), &this->vertices[0], GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, this->indices.size() * sizeof(int), &this->indices[0], GL_STATIC_DRAW);
// Set the vertex attribute pointers
// Vertex Positions
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(vertex), (GLvoid*)0);
// Vertex Normals
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(vertex), (GLvoid*)offsetof(vertex, normal));
// Vertex Texture Coords
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(vertex), (GLvoid*)offsetof(vertex, uv));
glBindVertexArray(0);
I do not know if this code make change to the vertices and indices or it just make copy of this two vector and render what I want is not make copy this vector and render I want to use this vector directly and make change to this vector is this possible

Usually on graphics we use what's called a transformation matrix for space operations such as translation / rotation / scale.
This allow us to avoid mixing data between model specific data (such as vertices, normals, etc..) and his state in the 3D world (transform).
So my advice here would be to use transformation matrix and update the model position in the vertex shader.
You can find more info here https://learnopengl.com/Getting-started/Transformations

Related

OpenGL: Storing combined mesh (multiple meshes per object) in a single VAO?

When I import a model from a file they are often combined from multiple meshes. Currently, I'm creating a VBO from the very first mesh because I don't know how to deal with others.
glGenVertexArrays(1, &m_VAO);
glBindVertexArray(m_VAO);
const Mesh & mesh = m_modelAsset->meshes[0];
glGenBuffers(1, &m_VBO[0]);
glBindBuffer(GL_ARRAY_BUFFER, m_VBO[0]);
glBufferData(GL_ARRAY_BUFFER, mesh.vertices.size() * sizeof(Vertex), mesh.vertices.data(), GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, position));
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, normal));
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, color));
if I loop through every mesh and simply gen other buffers I don't know how I can tell opengl how it should treat the memory with glVertexAttribPointer. If I call it with the same index it will overwrite previously stored data, won't it?
If I call it with the same index it will overwrite previously stored data, won't it?
Yes. So... don't do that.
If you want to store multiple meshes in the same buffer, you have to use the same buffer. That means you can't go around loading each mesh individually; you have to load them all at once, combine their data, and stick that into a single buffer.
Essentially, you're defining one big vertex array that just so happens to logically define multiple different meshes.

OpenGL can't update vertex buffer with VAO procedure

I'm attempting to move a vertex by modifying it's positional vertex attribute. As a test, I have added the line vertices[0] = 0.4f; both before and after the creation of my VAO procedure, to see whether I am able to modify the vertices array after an initial render. When I add it before the VAO creation, it modifies the location of the vertex, and when it is added afterwards it does not. This leads me to believe my rendering procedure:
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
glfwSwapBuffers(window);
glfwPollEvents();
Somehow isn't actually updating the buffer with the current float[] in memory. However, I can then replace the line glBindVertexArray(VAO); with the whole rendering procedure:
// 2. copy our vertices array in a buffer for OpenGL to use
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
// 2. copy our vertex indices in a buffer for OpenGL to use
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(indices), indices);
// 3. then set our vertex attributes pointers:
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 7 * sizeof(float), (void*)0); // Pos vec3
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 7 * sizeof(float), (void*)(3* sizeof(float))); // Col vec4
glEnableVertexAttribArray(1);
And with this as my rendering procedure, I can update the vertices array and this change is carried across to the GPU, updating the position of the vertex on-screen. Here is my VAO creation code:
// Generate a Vertex Array Object to store our rendering procedure.
unsigned int VAO;
glGenVertexArrays(1, &VAO);
// 1. bind Vertex Array Object, Element Buffer Object
glBindVertexArray(VAO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
// 2. copy our vertices array in a buffer for OpenGL to use
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
// 2. copy our vertex indices in a buffer for OpenGL to use
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(indices), indices);
// 3. then set our vertex attributes pointers:
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 7 * sizeof(float), (void*)0); // Pos vec3
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 7 * sizeof(float), (void*)(3* sizeof(float))); // Col vec4
glEnableVertexAttribArray(1);
So it works when I express the rendering procedure explicitly, but not when I store it in a VAO? From what I understand, a VAO is a construct for storing a rendering procedure, and when we then run glBindVertexArray(VAO);, this rendering procedure is carried out. Am I understanding this wrong? Is there another line I need in either the creation of the VAO or when rendering?
Here is the full source in C++: https://pastebin.com/DgZuZt4K
And the same thing written in OpenTK, C#: https://pastebin.com/DHj9UN16
[...] From what I understand, a VAO is a construct for storing a rendering procedure, [...]
No it is not. A Vertex Array Object stores states.
When glBufferData/glBufferSubData is called, then the buffer object's data store is initialized respectively updated.
When glVertexAttribPointer is called, then states are set in the state vector of the VAO. The buffer object which is currently bound to the target GL_ARRAY_BUFFER is associated to the specified vertex attribute in the currently bound VAO.
The VAO stores the information about how to interpret the vertex information and the id of the VBO for each attribute.
But the VAO does not store a procedure or even a process. When you have changed the vertices, then you have to update the Vertex Buffer Object by either glBufferSubData or buffer mapping.
Related: What is the proper way to modify OpenGL vertex buffer?
If you want to specify and enable a vertex attribute (glVertexAttribPointer / glEnableVertexAttribArray), then you have to bind the VAO and the VBO. The VAO stores the specification and the id of the VBO is stored in the VAO.
If you want to update the vertex coordinates and attributes (e.g. glBufferSubData), then you have to bind the VBO.
If you want to draw the mesh (e.g. glDrawArrays), then it is sufficient to bind the VAO.

How to fix OpenGL stack corruption when exiting

I've been following some opengl tutorials in C++ (moving from using java, so I know openGL alright, but memory management, pointers, etc I'm a little slow on) from http://www.opengl-tutorial.org, and I'm currently having problems with an error when exiting my application.
I am trying to add a normals vertex attrib array. It seems to work fine during runtime, but when I exit the application, I get this:
"Run-Time Check Failure #2 - Stack around the variable 'normalbuffer' was corrupted."
I of course did some googling, and found that this error was normally related to arrays and index out of bounds errors, but normalbuffer is just a GLuint. As far as I can tell, the code for implementing my normalbuffer is identical to that implementing my vertex positions and my uv texture map.
Here is my initialization code:
// Create Vertex Buffer
GLuint vertexbuffer;
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(glm::vec3), &vertices[0], GL_STATIC_DRAW);
// Create UV Buffer
GLuint uvbuffer;
glGenBuffers(1, &uvbuffer);
glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
glBufferData(GL_ARRAY_BUFFER, uvs.size() * sizeof(glm::vec2), &uvs[0], GL_STATIC_DRAW);
// Create Normals Buffer
GLuint normalbuffer;
glGenBuffers(2, &normalbuffer);
glBindBuffer(GL_ARRAY_BUFFER, normalbuffer);
glBufferData(GL_ARRAY_BUFFER, normals.size() * sizeof(glm::vec3), &normals[0], GL_STATIC_DRAW);
And then my looped code (run every frame):
//...
//Load the vertex positions array
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(
0, //Specify which attribute index we are using
3, //Size of the attribute
GL_FLOAT, //Type of attribute
GL_FALSE, //Normalized?
0, //Stride
(void*)0 //Array Buffer Offset
);
//Load the UV positions array
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
glVertexAttribPointer(
1, //Specify which attribute index we are using
2, //Size of the attribute
GL_FLOAT, //Type of attribute
GL_FALSE, //Normalized?
0, //Stride
(void*)0 //Array Buffer Offset
);
//Load the normal vectors array
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, normalbuffer);
glVertexAttribPointer(
2, //Specify which attribute index we are using
3, //Size of the attribute
GL_FLOAT, //Type of attribute
GL_FALSE, //Normalized?
0, //Stride
(void*)0 //Array Buffer Offset
);
//glDrawArrays() happens here
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
//...
This error doesn't seem to happen at all during run time, only when I close the program by hitting the escape key (so I'm not killing the process in VS).
The 1st parameter of glGenBuffers specifies the number of buffer object names to be generated.
You generate 2 objects, but pass the address of the single variable normalbuffer to glGenBuffers.
2 objects are generated and the names of the objects are written to the memory addressed by &normalbuffer and (&normalbuffer) + 1. This causes the stack corruption.
Change the number of objects to be generated:
GLuint normalbuffer;
glGenBuffers(2, &normalbuffer);
glGenBuffers(1, &normalbuffer);

Should I use the same VBO for passing different vertex attributes? Or should I use 2?

I know the glVertexAttribPointer will use the values from the VBO that was bound when it was called. But can you buffer twice onto the same object? Would it replace what was in? Or can you clear a buffer? I don't know if this approach is correct:
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO); // shared VBO
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(posLoc);
glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 3*sizeof(GLfloat),(GLvoid*)0);
glBufferData(GL_ARRAY_BUFFER, sizeof(colours), colours, GL_STATIC_DRAW);
glEnableVertexAttribArray(colLoc);
glVertexAttribPointer(colLoc, 4, GL_FLOAT, GL_FALSE, 4*sizeof(GLfloat),(GLvoid*)0);
glBindBuffer(GL_ARRAY_VERTEX, 0);
glBindVertexArray(0);
Or if I should be using 2 VBOs for buffering the data. What would happen if you call the glBufferData function twice to the same bound vertex array object? This is the other way I would think of for doing this:
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO1); // VBO for vertices
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(posLoc);
glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 3*sizeof(GLfloat),(GLvoid*)0);
glBindBuffer(GL_ARRAY_BUFFER, VBO2); // VBO for colours
glBufferData(GL_ARRAY_BUFFER, sizeof(colours), colours, GL_STATIC_DRAW);
glEnableVertexAttribArray(colLoc);
glVertexAttribPointer(colLoc, 4, GL_FLOAT, GL_FALSE, 4*sizeof(GLfloat),(GLvoid*)0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
The top example won't work as the second glBufferData call will overwrite all of the buffer space in the second one. To properly do that, you have to use the stride and pointer arguments properly, so that the data is interleaved. It's easier (and cleaner imo) to just have multiple VBO's, each storing a separate set of data.

C++/OpenGL - Drawing a cube VBO

Recently I started to learn OpenGL and I am beginning to learn the newer assets of it. For a while now I've been trying to work with VBOs, to draw a simple cube from a vertex point array. I am having trouble rendering it and understanding some of the arguments in the functions. It throws no errors but nothing is in my view.
float cubeVertPoints[72]; //An array containing the vertex points
Here is my VBO init
void loadBufferData()
{
glGenBuffers(1, &cubeVBO);
glBindBuffer(GL_ARRAY_BUFFER, cubeVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(cubeVertPoints[0])*3, &cubeVertPoints[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(cubeVertPoints[0])*3, (void*)sizeof(GL_FLOAT));
}
Drawing
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-ratio, ratio, -1.f, 1.f, 1.f, -1.f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glBindBuffer(GL_ARRAY_BUFFER, cubeVBO);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(cubeVertPoints[0])*3, (void*)sizeof(GL_FLOAT));
glDrawArrays(GL_TRIANGLES, 0, 1);
glDisableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
You are not transferring all your data into the vertex buffer. The 2nd parameter of glBufferData takes the size of all of your vertex data in bytes. You should set it to sizeof(vertex) * vertex_count.
Also, calling glEnableVertexAttribArray and glVertexAttribPointer in loadBufferData is redundant. You should call them only in your rendering function.
Your second problem is with glVertexAttribPointer. You are not passing the correct offset to your vertex position data in your vertex data "structure". Since your vertices only consist of positions, this offset should be 0. If you would have positions and colors for each vertex, these offset could be 0 (for position) and sizeof(float) * 3 (for color, because you have 3 coordinates).
Finally, you only draw a single vertex. You should draw 72/3=24 if your cube has 24 vertices.
I think you can make your life easier by defining an actual structure for your vertices, like so:
struct Vertex
{
float position[3];
};
Then, you can compute offsets for each of your vertex positions, colors, etc, with (GLvoid*)(&((Vertex*)NULL)->position).