Search code examples
opengl-esassimp

Incorrect skeleton mesh drawn using Assimp and OpenGL ES


I'm trying to draw a skeleton animation mesh(model boblampclean.md5mesh) using ASSIMP but meshes are drawn incorrectly. Meshes are loaded correctly I'm following ogld tutorials for loading and drawing meshes. Below is my some code and output:

This is how buffers are populated and initially VAO, VBO and EBO are generated:

    GLCall(glBufferData(GL_ARRAY_BUFFER, m_Positions.size() * sizeof(m_Positions[0]),&m_Positions[0],GL_STATIC_DRAW))
    GLCall(glEnableVertexAttribArray(POSITION_LOCATION))
    GLCall(glVertexAttribPointer(POSITION_LOCATION, 3, GL_FLOAT, GL_FALSE, 0,nullptr))

    GLCall(glBindBuffer(GL_ARRAY_BUFFER, m_Buffers[TEXCOORD_VB]))
    GLCall(glBufferData(GL_ARRAY_BUFFER, m_TexCoords.size() * sizeof(m_TexCoords[0]),&m_TexCoords[0],GL_STATIC_DRAW))
    GLCall(glEnableVertexAttribArray(TEX_COORD_LOCATION))
    GLCall(glVertexAttribPointer(TEX_COORD_LOCATION, 2, GL_FLOAT, GL_FALSE, 0, nullptr))

    GLCall(glBindBuffer(GL_ARRAY_BUFFER, m_Buffers[NORMAL_VB]))
    GLCall(glBufferData(GL_ARRAY_BUFFER, m_Normals.size() * sizeof(m_Normals[0]), &m_Normals[0], GL_STATIC_DRAW))
    GLCall(glEnableVertexAttribArray(NORMAL_LOCATION))
    GLCall(glVertexAttribPointer(NORMAL_LOCATION, 3, GL_FLOAT, GL_FALSE, 0, nullptr))

    GLCall(glBindBuffer(GL_ARRAY_BUFFER, m_Buffers[BONE_VB]))
    GLCall(glBufferData(GL_ARRAY_BUFFER, m_Bones.size() * sizeof(m_Bones[0]), &m_Bones[0],GL_STATIC_DRAW))

    GLCall(glEnableVertexAttribArray(BONE_ID_LOCATION))
    GLCall(glVertexAttribIPointer(BONE_ID_LOCATION, MAX_NUM_BONES_PER_VERTEX, GL_INT,sizeof(VertexBoneData), nullptr))

    GLCall(glEnableVertexAttribArray(BONE_WEIGHT_LOCATION))
    GLCall(glVertexAttribPointer(BONE_WEIGHT_LOCATION, MAX_NUM_BONES_PER_VERTEX, GL_FLOAT, GL_FALSE,sizeof(VertexBoneData),(const GLvoid *) (MAX_NUM_BONES_PER_VERTEX * sizeof(int32_t))))

    GLCall(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_Buffers[INDEX_BUFFER]))
    GLCall(glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_Indices.size() * sizeof(m_Indices[0]), &m_Indices[0],GL_STATIC_DRAW))

Draw call:

    GLCall(glUseProgram(meshProgram))
        glm::mat4 projection = glm::perspective(45.0f,
                                                (float) windowWidth / (float) windowHeight,
                                                0.1f,
                                                100.0f);
        glm::mat4 translate = glm::translate(glm::mat4(1.0), glm::vec3(0.0f, 0.0f, 50.0f));
        glm::mat4 rotation = glm::rotate(glm::mat4(1.0f), glm::radians(120.0f),
                                         glm::vec3(0.0f, 1.0f, 1.0f));
        glm::mat4 scale = glm::scale(glm::mat4(1.0), glm::vec3(0.2, 0.2, 0.2));
        glm::mat4 model = translate * rotation * scale;
        GLCall(GLuint projectionLocation = meshShader->getUniformLocation("projection"))
        GLCall(GLuint modelLocation = meshShader->getUniformLocation("model"))
        meshCamera->useCamera();

        std::vector<Matrix4f> boneMatrix;
        mesh->GetBoneTransforms(mesh->getAnimationSecond(), boneMatrix);

        GLuint mBoneLocation[100];
        for (unsigned int i = 0; i < ARRAY_SIZE_IN_ELEMENTS(mBoneLocation); i++) {
            char Name[128];
            memset(Name, 0, sizeof(Name));
            snprintf(Name, sizeof(Name), "gBones[%d]", i);
            GLCall(mBoneLocation[i] = meshShader->getUniformLocation(Name))
        }

        for (int i = 0; i < boneMatrix.size(); ++i) {
            if (i >= 100) {
                break;
            }
            Matrix4f matrix = boneMatrix[i];
            GLCall(glUniformMatrix4fv(mBoneLocation[i], 1, GL_TRUE, (const GLfloat *) matrix))
        }

        // GLCall(GLuint meshTextureLocation = meshShader->getUniformLocation("texture"))
        GLCall(meshShader->setUniformMatrix4fv(projectionLocation, 1, glm::value_ptr(projection)))
        GLCall(meshShader->setUniformMatrix4fv(modelLocation, 1, glm::value_ptr(model)))

        Vector3f localPos = mesh->GetWorldTransform().WorldPosToLocalPos(meshCamera->getCameraPos());
        GLCall(GLuint localCameraPosLocation = meshShader->getUniformLocation("gCameraLocalPos"))
        GLCall(glUniform3f(localCameraPosLocation, localPos.x, localPos.y, localPos.z))[![enter image description here][1]][1]

        GLCall(glBindVertexArray(m_VAO))

        for (auto &m_Meshe : m_Meshes) {

            unsigned int MaterialIndex = m_Meshe.MaterialIndex;

            if (m_Materials[MaterialIndex].pDiffuse) {
                Texture *texture = m_Materials[MaterialIndex].pDiffuse;
                GLCall(texture->bind())
                GLCall(GLuint diffuseLocation = glGetUniformLocation(program, "gSampler"))
                GLCall(glUniform1i(diffuseLocation, texture->getSlot()))
            }
            if (m_Materials[MaterialIndex].pSpecularExponent) {
                Texture *texture = m_Materials[MaterialIndex].pSpecularExponent;
                GLCall(GLuint specularLocation = glGetUniformLocation(program,
                               "gSamplerSpecularExponent"))
                GLCall(texture->bind())
                GLCall(glUniform1i(specularLocation, texture->getSlot()))
            }

            GLCall(glDrawElementsBaseVertex(GL_TRIANGLES, m_Meshe.NumIndices, GL_UNSIGNED_INT,
                                            (GLvoid *) (sizeof(unsigned int) * m_Meshe.BaseIndex),
                                            m_Meshe.BaseVertex))

        }
        GLCall(glBindVertexArray(0))

Output: Output


Solution

  • I managed to fix it by storing normals, vertices and Texchord correctly.