Wie kann ich eine Kamera um ihren Zielpunkt kreisen lassen?


18

Ich zeichne eine Szene, in der sich die Kamera frei im Universum bewegt. Die Kameraklasse verfolgt die Ansicht (oder Lesen ) Punkt, um die Position der Kamera, und die Aufwärts - Vektor. Diese Vektoren / Punkte werden dann an gluLookAt übergeben.

Schwenken und Zoomen sind nahezu trivial zu implementieren. Aber ich bin eine Drehung um die Suche nach Blick auf Punkt viel eher ein Problem zu sein. Ich möchte eine Funktion Camera.rotate schreiben , die 2 Winkel nimmt, eine , die sich dreht nach oben / unten und eine , die dreht sich nach links / rechts entlang einer imaginären Kugel , die über die zentriert Blick auf Punkt.

Gibt es eine einfache Möglichkeit, dies zu tun?

Ich habe (kurz) über Quaternionen gelesen, aber ich wollte sehen, ob es angesichts des relativ einfachen Aufbaus meiner Szene eine einfachere Lösung gibt.


Haben Sie irgendetwas in Ihrer Toolbox, um einen Punkt um den Ursprung zu drehen, wenn eine Achse und ein Winkel vorgegeben sind?
Sam Hocevar

Nichts anderes als mein loses Verständnis von Quaternions, nein. Je mehr ich mir das anschaue, desto mehr denke ich, dass Quaternions die Antwort sein könnten. Ich bin jedoch nicht sicher , wie die zur Berechnung Achse x, y und z - Werte zu verwenden , in den Formeln Quaternion.
Luke

Ich werde Ihnen nicht sagen, dass Quaternionen nicht der richtige Weg sind. Sie sind eine sehr gute Lösung für Ihr Problem. Sie benötigen jedoch eine Quaternion-Klasse und Möglichkeiten zur Interaktion mit GL und GLU, und ich bin der Meinung, dass Sie zuerst versuchen sollten, sich mit Transformationsmatrizen vertraut zu machen. Andere mögen anderer Meinung sein.
Sam Hocevar

Überlegen Sie, in welcher Reihenfolge Sie die Rotationen ausführen. Das Anwenden von Rotationen für das Bewegen in den Weltraum oder für das Bewegen in den Kameraraum ist unterschiedlich
Charlie

Antworten:


25

Was Sie verlangen, heißt Arcball-Rotation. Quaternionen sind nur dann die einfache Lösung, wenn Sie wissen, wie sie funktionieren. Sie können dies jedoch auch ohne Quaternionen erreichen.

Voraussetzungen

Wissen Sie, wie man Objekte im Allgemeinen dreht? Angenommen, Sie haben ein Objekt am Ursprung. Wissen Sie, wie Sie es drehen (Hinweis: Multiplizieren Sie mit einer Rotationsmatrix)? Wenn ja, dann gehe ich davon aus, dass Sie wissen, was passieren wird, wenn Sie das Objekt zuerst übersetzen und dann drehen?

Sie müssen wissen, wie man eine Rotationsmatrix aus der Winkelachse berechnet.

Lösung

  • Holen Sie sich die Kamera nach oben und die richtigen Vektoren. Beachten Sie, dass sie normalisiert werden sollten.
  • Liefert den Vektor vom Fokuspunkt zur Kamera (camPosition - Focus). Dies ist der Vektor, den Sie drehen werden. Nennen wir diesen camFocusVector .
  • Entscheiden Sie, um wie viel Sie sich in Gier- / Neigungsrichtung in Bezug auf die Kamera drehen möchten
  • Erstellen Sie zwei Rotationsmatrizen. Die erste Rotationsmatrix wird der Einsatz bis der Kamera wie die Achse und Gierwinkel , dass Sie sich entschieden. Die zweite Rotationsmatrix wird die Verwendung direkt von der Kamera wie die Achse und Pitch Winkel dass Sie sich entschieden.
  • Drehen Sie nun den camFocusVector mit den neuen Rotationsmatrizen. Dies ist nun Ihre neue Position der Kamera relativ zum Ursprung. Wir möchten natürlich, dass es relativ zum Fokuspunkt ist ...
  • Fügen Sie die Fokuspunktposition zu camFocusVector hinzu . Dies ist jetzt die neue Position Ihrer Kamera. Übersetzen Sie Ihre Kamera entsprechend.
  • Bitten Sie die Kamera abschließend, sich auf das Fokusmessfeld zu konzentrieren, indem Sie Ihre lookAt () - Funktion aufrufen

Vorbehalte

Sie müssen nach bestimmten Fällen oder Besonderheiten Ausschau halten, bei denen Ihre Kamera nicht mehr funktioniert. Zum Beispiel gerade nach unten / oben schauen. Ich werde Sie herausfinden lassen, wie Sie damit umgehen sollen.

EDIT1: Neuberechnung der Orthonormalvektoren der Kamera

Sie kennen bereits die Richtung der Kamera ((cameraPos - focusPoint) .normalize ()). Angenommen, Ihre Kamera ist auf + Y (oder die aktuelle Aufwärtsachse Ihrer Welt liegt bei Ihnen). Jetzt einfach die Richtung mit dem Pfeil nach oben kreuzen , um das richtige zu finden . Getan? Nee! Ihr Aufwärtsvektor ist nicht mehr orthogonal zu den beiden anderen. Um das Quer zu beheben rechts mit Richtung und Sie Ihren neuen bekommen oben .

Notiere dass der Gram-Schmidt is really what should be used to orthonormalize vectors.

Beachten Sie auch hier die Vorsichtsmaßnahmen, da dies in einigen Fällen nicht funktioniert (die Richtung ist beispielsweise parallel nach oben ).


Note that the right vector can be obtained using normalize(up ^ camFocusVector) (or its opposite if left-handed).
sam hocevar

Looking good so far, worked beautifully for left/right rotation (I have the up vector so that's easy). What does the '^' mean in your comment @SamHocevar? Is that cross product? Also, how can I recompute the up vector once I've made the translations?
Luke

@Luke: Check my EDIT1
Samaursa

1
@Samaursa Thank you very much. Your solution works perfectly, and I learned a lot in the process!
Luke

2
this is an EXCELLENT answer, thank you very much for your explanation. In my case, I wanted the camera to only rotate about the target point in the X-Y plane, and so after doing all the calculations, I always set the cameraRight.z to 0 and then calculated the cameraUp vector. This gave the desired effect. Just thought of sharing
codemonkey

1

What you need is a typical ArcBall camera, which is basically a camera that keeps a target location and allows you to move the camera in a "spherical" way around that target.

It's in XNA but IIRC I've used this implementation before, and it worked quite well:

http://roy-t.nl/index.php/2010/02/21/xna-simple-arcballcamera/


That implementation appears to only move directly along the right vector, which will approximate an arcball for small values of amount. He's also moving the LookAt point, as where I want to move the camera (close, but subtly different). I believe Samaursa has provided the simplest complete way of achieving this.
Luke

Thank you for your feedback. I must admit that I used this implementation a bit as a "blackbox" but I did not notice any problem. To clarify were you perhaps talking about the MoveCameraRight/MoveCameraForward methods? Those methods were added in order to pan the camera around, but are not part of the Arcball interface. If you want to rotate the camera around the target, you simply change the Yaw or Pitch properties.
David Gouveia

Sorry, you're right, those are panning methods. I didn't notice how he set a dirty flag for the matrix when yaw and pitch were changed.
Luke

0

Here's my code for rotating around a point, found myself reusing it a lot.

float distance;      // Straight line distance between the camera and look at point

// Calculate the camera position using the distance and angles
float camX = distance * -sinf(camAngleX*(M_PI/180)) * cosf((camAngleY)*(M_PI/180));
float camY = distance * -sinf((camAngleY)*(M_PI/180));
float camZ = -distance * cosf((camAngleX)*(M_PI/180)) * cosf((camAngleY)*(M_PI/180));

// Set the camera position and lookat point
gluLookAt(camX,camY,camZ,   // Camera position
          0.0, 0.0, 0.0,    // Look at point
          0.0, 1.0, 0.0);   // Up vector

1
That's basically the way I did it initially. There are many issues with doing it this way (at least for me). Basically this implementation rotates only about 2 fixed axes. Let's say you rotate up nearly to the north pole. Then rotate right. You'll find yourself spinning in a tiny circle rather than following the right vector of the camera all the way around the globe.
Luke

Now that you mentioned that, I guess there are two different ways to look at the problem. In my application I used the ArcBall camera to rotate around a target island on the sea, and if I used 3 axes of freedom it would look plain wrong (such as seeing the island upside down or sideways).
David Gouveia

How do I get the camera angles here?
rafvasq

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.