0

(可能重复:旋转 4x4 矩阵会导致随时间缩放

大家好。我一直在尝试让模型进入绑定姿势以外的姿势。目前我正在使用动画文件中的第一帧并尝试将模型设置为初始姿势。

我相信我的数学方程式现在是正确的。改造单根骨头效果很好(孩子们应该跟着做)。然而,通过复合变换(其中一个孩子被变换,其父母也被变换),非常年幼的孩子似乎高度畸形。(例如,模型的手指手腕、肘部和肩部骨骼也进行了变形。)

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];
        }
    }
}

为了帮助澄清一些代码:

  • b->position 是一个 glm::vec3,包含骨骼在其本地/骨骼空间中相对于父骨骼的位置。
  • bf 包含1 帧中1 个骨骼的变换信息。换句话说,你必须获得多个 Bone Frames 才能获得1帧中所有骨骼的变换信息。
  • bf->quaternion 是一个 4-float glm::quat,包含动画中骨骼框架的旋转信息。换句话说,它包含有关必须如何旋转骨骼以使模型从其绑定姿势到当前姿势的信息。
  • 类似地,bf->translation,一个 glm::vec3,包含骨骼框架的平移信息。因为人体骨骼是刚性的,所以 bf->translation 的大部分值都设置为 (0,0,0)。
  • relativeForm 和 absoluteForm 分别指变换骨骼的局部和全局矩阵。在运行此代码片段之前,relativeForm 只是将 b->position 转换为矩阵,absoluteForm 是骨骼的 Bind Pose 矩阵。

这是使用此代码显示模型的图像:http: //imgur.com/tbur5Lf

另外,这是使用此代码转换的模型中单个骨骼的图像(而不是 bf,使用了键盘控制的四元数):http ://t.co/wf38ibGoyc

我花了两个星期才走到这一步,所以我非常感谢任何帮助。谢谢,如果我需要提供任何其他信息,请告诉我。

编辑: 我正在上传一个视频,展示我的程序在单骨转换方面的成功,以及复合转换的问题。完成上传后,它将位于:http: //youtu.be/8Cv3jMYcz64

4

1 回答 1

0

2ch 为我节省了一天:

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 );
        }

    }
}
于 2013-07-31T21:22:01.880 回答