Comment extraire l'orientation d'une matrice de transformation?

10

J'ai une matrice de transformation 4x4 M, et je veux découvrir la forme d'une sphère lorsqu'elle est transformée par M. (La sphère est à l'origine et a un rayon 1.)

Je sais que je peux trouver le centre en multipliant simplement M par (0,0,0,1).

Cependant, le rayon devient un problème car M peut écraser et faire pivoter la sphère. Comment puis-je connaître le (s) nouveau (x) rayon (s) de l'ellipsoïde résultant? Existe-t-il un moyen de connaître l'orientation?

Plus précisément, j'ai besoin de connaître la taille de la sphère englobante qui entourerait la sphère transformée. En d'autres termes, quel est le maximum de | M * V - M * (0,0,0,1) |, où V est un vecteur unitaire (un point sur la sphère d'origine).

CaptainCodeman
la source
1
Ne pouvez-vous pas simplement calculer la longueur des vecteurs d'axes transformés? (3 colonnes de la partie rotation de votre matrice) La sphère englobante aurait un rayon égal à la longueur du vecteur le plus long.
Bart
Non, je ne pense pas que ce soit correct. La direction la plus longue peut ne pas être alignée sur l'axe. (Imaginez si vous l'écrasiez, le pivotiez, l'écrasiez de nouveau, le pivotiez encore, etc.)
CaptainCodeman
Hmm, pas sûr que ça compte. Si je parviens à me convaincre, je rédigerai une réponse plus tard dans la journée. ;)
Bart
Le problème est que si vous effectuez une transformation SCALE, les vecteurs de base de la matrice M n'ont pas à rester ORTHOGONAUX entre eux.
GPUquant

Réponses:

6

Mathématiquement, la quantité que vous demandez est appelée la norme d'opérateur . Malheureusement, il n'y a pas de formule simple pour cela. S'il s'agit d'une transformation affine entièrement générale - par exemple, si elle peut avoir une combinaison arbitraire de rotations et d'échelles non uniformes, dans n'importe quel ordre - alors je crains qu'il n'y ait rien d'autre à faire que d'utiliser la décomposition en valeurs singulières . Si vous appliquez SVD à votre matrice, la plus grande valeur singulière sera le rayon maximum de l'ellipsoïde résultant. Les autres valeurs singulières seront également ses deux autres rayons, et la procédure SVD peut également extraire l'orientation des axes pour vous.

La mise en œuvre de SVD n'est pas pour les faibles de cœur, car elle implique de trouver des valeurs propres. Si tout ce que vous voulez, ce sont les valeurs singulières elles-mêmes, ce sont les racines carrées des valeurs propres de M ^ T * M. Donc, si vous avez un solveur de valeurs propres 3x3 à portée de main, ou si cela ne vous dérange pas d'en écrire un, vous pouvez l'utiliser. Si vous souhaitez également extraire les orientations des axes, cela s'implique davantage car vous devez également trouver des vecteurs propres. Sur cet article Wikipédia, il y a une liste de liens vers des bibliothèques pour faire SVD, dont l'un peut être utilisé dans votre projet.

Si la forme de votre matrice est restreinte de manière à ce qu'une échelle non uniforme se produise au plus une fois et soit la première transformation appliquée, c'est-à-dire la plus à droite lorsque vous utilisez des vecteurs de colonne, vous pouvez simplifier cela pour ne regarder que les longueurs du vecteurs d'axe transformés. Dans ce cas seulement - c'est-à-dire une seule échelle non uniforme suivie d'une séquence de rotations, de réflexions et d'échelles uniformes - en regardant uniquement les vecteurs d'axe vous donnera la bonne réponse.

Nathan Reed
la source
Merci, j'apprécie la réponse détaillée. Où la décomposition fournie dans l'autre réponse ne fonctionne-t-elle pas?
CaptainCodeman
2
@CaptainCodeman L'autre réponse consiste simplement à regarder les vecteurs d'axe transformés (c'est-à-dire les colonnes de la matrice), comme ce que j'ai décrit dans mon troisième paragraphe. Il échoue dans le cas où il y a une échelle non uniforme après une rotation, car alors l'échelle ne s'applique pas le long des axes d'origine.
Nathan Reed
2

Peut-être extraire les facteurs d'échelle de la matrice, puis utiliser la valeur maximale de ses composants. En utilisant la matrice SRT (Scale-Rotation-Translation), vous pouvez faire ceci comme ça:

glm::mat4 m = ...;
// Extract col vectors of the matrix
glm::vec3 col1(m[0][0], m[0][1], m[0][2]);
glm::vec3 col2(m[1][0], m[1][1], m[1][2]);
glm::vec3 col3(m[2][0], m[2][1], m[2][2]);
//Extract the scaling factors
glm::vec3 scaling;
scaling.x = glm::length(col1);
scaling.y = glm::length(col2);
scaling.z = glm::length(col3);

float scaleFactor = MAX(scaling.x, MAX(scaling.y, scaling.z));

(basé sur http://wklej.org/id/950061/ - le nom est decomposeTRS et non decomposeSRT parce que j'utilise des noms en besed sur commande quelles matrices sont multipliées en OpenGL).

Vous pouvez maintenant multiplier le rayon de la sphère d'origine par scaleFactor et vous avez votre sphère englobante.

renverser
la source