user18305
user18305

Reputation: 3

Small errors in rotation causing model deformation

(Possible duplicate: Rotating a 4x4 Matrix Causes Scaling Over Time )

Hello everyone. I have been trying to get a model into a pose other than its bind pose. Currently I'm using the first frame out of an animation file and trying to set the model into that initial pose.

I believe my math equations are now correct. Transforming a single bone works perfectly (the children follow like it should). However, with Compound Transformations (where a child is transformed, and its parent has also been transformed), very young children seem to be highly deformed. (For example, the fingers of the model when the wrist, elbow, and shoulder bones have also been transformed.)

int targetFrame = CONST_TEST_FRAME_NUMBER;

    // root bone
    PMXBone   *b  = pmxInfo.bones[0];
    BoneFrame *bf = getBoneFrame(targetFrame, b->name);

    b->absoluteForm = b->relativeForm;      
    Bone[0] = b->absoluteForm * invBindPose[0];



    // other bones
    for (size_t i = 1; i < pmxInfo.bone_continuing_datasets; i++)
    {
        b  = pmxInfo.bones[i];
        PMXBone *parent = pmxInfo.bones[b->parentBoneIndex];
        bf = getBoneFrame(targetFrame, b->name);

        if(bf!=NULL)
        {
            b->finalRotation = bf->quaternion * parent->finalRotation;


            glm::vec4 homoPosition=glm::vec4(b->position + bf->translation, 1.0); //position in homogeneous coordinates
            glm::vec4 localPosition=glm::rotate(parent->finalRotation,homoPosition);

            b->relativeForm[3][0]=localPosition[0];
            b->relativeForm[3][1]=localPosition[1];
            b->relativeForm[3][2]=localPosition[2];
            b->relativeForm[3][3]=localPosition[3];

            b->absoluteForm = (b->relativeForm * glm::toMat4(bf->quaternion)) * parent->absoluteForm;

            Bone[i] = b->absoluteForm * invBindPose[i];
        }
        else
        {       
            b->finalRotation = parent->finalRotation;

            glm::vec4 homoPosition=glm::vec4(b->position,1.0); //position in homogeneous coordinates
            glm::vec4 localPosition=glm::rotate(b->finalRotation,homoPosition);

            b->relativeForm[3][0]=localPosition[0];
            b->relativeForm[3][1]=localPosition[1];
            b->relativeForm[3][2]=localPosition[2];
            b->relativeForm[3][3]=localPosition[3];

            b->absoluteForm = b->relativeForm * parent->absoluteForm;

            Bone[i] = b->absoluteForm * invBindPose[i];
        }
    }
}

To help clarify the code some:

Here is an image of how the model appears with this code: https://i.sstatic.net/tPJ1t.jpg

As an extra, here is an image of a single bone in the model being transformed using this code (Instead of bf, a keyboard-controlled quaternion was used): http://t.co/wf38ibGoyc

It took me a good two weeks to get this far, so I greatly appreciate any help. Thanks, and let me know if there is any other information I need to provide.

EDIT: I am uploading a video that demonstrates my program's success in single bone transformations, and issues with compound transformations. When it is done uploading, it will be at: http://youtu.be/8Cv3jMYcz64

Upvotes: 0

Views: 360

Answers (1)

user18305
user18305

Reputation: 3

2ch saved the day for me:

void setModelToKeyFrame(glm::mat4 Bone[], GLuint &shaderProgram, PMXInfo &pmxInfo, VMDInfo &vmdInfo)
{

    int targetFrame = CONST_TEST_FRAME_NUMBER;
    glm::mat4 aniMatrix;

    // root bone
    PMXBone   *b  = pmxInfo.bones[0];
    BoneFrame *bf = getBoneFrame(targetFrame, b->name);

    b->absoluteForm = b->relativeForm;
    if(bf!=NULL)
    {
        b->finalRotation = bf->quaternion;

        b->relativeForm = glm::translate( b->position ) * glm::toMat4(bf->quaternion);
        b->absoluteForm = glm::translate( bf->translation + b->position ) * glm::toMat4(bf->quaternion);
        Bone[i] = glm::translate( bf->translation + b->position ) * glm::toMat4(bf->quaternion) * glm::translate( -b->position );
    }
    Bone[0] = b->absoluteForm * invBindPose[0];



    // other bones
    for (size_t i = 1; i < pmxInfo.bone_continuing_datasets; i++)
    {
        b  = pmxInfo.bones[i];
        PMXBone *parent = pmxInfo.bones[b->parentBoneIndex];
        bf = getBoneFrame(targetFrame, b->name);

        if(bf!=NULL)
        {
            b->finalRotation = bf->quaternion * parent->finalRotation;

            b->relativeForm = glm::translate( bf->translation + b->position - parent->position ) * glm::toMat4(bf->quaternion);
            b->absoluteForm = parent->absoluteForm * glm::translate( bf->translation + b->position - parent->position ) * glm::toMat4(bf->quaternion);
            Bone[i] = parent->absoluteForm * glm::translate( bf->translation + b->position - parent->position ) * glm::toMat4(bf->quaternion) * glm::translate( -b->position );
        }
        else
        {
            b->finalRotation = parent->finalRotation;

            b->relativeForm = glm::translate( b->position - parent->position );
            b->absoluteForm = parent->absoluteForm * glm::translate( b->position - parent->position );
            Bone[i] = parent->absoluteForm * glm::translate( b->position - parent->position ) * glm::translate( -b->position );
        }

    }
}

Upvotes: 0

Related Questions