J'ai une réalisation simple de moteur de jeu entité / composant.
Le composant Transform a des méthodes pour définir la position locale, la rotation locale, la position globale et la rotation globale.
Si transform est en train de définir une nouvelle position globale, la position locale change également, pour mettre à jour la position locale dans ce cas, j'applique simplement la matrice locale de transformation actuelle à la matrice du monde de transformation du parent.
Jusque-là, je n'ai aucun problème, je peux obtenir une matrice de transformation locale mise à jour.
Mais j'ai du mal à mettre à jour la position locale et la valeur de rotation dans la transformation. La seule solution que j'ai en tête est d'extraire les valeurs de translation et de rotation de la matrice locale de transformation.
Pour la traduction, c'est assez facile - je prends juste les valeurs de la 4ème colonne. mais qu'en est-il de la rotation?
Comment extraire les angles d'Euler de la matrice de transformation?
Une telle solution est-elle correcte?:
Pour trouver la rotation autour de l'axe Z, nous pouvons trouver la différence entre le vecteur de l'axe X de localTransform et le vecteur de l'axe X de parent.localTransform et stocker le résultat dans Delta, puis: localRotation.z = atan2 (Delta.y, Delta .X);
Idem pour la rotation autour de X & Y, il suffit de permuter l'axe.
Il y a une grande synthèse sur ce processus par Mike Day: https://d3cw3dd2w32x2b.cloudfront.net/wp-content/uploads/2012/07/euler-angles1.pdf
Il est également désormais implémenté dans glm, à partir de la version 0.9.7.0, 02/08/2015. Découvrez l'implémentation .
Pour comprendre les mathématiques, vous devez regarder les valeurs qui se trouvent dans votre matrice de rotation. De plus, vous devez connaître l'ordre dans lequel les rotations ont été appliquées pour créer votre matrice afin d'extraire correctement les valeurs.
Une matrice de rotation à partir des angles d'Euler est formée en combinant des rotations autour des axes x, y et z. Par exemple, la rotation de θ degrés autour de Z peut être effectuée avec la matrice
Des matrices similaires existent pour la rotation autour des axes X et Y:
Nous pouvons multiplier ces matrices ensemble pour créer une matrice qui est le résultat des trois rotations. Il est important de noter que l'ordre de multiplication de ces matrices est important, car la multiplication matricielle n'est pas commutative . Cela veut dire que
Rx*Ry*Rz ≠ Rz*Ry*Rx
. Considérons un ordre de rotation possible, zyx. Lorsque les trois matrices sont combinées, il en résulte une matrice qui ressemble à ceci:où
Cx
est le cosinus de l'x
angle de rotation,Sx
est le sinus de l'x
angle de rotation, etc.Maintenant, le défi est d'extraire l'original
x
,y
et lesz
valeurs qui sont entrées dans la matrice.Voyons d'abord l'
x
angle. Si nous connaissons lesin(x)
etcos(x)
, nous pouvons utiliser la fonction tangente inverseatan2
pour nous rendre notre angle. Malheureusement, ces valeurs n'apparaissent pas seules dans notre matrice. Mais, si nous regardons de plus près les élémentsM[1][2]
etM[2][2]
, nous pouvons voir que nous le savons-sin(x)*cos(y)
aussicos(x)*cos(y)
. Étant donné que la fonction tangente est le rapport des côtés opposés et adjacents d'un triangle, la mise à l'échelle des deux valeurs de la même quantité (dans ce cascos(y)
) donnera le même résultat. Donc,Essayons maintenant d'obtenir
y
. Nous savonssin(y)
deM[0][2]
. Si nous avions cos (y), nous pourrions utiliser àatan2
nouveau, mais nous n'avons pas cette valeur dans notre matrice. Cependant, en raison de l'identité pythagoricienne , nous savons que:Ainsi, nous pouvons calculer
y
:Enfin, nous devons calculer
z
. C'est là que l'approche de Mike Day diffère de la réponse précédente. Puisqu'à ce stade, nous connaissons la quantitéx
et lay
rotation, nous pouvons construire une matrice de rotation XY et trouver la quantité dez
rotation nécessaire pour correspondre à la matrice cible. LaRxRy
matrice ressemble à ceci:Puisque nous savons que
RxRy
*Rz
est égal à notre matrice d'entréeM
, nous pouvons utiliser cette matrice pour revenir àRz
:L' inverse d'une matrice de rotation est sa transposition , nous pouvons donc l'étendre à:
Nous pouvons maintenant résoudre pour
sinZ
etcosZ
en effectuant la multiplication matricielle. Il suffit de calculer les éléments[1][0]
et[1][1]
.Voici une implémentation complète pour référence:
la source
M[1][3]
avecM[1][2]
etM[2][3]
avecM[2][2]
.