Войти
ПрограммированиеФорумГрафика

Скелетная анимация в directX (2 стр)

Страницы: 1 2
#15
13:43, 27 авг. 2014

Kroll
FindDXFrame ищет просто кость в иерархии кости по имени. Я нахожу кость, применяю к ней свою трансформацию и обновляю иерархию с помощью рекурсии, добавляя к преобразованиям дочерних преобразования родителей. но получаются вот такие аномалии.


#16
13:45, 27 авг. 2014

Kroll
void Object::SetMatrix(D3DXMATRIX *matTransformation, D3DXFRAME_DERIVED *Frame)
{
  Frame->CombinedMatrix = (*matTransformation)* Frame->TransformationMatrix;

  if (Frame->pFrameSibling)
    SetMatrix(matTransformation, (D3DXFRAME_DERIVED*)Frame->pFrameSibling);

  if (Frame->pFrameFirstChild)
    SetMatrix(&Frame->CombinedMatrix, (D3DXFRAME_DERIVED*)Frame->pFrameFirstChild);
}
вот функция обновления иерархии. в качестве первого параметра указываю единичную матрицу, а в качестве второго корневой фрейм. пример из книги

#17
13:52, 27 авг. 2014

Я так понял, есть веса костей? Средняя линия бокса принадлежит обеим костям? Тогда нужна инверсная матрица трансформации при экспорте.
Вообще чтобы найти косяк, надо весь код смотреть, вплоть до шейдера.
Чтобы искать косяк, я предложил простой вариант с двумя боксами, на картинке один бокс, но с двумя костями, этот вариант сложнее, и требует других манипуляций.

#18
13:58, 27 авг. 2014

Kroll
Да средняя линия принадлежит обеим костям. Инверсная матрица грузится из X файла(как и веса вершин)  и тоже используется(правда я пока не особо ее смысл понимаю). рендер происходит через стандартный конвеер ДХ. Могу скинуть весь проект, если не против посмотреть.

#19
14:15, 27 авг. 2014

Да нет у меня желания .x api ковырять. Да и блендером не занимался.
Давай по порядку. Что ты хочешь сделать для этого примера (на картинке)? Повернуть верхнюю кость?
.х файл текстовый? можешь показать?

#20
14:21, 27 авг. 2014

Kroll
да, хочу повернуть верхнюю кость
вот .x файл
xof 0303txt 0032

template XSkinMeshHeader {
  <3cf169ce-ff7c-44ab-93c0-f78f62d172e2>
  WORD nMaxSkinWeightsPerVertex;
  WORD nMaxSkinWeightsPerFace;
  WORD nBones;
}

template SkinWeights {
  <6f0d123b-bad2-4167-a0d0-80224f25fabb>
  STRING transformNodeName;
  DWORD nWeights;
  array DWORD vertexIndices[nWeights];
  array float weights[nWeights];
  Matrix4x4 matrixOffset;
}

Frame Root {
  FrameTransformMatrix {
    1.000000, 0.000000, 0.000000, 0.000000,
    0.000000,-0.000000, 1.000000, 0.000000,
    0.000000, 1.000000, 0.000000, 0.000000,
    0.000000, 0.000000, 0.000000, 1.000000;;
  }
  Frame Armature {
    FrameTransformMatrix {
      1.000000, 0.000000, 0.000000, 0.000000,
      0.000000, 1.000000, 0.000000, 0.000000,
      0.000000, 0.000000, 1.000000, 0.000000,
      0.000000, 0.000000,-0.420185, 1.000000;;
    }
    Frame Armature_Bone {
      FrameTransformMatrix {
        1.000000, 0.000000, 0.000000, 0.000000,
        0.000000, 0.000000, 1.000000, 0.000000,
        0.000000,-1.000000, 0.000000, 0.000000,
        0.000000, 0.000000,-0.415760, 1.000000;;
      }
      Frame Armature_Bone_001 {
        FrameTransformMatrix {
          1.000000, 0.000000, 0.000000, 0.000000,
          0.000000, 1.000000, 0.000000, 0.000000,
          0.000000, 0.000000, 1.000000, 0.000000,
          0.000000, 1.818799, 0.000000, 1.000000;;
        }
      } // End of Armature_Bone_001
    } // End of Armature_Bone
    Frame Cube {
      FrameTransformMatrix {
        1.000000, 0.000000, 0.000000, 0.000000,
        0.000000, 1.000000, 0.000000, 0.000000,
        0.000000, 0.000000, 1.000000, 0.000000,
        0.000000, 0.000000, 0.420185, 1.000000;;
      }
      Mesh { // Cube mesh
        40;
        1.000000; 1.000000;-1.000000;,
        1.000000;-1.000000;-1.000000;,
        -1.000000;-1.000000;-1.000000;,
        -1.000000; 1.000000;-1.000000;,
        -1.000000; 1.000000; 1.000000;,
        -1.000000;-1.000000; 1.000000;,
        -1.000000;-1.000000; 3.000000;,
        -1.000000; 1.000000; 3.000000;,
        1.000000; 1.000000;-1.000000;,
        1.000000; 0.999999; 1.000000;,
        0.999999;-1.000001; 1.000000;,
        1.000000;-1.000000;-1.000000;,
        1.000000;-1.000000;-1.000000;,
        0.999999;-1.000001; 1.000000;,
        -1.000000;-1.000000; 1.000000;,
        -1.000000;-1.000000;-1.000000;,
        -1.000000;-1.000000;-1.000000;,
        -1.000000;-1.000000; 1.000000;,
        -1.000000; 1.000000; 1.000000;,
        -1.000000; 1.000000;-1.000000;,
        1.000000; 0.999999; 1.000000;,
        1.000000; 1.000000;-1.000000;,
        -1.000000; 1.000000;-1.000000;,
        -1.000000; 1.000000; 1.000000;,
        1.000000; 0.999999; 3.000000;,
        -1.000000; 1.000000; 3.000000;,
        -1.000000;-1.000000; 3.000000;,
        0.999999;-1.000001; 3.000000;,
        -1.000000;-1.000000; 1.000000;,
        0.999999;-1.000001; 1.000000;,
        0.999999;-1.000001; 3.000000;,
        -1.000000;-1.000000; 3.000000;,
        1.000000; 0.999999; 1.000000;,
        -1.000000; 1.000000; 1.000000;,
        -1.000000; 1.000000; 3.000000;,
        1.000000; 0.999999; 3.000000;,
        0.999999;-1.000001; 1.000000;,
        1.000000; 0.999999; 1.000000;,
        1.000000; 0.999999; 3.000000;,
        0.999999;-1.000001; 3.000000;;
        10;
        4;3,2,1,0;,
        4;7,6,5,4;,
        4;11,10,9,8;,
        4;15,14,13,12;,
        4;19,18,17,16;,
        4;23,22,21,20;,
        4;27,26,25,24;,
        4;31,30,29,28;,
        4;35,34,33,32;,
        4;39,38,37,36;;
        MeshNormals { // Cube normals
          10;
          0.000000; 0.000000;-1.000000;,
          -1.000000; 0.000000; 0.000000;,
          1.000000;-0.000000; 0.000000;,
          -0.000000;-1.000000;-0.000000;,
          -1.000000; 0.000000;-0.000000;,
          0.000000; 1.000000; 0.000000;,
          0.000000;-0.000000; 1.000000;,
          -0.000000;-1.000000; 0.000000;,
          0.000000; 1.000000; 0.000000;,
          1.000000;-0.000001; 0.000000;;
          10;
          4;0,0,0,0;,
          4;1,1,1,1;,
          4;2,2,2,2;,
          4;3,3,3,3;,
          4;4,4,4,4;,
          4;5,5,5,5;,
          4;6,6,6,6;,
          4;7,7,7,7;,
          4;8,8,8,8;,
          4;9,9,9,9;;
        } // End of Cube normals
        MeshMaterialList { // Cube material list
          1;
          10;
          0,
          0,
          0,
          0,
          0,
          0,
          0,
          0,
          0,
          0;;
          Material Material {
            0.640000; 0.640000; 0.640000; 1.000000;;
            96.078431;
            0.500000; 0.500000; 0.500000;;
            0.000000; 0.000000; 0.000000;;
          }
        } // End of Cube material list
        XSkinMeshHeader {
          2;
          6;
          2;
        }
        SkinWeights {
          "Armature_Bone_001";
          40;
          0,
          1,
          2,
          3,
          4,
          5,
          6,
          7,
          8,
          9,
          10,
          11,
          12,
          13,
          14,
          15,
          16,
          17,
          18,
          19,
          20,
          21,
          22,
          23,
          24,
          25,
          26,
          27,
          28,
          29,
          30,
          31,
          32,
          33,
          34,
          35,
          36,
          37,
          38,
          39;
          0.156248,
          0.145666,
          0.156248,
          0.145666,
          0.909627,
          0.910313,
          1.000000,
          1.000000,
          0.156248,
          0.910313,
          0.909627,
          0.145666,
          0.145666,
          0.909627,
          0.910313,
          0.156248,
          0.156248,
          0.910313,
          0.909627,
          0.145666,
          0.910313,
          0.156248,
          0.145666,
          0.909627,
          1.000000,
          1.000000,
          1.000000,
          1.000000,
          0.910313,
          0.909627,
          1.000000,
          1.000000,
          0.910313,
          0.909627,
          1.000000,
          1.000000,
          0.909627,
          0.910313,
          1.000000,
          1.000000;
          1.000000, 0.000000, 0.000000, 0.000000,
          0.000000, 0.000000,-1.000000, 0.000000,
          0.000000, 1.000000, 0.000000, 0.000000,
          0.000000,-0.982854, 0.000000, 1.000000;;
        } // End of Armature_Bone_001 skin weights
        SkinWeights {
          "Armature_Bone";
          28;
          0,
          1,
          2,
          3,
          4,
          5,
          8,
          9,
          10,
          11,
          12,
          13,
          14,
          15,
          16,
          17,
          18,
          19,
          20,
          21,
          22,
          23,
          28,
          29,
          32,
          33,
          36,
          37;
          0.843752,
          0.854334,
          0.843752,
          0.854334,
          0.090373,
          0.089687,
          0.843752,
          0.089687,
          0.090373,
          0.854334,
          0.854334,
          0.090373,
          0.089687,
          0.843752,
          0.843752,
          0.089687,
          0.090373,
          0.854334,
          0.089687,
          0.843752,
          0.854334,
          0.090373,
          0.089687,
          0.090373,
          0.089687,
          0.090373,
          0.090373,
          0.089687;
          1.000000, 0.000000, 0.000000, 0.000000,
          0.000000, 0.000000,-1.000000, 0.000000,
          0.000000, 1.000000, 0.000000, 0.000000,
          0.000000, 0.835945, 0.000000, 1.000000;;
        } // End of Armature_Bone skin weights
      } // End of Cube mesh
    } // End of Cube
  } // End of Armature
} // End of Root

#21
15:10, 27 авг. 2014

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

Некая наша трансформация Ta.
Для каждой кости надо:
T = Ta * Tb;
T = InvTb * T.

Именно такой порядок.

ps. А нет меш правильный!

#22
15:35, 27 авг. 2014

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

#23
16:27, 27 авг. 2014

Тебе нужно задействовать инверсные матрицы от Armature_Bone и Armature_Bone_001.
И как выглядит трансформация вершин в шейдере?

#24
17:08, 27 авг. 2014

Kroll
инверсные матрицы задействованы(pSkinInfo->GetBoneOffsetMatrix(i)). я не использую шейдер. вывод через стандартный конвеер direcX
вот функция обновления вершин
HRESULT Object::UpdateMesh()
{
  for (DWORD i = 0; i<pSkinInfo->GetNumBones(); i++)
  {
    pBoneMatrix = (*pSkinInfo->GetBoneOffsetMatrix(i));
    pBoneMatrix
*= (*ppFrameMatrix);
  }

  void *SrcPtr, *DestPtr;
  MeshData.pMesh->LockVertexBuffer(D3DLOCK_READONLY, (void**)&SrcPtr);
  mesh->LockVertexBuffer(0, (void**)&DestPtr);

  pSkinInfo->UpdateSkinnedMesh(pBoneMatrix, NULL, SrcPtr, DestPtr);

  mesh->UnlockVertexBuffer();
  MeshData.pMesh->UnlockVertexBuffer();

  return S_OK;
}

в ppFrameMatrix хранятся комбинированные преобразования после обновления иерархии.
pBoneMatrix- конечная матрица с задействованной инверсной

#25
17:25, 27 авг. 2014

На каждом кадре лочится буфер и вычисляются вершины?
И тебе не доступен код трансформации вершин? Там должны матрицы умножаться на веса и суммироваться трансформации вершин.
GetBoneOffsetMatrix судя по названию не даёт инверсную матрицу. Для этого есть D3DXMatrixInverse.

#26
17:33, 27 авг. 2014

Kroll
Цитата из книги "Вызвав ID3DXSkinInfo::GetBoneOffsetMatrix, вы по-
лучите указатель на обратную матрицу преобразования кости."
да. код трансформации скрыт в библиотеках ДХ. Вершины вычисляются в каждом кадре

#27
17:35, 27 авг. 2014

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

#28
20:08, 27 авг. 2014

x
В будущем можно и сделать. Я бы хотел сначала принцип понять, как вообще со скелетной анимацией работать.
Все функции из книги.Что в Джиме Адамсе, что в Фленове они одинаковы, значит, скорее всего, должны работать.  Не знаю в чем проблема
буду благодарен, если кто-нибудь знающий согласится глянуть мой код.

#29
15:13, 8 сен. 2014

У меня возникла такая проблема при анимации. Если например угол поворота кости достаточный, то привязанный к кости меш как-бы отрыватся от родителя.
Вот набросал картинку:
Изображение
У меня финальные матрицы считаются при загрузке. Но я вот подумал, что если считать их каждый кадр, то тогда можно узнать длину ветора трансляции кости и тем самый узнавать позицыю не интерполяцией, а просчитыванием с помощю ориентации и интерполированной длиной.
Но терзают сомнения, правильно-ли это.
+ если просчитывать каждый кард иерархию, это дополнительно будет нагружать систему.

PS: за картинку сильно не бейте, поздно заметил ошибки =(

Страницы: 1 2
ПрограммированиеФорумГрафика

Тема в архиве.