两个4x4矩阵之间的插值

3

对于使用colladas进行骨架动画,我需要在两个矩阵之间进行线性插值。我在某处看到可以使用四元数来插值矩阵,但这仅适用于旋转部分,我还需要保留变换部分。以下是我的代码,它有效,但翻译部分有问题:

float total = (orderedBones[i]->Animation->keyFrames[nextKeyFrame] - orderedBones[i]->Animation->keyFrames[nextKeyFrame - 1]) * 100.0;
float progress = orderedBones[i]->Animation->accumTime - orderedBones[i]->Animation->keyFrames[nextKeyFrame - 1] * 100.0;
float interpolation = progress / total;

glm::quat firstQuat = glm::quat_cast(orderedBones[i]->Animation->Matrices[nextKeyFrame - 1]);
glm::quat secondQuat = glm::quat_cast(orderedBones[i]->Animation->Matrices[nextKeyFrame]);
glm::quat finalQuat = glm::slerp(firstQuat, secondQuat, interpolation);

orderedBones[i]->Animation->interpoltaedMatrix = glm::mat4_cast(finalQuat);

有没有办法实现这个功能?

我建议添加标签“四元数”(单数)。 - Severin Pappadeux
@SeverinPappadeux 已添加 :) - BlueSpud
@SeverinPappadeux collada是一种能够存储骨骼动画数据的3D文件格式。虽然它相对不那么重要,但我还是想提一下。 - BlueSpud
什么样的矩阵?对于一般的矩阵,线性插值就是(1-t)A+tB。 - rych
@user612313 这些是4x4的转换矩阵。我已经解决了问题并发布了答案以供日后参考。 - BlueSpud
2个回答

9

我通过更多的网络搜索解决了我的问题。供参考,以下是如何操作的:

转换组件存储在4x4矩阵中,如下所示:

r r r t
r r r t
r r r t
0 0 0 1

其中 r 是旋转分量,t 是平移分量。因此,我们可以将平移分量表示为向量。2个向量可以进行线性插值,因此,我们对这两个向量进行插值,然后在完成后将它们推回旋转矩阵中。下面是最终代码,但有点混乱:

float total = (orderedBones[i]->Animation->keyFrames[nextKeyFrame] - orderedBones[i]->Animation->keyFrames[nextKeyFrame - 1]) * ANIMATION_MULTIPLICATION_CONST;
float progress = orderedBones[i]->Animation->accumTime - orderedBones[i]->Animation->keyFrames[nextKeyFrame - 1] * ANIMATION_MULTIPLICATION_CONST;
float interpolation = progress / total;

glm::quat firstQuat = glm::quat_cast(orderedBones[i]->Animation->Matrices[nextKeyFrame - 1]);
glm::quat secondQuat = glm::quat_cast(orderedBones[i]->Animation->Matrices[nextKeyFrame]);
glm::quat finalQuat = glm::slerp(firstQuat, secondQuat, interpolation);

orderedBones[i]->Animation->interpoltaedMatrix = glm::mat4_cast(finalQuat);

glm::vec4 transformComp1 = glm::vec4(
    orderedBones[i]->Animation->Matrices[nextKeyFrame - 1][0][3],
    orderedBones[i]->Animation->Matrices[nextKeyFrame - 1][1][3],
    orderedBones[i]->Animation->Matrices[nextKeyFrame - 1][2][3],
    orderedBones[i]->Animation->Matrices[nextKeyFrame - 1][3][3]);
glm::vec4 transformComp2 = glm::vec4(
    orderedBones[i]->Animation->Matrices[nextKeyFrame][0][3],
    orderedBones[i]->Animation->Matrices[nextKeyFrame][1][3],
    orderedBones[i]->Animation->Matrices[nextKeyFrame][2][3],
    orderedBones[i]->Animation->Matrices[nextKeyFrame][3][3]);

glm::vec4 finalTrans = (float)(1.0 - interpolation) * transformComp1 + transformComp2 * interpolation;

// good for now, although in future the 2 transformation components need to be interpolated
orderedBones[i]->Animation->interpoltaedMatrix[0][3] = finalTrans.x;
orderedBones[i]->Animation->interpoltaedMatrix[1][3] = finalTrans.y;
orderedBones[i]->Animation->interpoltaedMatrix[2][3] = finalTrans.z;
orderedBones[i]->Animation->interpoltaedMatrix[3][3] = finalTrans.w;

希望这能回答其他人的问题 :)

在现代glm中,要访问变换组件,请使用matrix[3],即在上面的代码中: 1)glm :: vec4 transformComp1 = orderedBones [i]-> Animation-> Matrices [nextKeyFrame-1] [3] 2)glm :: vec4 transformComp2 = orderedBones [i]-> Animation-> Matrices [nextKeyFrame] [3] 3)orderedBones [i]-> Animation-> interpoltaedMatrix [3] = finalTrans - congard

2
这个函数对我有效:
glm::mat4 interpolate(glm::mat4& _mat1, glm::mat4& _mat2, float _time)
{
    glm::quat rot0 = glm::quat_cast(_mat1);
    glm::quat rot1= glm::quat_cast(_mat2);

    glm::quat finalRot = glm::slerp(rot0, rot1, _time);

    glm::mat4 finalMat = glm::mat4_cast(finalRot);

    finalMat[3] = _mat1[3] * (1 - _time) + _mat2[3] * _time;
    
    return finalMat;
}

比例部分是否正确插值?glm有类似的功能 https://glm.g-truc.net/0.9.6/api/a00205.html#ga45099a92c5c704503565619ac2bcd5c6 - Liu Hao

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接