I'm currently implementing Skeletal Animation into my 3D OpenGL Game Engine using the ASSIMP library, unfortunately it isn't going all that great. The problem I am currently facing is that the concatenated bone transforms (the parent-child relationship between bones) only act correctly when only one parent is being transformed.
What happens is that the thigh's bone transformation is carried out on global axes instead of the pelvis' local axes.
Here is my Skeleton class:
class Skeleton
{
public:
Skeleton();
unsigned int numBones;
std::vector<std::string> names;
std::vector<glm::mat4> offsets;
std::vector<glm::mat4> transforms;
std::vector<int> parents;
std::string GetName(int bone);
glm::mat4 GetWorldTransform(int bone);
int GetID(std::string bone_name);
};
and here is the function I use to calculate the world transform for each bone:
glm::mat4 Skeleton::GetWorldTransform(int bone)
{
int p = parents[bone];
glm::mat4 result = glm::mat4(1.0);
result *= glm::inverse(offsets[bone]);
result *= transforms[bone];
result *= offsets[bone];
while(p >= 0) //The root bone has a parent of -1
{
result *= glm::inverse(offsets[p]);
result *= transforms[p]; //Apply The Parent's Transform
result *= offsets[p];
p = parents[p];
}
return result;
}
And in my Mesh class I have this function UpdateSkeleton():
void Mesh::UpdateSkeleton(unsigned int shaderID)
{
std::vector<glm::mat4> mats;
for(int i = 0; i < skeleton->numBones; i++)
{
glm::mat4 matrix = glm::mat4(1.0);
matrix *= skeleton->GetWorldTransform(i);
mats.push_back(matrix);
}
if(mats.size() > 0)
glUniformMatrix4fv(glGetUniformLocation(shaderID,"gBones"),mats.size(),GL_FALSE,glm::value_ptr(mats[0]));
}
Thank you!