3D->2D Perspektive erhalten



  • Hallo Forum,
    ich habe eine 3D Punktewolke und möchte diese als 2D Abbildung aus verschiedenen Betrachtungswinkeln darstellen. Um dies zu erreichen verwende ich die homologen Koordinaten für Rotation, Translation und Skalierung. Im Ergebnis bekomme ich damit eine schöne isometrische Abbildung meiner Punktewolke – allerdings ohne Tiefe. Im folgenden ist Rotation eine Funktion, die um alle 3 Achsen eine 3x3 Rotationsmatrix entsprechend der Winkel ThetaX, ThetaY und ThetaZ zurück liefert. Scale ist ebenfalls eine 3x3 Matrix in deren Diagonale die Skalierungsfaktoren stehen. TM ist die 4x4 Homogene Abbildungsmatrix und POINT der 3D Punkt in homogenen Koordinaten.

    
      Sigma = Rotation(ThetaX, ThetaY, ThetaZ)*Scale;  
    
             | sigma11 sigma12 sigma13 0 |
        TM = | sigma21 sigma22 sigma23 0 |
             | sigma31 sigma32 sigma33 0 |
             | px      py      pz      1 |
        TP = TM*POINT;
    
    
    

    Aus TP habe ich dann die Bildschirmkoordinaten an der Kameraposition folgendermaßen berechnet:

    X = TP[0,0]/TP[3,0];
    Y = TP[1,0]/TP[3,0];

    Solange man keine perspektivische Verzerrung einbaut (px = py = pz = 0) funktioniert das Ganze auch, aber wenn man auch eine Bildtiefe in z.B. Z Richtung (pz != 0) hinzufügt, kann man die Punktewolke schon nicht mehr rotieren lassen, da sich die Verzerrung dann einfach mit dreht und letztere damit keinen Sinn mehr ergibt. Ich würde mich daher sehr freuen, wenn mir jemand einen Tipp geben könnte, wie ich das durch POINT definierte Objekt rotieren lassen kann, ohne dass sich die perspektivisch Verzerrung mit dreht.

    (Falls hier im Forum das Thema schon gelöst wurde, würde ich mich auch über einen Hinweis auf den entsprechenden Thread freuen).



  • Hallo Forum,
    die Lösung für mein Problem geht folgendermaßen:

    1. 3D Punkte rotieren und skalieren
      P‘ = Sigma*P;
    2. fertig rotierte und skalierte Punkte in homogene Koordinaten konvertieren
      HP[0] = P‘[0];
      HP[1] = P‘[1];
      HP[2] = P‘[2];
      HP[3] = 1;
    3. Mit der homogenen Transformationsmatrix TM nur noch die perspektivische Verzerrung durchführen – je nach Fluchtpunkt FP:
                 | 1     0   0  0 |                               
            HM = | 0     1   0  0 |
                 | 0     0   1  0 |
                 | FPx  FPy FPz 1 |
    
    

    HP‘ = HM*HP;
    4. Aus den homogenen Koordinaten nach 2D projizieren:

    X = HP‘[0]/HP‘[3];
    Y = HP‘[1]/HP‘[3];


  • |  Mod

    die stichwoerter die du fuer die suchmaschine suchst ist 3D transformation pipeline, z.B.
    https://docs.microsoft.com/en-us/windows/desktop/dxtecharts/the-direct3d-transformation-pipeline
    http://www.songho.ca/opengl/gl_transform.html

    im prinzip hast du dir das schon ararbeitet, man setzt verschiedene matrizen auf die nacheinander angewendet werden koennen. Im einfachsten fall hast du eine projektionsmatrix, oft auch eine camera matrix die das objekt inverse zur kamera transformiert, wenn du mehrere objekte hast, dann kommen object/world matrizen pro objekt hinzu.
    nach dieser eigentlichen pipeline gibt es noch implizit die screen/view/... transformation die die koordinaten vom sichtkegel (-1 bis +1 ) in pixelkoordinaten transformiert.

    Falls du viele punkte transformieren moechtest, macht es sinn erstmal alle matrizen der pipeline zu einer zu multiplizieren und dann jeden punkt nur noch mit dieser einen zu multiplizieren.

    Bei der perspektiwischen projektion musst du zudem, vor dem dividieren durch w, eventuel alle primitiven die ins negative fallen clippen.

    Ein kleines detail ist zudem wie gaengierweise die projektionsmatrix aufgesetzt wird, um divisionen durch 0 zu vermeiden und auch um eine bessere verteilung im depthbuffer zu erhalten, nutzt man eine near und far plane als tiefenbegrenzung, damit ist die projektionsmatrix dann etwas anders als du sie aufsetzt.