Используя формат .x для экспорта модели из Blender, я могу загрузить сетку, арматуру и анимацию. У меня нет проблем с генерацией сетки и просмотром моделей в игре. Кроме того, у меня есть анимации и арматура, правильно загруженная в соответствующие структуры данных.
Моя проблема - правильно применить анимацию к моделям. У меня есть рамки для применения моделей и код для выбора анимации и пошагового просмотра кадров.
Из того, что я понимаю, AnimationKey
элементы s внутри AnimationSet
снабжают преобразования для преобразования позы связывания в позу в анимированном кадре. В качестве небольшого примера:
Animation {
{Armature_001_Bone}
AnimationKey {
2; //Position
121; //number of frames
0;3; 0.000000, 0.000000, 0.000000;;,
1;3; 0.000000, 0.000000, 0.005524;;,
2;3; 0.000000, 0.000000, 0.022217;;,
...
}
AnimationKey {
0; //Quaternion Rotation
121;
0;4; -0.707107, 0.707107, 0.000000, 0.000000;;,
1;4; -0.697332, 0.697332, 0.015710, 0.015710;;,
2;4; -0.684805, 0.684805, 0.035442, 0.035442;;,
...
}
AnimationKey {
1; //Scale
121;
0;3; 1.000000, 1.000000, 1.000000;;,
1;3; 1.000000, 1.000000, 1.000000;;,
2;3; 1.000000, 1.000000, 1.000000;;,
...
}
}
Таким образом, чтобы применить кадр 2, я бы взял положение, поворот и масштаб из кадра 2, создал Transform_A
из них матрицу преобразования (назовем ее ) и применил эту матрицу к вершинам, управляемым по Armature_001_Bone
их весам. Так что я запихаю TransformA
в свой шейдер и преобразую вершину. Что-то вроде:
vertexPos = vertexPos * bones[ int(bfs_BoneIndices.x) ] * bfs_BoneWeights.x;
Где bfs_BoneIndices
и bfs_BoneWeights
значения, специфичные для текущей вершины.
При загрузке в вершины сетки я преобразую их с помощью rootTransform
и meshTransform
. Это гарантирует, что они ориентированы и правильно масштабированы для просмотра позы связывания.
Проблема в том, что когда я создаю эту матрицу преобразования (используя положение, вращение и масштаб из анимации), она неправильно трансформирует вершину. Скорее всего, это нечто большее, чем просто использование данных анимации. Я также попытался применить иерархию костных трансформаций, все еще без игры в кости. В основном я заканчиваю с некоторыми витыми моделями. Следует также отметить, что я работаю в openGL, поэтому следует учитывать любые преобразования матрицы, которые, возможно, потребуется применить.
Какие данные мне нужны и как их объединить для применения анимации .x к моделям?
Я сделал несколько макетов того, как это выглядит, на случай, если это будет полезно.
Сначала я хотел просто проверить перевод, это подпрыгивающая голова, как она выглядит в Blender:
http://i.stack.imgur.com/NAc4B.gif
И как это выглядит в игре (не обращайте внимания на цвета):
http://i.stack.imgur.com/nj2du.gif
Затем для простого поворота анимацией была голова, вращающаяся на 360 градусов вокруг вертикальной оси. Вот как это выглядит в игре:
http://i.stack.imgur.com/gVyUW.gif
Обратите внимание, не должно быть никакого наклона, только вращение как карусель.
Обновить
У меня работает переводная часть анимации. Но это кажется немного хакерским, и я не понимаю, как применить его к ротации.
Перевод работает, выполнив следующие действия:
- Возьмите позицию с кадр анимации и поменять местами
y
иz
значение - Перевести матрицу преобразования по измененной позиции
- Транспонировать матрицу преобразования
- Применить матрицу преобразования к вершинам
Вот как это может работать, но как это должно работать в целом для положения, масштаба и поворота?
источник
Ответы:
Может быть, это ключ, вы пытались свести на нет некоторые Z-координаты, чтобы преобразовать их из левосторонних координат DirectX в правые OpenGL?
Вы можете отрицать все Zs перед применением ваших преобразований и повторно отрицать, когда закончите, посмотрите, улучшится ли результат.
РЕДАКТИРОВАТЬ
Поменять местами координаты Y и Z - это еще один способ изменить руку. Так что вам нужно адаптировать свои преобразования, проверьте эту статью для деталей .
Тот факт, что вам нужно транспонировать матрицу, также означает, что вы переходите от основного ряда к главному столбцу или наоборот. Это должно быть менее сложным, вам, вероятно, просто нужно найти подходящее «место», чтобы сделать это в вашем конвейере. Я просто догадываюсь, но сделать это с кватернионами может просто означает заменить их на матрицы, транспонировать и вернуть кватернионы, если ваша математическая библиотека предлагает эту опцию.
источник
Хорошо, я потратил немного больше времени на это и заставил его работать на несколько костей, и значительно менее похож на хак (хотя все еще немного). Система, которую я использовал, изначально была почти правильной. Однако основными проблемами были:
Мой код для преобразования кватерниона в матрицу был неверным. Я на самом деле все еще не уверен, почему это неверно, но я знаю, что следующий код работает, как часть моего класса Quaternion:
Кроме этого, это просто:
finalMatrix = boneMatrix * skinMatrix * invertedBindMatrix;
Обратите внимание, что
boneMatrix
для каждой кости следует использовать анимированные матрицы вместо матриц связывания. Он также должен получить все свои родительские матрицы следующим образом:И это работает. Оставьте комментарий, если вам нужны разъяснения.
источник