(可能重复: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];
}
}
}
为了帮助澄清一些代码:
以下是使用此代码显示模型的图像: http://imgur.com/tbur5Lf
作为额外的,这里是使用此代码转换的模型中单个骨骼的图像(而不是bf,使用了键盘控制的四元数):http://t.co/wf38ibGoyc
我花了两个星期才走到这一步,所以我非常感谢任何帮助。谢谢,如果我需要提供任何其他信息,请告诉我。
修改 我上传的视频演示了我的程序在单骨转换中的成功,以及复合转换的问题。完成上传后,它将位于:http://youtu.be/8Cv3jMYcz64
答案 0 :(得分: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 );
}
}
}