glTranslate、正確にはどのように機能しますか?


7

glTranslateがどのように機能するのか理解できません。最初は、単に軸に値を追加して変換を行うだけだと思っていました。

ただし、ビットマップをロードする2つのオブジェクトを作成しました。1つはGL_TEXTUREに設定された行列を持っています。

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();
    }
}

GL_MODELVIEWにもう1つ:

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();
    }
}

これで、どちらもRenderer.OnDrawで描画されます。ただし、背景は正確に5倍速く移動します。私がboxScrolledを5倍すると、それらはsincになり、一緒に動きます。背景の頂点を次のように変更した場合

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

また、箱と一緒になります。では、glTranslateで何が行われているのでしょうか。


多分問題はあなたが行うglpush / glpop呼び出しの数にあります。すべての関数で、glpushを2回、glpopを1回だけ呼び出していることに注意してください。
Ali1S232

おそらく間違いなく、OpenGLのスタックには、マトリックスのタイプごとに32ユニットしかありません。これにより、シーンツリーである程度のレンダリング深度が可能になりますが、多すぎません。しかし、そのように、プログラムは1秒以内にクラッシュします:)
Grimshaw

まあ、私はそうは思わない、私が言ったように、背景の頂点をx軸で0から1に変更した場合、それはうまく機能します。
mykk

2
2番目のglPushMatrixは削除する必要があると思います。glPushMatrixは、現在のマトリックスのバックアップのようなものです。したがって、プッシュしていてポップしていない場合、スタックはオーバーフローします...
zacharmarz

そして2番目のこと:glTranslateは座標に何かを追加していません。現在の行列(モデルビューまたはテクスチャ)が変化しています。Modelview行列は頂点座標を乗算するために使用され、Texture行列はテクスチャ座標を乗算するために使用されます。
zacharmarz

回答:


5

これが私の完全な答えです:

glPushMatrixとglPopMatrixの数は等しくなければなりません。それが最初の問題です。

しかし、主な問題はマトリックスモードです。最初のケース(バックグラウンド)では、glTranslateによって変更されたテクスチャマトリックスを使用しています。つまり、すべてのステップでテクスチャ座標にこの変換が乗算されます。

テクスチャ座標は<0,1>の範囲にあり、背景の長方形は4単位の幅があるため、フレームごとに0.01ずつ変換されるのではなく、世界では0.04単位だけ変換されます。

2番目のケース(ボックス)では、モデルビューマトリックスを変更します。これにより、世界のフレームごとに0.01単位でボックスが変換されます。

背景の長方形を新しい座標(x座標は0と1)に変更すると、すべてのフレームテクスチャ座標は実際には0.01単位だけ変換されます。


ありがとうございました!私はあなたのコメントの後でそれをちょっと考えました、そして今、それははるかに明確です
mykk

(背景を5ユニット幅で追加したいだけです)
mykk

6

glTranslatef

glTranslatef現在選択されているマトリックスモードに対応するマトリックスを変換します(「変換」の特別な場合)。したがって、後で呼び出すとglMatrixMode(GL_MODELVIEW)は、モデルビューマトリックスglMatrixMode(GL_TEXTURE)を変換した後、テクスチャマトリックスを変換した後であるということです。これについて詳しくは、翻訳マトリックスに関するウィキペディアの記事を参照してください。

モデルビュー行列は、絶対的な世界座標は「カメラ」からの相対座標に変換される手段眼座標を取得するオブジェクトの座標に適用されます。(オブジェクトが実際にレンダリングされる前に、座標が余分に何度も変換されます。変換に関する詳細はOpenGL FAQにありますが、現時点では重要ではありません。)

テクスチャ行列は、それらがマップされる前に、それはテクスチャ座標に適用され、完全に異なる何かをします。これを使用すると、スクロール、回転、スケーリング、または遠近法ワープテクスチャ効果を実現できます。

うまくいけば、これらの2つの行列は、あなたが思っている方法では交換できないことがわかります。これらは、レンダリングプロセスのさまざまな段階で適用されます。両方の行列を変換した結果が画面上に並ぶ場合、それは純粋に偶然の一致であり、とりわけオブジェクトの位置やテクスチャ座標にも依存していました。

いくつかのちょっとした補足

次に、別のことを言うと、コメンターは、への呼び出しのバランスをとるべきだと言っていますglPush/PopMatrix。コードの残りの部分を表示せず、レンダリングされている他のオブジェクトを把握していないと、それを判別することは困難ですが、発生している効果の一部(5倍の変換スケーリング)がモデルビューに起因している可能性がありますオブジェクトがまだマトリックススタック上にあるため、あるオブジェクトのマトリックスが別のオブジェクトに誤って適用されています。

さらに:

  • glMatrixMode同じ引数で連続して呼び出しても、OpenGLの状態は同じであるため、何も変更されません。
  • glLoadIdentity単位行列をロードします。これは、適用されたものとまったく同じ座標を返す行列です。これは、現在の行列の「リセット」と見なすことができます。複数回呼び出しても効果はありません(間にある現在のマトリックスに対して何かを実行しない限り)。
  • glTranslatef(0f, 0f, 0f) 効果はありません。

1

glTranslateは正確には何をしますか?まず最初に、それは平行移動行列を計算します-これは、スロット3(xの場合)、7(yの場合)、および11(zの場合)の平行移動値を持つ同一行列です(列優先と仮定)。次に、現在の行列にこの変換行列を乗算して新しい行列を取得し、それを現在の行列に置き換えます。基本的にはそれだけです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.