Je suis développeur de jeux et je n'ai pas étudié les mathématiques. Je veux donc uniquement utiliser les Quaternions comme outil. Et pour pouvoir travailler avec la rotation 3D, il est nécessaire d'utiliser des quaternions (ou des matrices, mais restons aux quaternions ici dans cette question). Je pense qu'il est important pour de nombreux développeurs de les utiliser. C'est pourquoi je veux partager mes connaissances et, espérons-le, combler les trous que j'ai. À présent....
Donc, pour autant que j'ai compris:
Un Quaternion peut décrire 2 choses:
- L'orientation actuelle d'un objet 3D.
- Transformation de rotation qu'un objet pourrait effectuer. (rotationChange)
Vous pouvez faire avec un Quaternion:
Multiplications:
Quaternion endOrientation = Quaternion rotationChange * Quaternion currentOrientation;
Ainsi, par exemple: Mon objet 3D est tourné de 90 ° vers la gauche - et ma rotation que je multiplie est une rotation de 180 ° vers la droite, à la fin mon objet 3D de 90 ° est tourné vers la droite.
Quaternion rotationChange = Quaternion endRotation * Quaternion.Inverse (startRotation);
Avec cela, vous obtenez un rotationChange, qui peut être appliqué à une autre orientation.
Vector3 endPostion = Quaternion rotationChange * Vector3 currentPosition;
Ainsi, par exemple: mon objet 3D est en position (0,0,0) et ma rotation que je multiplie est une rotation de 180 ° vers la droite, ma position finale est quelque chose comme (0, -50,0). À l'intérieur de ce Quaternion, il y a un axe - et une rotation autour de cet axe. Vous tournez votre point autour de cet axe Y degrés.
Vector3 rotatedOffsetVector = Quaternion rotationChange * Vector3 currentOffsetVector;
Par exemple: Ma direction de départ montre UP - (0,1,0), et ma rotation que je multiplie est une rotation de 180 ° vers la droite, ma direction de fin montre vers le bas. (0, -1,0)
Mélange (Lerp et Slerp):
Quaternion currentOrientation = Quaternion.Slerp (startOrientation, endOrientation, interpolateur)
si l'interpolateur est 1: currentOrientation = endOrientation
si l'interpolateur est 0: currentOrientation = startOrientation
Slerp interpole plus précis, Lerp interpole plus performant.
Mes questions):
Tout ce que j'ai expliqué jusqu'à présent est-il correct?
Est-ce "tout" ce que vous pouvez faire avec les Quaternions? (év. pas)
Que pouvez-vous faire d'autre avec eux?
À quoi servent le produit Dot et le produit Cross entre 2 Quaternions?
Modifier:
Question mise à jour avec quelques réponses
la source
n
des orientations différentes (attitudes, poses, etc.). Ensuite, vous pouvez les faire la moyenne en utilisant des poids, généralisant efficacement slerp / lerp. Vous pouvez également convertir un quaternion en rotor, ce qui équivaut à appliquer une vitesse angulaire pendant un certain temps à un corps rigide. Par conséquent, vous pouvez également décrire l'intégration de la vitesse angulaire avec les quaternions. Vous pouvez également estimer la différence entre deux orientations (calculer la longueur de l'arc couvert par les deux quaternions sur l'hypersphère).Réponses:
Multiplication
Au moins en termes d'implémentation de Quaternions par Unity, l'ordre de multiplication décrit dans la question n'est pas correct. Ceci est important car la rotation 3D n'est pas commutative .
Donc, si je veux faire pivoter un objet en
rotationChange
partant de son,currentOrientation
je l'écrirais comme ceci:(c.-à-d. les transformations s'empilent vers la gauche - comme la convention de matrice d'Unity. La rotation la plus à droite est appliquée en premier / à l'extrémité "la plus locale")
Et si je voulais transformer une direction ou un vecteur de décalage par une rotation, je l'écrirais comme ceci:
(Unity générera une erreur de compilation si vous faites le contraire)
Mélange
Dans la plupart des cas, vous pouvez vous en tirer avec les rotations Lerping. C'est parce que l'angle utilisé "sous le capot" dans un quaternion est la moitié de l'angle de rotation, ce qui le rend sensiblement plus proche de l'approximation linéaire de Lerp que quelque chose comme une matrice (qui en général ne sera pas bien Lerp!). Découvrez environ 40 minutes dans cette vidéo pour plus d'explications .
Le seul cas où vous avez vraiment besoin de Slerp est lorsque vous avez besoin d'une vitesse constante dans le temps, comme l'interpolation entre les images clés sur une chronologie d'animation. Pour les cas où vous vous souciez simplement qu'une sortie est intermédiaire entre deux entrées (comme le mélange de couches d'une animation), alors Lerp sert généralement assez bien.
Quoi d'autre?
Le produit scalaire de deux quaternions unitaires donne le cosinus de l'angle entre eux, vous pouvez donc utiliser le produit scalaire comme mesure de similitude si vous devez comparer les rotations. C'est un peu obscur cependant, donc pour un code plus lisible, j'utiliserais souvent Quaternion.Angle (a, b) à la place, qui exprime plus clairement que nous comparons les angles, en unités familières (degrés).
Ces types de méthodes pratiques fournies par Unity pour les quaternions sont très utiles. Dans presque tous les projets, j'utilise celui-ci au moins quelques fois :
Cela construit un quaternion qui:
forward
argument vecteurup
argument vecteur, s'il est fourni, ou(0, 1, 0)
s'il est omisLa raison pour laquelle le "haut" n'est "aussi proche que possible" est que le système est surdéterminé. Faire face à z + à
forward
utilise jusqu'à deux degrés de liberté (c'est-à-dire lacet et tangage), il ne nous reste donc qu'un seul degré de liberté (roulis).Je trouve assez souvent que je veux quelque chose avec les propriétés d'exactitude opposées: je veux que le y + local pointe exactement le long
up
et que le z + local se rapproche le plus possible deforward
la liberté restante.Cela se produit par exemple lorsque vous essayez de former un cadre de coordonnées relatif à la caméra pour l'entrée de mouvement: je veux que ma direction locale vers le haut reste perpendiculaire au sol ou à une surface inclinée normale, donc mon entrée n'essaie pas de tunneler le personnage dans le terrain ou les léviter.
Vous pouvez également l'obtenir si vous souhaitez que le boîtier de la tourelle d'un char fasse face à une cible, sans décoller du corps du char lorsque vous visez vers le haut / vers le bas.
Nous pouvons construire notre propre fonction de confort pour ce faire, en utilisant
LookRotation
pour le levage de charges lourdes:Ici, nous tournons d'abord local y + vers z +, et local z + vers y-.
Ensuite, nous faisons pivoter le nouveau z + dans notre direction vers le haut (de sorte que le résultat net est local y + pointe directement le long
exactUp
), et le nouveau y + aussi près que possible de la direction avant négative (de sorte que le résultat net est local z + pointe aussi près que possible le long deapproximateForward
)Une autre méthode pratique est
Quaternion.RotateTowards
que j'utilise souvent comme ceci:Cela nous permet de nous rapprocher
targetRotation
à une vitesse constante et contrôlable quel que soit le framerate - important pour les rotations qui affectent le résultat / l'équité des mécanismes de jeu (comme tourner le mouvement d'un personnage ou avoir une tourelle sur le joueur). Naïvement Lerping / Slerping dans cette situation peut facilement conduire à des cas où le mouvement devient plus vif à des cadences élevées, affectant l'équilibre du jeu. (Cela ne veut pas dire que ces méthodes sont erronées - il existe des moyens de les utiliser correctement sans changer l'équité, cela nécessite simplement des soins.RotateTowards
Donne un raccourci pratique qui s'en occupe pour nous)la source
Où est utilisé le produit scalaire?
Dans Unity, l'un des utilisateurs les plus courants du produit scalaire est chaque fois que vous vérifiez si deux quaternions sont égaux via
==
ou!=
. Unity calcule le produit scalaire pour vérifier la similitude plutôt que de comparer directement les valeurs internes x, y, z, w. Cela vaut la peine de garder celui-ci à l'esprit car cela rend l'appel plus cher que vous ne le pensez.Nous l'utilisons également dans un cas d'utilisation intéressant.
Amusez-vous avec les produits à points quaternion - Mondes sphériques et orbitales
Les simulations de planètes entières et même de systèmes solaires entiers deviennent de plus en plus courantes. Afin de réussir cela en temps réel, nous avons également besoin du produit scalaire quaternion. Beaucoup d'entre eux. Le produit quaternion dot est très sous-utilisé mais il a certainement ses utilisations - Jetons un coup d'œil!
Premièrement, nous avons toute une série de rotations à considérer:
Combinez-les tous ensemble et vous vous retrouvez avec beaucoup de complexité (et beaucoup de nombres énormes!). Lorsque le spectateur se tient à la surface de la planète, nous ne voulons pas qu'il se précipite à une vitesse folle à travers notre espace de jeu. Nous préférons en fait qu'ils soient stationnaires et quelque part près de l'origine - déplacez plutôt l'univers autour du joueur.
Surtout, pour que nous puissions obtenir le spin et l'inclinaison de la planète correctement dans ce scénario, nous devons verrouiller l'axe du pôle de sorte qu'il ne puisse que basculer vers le haut / bas sur l'image ci-dessus (c'est-à-dire basculer "vers le haut" pendant que le joueur voyage Nord). C'est là qu'intervient un produit scalaire quaternion. Si nous n'utilisions pas de produit scalaire ici et que nous multiplions plutôt l'inclinaison, cela se produirait:
Remarquez comment les pôles de nos «planètes» en orbite sont toujours inclinés vers l'étoile. Ce n'est pas ce qui se passe en réalité - l'inclinaison est dans une direction fixe .
Sans aller trop loin, voici un bref résumé:
En obtenant uniquement l'angle, nous supprimons une partie de cette rotation indésirable . Dans le même temps, nous nous sommes également retrouvés avec une mesure de longitude qui est utile pour la navigation ainsi que le climat local.
* Les planètes sont construites à partir de nombreuses cellules de la grille . Seuls les plus proches sont affichés.
la source
dot(a, b) = a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w
par opposition à la composition quaternion que nous utiliserions pour enchaîner) rotations) nous aiderait à résoudre ce problème. Je serais ravi de voter si vous êtes en mesure de développer cela un peu plus tard (je ne veux pas vous garder de votre slerp ... je veux dire dormir!)