3D-Kameradrehung

9

Bitte, vergib mir, aber ich brauche Hilfe und bin seit ein paar Wochen dabei. Ich mache keine Fortschritte und überall, wo ich hingehe und eine andere Antwort sehe, funktioniert alles, was ich versuche, nicht. Ich hatte genug Tipps und Ratschläge, jetzt brauche ich wirklich nur noch jemanden, der mir die Antwort gibt, damit ich rückwärts arbeiten kann, weil ich das nicht verstehen kann.

Was dieses Thema am verwirrendsten gemacht hat, ist die Art und Weise, wie jeder andere Konventionen oder Regeln verwendet und ihre Antworten auf seinen eigenen Konventionen basieren, ohne zu definieren, was sie sind.

Hier sind die Konventionen, die ich basierend auf den häufigsten und logischsten Konventionen gebildet habe:

  1. Rechte Regel für die Achse.
  2. Positives Y ist oben, Positives Z ist dem Betrachter zugewandt, Positives X ist rechts.
  3. Row Major-Matrizen, transponiert, wenn sie an Shader gesendet werden.
    • Pitch: Drehung um die X-Achse
    • Gieren: Drehung um die y-Achse
    • Rolle: Drehung um die z-Achse
  4. Rotationsreihenfolge: Rollen, Neigen, Gieren (ist das richtig? Kann mich jemand darauf überprüfen?)
  5. Positive Rotationswerte vom positiven Ende einer Achse nach unten führen zu einer Rotation im Uhrzeigersinn.
  6. Die Standardrichtung für die Drehung um 0 über alle Achsen ist ein Vektor, der auf das negative Y zeigt.

.. wie funktioniert man angesichts dieser Konventionen (korrigieren Sie mich auf jeden Fall, wenn sie falsch sind!):

  • Eine LookAt-Funktion schreiben? (lookAt (Vektorposition, Vektoraugenfokus, Vektor nach oben))
  • Berechnen Sie eine Rotationsmatrix. (Drehung (x, y, z))

Ich habe versucht, diese beiden Fragen mindestens in den letzten 3 Wochen selbst zu beantworten. Ich habe meine LookAt & Rotation Matrix-Funktion mindestens 30 Mal neu geschrieben, Dutzende von Methoden getestet und Material durchgelesen, das ich gesehen habe Hunderte von Websites und viele beantwortete Fragen gelesen, den Code anderer Leute kopiert, und nichts, was ich bisher gemacht habe, hat funktioniert, alles hat das falsche Ergebnis hervorgebracht. Einige davon haben einige unglaublich bizarre Ausgaben erzeugt, die nicht einmal annähernd der korrekten Rotation entsprechen.

Ich habe jede Nacht daran gearbeitet, mit Ausnahme der letzten Nacht, weil ich von dem wiederholten Versagen so frustriert war, dass ich anhalten und eine Pause machen musste.

Bitte zeigen Sie mir einfach, was die richtige Methode ist, damit ich rückwärts arbeiten und herausfinden kann, wie es funktioniert. Ich bekomme einfach nicht die richtige Antwort und das macht mich ein bisschen verrückt!

Ich schreibe in Java, aber ich nehme Code, der in einer beliebigen Sprache geschrieben ist. Der größte Teil meines 3D-Rendering-Codes funktioniert tatsächlich ziemlich hervorragend. Es ist nur die Mathematik, die ich nicht verstehen kann.

UPDATE: Gelöst

Danke für deine Hilfe! Ich habe jetzt eine funktionierende LookAt-Funktion, die ich tatsächlich verstehe und ich könnte nicht glücklicher sein (wenn jemand sie auf jeden Fall sehen möchte, fragen Sie).

Ich habe erneut versucht, eine Rotationsmatrix zu erstellen, die auf Pitch / Yaw / Roll-Variablen basiert, und es schien erneut zu scheitern, aber ich habe mich entschlossen, den Versuch, Euler-Winkel für die Freelook-Kamera zu verwenden, zu löschen, da sie für die Kamera ungeeignet zu sein scheint Rolle, stattdessen werde ich eine Quaternionsklasse erstellen, könnte besseres Glück haben, diesen Weg zu gehen, andernfalls werde ich die Tonhöhe / Gier als sphärische Koordinaten verwenden und mich für die Rotation auf die neue funktionierende LookAt-Funktion verlassen.

Wenn jemand anderes vor einem ähnlichen Problem steht und mir Fragen stellen möchte, wenden Sie sich bitte an.

Zumindest stecke ich nicht mehr fest, danke für die Hilfe!

Grady
quelle

Antworten:

13

Was Sie suchen, finden Sie in dieser sehr guten Erklärung: http://www.songho.ca/opengl/gl_transform.html

Aber da ich es ohne Händchenhalten verwirrend fand, werde ich versuchen, es hier zu erklären.

An dieser Stelle müssen Sie 5 Koordinatensysteme und deren Beziehung zueinander berücksichtigen. Dies sind die Fensterkoordinaten, die normalisierten Gerätekoordinaten, die Augenkoordinaten, die Weltkoordinaten und die Objektkoordinaten.

Die Fensterkoordinaten können als "physische" Pixel auf Ihrem Bildschirm angezeigt werden. Dies sind die Koordinaten, auf die sich das Fenstersystem bezieht. Wenn Sie mit der nativen Auflösung Ihres Monitors arbeiten, handelt es sich tatsächlich um einzelne Pixel. Das Fensterkoordinatensystem besteht aus 2D-Ganzzahlen und ist relativ zu Ihrem Fenster. Hier ist das x + links und y + unten mit dem Ursprung in der oberen linken Ecke. Sie begegnen diesen, wenn Sie zum Beispiel anrufen glViewport.

Der zweite Satz sind die normalisierten Gerätekoordinaten. Diese beziehen sich auf die Speicherplatzkonfiguration durch den aktiven Ansichtsport. Der sichtbare Bereich des Ansichtsfensters reicht von -1 bis +1 und hat somit den Ursprung in der Mitte. Das x + ist links und das y + ist oben. Sie haben auch das z + ist "out" aus der Szene. Dies beschreiben Sie in 1.

Sie haben keine Kontrolle darüber, wie Sie von den normalisierten Gerätekoordinaten zu den Fensterkoordinaten gelangen. Dies erfolgt implizit für Sie. Die einzige Kontrolle, die Sie haben, ist durch glViewportoder ähnlich.

Wenn Sie mit openGL arbeiten, wird Ihr Endergebnis immer in normalisierten Gerätekoordinaten angegeben. Infolgedessen müssen Sie sich Sorgen machen, wie Ihre Szene in diesen gerendert werden kann. Wenn Sie die Projektions- und Modellansichtsmatrix auf die Identitätsmatrix setzen, können Sie diese Koordinaten direkt zeichnen. Dies geschieht beispielsweise beim Anwenden von Vollbildeffekten.

Das nächste sind die Augenkoordinaten. Dies ist die Welt von der Kamera aus gesehen. Infolgedessen liegt der Ursprung in der Kamera und es gelten die gleichen Achsenelemente wie die Gerätekoordinaten.

Um von den Augenkoordinaten zu den Gerätekoordinaten zu gelangen, erstellen Sie die Projektionsmatrix. Am einfachsten ist die orthografische Projektion, bei der die Werte nur entsprechend skaliert werden. Die perspektivische Projektion ist komplizierter und beinhaltet eine Simulationsperspektive.

Endlich haben Sie das Weltkoordinatensystem. Dies ist das Koordinatensystem, in dem Ihre Welt definiert ist und Ihre Kamera Teil dieser Welt ist. Hierbei ist zu beachten, dass die Achsenausrichtungen genau so sind, wie Sie sie definieren . Wenn Sie z + als up bevorzugen, ist das völlig in Ordnung.

Um von Weltkoordinaten zu Augenkoordinaten zu gelangen, definieren Sie die Ansichtsmatrix. Dies kann mit so etwas gemacht werden lookAt. Diese Matrix "bewegt" die Welt so, dass sich die Kamera am Ursprung befindet und auf die z-Achse schaut.

Um die Ansichtsmatrix überraschend einfach zu berechnen, müssen Sie die Transformation der Kamera durchführen. Grundsätzlich müssen Sie folgende Matrix formulieren:

M.=x[1]]y[1]]z[1]]- -p[1]]x[2]]y[2]]z[2]]- -p[2]]x[3]]y[3]]z[3]]- -p[3]]0001

Die x-, y- und z-Vektoren können direkt von der Kamera aufgenommen werden. Im Fall von Blick auf würden Sie sie von den Ziel-, Augen- (Mitte) und Aufwärtswerten ableiten. Wie so:

z=nÖrmeinlichze(eye- -teinrGet)x=nÖrmeinlichze(up×z)y=zx

Aber wenn Sie diese Werte zufällig nur herumliegen haben, können Sie sie einfach so nehmen, wie sie sind.

P zu bekommen ist etwas schwieriger. Es ist nicht die Position in Weltkoordinaten, sondern die Position in Kamerakoordinaten. Eine einfache Problemumgehung besteht darin, zwei Matrizen zu initialisieren, eine mit nur x, y und z und eine zweite mit -eye, und sie miteinander zu multiplizieren. Das Ergebnis ist die Ansichtsmatrix.

Wie dies im Code aussehen kann:

mat4 lookat(vec3 eye, vec3 target, vec3 up)
{
    vec3 zaxis = normalize(eye - target);    
    vec3 xaxis = normalize(cross(up, zaxis));
    vec3 yaxis = cross(zaxis, xaxis);     

    mat4 orientation(
       xaxis[0], yaxis[0], zaxis[0], 0,
       xaxis[1], yaxis[1], zaxis[1], 0,
       xaxis[2], yaxis[2], zaxis[2], 0,
         0,       0,       0,     1);

    mat4 translation(
              1,       0,       0, 0,
              0,       1,       0, 0, 
              0,       0,       1, 0,
        -eye[0], -eye[1], -eye[2], 1);

    return orientation * translation;
}

vollständiger Code

Der Vollständigkeit halber haben Sie schließlich auch das Objektkoordinatensystem. Dies ist das Koordinatensystem, in dem Netze gespeichert werden. Mit Hilfe der Modellmatrix werden die Netzkoordinaten in das Weltkoordinatensystem konvertiert. In der Praxis werden die Modell- und Ansichtsmatrizen in der sogenannten Modellansichtsmatrix kombiniert.

Rioki
quelle
1
Wenn ich diese Antwort hundertmal abstimmen könnte, würde ich. Vielen Dank für eine gründliche und vollständige Antwort auf alles, was mich verwirrt hat, und für die Bereitstellung von Code und des Links! Ich habe den ganzen Tag damit verbracht, Mathematikbücher zu diesem Thema und mit Ihrer Antwort sowie dem Beispielcode und der verknüpften Seite zu lesen. Wenn dies nicht ausreicht, um dies herauszufinden, sollte ich jetzt aufhören. Wenn ich in diesem letzten Codebeispiel nur um eine Klarstellung bitten könnte, würde ich zu Recht sagen, dass diese Matrizen in der Hauptreihenfolge der Spalten und die oben genannte in der Hauptreihenfolge sind?
Grady
Dies ist etwas verwirrend, die Matrizen sind Spaltenmajor, aber die Spalte befindet sich in der Zeile. Um die eigentliche Mathematik dem Code zuzuordnen, müssen Sie die Matrix transponieren. Siehe github.com/rioki/glm/blob/master/src/matrix.h#l72. Dies entspricht genau openGL und wie es wäre, wenn es verwendet würde float[16].
Rioki
Ah, ich dachte schon, wollte aber nur sicher sein, nochmals vielen Dank! Du warst eine große Hilfe, ich weiß das wirklich zu schätzen.
Grady