Search code examples
androidopengl-esandroid-ndkassimp

Android OpenGL ES 2 Random Model Deformation


I've ported a desktop OpenGL application to Android NDK (under OpenGL ES 2), and there seems to be a random deformation of my mesh. On most application runs, it looks 100% perfect, but sometimes it looks as follows:

enter image description here

The inconsistency of the problem is the most concerning to me. I don't know if it's because of my Android simulator, or if it's something else. Through my testing, I can establish that it's either:

  • An OpenGL setting that doesn't play nice on Android, but does on everything else
  • A bug in the Open Asset Import Library (Assimp) which I've compiled by hand to work on Android
  • A bug in the Android simulator

My model process looks as follows:

On every draw:

- bind the program
- change the uniforms

- if (has vao support)
    - bind vao

- enable all vertex attribute arrays

- for every mesh
    - bind array buffer
    - set the attribute pointer for each vertex array
    - bind element buffer
    - bind texture & set uniform of texture location
    - glDrawElements

- disable all vertex attribute arrays

And this is the actual code:

glUseProgram(program_);

if (loaded_vao_)
{
    #if !defined(TARGET_OS_IPHONE) && !defined(__ANDROID__)
    glBindVertexArray(vao_);
    #else
    glBindVertexArrayOES(vao_);
    #endif
}

glEnableVertexAttribArray(vPosition_);
glEnableVertexAttribArray(vTexCoord_);
glEnableVertexAttribArray(boneids_);
glEnableVertexAttribArray(weights_);

for (unsigned int i = 0; i < vbo_.size(); i++)
{
    glBindBuffer(GL_ARRAY_BUFFER, vbo_[i]);

    glVertexAttribPointer(vPosition_, 3, GL_FLOAT, GL_FALSE, 0, 0);
    glVertexAttribPointer(vTexCoord_, 2, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<void*>(texcoord_locations_[i]));

    #if !defined(TARGET_OS_IPHONE) && !defined(__ANDROID__)
    glVertexAttribIPointer(boneids_, 4, GL_INT, 0, reinterpret_cast<void*>(bone_id_locations_[i]));
    #else // APPLE OR ANDROID
    glVertexAttribPointer(boneids_, 4, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<void*>(bone_id_locations_[i]));
    #endif

    glVertexAttribPointer(weights_, 4, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<void*>(bone_weight_locations_[i]));

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo_[i]);

    // Textures
    if (!textures_.empty())
    {
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, textures_[texture_numbers_[i]]);
        glUniform1i(textureSample_, 0);
    }

    glDrawElements(GL_TRIANGLES, ind_size_[i], GL_UNSIGNED_SHORT, 0);
}

glDisableVertexAttribArray(vPosition_);
glDisableVertexAttribArray(vTexCoord_);
glDisableVertexAttribArray(boneids_);
glDisableVertexAttribArray(weights_);

As well, my vertex shader looks as follows:

precision mediump float;

attribute vec3 vPosition;
attribute vec2 vTexCoord;
attribute vec4 boneids;
attribute vec4 weights;

uniform mat4 pos;
uniform mat4 view;
uniform mat4 scale;
uniform mat4 rotate;
uniform mat4 proj;
uniform mat4 bones[50];
uniform int has_bones;

varying vec4 color;
varying vec2 texcoord;

void main()
{
    color = vec4(1.0f);
    texcoord = vTexCoord;

    vec4 newPos = vec4(vPosition,1.0);

    if (has_bones == 1)
    {
        mat4 bone_transform = bones[int(boneids[0])]*weights[0];
        bone_transform += bones[int(boneids[1])]*weights[1];
        bone_transform += bones[int(boneids[2])]*weights[2];
        bone_transform += bones[int(boneids[3])]*weights[3];

        newPos = bone_transform * newPos;
    }

    gl_Position = proj * view * pos * scale * rotate * newPos;
}

Do note that I've tried commenting out the bone_transform in the vertex shader, and the problem still persists.

EDIT:

It seems that I was able to recreate some deformations on my Linux OpenGL 3.3 version by removing any assimp optimization post process flags:

scene = importer.ReadFile(file_path.c_str(), aiProcess_Triangulate | aiProcess_FlipUVs | aiProcess_LimitBoneWeights | aiProcess_ValidateDataStructure);

Based on the output of the Assimp::DefaultLogger, there's no errors or vertex warnings.


Solution

  • The issue seemed to be a part of Blender's COLLADA export, or Assimp's COLLADA reader.

    By exporting to FBX and using Autodesk's free FBX to DAE tool, the deformation was fixed.

    • Blender was version 2.71
    • Assimp was version 3.1.1

    Assimp, even with all logging and data integrity flags on, did not post any errors about corruption, so I don't know which component to blame. Regardless, I'm happy I've found a workaround.