Hey guys! I have a model loader that works like this:
- Loads all the meshes
Every mesh contains:
- vector of Vertices (Position, Normal, Texture Coordinates, Tangent and Bitangent)
- vector of Indices
- Sets openGl data (creating buffers, binding stuff and so on).
With this way of loading models when I draw model It has to bne done for every mesh, and I’d like to batch it all into one vertexArray and then draw it simply by ione draw call, so I created this fuction:
(I know that there is some of my own code but It just covers simple OpenGl command and I dont thing it would be a problem)
std::vector<float> vertexBufferData;
std::vector<unsigned int> indexBufferData;
unsigned int indexOffset = 0;
for (int i = 0; i < meshes.size(); i++)
{
for (int t = 0; t < meshes[i].vertices.size(); t++)
{
//This chunk of code simply adds data to vector taken from mesh data I explained above
vertexBufferData.push_back(meshes[i].vertices[t].Position.x);
vertexBufferData.push_back(meshes[i].vertices[t].Position.y);
vertexBufferData.push_back(meshes[i].vertices[t].Position.z);
vertexBufferData.push_back(meshes[i].vertices[t].Normal.x);
vertexBufferData.push_back(meshes[i].vertices[t].Normal.y);
vertexBufferData.push_back(meshes[i].vertices[t].Normal.z);
vertexBufferData.push_back(meshes[i].vertices[t].TexCoords.x);
vertexBufferData.push_back(meshes[i].vertices[t].TexCoords.y);
vertexBufferData.push_back(meshes[i].vertices[t].Tangent.x);
vertexBufferData.push_back(meshes[i].vertices[t].Tangent.y);
vertexBufferData.push_back(meshes[i].vertices[t].Tangent.z);
vertexBufferData.push_back(meshes[i].vertices[t].Bitangent.x);
vertexBufferData.push_back(meshes[i].vertices[t].Bitangent.y);
vertexBufferData.push_back(meshes[i].vertices[t].Bitangent.z);
}
for (int t = 0; t < meshes[i].indices.size(); t++)
{
unsigned int temp = meshes[i].indices[t];
temp += indexOffset; //Here I increase every index by offset since Im connecting a few vectors together I supposed that every next has to have all valuse increased by certain amount
indexBufferData.push_back(temp);
}
indexOffset += meshes[i].indices.size();
}
Ref<VertexBuffer> vb = VertexBuffer::Create(&vertexBufferData[0], sizeof(float) * vertexBufferData.size());
//line of code above simply creates and sets up opengl vertexBuffer with all the data
vb->SetLayout(BufferLayout{ //This code creates data for setting up attribPointers (the string is just a comsetic thing so I know what Im doing)
{ShaderDataType::Float3, "a_Positions"},
{ShaderDataType::Float3, "a_Normals"},
{ShaderDataType::Float2, "a_TexCoords"},
{ShaderDataType::Float3, "a_Tangents"},
{ShaderDataType::Float3, "a_BiTangents"}
});
//Code above translates in shader to:
//layout (location = 0) in vec3 a_Positions;
//layout (location = 1) in vec3 a_Normals;
//layout (location = 2) in vec2 a_TexCoords;
//layout (location = 3) in vec3 a_Tangents;
//layout (location = 4) in vec3 a_Bitangents;
Ref<IndexBuffer> ib = IndexBuffer::Create(&indexBufferData[0], indexBufferData.size());
//this line above also creates and sets up openGl IndexBuffer
m_FinalVA->AddVertexBuffer(vb); //This command creats all attribPointers based on BufferLayout that every vertexBuffer has and adds VertexBuffer to VertexArray
m_FinalVA->SetIndexBuffer(ib); //This command just binds VertexArray and IndexBuffer together
So it works fine with one mesh but It blows up when there is mopre then one mesh!
What I get vs what I should Get:
Im drawing using
glDrawIndexed()
with GL_TRiANGLES
So where did I go wrong with the code?
EDIT:
I changed
indexOffset += meshes[i].indices.size();
to
auto it = std::max_element(std::begin(meshes[i].indices), std::end(meshes[i].indices));
indexOffset += *it;
which resulted in this:
Closer, but not there yet
EDIT2:
Okay I solved it, actually all I had to do was
auto it = std::max_element(std::begin(meshes[i].indices), std::end(meshes[i].indices));
indexOffset += *it + 1; //Instead of indexOffset += *it;