Open virtualenv opened 4 years ago
Even though the issue was opened about a year ago, here's my implementation.
First, we need to load the mesh itself. And for that we need a loader. So it's objl::Loader loader;
for the loader and loader.LoadFile(filepath);
to load the mesh, where filepath
is.. well.. path to the .obj file.
Great, we should've got the mesh in. Now we need to access it, objl::Mesh mesh = loader.LoadedMeshes.back();
. Note: some people are using loader.LoadedMeshes[0]
to get the mesh. Which is correct, if you make a new loader every time you want to load a mesh. In case if you have one constant loader, LoadedMeshes.back()
would give you the mesh you need.
Now, when we have the mesh
, we have to get its vertex data. I personally used another array(vector) for that. Let's call it vertexData
: vector<float> vertexData;
. And now we need to fill it with vertex positions, just like we did in OpenGL tutorials, but this time we do that in a loop:
for(int vertex = 0; vertex < mesh.Vertices.size(); vertex++){
vertexData.push_back(mesh.Vertices[vertex].Position.X);
vertexData.push_back(mesh.Vertices[vertex].Position.Y);
vertexData.push_back(mesh.Vertices[vertex].Position.Z);
}
And now we do the usual, make a Vertex Array Object:
GLuint VAO;
glGenVertexArrays(1, &VAO);
make a Vertex Buffer Object:
GLuint VBO;
glGenBuffers(1, &VBO);
bind them and load the data:
glBindVertexArray(VAO);
glBindBuffer(GL_VERTEX_BUFFER, VBO);
glBufferData(GL_VERTEX_BUFFER, vertexData.size() * sizeof(float), vertexData.data(), GL_STATIC_DRAW);
We used `vertexData.size() sizeof(float)to get the byte length of the vertex data array. If you want to type less, you can replace
sizeof(float)with
4`.
Don't forget to pass this data to the shaders in a form of attribute:
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void *)0);
glEnableVertexAttribArray(0);
You can learn more about glVertexAttribPointer
function on learnopengl website.
Wonderful, you can render loaded mesh by binding corresponding VAO and calling glDrawArrays(GL_TRIANGLES, 0, vertCount);
, where vertCount
is the amount of vertices. You can get them using mesh.Vertices.size();
.
Please note, that explanation/example above works only for triangulated meshes and doesn't incorporate UVs.
To incorporate UVs, in first loop also push_back
texture coordinates:
...
vertexData.push_back(mesh.Vertices[vertex].TextureCoordinate.X);
vertexData.push_back(mesh.Vertices[vertex].TextureCoordinate.Y);
Don't forget to update vertex attributes:
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void *)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void *)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
Now you can access your UVs from vertex shaders using layout (location = 1) in vec2 aUV;
, and pass them to fragment shaders. This process is neatly described in other OpenGL tutorials. For example learnopengl.
If your mesh is not triangulated (has quads in it, or other non-triangle faces), mesh.Vertices.size()
and mesh.Indices.size()
will be different, usually Indices > Vertices. You can check for that, and in that case use another buffer, Element Buffer Object. Note that in this case you would need to draw your VAO using glDrawElements(GL_TRIANGLES, vertCount, GL_UNSIGNED_INT, 0);
, where vertCount
is equal to mesh.Indices.size();
To actually fill EBO, make it
GLuint EBO;
glGenBuffers(1, &EBO);
and fill it
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, mesh.Indices.size() * sizeof(unsigned int), mesh.Indices.data(), GL_STATIC_DRAW);
mesh.Indices.size() * sizeof(unsigned int)
with the same intention as above. You can replace sizeof(unsigned int)
with 4
.Please note that you can't always use indices. If the mesh is triangulated, mesh.Vertices
will be in the right order already, and indices would be incorrectly applied.
Hopefully this will help someone some day. And it's readable. Best regards, Kriper @ 2:45am
Is there any OpenGL GLFW rendering sample that I could learn from ?
Thank you.