En utilisant le format .x pour exporter un modèle depuis Blender, je peux charger un maillage, une armature et une animation. Je n'ai aucun problème à générer le maillage et à visualiser les modèles en jeu. De plus, j'ai des animations et l'armature correctement chargées dans les structures de données appropriées.
Mon problème est d'appliquer correctement l'animation aux modèles. J'ai le cadre pour appliquer les modèles et le code pour sélectionner les animations et parcourir les cadres.
D'après ce que je comprends, le AnimationKey
s à l'intérieur du AnimationSet
fournit les transformations pour transformer la pose de reliure en pose dans le cadre animé. Comme petit exemple:
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;;,
...
}
}
Donc, pour appliquer l'image 2, je prendrais la position, la rotation et l'échelle de l'image 2, créerais une matrice de transformation (appelez-la Transform_A
) à partir d'eux et appliquerais cette matrice aux sommets contrôlés par Armature_001_Bone
leurs poids. Donc je fourrerais TransformA
dans mon shader et transformerais le sommet. Quelque chose comme:
vertexPos = vertexPos * bones[ int(bfs_BoneIndices.x) ] * bfs_BoneWeights.x;
Où bfs_BoneIndices
et bfs_BoneWeights
sont des valeurs spécifiques au sommet actuel.
Lors du chargement dans les sommets du maillage, je les transforme par le rootTransform
et le meshTransform
. Cela garantit qu'ils sont orientés et mis à l'échelle correctement pour afficher la pose de liaison.
Le problème est que lorsque je crée cette matrice de transformation (en utilisant la position, la rotation et l'échelle de l'animation), elle ne transforme pas correctement le sommet. Il y a probablement plus que l'utilisation des données d'animation. J'ai également essayé d'appliquer les hiérarchies de transformation osseuse, toujours pas de dés. En gros, je me retrouve avec des modèles tordus. Il convient également de noter que je travaille dans openGL, donc toute transposition de matrice qui pourrait devoir être appliquée doit être prise en compte.
De quelles données ai-je besoin et comment les combiner pour appliquer des animations .x aux modèles?
J'ai fait quelques maquettes de ce à quoi cela ressemble, au cas où cela serait utile.
Je voulais d'abord tester la traduction, c'est une tête flottante, à quoi ça ressemble dans Blender:
http://i.stack.imgur.com/NAc4B.gif
Et à quoi cela ressemble dans le jeu (ne vous occupez pas des couleurs):
http://i.stack.imgur.com/nj2du.gif
Ensuite, pour la rotation, l'animation était la tête tournant à 360 degrés autour de l'axe vertical. Voici à quoi cela ressemble en jeu:
http://i.stack.imgur.com/gVyUW.gif
Notez qu'il ne doit pas y avoir d'inclinaison, seulement une rotation comme un manège.
Mise à jour
J'ai la partie traduction de l'animation qui fonctionne. Mais ça fait un peu hacky et je ne vois pas comment l'appliquer à la rotation.
La traduction fonctionne en suivant ces étapes:
- Prenez la position du cadre d'animation et échangez les valeurs
y
etz
- Traduire la matrice de transformation par la position modifiée
- Transposer la matrice de transformation
- Appliquer la matrice de transformation aux sommets
Voilà comment cela peut fonctionner, mais comment est-il censé fonctionner généralement pour la position, l'échelle et la rotation?
la source
Réponses:
C'est peut-être la clé, avez-vous essayé d'annuler certaines coordonnées Z pour convertir des coordonnées gauches DirectX en coordonnées droitières OpenGL?
Vous pouvez annuler tous les Z avant d'appliquer vos transformations et annuler à nouveau lorsque vous avez terminé, voyez si la sortie s'améliore.
ÉDITER
L'échange des coordonnées Y et Z est une autre façon de changer la neutralité. Vous devez donc adapter vos transformations, consultez ce document pour plus de détails .
Le fait que vous deviez transposer votre matrice signifie également que vous passiez de la ligne principale à la colonne principale ou vice versa. Cela devrait être moins compliqué à gérer, vous n'aurez probablement qu'à trouver le bon "endroit" pour le faire dans votre pipeline. Je suis juste en train de deviner, mais le faire sur des quaternions pourrait simplement signifier les changer en matrices, transposer et revenir en quaternions, si votre bibliothèque Math vous offre cette option.
la source
OK, j'ai mis un peu plus de temps pour cela et je l'ai fait fonctionner pour plusieurs os, et considérablement moins comme un hack (bien que toujours un peu). Le système que j'avais en place à l'origine était presque correct. Cependant, les principaux problèmes étaient:
Mon code pour convertir un Quaternion en matrice était incorrect. En fait, je ne sais toujours pas pourquoi cela est incorrect, mais je sais que le code suivant fonctionne, dans le cadre de ma classe Quaternion:
A part ça, c'est juste:
finalMatrix = boneMatrix * skinMatrix * invertedBindMatrix;
Notez que le
boneMatrix
doit utiliser les matrices animées pour chaque os au lieu des matrices de liaison. Il devrait également obtenir toutes ses matrices parent comme ceci:Et il fonctionne. Laissez un commentaire si vous avez besoin d'éclaircissements.
la source