【问题标题】:Small errors in rotation causing model deformation旋转中的小误差导致模型变形
【发布时间】:2013-07-31 07:33:11
【问题描述】:

(可能重复:Rotating a 4x4 Matrix Causes Scaling Over Time

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

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

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

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

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

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

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

【问题讨论】:

  • 我不太确定你的矩阵是如何设置的,但你不应该在左边乘以 parent-&gt;absoluteForm 吗?所以b-&gt;absoluteForm = parent-&gt;absoluteForm * (glm::toMat4(bf-&gt;quaternion * b-&gt;relativeForm * )) ; 而不是b-&gt;absoluteForm = (b-&gt;relativeForm * glm::toMat4(bf-&gt;quaternion)) * parent-&gt;absoluteForm; 和其他诸如“先本地旋转然后本地翻译”之类的东西,而不是相反?换句话说,您确定矩阵乘法中操作数的顺序是正确的吗?
  • 在 OpenGL 中,应用矩阵的顺序是从右到左。因此,以从左到右的典型数学顺序(例如,'Bone[i]=invBindPose * absoluteForm')编写函数会导致混乱。同样,此代码适用于任何单独的骨骼旋转;仅当您尝试组合多个骨骼变换时才会失败,并且变换后的骨骼彼此之间存在层次关系。
  • 嗯,是的。顶点通常在右侧相乘(不是必须以这种方式完成,这是一个固定功能的管道构造)。但这意味着您将在最右侧进行局部旋转,然后进行局部平移,然后进行其余的全局变换。

标签: c++ opengl 3d transformation


【解决方案1】:

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

    }
}

【讨论】:

    猜你喜欢
    • 2020-10-31
    • 2021-10-12
    • 2015-07-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多