скелетная анимация

Я новичок в терминах скелетной анимации, и я читал, что для анимации меша с использованием скелета мне пришлось бы использовать иерархию костей, которую я сделал, создав каждый узел кости в моем графе сцены, а затем, чтобы деформировать меш, я должен получить обратную абсолютную матрицу кости перед интерполяцией (которую, как я полагаю, они называют позой), умножить ее для интерполированной абсолютной матрицы кости, чтобы получить матрицу перехода, и чтобы деформировать сетку, мне пришлось бы умножить вершину, умноженную на матрица перехода, умноженная на вес, и суммируйте весь этот результат с любой другой костью, деформирующей ту же вершину.

чтобы быть более конкретным, чтобы получить абсолют каждой кости, я делаю это

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 перед любой интерполяцией, которая изменяет относительную матрицу только один раз, так что деформация вершины - это эта функция

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;
}

теперь это не работает для меня, потому что каждая вершина вращается вокруг центра оси сетки, а не родитель кости кости, которая деформирует вершины, я подумал, что это логично, учитывая, что переход = InverAbs *absoulteMatrix даст мне количество вращения кость имеет усиление из-за интерполяции, поэтому, если предположить, что она вращается на 20 градусов, вершины будут поворачиваться на 20 градусов от начала координат, поэтому я предполагаю, что мне что-то не хватает, чтобы вершины вращались вокруг родителя кости, которая их деформирует, пожалуйста Помоги мне.

вот как я делаю интерполяцию только не в абсолютную матрицу, а в относительную матрицу, код, который я обновляю, абсолютный, тот, что выше.

//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;
        }

}

person Jman    schedule 26.10.2012    source источник
comment
Пробовали ли вы применить обратную абсолютную матрицу кости напрямую к вашим вершинам и отрисовать их, чтобы убедиться, что это преобразование ведет себя так, как задумано? Эта операция должна перевести вершины в «костяное пространство», то есть вершины, «близкие к кости», должны оказаться «близкими к началу координат». Подтверждение того, что это преобразование ведет себя должным образом, может помочь сузить проблему.   -  person WeirdlyCheezy    schedule 27.10.2012
comment
Кроме того, можете ли вы кратко объяснить, как вы вычисляете интерполированную абсолютную матрицу? Если я следую, эта матрица должна содержать только преобразование между «нейтральной» позой и текущей интерполированной позой кости, указанной в пространстве сетки; это правильно?   -  person WeirdlyCheezy    schedule 27.10.2012
comment
когда я умножаю вершины на обратный абсолют кости перед интерполяцией, он приближает вершины к началу координат, а когда умножаю на абсолют после интерполяции, возвращаю их обратно плюс изменения, и таким образом анимация работает так, как предполагалось, но таким образом Мне нужно умножить для каждой вершины.   -  person Jman    schedule 28.10.2012
comment
Я все еще немного смущен; во введении вы говорите, что вычисляете матрицу перехода, умножая inversePose на absoluteInterpolated, но это то же самое умножение, которое вы делаете во втором CMesh::skinMesh. Почему два skinMesh ведут себя по-разному? Вы уверены, что transitionMatrix вычисляется так, как вы говорите?   -  person WeirdlyCheezy    schedule 31.10.2012


Ответы (1)


теперь код работает, похоже, что мое матричное умножение было в неправильном порядке, потому что он делал это как inverPose * absoluteMatrx и был неправильным, теперь это absoluteMatrx * inverPose и работает нормально

person Jman    schedule 02.11.2012