Search code examples
c++openglblenderglm-mathassimp

Incorrect bone rotations, based on bone structure in edit mode


I am having a trouble/question regarding assimp and blender exporting. I export model from blender to gltf binary (.glb), and everything is working correct, unless the bones inside blender are rotated not inside the pose mode (created and rotated inside edit mode) i am curious if the trouble can be solved inside the code, or i have to modify blender's export to fix it.comparison

as you can see, one bone bone is facing upwards in first comparison and on second its rotated in edit mode, causing it to have incorrect rotations.

heres my c++ code to calculate the animations matrices

class Bone
{
    public:
    int Id;
    glm::mat4 Transform;
    Bone* BoneParent;
    std::vector<Bone*> BoneChild;
    glm::mat4 NodeTran;
    glm::mat4 MTran;
    
    std::vector<glm::vec3> LocFrames;
    std::vector<glm::quat> RotFrames;
    std::vector<glm::vec3> ScaleFrames;
    glm::mat4 Offset;

    
    
    glm::mat4 getLocalTransform()
    {
        float Factor= 1.0;

                    glm::vec3 T= this->LocFrames[1]+ (Factor * (this->LocFrames[1] - this->LocFrames[0]));
                    glm::mat4 TR = glm::translate(glm::mat4(1.0f), T);
                    
                    
                    glm::quat R = glm::normalize(glm::mix(this->RotFrames[0],this->RotFrames[1],Factor));
                    glm::mat4 RT = glm::toMat4(R);
                    
                    return TR*RT ;
        
    }
    
    
    glm::mat4 getParentTransform()
{
    if (this->BoneParent){
        return BoneParent->NodeTran;
        
        
    }
    else {
        return glm::mat4(1.0f);
        
    }
}

    class Skeleton
{
    public:
    std::vector<Bone> BoneList;
    Bone *Root;
    glm::mat4 inverse;
    aiMatrix4x4 inverseai;
    void Calc(Bone* bone = NULL)
    {
    

    
    bone->NodeTran = bone->getParentTransform()* // parent
    bone->getLocalTransform(); // T*R

    bone->Transform = inverse * // ai inverse
    bone->MTran* // node->mTransformation of bone
    bone->NodeTran*
    bone->Offset; // bone->mOffsetMatrix
    for (int i = 0; i < bone->BoneChild.size(); i++) {

       Calc(bone->BoneChild[i]);
    }
    
    }

    };

//...
//...
ObjModel->ModelSkeleton.Calc(ObjModel->ModelSkeleton.Root);
for(int i=0; i<ObjModel->ModelSkeleton.BoneList.size();i++){
glm::mat4 matrix = ObjModel->ModelSkeleton.BoneList[i].Transform;
        glUniformMatrix4fv(glGetUniformLocation(ActiveShader->ID, "Anim[0]")+i, 1, GL_FALSE, glm::value_ptr(matrix );
}

Solution

  • By debugging various things, i found out that blender/assimp gltf2 importer put the bone translations (rotation,location,size) and offset of nodes (static bones) in location/rotation/scale frames, i solved that by :

    1. creating 'unanimated' sequence which as name suggest, contains unanimated bones
    2. saving the unanimated loc/rot/scale frames
    3. substracting all the animation frames by the unanimated frames

    i am aware of this being an "hackfix" but this is beyond my grasp, since the bug is inside blender or assimp import