Menu

BonedModel Loading

Help
Azelekia
2014-05-22
2014-07-25
  • Azelekia

    Azelekia - 2014-05-22

    I'm trying to get my model to show. Currently I am having trouble and cant get it to show correctly.

    If i have

    void CModelBone::_ProcessTransforms(const CModelAnimator & animator, CModelBone *pBone, const aat::matrix4f & parentTransform)
    {
        aat::matrix4f transformation = pBone->m_transform;
    
        // temp - just get working without animator affecting it first
        /*if (animator.HasAnimations() && animator.BoneHasKeyframes(pBone))
       {
           aat::matrix4f translation = animator.GetInterpolatedTranslation(pBone);
           aat::matrix4f rotation = animator.GetInterpolatedRotation(pBone);
           aat::matrix4f scale = animator.GetInterpolatedScale(pBone);
    
           transformation = translation * rotation * scale;
       }*/
    
        transformation = parentTransform * aat::matrix4f().Identity();
    
        pBone->m_finalTrans = transformation;
    
        foreach (pBone->m_subBones, bone)
            _ProcessTransforms(animator, (*bone), transformation);
    }
    

    I can get my original pose of the model, just standing there with his arms out. (since everything is an identity, vertex positions dont change in the shader)

    However when i try to get the pose, it gets messed up with

    void CModelBone::_ProcessTransforms(const CModelAnimator & animator, CModelBone *pBone, const aat::matrix4f & parentTransform)
    {
        aat::matrix4f transformation = pBone->m_transform;
    
        // temp - just get working without animator affecting it first
        /*if (animator.HasAnimations() && animator.BoneHasKeyframes(pBone))
       {
           aat::matrix4f translation = animator.GetInterpolatedTranslation(pBone);
           aat::matrix4f rotation = animator.GetInterpolatedRotation(pBone);
           aat::matrix4f scale = animator.GetInterpolatedScale(pBone);
    
           transformation = translation * rotation * scale;
       }*/
    
        transformation = parentTransform * transformation;
    
        pBone->m_finalTrans = transformation * pBone->m_offset;
    
        foreach (pBone->m_subBones, bone)
            _ProcessTransforms(animator, (*bone), transformation);
    }
    

    Am i doing something wrong here or do you think it will be elsewhere, does this look remotely right?
    The code before it called once per frame with

    void CModelBone::ProcessTransforms(const CModelAnimator & animator)
    {
        _ProcessTransforms(animator, this, aat::matrix4f().Identity());
    }
    

    which is called with the rootbone from the bonedmodel

    void CBonedModel::Update(float elapsed)
    {
        m_animator.Update(elapsed);
    
        m_pRootBone->ProcessTransforms(m_animator);
    }
    

    My data is extracted from assimp:

    pBone->m_transform == pNode->mTransformation [this was always set]
    pBone->m_offset == pMesh->mBones[bone]->mOffsetMatrix [i set this to identity matrix if the node had no bone]

    My shaders are

    #version 130
    
    const int MAX_BONES_PER_MESH = 100;
    
    uniform mat4  mvp_matrix;
    uniform float alpha;
    uniform mat4  bone_matrix[MAX_BONES_PER_MESH];
    
    in vec3  in_vertex;
    in vec3  in_colour;
    in vec2  in_texCoord0;
    in vec3  in_normal;
    in ivec4 in_boneID;
    in vec4  in_boneWeight;
    
    out vec4 colour;
    out vec2 texCoord0;
    out vec3 normal;
    
    void main(void) 
    {
        vec4 position = vec4(in_vertex, 1.0);
    
        if (in_boneWeight != vec4(0.0, 0.0, 0.0, 0.0))
        {
            mat4 aniMatrix = bone_matrix[in_boneID[0]] * in_boneWeight[0];
    
            aniMatrix +=     bone_matrix[in_boneID[1]] * in_boneWeight[1];
            aniMatrix +=     bone_matrix[in_boneID[2]] * in_boneWeight[2];
            aniMatrix +=     bone_matrix[in_boneID[3]] * in_boneWeight[3];
    
            position = aniMatrix * position;
        }
    
        gl_Position = mvp_matrix * position;
    
        colour = vec4(in_colour, alpha);
        texCoord0 = in_texCoord0;
        normal = in_normal; 
    }
    

    and

    #version 130
    
    uniform sampler2D texture0;
    
    in vec4 colour;
    in vec2 texCoord0;
    in vec3 normal;
    
    out vec4 out_colour;
    
    void main(void)
    {
        out_colour = texture(texture0, texCoord0.st) * colour;
    }
    

    From assimp what information do I need to store. atm I have a struct

    struct BONED_MODEL_SKELETON_BONE
    {
        int m_id;
        char m_name[MAX_BONE_NAME];
        float m_transform[16];
        float m_boneOffset[16];
        int m_numChildren;
    };
    

    which exists for each node, I have all the keyframe info too, but I want to get it working without
    adding in the animation.

    // ===========================================================================

    can anyone help me or notice anything immediately wrong by design. Can post more info if needed!

    Ive tried reading a few guides I cant wrap my head around some things, any guides/tutorials you guys recommend?

    ty for any help at all!

     
  • Azelekia

    Azelekia - 2014-05-25

    I managed to get it working without the animator. My current code is

    void CModelBone::_ProcessTransforms(const CModelAnimator & animator, CModelBone *pBone, const aat::matrix4f & parentTransform, const aat::matrix4f & globalInverse)
    {
        aat::matrix4f transformation = pBone->m_transform;
        if (animator.HasAnimations() && animator.BoneHasKeyframes(pBone))
        {
            aat::matrix4f translation = animator.GetInterpolatedTranslation(pBone);
            aat::matrix4f rotation = animator.GetInterpolatedRotation(pBone);
            aat::matrix4f scale = animator.GetInterpolatedScale(pBone);
    
            transformation = translation * rotation * scale;
        }
    
        transformation = parentTransform * transformation;
    
        pBone->m_finalTrans = globalInverse * transformation * pBone->m_offset;
    
        foreach (pBone->m_subBones, bone)
            _ProcessTransforms(animator, (*bone), transformation, globalInverse);
    }
    

    However I've found my rotation matrix isn't correct. I compared it with an example for Assimp.

    // temp
    // test
    aiQuaternion aq;
    aq.w = -0;
    aq.x = -0.707107f;
    aq.y = -0.000242f;
    aq.z = -0.707107f;
    
    aat::quaternion myq;
    myq.w = -0;
    myq.x = -0.707107f;
    myq.y = -0.000242f;
    myq.z = -0.707107f;
    
    LOG->out << "=====================================TEST=============================================" << std::endl;
    LOG->out << "assimp quat" << std::endl;
    LOG->out <<  aq.w << ", " << aq.x << ", " << aq.y << ", " << aq.z << std::endl;
    LOG->out << "my quat" << std::endl;
    LOG->out <<  myq.w << ", " << myq.x << ", " << myq.y << ", " << myq.z << std::endl<< std::endl;
    
    CMatrix am(aq.GetMatrix());
    LOG->out << "assimp matrix" << std::endl;
    LOG->out <<  am.m[0][0] << ", " << am.m[0][1] << ", " << am.m[0][2] << ", " << am.m[0][3] << std::endl;
    LOG->out <<  am.m[1][0] << ", " << am.m[1][1] << ", " << am.m[1][2] << ", " << am.m[1][3] << std::endl;
    LOG->out <<  am.m[2][0] << ", " << am.m[2][1] << ", " << am.m[2][2] << ", " << am.m[2][3] << std::endl;
    LOG->out <<  am.m[3][0] << ", " << am.m[3][1] << ", " << am.m[3][2] << ", " << am.m[3][3] << std::endl << std::endl;
    
    aat::matrix4f mm(myq.GetMatrix());
    LOG->out << "my matrix" << std::endl;
    LOG->out <<  mm.m_data[ 0] << ", " << mm.m_data[ 4] << ", " << mm.m_data[ 8] << ", " << mm.m_data[12] << std::endl;
    LOG->out <<  mm.m_data[ 1] << ", " << mm.m_data[ 5] << ", " << mm.m_data[ 9] << ", " << mm.m_data[13] << std::endl;
    LOG->out <<  mm.m_data[ 2] << ", " << mm.m_data[ 6] << ", " << mm.m_data[10] << ", " << mm.m_data[14] << std::endl;
    LOG->out <<  mm.m_data[ 3] << ", " << mm.m_data[ 7] << ", " << mm.m_data[11] << ", " << mm.m_data[15] << std::endl << std::endl;
    
    if (am.m[0][0] != mm.m_data[ 0]) LOG->out << "Cell 0 - Incorrect." << "[" << am.m[0][0] << " != " << mm.m_data[ 0] << "]" << std::endl;
    if (am.m[1][0] != mm.m_data[ 1]) LOG->out << "Cell 1 - Incorrect." << "[" << am.m[1][0] << " != " << mm.m_data[ 1] << "]"<<  std::endl;
    if (am.m[2][0] != mm.m_data[ 2]) LOG->out << "Cell 2 - Incorrect." << "[" << am.m[2][0] << " != " << mm.m_data[ 2] << "]" << std::endl;
    if (am.m[3][0] != mm.m_data[ 3]) LOG->out << "Cell 3 - Incorrect." << "[" << am.m[3][0] << " != " << mm.m_data[ 3] << "]" << std::endl;
    if (am.m[0][1] != mm.m_data[ 4]) LOG->out << "Cell 4 - Incorrect." << "[" << am.m[0][1] << " != " << mm.m_data[ 4] << "]" << std::endl;
    if (am.m[1][1] != mm.m_data[ 5]) LOG->out << "Cell 5 - Incorrect." << "[" << am.m[1][1] << " != " << mm.m_data[ 5] << "]" << std::endl;
    if (am.m[2][1] != mm.m_data[ 6]) LOG->out << "Cell 6 - Incorrect." << "[" << am.m[2][1] << " != " << mm.m_data[ 6] << "]" << std::endl;
    if (am.m[3][1] != mm.m_data[ 7]) LOG->out << "Cell 7 - Incorrect." << "[" << am.m[3][1] << " != " << mm.m_data[ 7] << "]" << std::endl;
    if (am.m[0][2] != mm.m_data[ 8]) LOG->out << "Cell 8 - Incorrect." << "[" << am.m[0][2] << " != " << mm.m_data[ 8] << "]" << std::endl;
    if (am.m[1][2] != mm.m_data[ 9]) LOG->out << "Cell 9 - Incorrect." << "[" << am.m[1][2] << " != " << mm.m_data[ 9] << "]" << std::endl;
    if (am.m[2][2] != mm.m_data[10]) LOG->out << "Cell 10 - Incorrect." << "[" << am.m[2][2] << " != " << mm.m_data[10] << "]" << std::endl;
    if (am.m[3][2] != mm.m_data[11]) LOG->out << "Cell 11 - Incorrect." << "[" << am.m[3][2] << " != " << mm.m_data[11] << "]" << std::endl;
    if (am.m[0][3] != mm.m_data[12]) LOG->out << "Cell 12 - Incorrect." << "[" << am.m[0][3] << " != " << mm.m_data[12] << "]" << std::endl;
    if (am.m[1][3] != mm.m_data[13]) LOG->out << "Cell 13 - Incorrect." << "[" << am.m[1][3] << " != " << mm.m_data[13] << "]" << std::endl;
    if (am.m[2][3] != mm.m_data[14]) LOG->out << "Cell 14 - Incorrect." << "[" << am.m[2][3] << " != " << mm.m_data[14] << "]" << std::endl;
    if (am.m[3][3] != mm.m_data[15]) LOG->out << "Cell 15 - Incorrect." << "[" << am.m[3][3] << " != " << mm.m_data[15] << "]"<<  std::endl;
    
    LOG->out << "=====================================TEST=============================================" << std::endl;
    

    The output was

    =====================================TEST=============================================
    assimp quat
    0, -0.707107, -0.000242, -0.707107
    my quat
    0, -0.707107, -0.000242, -0.707107
    
    assimp matrix
    -7.57249e-007,  0.00034224,  1,            0
     0.00034224,   -1,           0.00034224,   0
     1,             0.00034224, -7.57249e-007, 0
     0,             0,           0,            1
    
    my matrix
    -7.13174e-007,  0.00034224,  1,            0
     0.00034224,   -1,           0.00034224,   0
     1,             0.00034224, -7.13174e-007, 0
     0,             0,           0,            1
    
    Cell 0 - Incorrect.[-7.57249e-007 != -7.13174e-007]
    Cell 5 - Incorrect.[-1 != -1]
    Cell 10 - Incorrect.[-7.57249e-007 != -7.13174e-007]
    =====================================TEST=============================================
    

    The code I currently use for creating my matrix from a quaternion is

    aat::matrix4f aat::quaternion::GetMatrix(void) const
    {
        aat::matrix4f mat;
    
        float xx = x * x;
        float yy = y * y;
        float zz = z * z;
    
        mat[ 0] = 1.0f - 2.0f * (yy + zz); mat[ 4] = 2.0f * (x * y - z * w);  mat[ 8] = 2.0f * (x * z + y * w);  mat[12] = 0;
        mat[ 1] = 2.0f * (x * y + z * w);  mat[ 5] = 1.0f - 2.0f * (xx + zz); mat[ 9] = 2.0f * (y * z - x * w);  mat[13] = 0;
        mat[ 2] = 2.0f * (x * z - y * w);  mat[ 6] = 2.0f * (y * z + x * w);  mat[10] = 1.0f - 2.0f * (xx + yy); mat[14] = 0;
        mat[ 3] = 0;                       mat[ 7] = 0;                       mat[11] = 0;                       mat[15] = 1;
    
        return mat;
    }
    

    Anyone notice anything wrong?
    Ty for any help

     
  • Azelekia

    Azelekia - 2014-05-27

    I solved the problem above by removing the float xx = x * x; etc lines and plugging them straight into the equation.

    My matrices now match that of the example. However I still can't get rid of the distortions.

    I checked every final transformation for each bone against the assimp example and at the same animation time our final transformations matched.

    So then i checked the vertices had the correct boneID and weight assigned to them. Mine match the assimp example too.

    I checked I was using the correct types, ivec4 for boneIDs (4 ints) and vec4 for weights (4 floats). I also check I used glVertexAttribIPointer for the boneIDs as they're int.

    I rechecked my shader which seems correct too me.

    I not sure where I'm going wrong or what else to check next.

    Ty for any help

     
  • Azelekia

    Azelekia - 2014-05-30

    I figured it out, it was such a silly mistake :(

    When i first made my static models i flipped the vertex z and y's because the blender file i used had them flipped. I totally forgot I did this!! Ofc the vectors and quaternions i left the same for animation. Which meant all my transforms looked like the other program I was trying to match and it was my vertices wrong!!!!!!!!

    So sorry :|

     
  • Kim Kulling

    Kim Kulling - 2014-07-25

    Great that you figured out on your own what went wrong. And one hint: don't compare floats with equal. See http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm . Always keep in mind that there is a absolute rounding error you have to use called epsilon.

    Kimmi

     

Log in to post a comment.