我是骨骼动画术语的新手,我已经读过,要使用骨骼动画网格,我必须使用骨骼层次结构,我在场景图中制作每个骨骼节点,然后使网格变形我必须在插值之前获得骨骼的逆绝对矩阵(我相信这就是他们所说的姿势)乘以骨骼的插值绝对矩阵以获得过渡矩阵和变形网格我必须将顶点乘以过渡矩阵乘以权重,并将所有这些结果与使同一顶点变形的任何其他骨骼相加。
为了更具体地获得每块骨头的绝对值,我这样做了
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();
}
}
现在我得到了这个 absMatrix 矩阵的逆矩阵,在任何只改变 relativeMatrix 一次的插值之前,做顶点变形就是这个函数
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;
}
现在这对我不起作用,因为每个顶点都围绕网格轴的中心旋转,而不是围绕使顶点变形的骨骼的父骨骼,考虑到 transition = InverAbs *absoulteMatrix 会让我得到数量,我认为这是合乎逻辑的旋转骨骼由于插值而获得增益,因此假设它旋转 20 度,顶点将从顶点原点旋转 20 度,所以我想我缺少一些东西来使顶点围绕正在变形它们的骨骼的父级旋转,请帮我。
所以这就是我做插值的方式,不是对绝对矩阵而是对relativeMatrix,我更新绝对值的代码就是上面的那个。
//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);
}
是的,我这样做了,并将骨骼乘以它的逆绝对值,然后乘以绝对矩阵,它工作得很好,但是很多乘法正在发生,比如。
//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;
}
}