Some meshes are drawn wrong.

Help
JohanJ
2013-05-03
2013-06-03
  • JohanJ
    JohanJ
    2013-05-03

    Hello,
    First of all, awesome library, I enjoy it very much. I have some problems, though.

    Some of my meshes are drawn correctly, typically the simpler ones like a minimalistic cube or this model http://thefree3dmodels.com/stuff/furniture/chair/12-1-0-4869

    Some meshes either gets drawn mostly correctly or not at all. For example  http://thefree3dmodels.com/stuff/vehicles/btr_40/13-1-0-5453 does not get drawn at all, http://thefree3dmodels.com/stuff/characters/uhura/14-1-0-5461 gets drawn almost perfectly

    I do not know what is causing this. I can verify that the models are correct, because when I open them in the assimp viewer, they look correct.

    Here's how I iterate over all the nodes in the scene:

    PackageModel AssetImporter::ProcessModel(const aiScene* scene, const aiNode* node)
        {
            PackageModel model;
            model.mName = node->mName.C_Str();
            model.mTransform = aiMat4ToJonsMat4(node->mTransformation);
            
            for(unsigned int i = 0; i < node->mNumMeshes; i++)
            {
                PackageMesh mesh;
                const aiMesh* m = scene->mMeshes[node->mMeshes[i]];
                
                // vertice, normal and texcoord data
                for (unsigned int j = 0; j < m->mNumVertices; j++)
                {
                    mesh.mVertexData.push_back(Vec3(m->mVertices[j].x, m->mVertices[j].y, m->mVertices[j].z));
                    
                    if (m->HasNormals())
                        mesh.mNormalData.push_back(Vec3(m->mNormals[j].x, m->mNormals[j].y, m->mNormals[j].z));
                    if (m->HasTextureCoords(0))
                        mesh.mTexCoordsData.push_back(Vec2(m->mTextureCoords[0][j].x, m->mTextureCoords[0][j].y));
                }
                
                // index data
                for (unsigned int j = 0; j < m->mNumFaces; j++)
                    mesh.mIndiceData.insert(mesh.mIndiceData.end(), m->mFaces[j].mIndices, m->mFaces[j].mIndices + m->mFaces[j].mNumIndices);
                // add mesh to collection
                model.mMeshes.push_back(mesh);
            }
            
            for(unsigned int i = 0; i < node->mNumChildren; i++)
                model.mChildren.push_back(ProcessModel(scene, node->mChildren[i]));
            return model;
        }
    

    The "PackageMesh" and "PackageModel" looks like this:

    /* PackageMesh definition */
        struct PackageMesh
        {
            std::vector<Vec3> mVertexData;
            std::vector<Vec3> mNormalData;
            std::vector<Vec2> mTexCoordsData;
            std::vector<uint32_t> mIndiceData;
            uint16_t mMaterialIndex;
            
            PackageMesh();
        };
        /* PackageModel definition */
        struct PackageModel
        {
            std::string mName;
            std::vector<PackageModel> mChildren;
            std::vector<PackageMesh> mMeshes;
            Mat4 mTransform;
            PackageModel();
        };
    

    The data of these packages are then used when constructing a VertexBuffer class, which orders them into opengl VBOs and VAOs for drawing the meshes..

    OpenGLVertexBuffer::OpenGLVertexBuffer(const std::vector<Vec3>& vertexData, const std::vector<Vec3>& normalData, const std::vector<Vec2>& texCoords, const std::vector<uint32_t>& indexData) : mIndices(indexData.size())
         {
            glGenBuffers(1, &mVBO);
            glGenBuffers(1, &mIndexBuffer);
            glGenVertexArrays(1, &mVAO);
    
            // buffer vertex, normals and index data
            glBindVertexArray(mVAO);
            glBindBuffer(GL_ARRAY_BUFFER, mVBO);
            glBufferData(GL_ARRAY_BUFFER, (vertexData.size() + normalData.size()) * sizeof(Vec3), NULL, GL_STATIC_DRAW);
            glBufferSubData(GL_ARRAY_BUFFER, NULL, vertexData.size() * sizeof(Vec3), &vertexData[0]);
            glBufferSubData(GL_ARRAY_BUFFER, vertexData.size() * sizeof(Vec3), normalData.size() * sizeof(Vec3), &normalData[0]);
            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
            glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexData.size() * sizeof(uint32_t), &indexData[0], GL_STATIC_DRAW);
            glEnableVertexAttribArray(0);
            glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
            glEnableVertexAttribArray(1);
            glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)(vertexData.size() * sizeof(Vec3)));
           // unbind array buffer and VAO
            glBindBuffer(GL_ARRAY_BUFFER, 0);
            glBindVertexArray(0);
         }
    

    I am using the latest official source release and am using the aiProcessPreset_TargetRealtime_MaxQuality flag in the importer.

    Is there anything that looks odd and might be causing some meshes to look only partly correct or not viewed at all?

     
  • I don't know OpenGL, but from what I can tell your mesh setup looks correct to me. Check the following:

    - Calculate the bounds of the scene. Maybe this one specific mesh is offset in some direction, or scaled huge and therefore cut off by the far plane when rendering.
    - Use a GPU debugging tool to check what happens to the vertices in the shader. Maybe your matrix layout is differing from the Assimp choice.
    - Check the materials, if you are using them. Maybe the model's author used the alpha channel of the texture for some other purpose (which is perfectly fine) and now the whole mesh falls victim to alpha testing or -blending when rendering.

     
  • Kim Kulling
    Kim Kulling
    2013-05-06

    You made a small mistake while copying te vertex-and normal-data into you vertex buffers. You copied the vertex data twice and no normal data will be copied, if I understand your code right.

    Kimmi