glTranslate, wie genau funktioniert es?

7

Ich habe einige Probleme zu verstehen, wie glTranslate funktioniert. Zuerst dachte ich, es würde einfach Werte zur Achse hinzufügen, um die Transformation durchzuführen.

Dann habe ich jedoch zwei Objekte erstellt, die Bitmaps laden würden, eines hat die Matrix auf GL_TEXTURE gesetzt:

public class Background
{
    float[] vertices = new float[]
        { 0f, -1f, 0.0f, 
          4f, -1f, 0.0f, 
          0f, 1f, 0.0f, 
          4f, 1f, 0.0f };

    ....
    private float backgroundScrolled = 0;
    public void scrollBackground(GL10 gl)
    {
        gl.glLoadIdentity();
        gl.glMatrixMode(GL10.GL_MODELVIEW);
        gl.glTranslatef(0f, 0f, 0f);
        gl.glPushMatrix();

        gl.glLoadIdentity();
        gl.glMatrixMode(GL10.GL_TEXTURE);
        gl.glTranslatef(backgroundScrolled, 0.0f, 0.0f);
        gl.glPushMatrix();

        this.draw(gl);
        gl.glPopMatrix();

        backgroundScrolled += 0.01f;
        gl.glLoadIdentity();
    }
}

und noch eine zu GL_MODELVIEW:

public class Box
{
    float[] vertices = new float[]
        { 0.5f, 0f, 0.0f, 
          1f, 0f, 0.0f, 
          0.5f, 0.5f, 0.0f, 
          1f, 0.5f, 0.0f };

    ....

    private float boxScrolled = 0;
    public void scrollBackground(GL10 gl)
    {
        gl.glMatrixMode(GL10.GL_MODELVIEW);
        gl.glLoadIdentity();
        gl.glTranslatef(0f, 0f, 0f);
        gl.glPushMatrix();

        gl.glMatrixMode(GL10.GL_MODELVIEW);
        gl.glLoadIdentity();
        gl.glTranslatef(boxScrolled, 0.0f, 0.0f);
        gl.glPushMatrix();

        this.draw(gl);
        gl.glPopMatrix();

        boxScrolled+= 0.01f;
        gl.glLoadIdentity();
    }
}

Jetzt werden beide in Renderer.OnDraw gezeichnet. Der Hintergrund bewegt sich jedoch genau fünfmal schneller. Wenn ich boxScrolled mit 5 multipliziere, sind sie aufrichtig und bewegen sich zusammen. Wenn ich Hintergrundscheitelpunkte so ändere, dass sie sind

    float[] vertices = new float[]
        { 1f, -1f, 0.0f, 
          0f, -1f, 0.0f, 
          1f, 1f, 0.0f, 
          0f, 1f, 0.0f };

Es wird auch aufrichtig mit der Box sein. Also, was ist unter glTranslate los?

mykk
quelle
Vielleicht liegt das Problem an der Anzahl der von Ihnen getätigten glpush / glpop-Anrufe. Beachten Sie, dass Sie in jeder Funktion glpush zweimal und glpop nur einmal aufrufen.
Ali1S232
Nicht vielleicht, es ist sicher, OpenGL hat einen Stapel mit nur 32 Einheiten pro Matrixtyp, wenn ich mich nicht irre. Dies ermöglicht eine gewisse Rendertiefe in Ihrem Szenenbaum, jedoch nicht zu viel. Aber so sollte das Programm innerhalb einer Sekunde abstürzen :)
Grimshaw
Nun, ich denke nicht, wie ich bereits sagte, wenn ich die Eckpunkte des Hintergrunds so ändere, dass sie in der x-Achse von 0 bis 1 sind, funktioniert das einwandfrei.
Mykk
2
Ich denke, dass die zweite glPushMatrix gelöscht werden sollte. glPushMatrix ist so etwas wie ein Backup Ihrer aktuellen Matrix. Wenn Sie also drücken und nicht platzen, ist der Stapel übergelaufen ...
Zacharmarz
Und zweitens: glTranslate fügt den Koordinaten nichts hinzu. Es ändert die aktuelle Matrix (Modellansicht oder Textur in Ihrem Fall). Die Modelview-Matrix wird zum Multiplizieren der Scheitelpunktkoordinaten und die Texturmatrix zum Multiplizieren der Texturkoordinaten verwendet.
Zacharmarz

Antworten:

5

Hier ist meine vollständige Antwort:

Ihre glPushMatrix- und glPopMatrix-Anzahl sollte gleich sein. Es ist das erste Problem.

Das Hauptproblem liegt jedoch im Matrixmodus. Im ersten Fall (Hintergrund) verwenden Sie eine Texturmatrix, die von glTranslate geändert wird. Dies bedeutet, dass in jedem Schritt Texturkoordinaten mit dieser Übersetzung multipliziert werden.

Da die Texturkoordinaten im Bereich <0,1> liegen und Ihr Hintergrundrechteck 4 Einheiten breit ist, wird es nicht in jedem Frame um 0,01 , sondern in der Welt um 0,04 Einheiten übersetzt .

Im zweiten Fall (Feld) ändern Sie die Modellansichtsmatrix. Dadurch wird Ihre Box in jedem Frame der Welt um 0,01 Einheiten verschoben.

Wenn Sie das Hintergrundrechteck in neue Koordinaten ändern (x-Koordinaten sind 0 und 1), werden alle Rahmentexturkoordinaten tatsächlich um 0,01 Einheiten übersetzt.

zacharmarz
quelle
Vielen Dank! Ich habe es nach Ihren Kommentaren irgendwie herausgefunden und jetzt ist es viel klarer
mykk
(Ich möchte nur hinzufügen, dass der Hintergrund 5 Einheiten breit ist)
Mykk
6

glTranslatef

glTranslatefübersetzt (ein Sonderfall des "Transformierens") die Matrix, die dem aktuell ausgewählten Matrixmodus entspricht. Wenn Sie es also nachher aufrufen, glMatrixMode(GL_MODELVIEW)transformieren Sie die Modellansichtsmatrix und nachdem glMatrixMode(GL_TEXTURE)Sie die Texturmatrix transformiert haben. Weitere Informationen hierzu finden Sie im Wikipedia-Artikel zu Übersetzungsmatrizen .

Die Modellansichtsmatrix wird auf Objektkoordinaten angewendet, um Augenkoordinaten zu erhalten, was bedeutet, dass absolute Weltkoordinaten in Koordinaten relativ zur "Kamera" transformiert werden. (Bevor das Objekt tatsächlich gerendert wird, werden seine Koordinaten einige zusätzliche Male transformiert. Einzelheiten zu Transformationen finden Sie in den OpenGL-FAQ , sind aber derzeit nicht wichtig.)

Die Texturmatrix macht etwas völlig anderes, sie wird auf Texturkoordinaten angewendet, bevor sie zugeordnet werden. Mit dieser Funktion können Sie einen Textureffekt zum Scrollen, Drehen, Skalieren oder Perspektivverzerren erzielen.

Hoffentlich werden Sie jetzt sehen, dass diese beiden Matrizen nicht so austauschbar sind, wie Sie denken. Sie werden in verschiedenen Phasen des Renderprozesses angewendet. Wenn die Ergebnisse der Transformation beider Matrizen auf Ihrem Bildschirm ausgerichtet sind, ist dies ein reiner Zufall, der unter anderem auch von den Positionen und Texturkoordinaten Ihrer Objekte abhängt.

Einige kleinere zusätzliche Bemerkungen

Dann sagen die Kommentatoren zu Recht, dass Sie Ihre Anrufe ausgleichen sollten glPush/PopMatrix. Ohne den Rest Ihres Codes zu sehen und zu wissen, welche anderen Objekte gerendert werden, ist es schwer zu sagen, aber es ist möglich, dass ein Teil des Effekts, den Sie erleben (die Skalierung der Übersetzung um den Faktor 5), auf die Modellansicht zurückzuführen ist Die Matrix für ein Objekt wird fälschlicherweise auf ein anderes Objekt angewendet, da es sich noch auf dem Matrixstapel befindet.

Außerdem:

  • Das Aufrufen glMatrixModenacheinander mit denselben Argumenten ändert nichts, da der OpenGL-Status unverändert bleibt.
  • glLoadIdentityLädt die Identitätsmatrix: Eine Matrix, die genau die Koordinaten zurückgibt, auf die sie angewendet wurde. Es könnte als "Zurücksetzen" der aktuellen Matrix angesehen werden. Ein mehrmaliger Aufruf hat keine Auswirkung (es sei denn, Sie tun etwas mit der aktuellen Matrix dazwischen).
  • glTranslatef(0f, 0f, 0f) wird keine Wirkung haben.
Eric
quelle
1

Was genau macht glTranslate? Zunächst wird eine Übersetzungsmatrix berechnet - dies ist nur eine Identitätsmatrix mit den Übersetzungswerten in den Slots 3 (für x), 7 (für y) und 11 (für z) (unter der Annahme eines Spaltenmajors). Dann multipliziert es die aktuelle Matrix mit dieser Übersetzungsmatrix, um eine neue Matrix zu erhalten, durch die es dann die aktuelle Matrix ersetzt. Das ist es im Grunde.

Maximus Minimus
quelle