For skeletal animation using colladas, I need to linearly interpolate between 2 matrices. I saw somewhere that I can use quaternions to interpolate between matrices, but that only works for the rotational component, and I need to preserve the transform as well. Here is my code, which works, except for the translation part:
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);
Is there any way that I can do this?
I ended up solving my question through a bit more web surfing. For future reference, heres how to do it.
The transformation component is stored in a 4x4 matrix like this:
r r r t
r r r t
r r r t
0 0 0 1
where r is the rotational component and t is the translation component. Because of this, we can represent the translation component as a vector. 2 Vectors can be linearly interpolated, so we interpolate those two vectors and then shove them back into the rotation matrix when they're done. Heres the final code, but its a bit messy:
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;
Hope that answers anybody else's questions :)