3D-Projektionen: Theroie

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • 3D-Projektionen: Theroie

    Hoihoi! (muss mich nur wieder mal melden, sonst verstaubt mein Profil noch :P )

    Eins vorweg: es geht nicht ums Programmieren, sonder um die Theorie dahinter.

    Ich bin gerade dabei (arbeitsbedingt) CorelDraw mit einem 3D-Modus auszustatten. Dafür habe ich mir eine kleine vba-Test-Engine zusammengebastelt, welche die grundlegenden Operationen beherscht:
    - Erstellung von Translations-, Skalierungs- und Rotationsmatrizen
    - Vektor in homogene 1x4 Matrix umwandeln
    - Matrixaddition und -multiplikation

    Ich habe im Internet zahlreiche Referenzen gefunden, die mir diese Engine möglich machten.

    Zu Probezwecken wandle ich die Koordinaten eines Würfels in einzelne homogene Matrizen um. Diese werden dann nacheinander mit der View- und Rotationsmatrix multipliziert. Aus den 1x4-Ergebnis-Matrizen der Eckpunkte nehm ich mir die x und y Koordinaten raus, an denen ich dann in CorelDraw die Punkte einzeichne. Die Matrizen der Würfel-Punkte sowie die Matrix der View bleiben immer gleich. Die Rotationsmatrix wird je nachdem, um welche Achse gedreht werden soll, mit 1 Grad Plus/Minus erzeugt. Funktioniert eigentlich auch ganz gut. Nur bei mir rotiert der Würfel. Ich möchte aber, dass sich die Camera/View um den Würfel bewegt. Ich habe leider immer noch nicht genau verstanden, in welcher Reihenfolge die Matrizen zu multiplizieren sind, um gewisse Ergebnisse (wie eben das Rotieren der View) zu erziehlen. Zudem bin ich mir nicht sicher, ob meine Methode zum Rückkonvertieren von 3D zu 2D einwandfrei ist.

    Wenn mir bitte die 3D-Profis unter euch die Theorie zu:
    - Reihenfolge Multiplikation Projektionsmatrizen
    - Konvertieren 3D-Matrix zu 2D-Vektor
    erklären, oder mir gute Internetseiten/Referenzen empfehlen könnten, wäre ich sehr dankbar. Bitte wenn möglich ohne Mathematik-Kauderwelsch wie auf Wikipedia (de.wikipedia.org/wiki/Projektionsmatrix). Sprache wäre gleich, solange: de, en, it;

    Ich möchte die Theorie dahinter verstehen, nicht, wie ich es umsetzen muss.

    ps: sorry, wusste nicht wo ich dieses Thema am Besten hinpacken sollte: andere Programmiersprachen, Smalltalk, (Expertenrunde ist nur GM bezogen). Einfach verschieben, wenns nicht passt.
    "Es gibt nie ein glückliches Ende, denn es endet nichts." - Schmendrick
  • Ich habe unlängst einmal einen kleinen Software-Renderer geschrieben, der auf SDL basiert. Er kann nichts besonderes, nur Wireframe-Objekte darstellen, nicht einmal Culling habe ich eingabaut. ^^
    Die Theorie habe ich aus diesem Buch gelernt (wirklich zu empfehlen), aber diese Artikelreihe sollte für dich reichen.

    Btw: Wenn du die View um den Würfel drehen willst, musst du logischerweise deine Viewmatrix ändern.

    © 2008 by Teamgrill Productions
  • Vielen Dank für die schnelle Antwort!
    Ich werde mir Deine Referenzen auf jeden Fall mal genauer anschauen. :thumbsup:

    Zum Rotationsproblem:
    Ich rotiere ja die View-Matrix (glaub ich zumindest ?( ). Zum Start meiner Engine generiere ich mir eine View-Matrix, die einzelnen Matrizen für die Objektpunkte und eine Default-Rotations-Matrix. Eine Welt-Matrix hab ich mir mal gespart, da das Objekt in der Welt ja nicht geändert wird. Mit jeder Änderung des Betrachtungswinkels wird die Rotations-Matrix erneuert. Dann multipliziere ich die View-Matrix mit der Rotations-Matrix und ersetze damit die alte View-Matrix. Diese neue View-Matrix multipliziere ich dann mit den einzelnen Punkten des Würfels. Der Würfel rotiert einwandfrei, nur sieht man auch ganz deutlich, dass dieser um seine Achsen rotiert, und nicht um die Achse der View.
    "Es gibt nie ein glückliches Ende, denn es endet nichts." - Schmendrick
  • Ich würde die ganze Projektion wie folgt machen. So ist es meiner Meinung nach am einfachsten zu verstehen und man umgeht homogene Koordinaten.

    Zunächst mal sei die Kamera gegeben durch ihre Position und ihre Orientierung . Letztere ist eine Rotationsmatrix, die wie folgt zu interpretieren ist. Rotationsmatrizen sind ja bekanntlich orthogonale Matrizen, d.h. ihre Spaltenvektoren haben die Länge 1 und stehen jeweils senkrecht aufeinander. Der erste Spaltenvektor zeige dabei von der Blickrichtung der Kamera aus gesehen nach links, der zweite nach oben und der dritte in Blickrichtung. Durch p und O ist die Kamera also vollständig beschrieben. Will man die Kamera verschieben, muss man nur p verändern, will man sie drehen, multipliziert man einfach eine entsprechende Rotationsmatrix auf O.

    Nun zur eigentlichen Projektion. Will man nun für einen gegebenen Punkt wissen, welche Koordinaten er bezüglich der oben beschriebenen Kamera auf dem Bildschirm hat, geht man wie folgt vor. Man sucht einen Vektor , sodass gilt. Umgestellt erhält man , da die Inverse einer orthogonalen Matrix gleich ihrer transponierten ist. Hat man nun den Vektor berechnet, so ist der gesuchte Punkt auf dem Bildschirm, wobei (0,0) dem Mittelpunkt des Bildschirms entspricht. Man beachte, dass sich der Punkt x hinter der Kamera befindet, also nicht sichtbar ist, falls gilt. Je nach Aufnahmewinkel der Kamera muss man den Punkt auf dem Bildschirm noch skalieren. Hat man beispielsweise horizontal einen Aufnahmewinkel von 90° gewählt (also je 45° nach links und rechts), so entspricht die x-Koordinate 1 dem linken Bildschirmrand und -1 dem rechten Bildschirmrand.

    Wenn du nun beispielsweise einen gedrehten Würfel projizieren willst und x eine Ecke des ungedrehten Würfels ist, musst du x einfach noch mit der entsprechenden Rotationsmatrix multiplizieren (weißt du sicher). Dadurch wird der Punkt um den Koordinatenursprung gedreht. Willst du den Würfel um einen anderen Punkt drehen, musst du ihn erst verschieben, dann rotieren und anschließend wieder zurück verschieben.

    Eventuell hilft dir diese Erklärung weiter, da es meiner Meinung nach mit der Projektionsmatrix und den homogenen Koordinaten erst mal schwieriger zu verstehen ist.
  • Ohje! Ich glaub ich muss noch viel lernen... :S

    Also:
    p müsste ein stinknormaler Vektor/Punkt im 3dimensionalem Raum sein: p(x, y, z), richtig?

    Schwieriger wirds jetzt mit der Rotations-Matrix. x nach links -> -1; y nach oben -> 1; z zur Kamera -> (px, py, pz)

    -1 0 px
    0 1 py
    0 0 pz


    Aber orthogonal bzw. senkrecht zueinander heißt ja: Vektor1 * Vektor2 = 0, Vektor1 * Vektor3 = 0, Vektor2 * Vektor3 = 0; also kann das ja mal nicht stimmen... :huh:

    Den Rest glaub ich mehr oder weniger verstanden zu haben:
    y ist dann quasi der rotierte Punkt x in Entfernung zur Kamera p, nicht? -> Rotationsmatrix * Vektorsubtraktion(x, p)
    y3 wäre die z-Koordinate vom Bildschirm, welche mir eigentlich "nur" die Entfernung in den Bildschirm hinein, bzw. aus dem Bildschirm heraus angibt.

    Achja:

    Bl@ckSp@rk schrieb:

    die Inverse einer orthogonalen Matrix gleich ihrer transponierten
    Schon wieder was gelernt 8)

    Bl@ckSp@rk schrieb:

    Wenn du nun beispielsweise einen gedrehten Würfel projizieren willst
    Ich glaub da hast du mich falsch verstanden: genau das will ich nicht. Das funktioniert schon... Ich möchte den Würfel im Weltkoordinatensystem fixiert lassen und nur die Kamera außen herum drehen. Bei mir rotiert der Würfel um seine eigene Achse (rote punktierte Linie im Bild). Ich möchte aber, dass er um die Bildschirm Z Achse (grüner Punkt mitten im Bild) rotiert.
    Ich habe des öfteren gelesen, dass die Reihenfolge bei Matrix-Multiplikationen eine Rolle spielt, also A*B <> B*A. Demach wird (A*B)*C <> (A*C)*B sein, oder? Momentan hab ichs ja so:
    View = View * Rotate
    und dann
    Punkt2D = Punkt3D * View
    Mein größtes Problem ist zu verstehen, in welcher Reihenfolge die einzelnen Matrizen miteinander multipliziert werden müssen (und warum genau in dieser Reihenfolge?), um die Rotation der View zu erzeugen (sofern dies überhaupt so möglich ist)
    Bilder
    • Unbenannt-1.png

      13,61 kB, 496×422, 351 mal angesehen
    "Es gibt nie ein glückliches Ende, denn es endet nichts." - Schmendrick
  • Da habe ich meine Erklärungen vielleicht doch etwas zu knapp gehalten.

    p müsste ein stinknormaler Vektor/Punkt im 3dimensionalem Raum sein: p(x, y, z), richtig?

    Richtig.

    Aber orthogonal bzw. senkrecht zueinander heißt ja: Vektor1 * Vektor2 = 0, Vektor1 * Vektor3 = 0, Vektor2 * Vektor3 = 0; also kann das ja mal nicht stimmen... :huh:

    Genau, die Matrix stimmt so nicht. Hier nochmal im Detail wie sie aussehen muss:



    Hierbei zeigt der erste Spaltenvektor von der Kamera aus gesehen nach links. Dies entspricht dem x in der Grafik unten. Um genau zu sein zeigt er in der Grafik nach rechts. Es ist eigentlich auch völlig egal ob nach links oder rechts, man sollte sich nur auf eine Richtung festlegen. Je nach dem kehrt sich dann die Bildschirmkoordinate in x-Richtung um. Der zweite Spaltenvektor zeigt nach oben, was in der Grafik dem y entspricht. Auch hier könnte man den Vektor auch nach unten zeigen lassen, womit sich die y-Koordinate am Bildschirm umkehrt. Der letzte Spaltenvektor zeigt in Blickrichtung (Bildschirm z-Achse), entspricht also dem z in der Grafik.

    Setzt man die Matrix zu Beginn z.B. auf die Einheitsmatrix



    dann "liegt" die Kamera auf der x-y-Ebene (oder einer parallelen Ebene dazu, wenn die Kamera verschoben ist) und schaut nach oben parallel zur z-Achse.


    (Die Achsen sollen hier dem lokalen Koordinatensystem der Kamera entsprechen.)



    y3 wäre die z-Koordinate vom Bildschirm, welche mir eigentlich "nur" die Entfernung in den Bildschirm hinein, bzw. aus dem Bildschirm heraus angibt.

    Richtig. Deshalb lässt sich damit auch so schön prüfen, ob der Punkt vor oder hinter der Kamera ist.

    Bei mir rotiert der Würfel um seine eigene Achse (rote punktierte Linie im Bild). Ich möchte aber, dass er um die Bildschirm Z Achse (grüner Punkt mitten im Bild) rotiert.

    Ok, da habe ich dich tatsächlich falsch verstanden.

    Also um es anders auszudrücken: Du willst den Würfel um die Achse drehen, in die der dritte Spaltenvektor der Matrix O zeigt, der ja, wie oben nochmal erklärt, in die Blickrichtung der Kamera zeigt. Dazu baut man sich zunächst mal eine Rotationsmatrix, die eine Drehung um eine bestimmte Achse und einen bestimmten Winkel durchführt. Auf Wikipedia ist diese Matrix direkt angegeben und man muss nur noch seine Werte einsetzen: de.wikipedia.org/wiki/Rotation…trizen_des_Raumes_R.C2.B3. Dort ist von einem Einheitsvektor n die Rede. Für diesen setzt du wie gesagt einfach den letzten Spaltenvektor von O ein. Den Winkel kannst du natürlich frei wählen.

    Die erstellte Rotationsmatrix musst du jetzt nur noch auf die Eckpunkte deines Würfels multiplizieren um diese wie gewünscht zu drehen. Wenn die Drehachse durch den Mittelpunkt des Würfels gehen soll, musst du diesen natürlich vorher in den Ursprung verschieben und nach der Drehung wieder zurück.

    Ich habe des öfteren gelesen, dass die Reihenfolge bei Matrix-Multiplikationen eine Rolle spielt, also A*B <> B*A. Demach wird (A*B)*C <> (A*C)*B sein, oder?

    Ja, das ist richtig. Matrixmultiplikation ist im Allgemeinen nicht kommutativ. Wenn du die Kameramatrix O drehen willst solltest du die Rotationsmatrix von links multiplizieren. Der Grund ist, dass du ja auch einen einzelnen Punkt im Raum drehst, indem du eine Rotationsmatrix von links dranmultiplizierst. Und die Matrix O besteht im Grunde aus drei solchen Punkten, die gedreht werden sollen, nämlich den Spaltenvektoren.


    Ich hoffe ich habe nochmal ein bisschen Klarheit verschafft. Ansonsten einfach fragen.