2016-04-18 7 views
1

Ich versuche, eine Kamera um einen Punkt im Raum, so etwas zu drehen:um die falsche Achse dreht

Rotating around an object

Wo der rote Punkt das Zentrum das so etwas wie ein sein, wird in der Regel gehen Objekt.

Der Benutzer kann die Kamera mit der Maus drehen, wobei sich die vertikale Bewegung vertikal (x-Achse) und die horizontale horizontal (y-Achse) drehen sollte.

Was ich

Rotationen auf der y-Achse wollen, sind immer auf die offensichtlich y-Achse der Kamera und gleichen mit x. Wenn der Benutzer beispielsweise die Maus nach oben bewegt, sollte er immer so aussehen, als ob Sie sich über das Objekt bewegen, auf das sich die Kamera konzentriert. Wenn der Benutzer die Maus von links nach rechts bewegt, sollte es so aussehen, als ob sich das Objekt auf seiner Y-Achse dreht (oder dass sich die Kamera um ihre Y-Achse bewegt).

Wenn also der Benutzer die Maus ein wenig nach links bewegt und dann anfängt, ihn nach oben zu bewegen, sollte er immer noch so aussehen, als würde er aus der neuen Perspektive über das Objekt hinausgehen, statt sich in einem Winkel zu drehen die tatsächliche x-Achse der Welt.

Dies scheint Standard in den meisten 3D-Software, die ich zum Beispiel verwendet habe.

Was ich versucht habe

Mit Hilfe von vielen Fragen hier, habe ich ziemlich nahe gekommen, was ich will, aber nicht ganz.

Für folgende Bits des Codes: view_ die Matrix 4x4 Ansicht ist, origin_ die Stelle im Bild würden wir um sind zu drehen, ist position_ die blaue Linie in dem Bild darstellt, wie weit zurück die Kamera vom Ursprung (oder ein Kameraschwenk, aber das ist noch nicht implementiert), und pitch, yaw und roll sind die Beträge, die wir drehen möchten (in diesem Fall ist roll immer Null).

Mein bestes Ergebnis war bisher mit diesem:

// rotation_ is a vec3 here 
rotation_ += glm::vec3(glm::radians(pitch), glm::radians(yaw), glm::radians(roll)); 
glm::mat4 rot = glm::rotate(glm::mat4(1.0f), rotation_.x, glm::vec3(1.0f, 0.0f, 0.0f)); 
rot = glm::rotate(rot, rotation_.y, glm::vec3(0.0f, 1.0f, 0.0f)); 
rot = glm::rotate(rot, rotation_.z, glm::vec3(0.0f, 0.0f, 1.0f)); 
view_ = glm::translate(glm::translate(glm::mat4(1.0f), position_) * rot, origin_); 

schließen, aber Drehen von ~ 90 Grad entlang der x-Achse verursacht weitere Drehungen um die y-Achse erscheinen um die z-Achse zu sein. Ich kann das nicht mit der y-Achse zur x-Achse replizieren, also bin ich neugierig, ob das tatsächlich eine kardanische Sperre oder etwas anderes ist.

Um dies zu lösen, habe ich versucht, rotation_ als Quaternion, und bekam die Rotation wie folgt zu speichern:

// rotation_ is a quaternion here. 
rotation_ *= glm::fquat(glm::vec3(glm::radians(pitch), glm::radians(yaw), glm::radians(roll))); 
glm::vec3(1.0f, 0.0f, 0.0f)); 
view_ = glm::translate(glm::translate(glm::mat4(1.0f), position_) * rot, origin_); 

Dies ist eigentlich noch schlimmer. Es sieht so aus, als würde ich immer um die Achsen der Welt rotieren und nicht durch die Ausrichtung der Kamera, was ich nicht will.

Wie kann ich die Kamera auf immer schauen, wie es vertikal dreht, wenn die Maus/unten nach oben bewegt, und immer schauen, wie es horizontal dreht, wenn nach links/rechts zu verschieben?

+0

@immibis Falls Sie es verpasst haben, habe ich eine Quaternion-Lösung versucht, und ich vermute, dass die Antwort wahrscheinlich Quaternionen beinhalten wird. Ich gebe zu, dass ich nicht das tiefste Verständnis von Quaternionen habe, aber ich kenne die Grundlagen und habe sie schon mehrmals benutzt. – Claytorpedo

Antwort

3

Ich habe meine Quaternionen in der falschen Reihenfolge kombiniert!

// rotation_ is a quaternion here. 
rotation_ *= glm::fquat(glm::vec3(glm::radians(pitch), glm::radians(yaw), glm::radians(roll))); 
glm::vec3(1.0f, 0.0f, 0.0f)); 
view_ = glm::translate(glm::translate(glm::mat4(1.0f), position_) * rot, origin_); 

Die Linie

rotation_ *= glm::fquat(glm::vec3(glm::radians(pitch), glm::radians(yaw), glm::radians(roll))); 

statt

sein sollte
rotation_ = glm::fquat(glm::vec3(glm::radians(pitch), glm::radians(yaw), glm::radians(roll))) * rotation_; 

Mag die quaternion Lösung funktioniert wie ich es erwartet hatte.

Wenn ich richtig verstehe, ist das, weil ich zuerst zu der neuen Deltarotation drehen und dann die alte Rotation hinzufügen wollte. Dadurch kann ich die neue Drehung zuerst auf die Achsen der Kamera anwenden, bevor ich den Rest der Drehung berücksichtige.

Wenn Sie es anders herum drehen, wird es zur alten Rotation rotieren und dann die neue Rotation hinzufügen, was dazu führt, dass die neue Rotation nicht in den erwarteten Richtungen angewendet wird.

Verwandte Themen