2008-09-20 3 views
13

Ich habe ein 3D-Objekt, das ich in der Lage sein möchte, in 3D zu drehen. Der einfachste Weg besteht darin, die X- und Y-Mausbewegung direkt in Drehung um die Y- und X-Achse zu übersetzen. Wenn jedoch eine Drehung um beide Achsen stattfindet, wird die Art der Drehung des Modells höchst kontraintuitiv (dh wenn Sie das Objekt um 180 Grad umdrehen) Achse, Ihre Bewegung entlang der anderen Achse ist umgekehrt).Der beste Weg, um die Mausbewegung in 3D-Rotation eines Objekts zu übersetzen

Ich könnte einfach die obige Methode tun, aber anstatt die Menge zu speichern, um die zwei Achsen zu drehen, konnte ich die volle Rotationsmatrix speichern und sie weiter entlang der gleichen Achsen für jeden Mauswiderstand drehen, aber ich bin besorgt, dass das schnell Genauigkeitsprobleme haben würde.

Antwort

4

Erstellen Sie eine Akkumulatormatrix und initialisieren Sie sie mit der Identität.

Jeder Rahmen, wenden Sie das auf Ihren Modellansicht/Welt-Matrix-Zustand an, bevor Sie das Objekt zeichnen.

Nach der Mausbewegung, konstruieren Sie eine Rotationsmatrix um die X-Achse mit einigen sensitivity_constant * delta_x. Konstruiere eine andere Rotationsmatrix um die Y-Achse für die andere Komponente. Multiplizieren Sie eins, dann das andere auf den Akkumulator.

Der Akku ändert sich, wenn Sie die Maus bewegen. Beim Zeichnen wird das Objekt wie erwartet ausgerichtet.

Auch die Person über Quaternionen ist richtig; Dies wird nur für kleine inkrementelle Änderungen gut aussehen. Wenn Sie es schnell auf eine Diagonale ziehen, dreht es sich nicht so, wie Sie es erwarten.

+0

I die Wirkung von Gleitkomma Ungenauigkeit überschätzt. Einfach die Rotationen zu akkumulieren funktioniert gut. Ich werde in Quaternionen schauen, aber da ich nur um 2 Achsen rotiere, sieht alles gut aus. –

3

Sie können mit Präzisionsverlust umgehen, indem Sie Ihre Rotationsmatrix renormieren, so dass jede der 3 Reihen wieder senkrecht ist. Oder Sie können die Rotationsmatrix, die Sie gerade ändern möchten, basierend auf vorhandenen Informationen über das Objekt neu generieren, und dies macht eine Renormierung überflüssig.

Alternativ können Sie quaternions verwenden, die Euler eine Alternative Winkel mit Rotationen für den Umgang.

Ich lernte viel davon in meinen frühen Tagen von this faq, die sich mit diesem Problem befasst (obwohl für eine andere Anwendung) in Euler's are Evil.

6

Es ist wahrscheinlich am intuitivsten, das Objekt um die Achse senkrecht zur aktuellen Ziehrichtung zu drehen, entweder inkrementell mit jeder Mausbewegung oder relativ zur Anfangsposition des Ziehvorgangs. Die zwei Optionen geben leicht unterschiedliche Benutzerinteraktionen, die jeweils ihre Vor- und Nachteile haben.

Es gibt eine relatively straightforward Möglichkeit, einen Winkel und einen 3D-Vektor zu konvertieren, der die Achse darstellt, die in eine Rotationsmatrix gedreht wird.

Sie sind in das Recht vor, eine rohe Rotationsmatrix durch Inkrementrotationen Aktualisierung nicht in der Matrix führen wird länger eine reine Rotationsmatrix ist. Dies liegt daran, dass eine 3 × 3-Rotationsmatrix dreimal so viele Daten aufweist, wie benötigt wird, um eine Rotation darzustellen.

Eine kompaktere Art, Rotationen darzustellen, ist Euler Angles mit einem minimalen 3-Wert-Vektor. Sie könnten die aktuelle Rotation als Euler-Winkelvektor verwenden, sie in eine Matrix umwandeln, die Rotation (inkrementell oder anders) anwenden und die Matrix zurück in einen Euler-Winkelvektor konvertieren. Dieser letzte Schritt würde natürlich jede nicht-rotatorische Komponente zu Ihrer Matrix eliminieren, so dass Sie wieder eine reine Rotationsmatrix für den nächsten Zustand erhalten.

Euler Winkel sind konzeptionell nett, aber es ist eine Menge Arbeit, um die Hin-und Her-Konvertierungen zu tun.

Eine praktischere Wahl ist Quaternions (also), die Vektoren mit vier Elementen sind. Die vier Elemente geben eine Drehung und eine einheitliche Skalierung an, und wenn Sie den Vektor in Einheitslänge eingeben und normalisieren, erhalten Sie einen Skalierungsfaktor von 1,0. Es stellt sich heraus, dass ein Winkel-Achsen-Wert kann auch durch

q.x = sin(0.5*angle) * axis.x; 
q.y = sin(0.5*angle) * axis.y; 
q.z = sin(0.5*angle) * axis.z; 
q.w = cos(0.5*angle); 

Sie dann das quaternion Produkt nehmen können sehr leicht auf einen Quaternionwert umgewandelt wird von der aktuellen Dreh quaternion (die nur einfache Multiplikation und Addition verwendet) und inkrementellen Rotationsquaternion, um eine neue Quaternion zu erhalten, die beide Rotationen darstellt. An diesem Punkt können Sie die Länge normalisieren, um eine reine Rotation zu gewährleisten, ansonsten aber iterativ Rotationen kombinieren.

Die Umwandlung der Quaternion in eine Rotationsmatrix ist sehr einfach (verwendet nur Multiplikation und Addition), wenn Sie das Modell in seinem gedrehten Zustand mit herkömmlichen Grafik-APIs anzeigen möchten.

5

In meinem Kurs Computergrafik erhielten wir den folgenden Code, der es uns ermöglichte, das Rad nicht neu zu erfinden.

trackball.h

trackball.c

Verwandte Themen