Wie können Sie die Orientierung aus einer Transformationsmatrix extrahieren?

10

Ich habe eine 4x4-Transformationsmatrix M und möchte die Form einer Kugel herausfinden, wenn sie von M transformiert wird. (Die Kugel befindet sich am Ursprung und hat den Radius 1.)

Ich weiß, dass ich das Zentrum finden kann, indem ich M mit (0,0,0,1) multipliziere.

Der Radius wird jedoch zu einem Problem, da M die Kugel quetschen und drehen kann. Wie kann ich die neuen Radien des resultierenden Ellipsoids ermitteln? Gibt es eine Möglichkeit, die Orientierung herauszufinden?

Insbesondere muss ich die Größe der Begrenzungskugel kennen, die die transformierte Kugel einschließen würde. Mit anderen Worten, was ist das Maximum von | M * V - M * (0,0,0,1) |, wobei V ein Einheitsvektor ist (ein Punkt auf der ursprünglichen Kugel).

CaptainCodeman
quelle
1
Können Sie nicht einfach die Länge der transformierten Achsenvektoren berechnen? (3 Spalten des Rotationsteils Ihrer Matrix) Die Begrenzungskugel hätte einen Radius, der der Länge des längsten Vektors entspricht.
Bart
Nein, ich denke nicht, dass das richtig ist. Die längste Richtung ist möglicherweise nicht achsenausgerichtet. (Stellen Sie sich vor, Sie hätten es gequetscht, gedreht, erneut gequetscht, noch mehr gedreht usw.)
CaptainCodeman
Hmm, ich bin mir nicht sicher, ob das wichtig ist. Wenn ich mich selbst überzeugen kann, schreibe ich später heute eine Antwort. ;)
Bart
Das Problem ist, dass bei einer SCALE-Transformation die Basisvektoren der M-Matrix nicht ORTHOGONAL zueinander bleiben müssen.
GPUquant

Antworten:

6

Mathematisch wird die Menge, nach der Sie fragen, als Operatornorm bezeichnet . Leider gibt es keine einfache Formel dafür. Wenn es sich um eine ganz allgemeine affine Transformation handelt - zum Beispiel wenn sie eine beliebige Kombination von Rotationen und ungleichmäßigen Skalen in beliebiger Reihenfolge haben könnte - dann gibt es leider nichts anderes, als eine Singularwertzerlegung zu verwenden . Wenn Sie SVD auf Ihre Matrix anwenden, ist der größte Singularwert der maximale Radius des resultierenden Ellipsoids. Die anderen singulären Werte sind auch die beiden anderen Radien, und das SVD-Verfahren kann auch die Ausrichtung der Achsen für Sie extrahieren.

Die Implementierung von SVD ist nichts für schwache Nerven, da Eigenwerte gefunden werden müssen. Wenn Sie nur die Singularwerte selbst wollen, sind sie die Quadratwurzeln der Eigenwerte von M ^ T * M. Wenn Sie also einen 3x3-Eigenwertlöser zur Hand haben oder nichts dagegen haben, einen zu schreiben, können Sie diesen verwenden. Wenn Sie auch die Ausrichtungen der Achsen extrahieren möchten, wird dies komplizierter, da Sie auch Eigenvektoren finden müssen. In diesem Wikipedia-Artikel finden Sie eine Liste mit Links zu Bibliotheken für SVD, von denen Sie möglicherweise einen in Ihrem Projekt verwenden können.

Wenn die Form Ihrer Matrix so eingeschränkt ist, dass eine ungleichmäßige Skalierung höchstens einmal auftritt und die erste Transformation angewendet wird, dh ganz rechts, wenn Sie Spaltenvektoren verwenden, können Sie dies vereinfachen, um nur die Längen der Matrix zu betrachten transformierte Achsenvektoren. Allein in diesem Fall - dh einer einzelnen ungleichmäßigen Skala, gefolgt von einer beliebigen Folge von Rotationen, Reflexionen und gleichmäßigen Skalen - erhalten Sie die richtige Antwort, wenn Sie nur die Achsenvektoren betrachten.

Nathan Reed
quelle
Vielen Dank, ich freue mich über die ausführliche Antwort. Wo funktioniert die in der anderen Antwort angegebene Zerlegung nicht?
CaptainCodeman
2
@CaptainCodeman Die andere Antwort betrifft nur die transformierten Achsenvektoren (dh die Spalten der Matrix), wie ich es in meinem dritten Absatz beschrieben habe. Dies schlägt fehl, wenn nach einer Drehung eine ungleichmäßige Skalierung vorliegt, da die Skalierung dann nicht entlang der ursprünglichen Achsen angewendet wird.
Nathan Reed
2

Extrahieren Sie möglicherweise Skalierungsfaktoren aus der Matrix und verwenden Sie dann den Maximalwert ihrer Komponenten. Mit der SRT-Matrix (Scale-Rotation-Translation) können Sie dies folgendermaßen tun:

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));

(basierend auf http://wklej.org/id/950061/ - der Name ist decomposeTRS und nicht decomposeSRT, da ich Namen verwende, die in der Reihenfolge angegeben sind, in der die Matrizen in OpenGL multipliziert werden).

Jetzt können Sie den ursprünglichen Kugelradius mit scaleFactor multiplizieren und haben Ihre Begrenzungskugel.

Revers
quelle