I am new to the terms of skeletal animation and I have read that, to animate a mesh using skeletal I would have to use a hierarchy of bones which I did making each bone node in my scene graph and then to deform the mesh I have to get the inverse absolute matrix of the bone before interpolation (which I believe is what they call the pose) multiply that for the interpolated absolute matrix of the bone to get transition matrix and the to deform the mesh I would have to multiply the vertex times the transition matrix times the weight and sum all this result with any other bone that deform the same vertex.
to be more specific to get the absolute of each bone I do this
void CNode::update()
{
if(this->Parent!=null)
absMatrix = this->Parent->absMatrix * relativeMatrix;
else
absMatrix = RelativeMatrix;
for(int n=0; n<childs.count; n++)
{
childs[n]->update();
}
}
now I get the inverse of this absMatrix matrix before any interpolation that change the relativeMatrix one time only so to do the vertex deformation is this function
void CMesh::skinMesh(){
CVec3 vec;
for(int n=0; n < vertex.count; n++)
{
vec.clear();
for(int i=0; i < vertex[n].weight.count && vertex[n].bindBone[i] ; i++)
{
vec+= vertex[n].vec * vertex[n].bindBone[i]->transitionMatrix * vertex[n].weight[i];
}
outVertex[n] = vec;
}
now that doesn't work for me because every vertex rotate around the center of the mesh axis instead of the parent of bone the bone that deform the vertices, I thought it was logical considering that transition = InverAbs *absoulteMatrix will get me the the amount of rotation the bone has gain due to the interpolation so assuming it rotate 20 degrees the vertices will rotate 20 deg from the vertices origin so I guess I am missing something to make the vertices rotation around the parent of the bone which is deforming them, please help me.
so this is how I do the interpolation just that is not to the absolute matrix but to the relativeMatrix the code I update the absolute is the one above.
//CAnimateObject is a decendent class of CNode
void CAnimateObject::UpdateFrame(unsigned AniNum, float Time)
{
float fInterp;
if(m_AniCount > AniNum)
{
CKeyFrame *CurAni = &Ani[ AniNum ];
if(CurAni->Pos.list.count>0)
{
CFrame<CVector3>::CKEY *begin, *end;
if( CurAni->Pos.getBetweenKeys(&begin, &end, Time, fInterp)){
m_Pos.x = begin->Object->x + (end->Object->x - begin->Object->x) * fInterp;
m_Pos.y = begin->Object->y + (end->Object->y - begin->Object->y) * fInterp;
m_Pos.z = begin->Object->x + (end->Object->z - begin->Object->z) * fInterp;
}
}
if(CurAni->Scale.list.count>0)
{
CFrame<CVector3>::CKEY *begin, *end;
if( CurAni->Scale.getBetweenKeys(&begin, &end, Time, fInterp)){
m_Scale.x = begin->Object->x + (end->Object->x - begin->Object->x) * fInterp;
m_Scale.y = begin->Object->y + (end->Object->y - begin->Object->y) * fInterp;
m_Scale.z = begin->Object->x + (end->Object->z - begin->Object->z) * fInterp;
}
}
if(CurAni->Rot.list.count > 1)
{
CFrame<CQuaternion>::CKEY *begin, *end;
if( CurAni->Rot.getBetweenKeys(&begin, &end, Time, fInterp)){
m_Qrel.SLERP(*begin->Object, *end->Object, fInterp);
}
}else
if(CurAni->Rot.list.count==1)
m_Qrel = *(CQuaternion*)CurAni->Rot.list.start[0].Object;
}
CMatrix4 tm, scale;
scale.identity();
tm.identity();
scale.Scale(m_Scale.Get());
tm.fromQuaternion(m_Qrel);
m_Rel = tm * scale;
m_Rel.Translate(m_Pos);
}
and yes I did this and work multiply the bone by it's inverse absolute and then by the absolutematrix and it works perfectly but to many multiplication are happening, like.
//inversePose is the absoluteMatrix before applying the interpolation of the relative matrix
void CMesh::skinMesh(){
CVec3 vec;
for(int n=0; n < vertex.count; n++)
{
outVertex[n].clear();
for(int i=0; i < vertex[n].weight.count && vertex[n].bindBone[i] ; i++)
{
vec = vertex[n].vec3 * vertex[n].bindBone[i]->inversePose;
vec = vec * vertex[n].bindBone[i]->absMatrix * vertex[n].weight[i];
outVertex[n]+= vec;
}
}