Neue Ebenengleichung aus Modelmatrix errechnen



  • Hallo,
    ich habe die Ebenengleichung z = 0 in meinem Programm als Vektor(0, 0, 1, 0) dargestellt.
    Nun möchte ich diese Ebene transformieren. Dazu habe ich folgendes versucht:

    neueEbene = modelMatrix * alteEbene;
    

    Das funktioniert jedoch nicht ganz, da wenn die Modelmatrix in z-Richtung um eine Einheit translatiere so aussieht (anfänglich ist es eine Identitätsmatrix):

    1 0 0 0
    0 1 0 0
    0 0 1 1
    0 0 0 1
    

    Diese Information geht nun aber mit der Multiplikation meines Ebenenvektors verloren, was jedoch nicht mein Ziel war.
    Nun stellt sich mir also die Frage wie ich Ebenen korrekt mit Matrizen transformiere.

    Vielen Dank schonmal im Voraus 🙂



  • Wenn du den Normalenvektor deiner Ebene in homogenen Koordinaten darstellen willst, dann muss die letzte Komponente eine 1 sein. Dein Normalenvektor ist also [latex](0, 0, 1, 1)^T[/latex].



  • Hmm ich habe gedacht, dass ich ich die Ebene in der Form

    nx * x + ny * y + nz * z + d = 0
    

    einfach als Vektor(nx, ny, nz, d) darstellen kann. Wenn ich jetzt nur den Normalenvektor nehme, geht mir ja das d als Information über die Position im Raum verloren. Allerdings brauche ich dieses noch.



  • Transall schrieb:

    Hmm ich habe gedacht, dass ich ich die Ebene in der Form

    nx * x + ny * y + nz * z + d = 0
    

    einfach als Vektor(nx, ny, nz, d) darstellen kann. Wenn ich jetzt nur den Normalenvektor nehme, geht mir ja das d als Information über die Position im Raum verloren. Allerdings brauche ich dieses noch.

    versuch mal (nx,ny,nz,d) als Normalenvektor...



  • Okay... kleines Missverständnis. Vergiss, was ich oben schrieb.

    Im projektivem Raum haben deine Punkte die Koordinaten q=(q_x,q_y,q_z,q_w)Tq = (q\_x, q\_y, q\_z, q\_w)^T. Du kannst also in der Tat die Punkte, die in einer Ebene liegen mit

    n,q:=(n_xq_x+n_yq_y+n_zq_z+n_wq_w)=0\langle n, q \rangle := (n\_x q\_x + n\_y q\_y + n\_z q\_z + n\_w q\_w) = 0

    beschreiben, wobei n_w=(p_xn_x+p_yn_y+p_znz)n\_w = - (p\_x n\_x + p\_y n\_y + p\_z n_z) und pp ein beliebiger Punkt in der Ebene.

    Möchtest du alle Punkte deiner Ebene mit einer affinen Transformation MM verschieben, so gilt für die verschobenen Punkte q~\tilde q der Ebene offensichtlich

    n,M1q~=0\langle n, M^{-1} \tilde q \rangle = 0

    und das ist äquivalent zu

    (M1)Tn,q~\langle \left(M^{-1}\right)^T n, \tilde q \rangle

    und damit hat die verschobene Ebene die Darstellung

    n~=(M1)Tn\tilde n = \left( M^{-1}\right)^T n .

    Du musst also mit der transponierten der inversen Matrix multiplizieren, wenn du deine Ebenendarstellung in dieser Form transformieren willst. In deinem Fall wäre das die Matrix

    [1000010000100011]\begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & -1 & 1 \end{bmatrix}

    .



  • Vielen Dank für die ausführliche Erklärung 👍
    Mein Problem ist nun gelöst und wie habe ich auch verstanden 🙂



  • Ich habe nochmal eine Matrix bezüglich der Thematik.
    An der Ebene, die ich berechne möchte ich eine Kamera spiegeln. Das ganze habe ich so gelöst:

    //transform the plane in world coordinates
    vec4 waterPlane = modelMatrix.inverse().transpose() * vec4(0.0, 0.0, 1.0, 0.0);
    //calculate reflection matrix
    mat4 mReflection = mat4
    (
      1.0 - 2.0 * waterPlane.getX() * waterPlane.getX(), -2.0 * waterPlane.getX() * waterPlane.getY(), -2.0 * waterPlane.getX() * waterPlane.getZ(), -2.0 * waterPlane.getX() * waterPlane.getL(),
      -2.0 * waterPlane.getX() * waterPlane.getY(), 1.0 - 2.0 * waterPlane.getY() * waterPlane.getY(), -2.0 * waterPlane.getY() * waterPlane.getZ(), -2.0 * waterPlane.getY() * waterPlane.getL(),
      -2.0 * waterPlane.getX() * waterPlane.getZ(), -2.0 * waterPlane.getY() * waterPlane.getZ(), 1.0 - 2.0 * waterPlane.getZ() * waterPlane.getZ(), -2.0 * waterPlane.getZ() * waterPlane.getL(),
      0.0, 0.0, 0.0, 1.0
      );
    //set new camera position
    camera.from = mReflection * camera.from;
    camera.at = mReflection * camera.at;
    camera.up = mReflection * camera.up;
    

    Das durch diese Kamera gezeichnete Textur soll mit projektiven Texturkoordinaten gezeichnet werden. Die Texturkoordinaten errechne ich so:

    vec4 mvpvertex = mvp * vec4(vertex, 1.0);
    vec4 tmp = vec4(1.0 / mvpvertex.w);
    vec4 projCoord = mvpvertex * tmp;
    projCoord += vec4(1.0);
    projCoord *= vec4(0.5);
    projCoord = clamp(projCoord, 0.0, 1.0);
    // ohne diese Zeile würde die Textur gespiegelt aussehen, woran liegt das
    projCoord.x = 1.0 - projCoord.x;
    vec2 texCoord = projCoord.xy;
    

    Das Problem mit der ganzen Sache ist nun, dass mein Code nur so lange funktioniert, solange meine modelMatrix nur Rotationen abbildet. Sobald ich z.B. die Ebene entlang der z-Achse verschieben will, sieht das Bild, welches die Kamera zeichnet total falsch aus.
    Woran liegt das? Daran, dass ich die x-Koordinate der projektiven Texturkoordinaten zurechtbiegen muss, oder habe ich irgendeinen Fehler bei der Kameraspiegelung?



  • Hallo,

    also ich verstehe nicht, wie du auf deine Reflexionsmatrix kommst. Im nicht-projektivem Fall hast du gerade

    I2nnTI - 2 n \cdot n^T

    für die Spiegelung an der Einheitsnormalen nn.

    Sei jetzt vv der Vektor, der deine Ebene beschreibt. Dann ist mit

    n~=(v_x,v_y,vz)T\tilde n = (v\_x, v\_y, v_z)^T

    der Vektor

    n=n~/n~n = \tilde n / \| \tilde n \|

    der Normalenvektor. Und

    p=nvwn~,n~p = - n \cdot \frac{v_w}{\langle \tilde n, \tilde n \rangle}

    ein Punkt in der Ebene.

    Ist jetzt TpT_p die Verschiebung Matrix, die die Verschiebung in Richtung pp beschreibt, dann ist

    T_p[I2nnT001]T_pT\_p \begin{bmatrix} I - 2 n n^T & 0 \\ 0 & 1 \end{bmatrix} T\_{-p}

    die von dir gesuchte Reflexion. Ich sehe gerade nicht, dass das äquivalent ist, zu dem, was du ausrechnest.



  • Die Berechnung der gespiegelten Punkte habe ich aus der Wikipedia
    Allerdings fällt mir erst jetzt die Notiz auf, dass diese Transformation nur dann funktioniert, wenn die Ebene durch den Ursprung geht 🙄
    Ich suche jetzt also Methode mit der ich im 3-Dimensionalen einen Punkt an jeder beliebigen Ebene spiegeln kann. Allerdings bin ich gerade leider zu müde um deine Rechnung nachzuvollziehen, dass werde ich morgen nachholen.



  • Transall schrieb:

    dass werde ich morgen nachholen.

    Ja, ich war wirklich müde 😃
    Also ich habe mir das ganze mal versucht klar zu machen und in Code zu fassen. Mein aktueller Entwurf sieht so aus (kann es im moment leider noch nicht testen):

    // Ebene berechnen
    vec4 waterPlane = modelMatrix.inverse().transpose() * vec4(0.0, 0.0, 1.0, 0.0);
    // Punkt spiegeln
    vec3 n = vec3(waterPlane.x, waterPlane.y, waterPlane.z);
    double d = waterPlane.w;
    vec3 new = old - 2 * n * ((n * old) - d);
    

    Ich hab es per Hand mal mit ein paar Werten nachgerechnet und es kam immer das richtige raus.



  • Transall schrieb:

    Ich suche jetzt also Methode mit der ich im 3-Dimensionalen einen Punkt an jeder beliebigen Ebene spiegeln kann.

    Wie ich oben beschrieben habe, kannst du einfach erst alle Punkt in den Ursprung verschieben (TpT_{-p}), dann die Reflexion durchführen und dann wieder alle Punkte zurück schieben (TpT_p).


Log in to reply