旋转中的小误差导致模型变形

Small errors in rotation causing model deformation

本文关键字:模型 变形 误差 旋转      更新时间:2023-10-16

(可能重复:旋转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->位置是一个glm::vec3,包含骨骼在其局部/骨骼空间,相对于父骨骼
  • bf包含11骨骼的转换信息框架换句话说,必须获得多个骨骼框架才能获得1帧中所有骨骼的变换信息
  • bf->四元数是一个包含旋转的4浮点glm::quat动画中骨骼帧的信息。换句话说包含有关必须如何旋转骨骼才能获得模型的信息从其绑定姿势到当前姿势
  • 类似地,bf->translation,一个glm::vec3,包含translation骨骼框架的信息。因为人类骨骼是刚性的,bf->translation的大多数值都设置为(0,0,0)
  • relativeForm和absoluteForm指的是局部矩阵和全局矩阵分别为变换骨骼的。在此代码段之前运行时,relativeForm只需b->位置转换为矩阵,并且absoluteForm是骨骼的绑定姿势矩阵

以下是使用此代码显示模型的图像:https://i.stack.imgur.com/tPJ1t.jpg

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

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

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

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