DirectX - неправильный метод скелетной анимации - PullRequest
1 голос
/ 11 февраля 2012

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

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

void cAnimationCollection::Update(DWORD AnimSetIndex, DWORD time)
{
    D3DXFRAME_EXTENDED *currentFrame = (D3DXFRAME_EXTENDED*)m_entity->m_frameRoot;

    cAnimationSet *AnimSet = m_AnimationSets;

    assert(AnimSetIndex <= index);
    while(AnimSet != NULL)
    {
        if(AnimSet->m_index == AnimSetIndex)
        {
            cAnimation *Anim = AnimSet->m_Animations;
            while(Anim != NULL)
            {   
                D3DXMatrixIdentity(&Anim->m_Frame->TransformationMatrix);
                if(Anim->m_NumScaleKeys && Anim->m_ScaleKeys)
                {
                    DWORD ScaleKey=0, ScaleKey2=0;
                    for(DWORD i = 0; i < Anim->m_NumScaleKeys; i++)
                    {
                        if(time >= Anim->m_ScaleKeys[i].m_Time)
                            ScaleKey = i;
                    }
                    ScaleKey2 = (ScaleKey>=(Anim->m_NumScaleKeys-1))?ScaleKey:ScaleKey+1;
                    float TimeDiff = Anim->m_ScaleKeys[ScaleKey2].m_Time - Anim->m_ScaleKeys[ScaleKey].m_Time;
                    if(!TimeDiff)
                        TimeDiff = 1;
                    float Scalar = ((float)time - Anim->m_ScaleKeys[ScaleKey].m_Time) / (float)TimeDiff;
                    D3DXVECTOR3 vecScale = Anim->m_ScaleKeys[ScaleKey2].m_VecKey - Anim->m_ScaleKeys[ScaleKey].m_VecKey;
                    vecScale *= Scalar;
                    vecScale += Anim->m_ScaleKeys[ScaleKey].m_VecKey;

                    D3DXMATRIX matScale;
                    D3DXMatrixScaling(&matScale, vecScale.x, vecScale.y, vecScale.z);
                    Anim->m_Frame->TransformationMatrix *= matScale;
                }
                if(Anim->m_NumRotationKeys && Anim->m_RotationKeys)
                {
                    DWORD RotKey=0, RotKey2=0;
                    for(DWORD i = 0; i < Anim->m_NumRotationKeys; i++)
                    {
                        if(time >= Anim->m_RotationKeys[i].m_Time)
                            RotKey = i;
                    }
                    RotKey2 = (RotKey>=(Anim->m_NumRotationKeys-1))?RotKey:RotKey+1;
                    float TimeDiff = Anim->m_RotationKeys[RotKey2].m_Time - Anim->m_RotationKeys[RotKey].m_Time;
                    if(!TimeDiff)
                        TimeDiff = 1;
                    float Scalar = ((float)time - Anim->m_RotationKeys[RotKey].m_Time) / (float)TimeDiff;
                    D3DXQUATERNION quatRotation;
                    D3DXQuaternionSlerp(&quatRotation,
                        &Anim->m_RotationKeys[RotKey].m_QuatKey,
                        &Anim->m_RotationKeys[RotKey2].m_QuatKey,
                        Scalar);

                    D3DXMATRIX matRotation;
                    D3DXMatrixRotationQuaternion(&matRotation, &quatRotation);
                    Anim->m_Frame->TransformationMatrix *= matRotation;
                }
                if(Anim->m_NumTranslationKeys && Anim->m_TranslationKeys)
                {
                    DWORD PosKey=0, PosKey2=0;
                    for(DWORD i = 0; i < Anim->m_NumTranslationKeys; i++)
                    {
                        if(time >= Anim->m_TranslationKeys[i].m_Time)
                            PosKey = i;
                    }
                    PosKey2 = (PosKey>=(Anim->m_NumTranslationKeys-1))?PosKey:PosKey+1;
                    float TimeDiff = Anim->m_TranslationKeys[PosKey2].m_Time - Anim->m_TranslationKeys[PosKey].m_Time;
                    if(!TimeDiff)
                        TimeDiff = 1;
                    float Scalar = ((float)time - Anim->m_TranslationKeys[PosKey].m_Time) / (float)TimeDiff;
                    D3DXVECTOR3 vecPos = Anim->m_TranslationKeys[PosKey2].m_VecKey - Anim->m_TranslationKeys[PosKey].m_VecKey;
                    vecPos *= Scalar;
                    vecPos += Anim->m_TranslationKeys[PosKey].m_VecKey;;
                    D3DXMATRIX matTranslation;
                    D3DXMatrixTranslation(&matTranslation, vecPos.x, vecPos.y, vecPos.z);
                    Anim->m_Frame->TransformationMatrix *= matTranslation;
                }
                if(Anim->m_NumMatrixKeys && Anim->m_MatrixKeys)
                {
                    DWORD Key1 = 0, Key2 = 0;
                    for(DWORD i=0;i<Anim->m_NumMatrixKeys;i++)
                    {
                        if(time >= Anim->m_MatrixKeys[i].m_Time)
                            Key1 = i;
                    }
                    Key2 = (Key1>=(Anim->m_NumMatrixKeys-1))?Key1:Key1+1; 
                    float TimeDiff = Anim->m_MatrixKeys[Key2].m_Time - Anim->m_MatrixKeys[Key1].m_Time;
                    if(!TimeDiff)          
                        TimeDiff = 1;        
                    float Scalar = ((float)time - Anim->m_MatrixKeys[Key1].m_Time) / (float)TimeDiff; 
                    D3DXMATRIX matDiff = Anim->m_MatrixKeys[Key2].m_MatKey - Anim->m_MatrixKeys[Key1].m_MatKey;
                    matDiff *= Scalar;        
                    matDiff += Anim->m_MatrixKeys[Key1].m_MatKey;
                    Anim->m_Frame->TransformationMatrix *= matDiff;     
                }

                Anim = Anim->m_Next;
            }
        }
        AnimSet = AnimSet->m_Next;
    }
    m_entity->UpdateFrameMatrices(m_entity->m_frameRoot, 0);
    m_entity->UpdateSkinnedMesh(m_entity->m_frameRoot);
    if(AnimSet == NULL)
        return;
}

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

Есть идеи?

...