J'ai un Vector3 qui a un angle euler pour chaque axe.
Habituellement, lorsque je veux créer une matrice de rotation, j'utilise des fonctions telles que D3DXMatrixRotationX en passant l'angle respectif de mon vecteur de rotation ci-dessus et multiplie les matrices (ZXY) pour créer la matrice de rotation globale qui est utilisée pour former la matrice de transformation d'objet complète.
Cependant, cette méthode produira un ensemble de rotations dans l'espace objet. C'est-à-dire que le passage d'un vecteur de (90, 0, 90) dans ma méthode créera une rotation dans l'espace mondial de (90, 90, 0).
Existe-t-il un moyen de toujours garantir que chaque composant de mon vecteur de rotation entraîne une rotation autour des axes respectifs alignés sur l'espace mondial?
ÉDITER:
Ceci est une animation de ce qui se passe actuellement - je veux un moyen de tourner autour des axes bleus, pas du rouge.
EDIT 2:
Juste pour noter que je ne cherche pas une solution impliquant des angles d'Euler, mais simplement une manière dont je peux représenter une transformation de rotations multiples autour des axes mondiaux.
la source
Réponses:
Sur la base de vos commentaires, il semble que vous stockiez l'orientation de l'objet sous la forme d'un ensemble d'angles d'Euler et que vous diminuez / décrivez les angles lorsque le joueur fait pivoter l'objet. Autrement dit, vous avez quelque chose comme ce pseudocode:
Comme le note Charles Beattie , parce que les rotations ne font pas la navette, cela ne fonctionnera pas comme prévu à moins que le joueur fasse pivoter l'objet dans le même ordre dans lequel il
eulerAnglesToMatrix()
applique les rotations.En particulier, considérez la séquence de rotations suivante:
Dans la représentation naïve de l'angle d'Euler, telle qu'implémentée dans le pseudocode ci-dessus, ces rotations s'annuleront et l'objet reviendra à son orientation d'origine. Dans le monde réel, cela ne se produit pas - si vous ne me croyez pas, prenez un dé à six faces ou un cube de Rubik, laissez x = y = 90 °, et essayez-le vous-même!
La solution, comme vous le notez dans votre propre réponse , consiste à stocker l'orientation de l'objet en tant que matrice de rotation (ou quaternion) et à mettre à jour cette matrice en fonction des entrées de l'utilisateur. Autrement dit, au lieu du pseudocode ci-dessus, vous feriez quelque chose comme ceci:
(Techniquement, comme toute matrice de rotation ou quaternion peut être représenté comme un ensemble d'angles d'Euler, il est possible de les utiliser pour stocker l'orientation de l'objet. Mais la règle physiquement correcte pour combiner deux rotations séquentielles, chacune représentée sous forme d'angles d'Euler, en une seule rotation est plutôt compliqué et revient essentiellement à convertir les rotations en matrices / quaternions, à les multiplier, puis à reconvertir le résultat en angles d'Euler.)
la source
Le problème avec les rotations, c'est que, la plupart des gens le pensent en termes d'angles d'Euler, car ils sont faciles à comprendre.
Pourtant, la plupart des gens oublient que les angles d'Euler sont trois angles séquentiels . Cela signifie que la rotation autour du premier axe rendra la rotation suivante relative à la première rotation d'origine, vous ne pouvez donc pas faire pivoter indépendamment un vecteur autour de chacun des 3 axes à l'aide des angles d'Euler.
Cela se traduit directement en matrices lorsque vous multipliez deux matrices, vous pouvez penser à cette multiplication comme transformant une matrice en l'espace de l'autre matrice.
Cela est censé se produire avec 3 rotations séquentielles, même lorsque vous utilisez des quaternions.
Je tiens à souligner le fait que les quaternions ne sont pas une solution pour le verrouillage de vrille. En fait, le verrouillage de vrille se produira toujours si vous représentez les angles d'Euler à l'aide de quaternions. Le problème n'est pas la représentation, le problème est les 3 étapes séquentielles.
La solution?
La solution pour faire tourner un vecteur autour de 3 axes indépendamment est de combiner en un seul axe et un seul angle, de cette façon, vous pouvez vous débarrasser de l'étape où vous devez faire une multiplication séquentielle. Cela se traduira effectivement par:
Ma matrice de rotation représente le résultat de la rotation autour de X et Y et Z.
plutôt que l'interprétation d'Euler de
Ma matrice de rotation représente la rotation autour de X puis Y puis Z.
Pour clarifier cela, je vais citer le théorème de rotation d'Euler de wikipedia:
Notez que la multiplication de 3 matrices représentera toujours 3 rotations séquentielles.
Maintenant, pour combiner les rotations autour de 3 axes, vous devez obtenir un seul axe et des angles simples qui représentent la rotation autour de X, Y, Z. En d'autres termes, vous devez utiliser une représentation Axe / Angle ou quaternion pour vous débarrasser des rotations séquentielles.
Cela se fait généralement en commençant par une orientation initiale (l'orientation peut être considérée comme un angle d'axe), généralement représentée comme un quaternion ou un angle d'axe, puis en modifiant cette orientation pour représenter l'orientation de votre destination. Par exemple, vous commencez par le quaterion d'identité, puis vous tournez par la différence pour atteindre l'orientation de destination. De cette façon, vous ne perdez aucun degré de liberté.
la source
Changer une combinaison de rotations de l'espace objet vers l'espace monde est trivial: il suffit d'inverser l'ordre dans lequel les rotations sont appliquées.
Dans votre cas, au lieu de multiplier les matrices
Z × X × Y
, il vous suffit de calculerY × X × Z
.Une justification à cela peut être trouvée sur Wikipedia: conversion entre les rotations intrinsèques et extrinsèques .
la source
Z
(espace objet), puis 50 degrés autourX
(espace objet), puis 45 degrés autourY
(espace objet). C'est exactement la même chose qu'une rotation de 45 degrés autourY
( espace mondial ), puis 50 degrés autourX
( espace mondial ), puis 50 degrés autourZ
( espace mondial ).Je vais fournir ma solution comme réponse jusqu'à ce que quelqu'un puisse expliquer pourquoi cela fonctionne.
À chaque rendu, je reconstruisais mon quaternion en utilisant les angles stockés dans mon vecteur de rotation, puis j'appliquais le quaternion à ma transformation finale.
Cependant, afin de le garder autour des axes mondiaux, j'ai dû conserver le quaternion sur toutes les images et ne faire pivoter les objets qu'en utilisant une différence d'angle, c'est-à-dire ..
(Verbose pour la lisibilité)
Je pense que dsilva.vinicius essayait d'arriver à ce point.
la source
Vous devrez enregistrer l'ordre des rotations.
Stockez votre matrice de rotation actuelle et prémultipliez chaque rotation au fur et à mesure.
la source
En plus de @ concept3d answer, vous pouvez utiliser 3 matrices de rotation extrinsèque pour faire pivoter autour de l'axe en coordonnées universelles. Citation de Wikipedia :
Il vous faut donc inverser l'ordre des rotations par rapport à ce que vous feriez en utilisant des rotations intrinsèques (ou locales). @Syntac a demandé une rotation zxy, nous devrions donc faire une rotation extrinsèque yxz pour obtenir le même résultat. Le code est ci-dessous:
Explication des valeurs de matrice ici .
Ce code est didactique, pas optimal, car vous pouvez réutiliser plusieurs matrices D3DXMATRIX.
la source