Search code examples
c++openglassimpwavefront

Loading mtl colors using assimp


I've been trying to load a Wavefront obj model with ASSIMP. However, I can't get mtl materials colors to work (Kd rgb). I know how to load then, but, I don't know how to get the corresponding color to each vertex.

usemtl material_11
f 7//1 8//1 9//2
f 10//1 11//1 12//2

For example, the Wavefront obj snippet above means that thoose vertices uses material_11.

Q: So how can I get the material corresponding to each vertex?

Error

Wavefront obj materials aren't in the right vertices:

Original Model (Rendered with ASSIMP model Viewer): enter image description here

Model renderered with my code: enter image description here

Code:

Code that I use for loading mtl materials color:

std::vector<color4<float>> colors = std::vector<color4<float>>();

                            ...

for (unsigned int i = 0; i < scene->mNumMeshes; i++)
{
    const aiMesh* model = scene->mMeshes[i];
    const aiMaterial *mtl = scene->mMaterials[model->mMaterialIndex];

    color4<float> color = color4<float>(1.0f, 1.0f, 1.0f, 1.0f);
    aiColor4D diffuse;
    if (AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_DIFFUSE, &diffuse))
        color = color4<float>(diffuse.r, diffuse.g, diffuse.b, diffuse.a);
    colors.push_back(color);

                            ...
}

Code for creating the vertices:

vertex* vertices_arr = new vertex[positions.size()];
for (unsigned int i = 0; i < positions.size(); i++)
{
    vertices_arr[i].SetPosition(positions.at(i));
    vertices_arr[i].SetTextureCoordinate(texcoords.at(i));
}

// Code for setting vertices colors (I'm just setting it in ASSIMP vertices order, since I don't know how to set it in the correct order).
for (unsigned int i = 0; i < scene->mNumMeshes; i++)
{
    const unsigned int vertices_size = scene->mMeshes[i]->mNumVertices;
    for (unsigned int k = 0; k < vertices_size; k++)
    {
        vertices_arr[k].SetColor(colors.at(i));
    }
}

EDIT:

Looks like that the model vertices positions aren't being loaded correctly too. Even when I disable face culling and change the background color.

enter image description here


Solution

  • Ignoring issues related to the number of draw calls and extra storage, bandwidth and processing for vertex colours,

    It looks like vertex* vertices_arr = new vertex[positions.size()]; is one big array you're creating to hold the entire model (which has many meshes, each with one material). Assuming your first loop is correct and positions contains all positions for all meshes of your model. The second loop starts duplicating mesh colours for each vertex within the mesh. However, vertices_arr[k] always starts at zero and needs to begin after the last vertex of the previous mesh. Instead, try:

    int colIdx = 0;
    for (unsigned int i = 0; i < scene->mNumMeshes; i++)
    {
        const unsigned int vertices_size = scene->mMeshes[i]->mNumVertices;
        for (unsigned int k = 0; k < vertices_size; k++)
        {
            vertices_arr[colIdx++].SetColor(colors.at(i));
        }
    }
    assert(colIdx == positions.size()); //double check
    

    As you say, if the geometry isn't drawing properly, maybe positions doesn't contain all vertex data. Perhaps a similar issue to the above code? Another issue could be in joining the indices for each mesh. The indices will all need to be updated with an offset to the new vertex locations within the vertices_arr array. Though now I'm just throwing out guesses.