2011-08-11 8 views
9

オンラインで画面を横切ってボックスを移動し、ボックスが画面の最後に当たった後にリセットするコードをオンラインで見つけました。ここで
コードです:今glPushMatrix()とglPopMatrix()はどのようにシーンを同じに保ちますか?

void display(void) { 
    int sign = 1; 
    if (lastFrameTime == 0) { 
    /* 
    * sets lastFrameTime to be the number of milliseconds since 
    * Init() was called; 
    */ 
    lastFrameTime = glutGet(GLUT_ELAPSED_TIME); 
    } 

    int now = glutGet(GLUT_ELAPSED_TIME); 
    int elapsedMilliseconds = now - lastFrameTime; 
    float elapsedTime = float(elapsedMilliseconds)/1000.0f; 
    lastFrameTime = now; 

    int windowWidth = glutGet(GLUT_WINDOW_WIDTH); 

    if (boxX > windowWidth) { 
    boxX -= windowWidth; 
    } 
    boxX += (sign)*256.0f * elapsedTime; 

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

    glPushMatrix(); 
    //creates a new matrix at the top that we can do things to? 
    glTranslatef(boxX, 0.0f, 0.0f); 

    /* 
    * draw a "quad" (rectangle) 
    */ 
    glBegin(GL_QUADS); 
    glVertex2f(0.0f, 0.0f); 
    glVertex2f(128.0f, 0.0f); 
    glVertex2f(128.0f, 128.0f); 
    glVertex2f(0.0f, 128.0f); 
    glEnd(); 
    glPopMatrix(); 
    //pops that matrix off the stack so we can have a "clean" version to do something next time.? 

    glutSwapBuffers(); 
} 

した後、あなたがそれを開くように、私はglPushMatrix()glPopMatrix()を理解する方法は、スタック上glPushMatrix()プット(またはプッシュ)新しい行列は、あなたが物事を行うためということですあなたはもう一度 "きれいな"スレートを持っています。これは、の後にglPopMatrix()を無視すると、私の四角形は一定の速度で動くのではなく、加速するように見えます。

しかし、私がglPushMatrix()glPopMatrix()の内部で行った変更はどのように保たれていますか? glPushMatrix()を使用してトップマトリックスを変更すると、変更が視覚化されますが、glPopMatrix()を使用すると、それらの変更はすべて終了していませんか?私が「クリーン」スレートに再び復元されたとき、私のボックスは画面上をどのように動きますか?

変更を加えた後にマトリックスをもう一度ポップすると、その翻訳の状態はどのように記録されますか?

+7

ところで。あなたは、減価償却されたコードを読んでOpenGLを学んでいることを知っていますか? PushMatrixとPopMatrixはOpenGL 3.0では廃止されているためです。 http://www.opengl.org/registry/doc/glspec30.20080923.pdf(406ページ) あなたの描画方法(begin; vertex; end)も廃止予定です。それは実際にそれを行う最悪の方法です。 私は問題を指摘していますが、私はそれらのための良い解決策を持っていません。 OpenGL 3.1チュートリアルのためにgoogleを試してみてください。良いOpenGL ESのチュートリアルを見つけることさえできます。 OpenGLを学習し始めたばかりの方は、きれいな方法でOpenGLを学んでみてください。 – petraszd

+0

@petraszd:問題は、古いスタイルを使ってOpenGLを教える多くのリソースがあるということです。 NeHeなどのリソースがアップグレードされるまで、これらの問題に対するソリューションを提供する必要があります。 –

+0

@ミハイ:NeHeはかなり死んでいる(アップデートしていない)ので、アップグレードするつもりはない。 –

答えて

5

これは、座標を変換するために使用される行列で、glPopMatrixによって復元されます。フレームバッファ全体ではありません。フレームバッファには四辺形のレンダリングが含まれ、後でマトリックスを変更してもレンダリングされたものには影響しません。

+0

だから、マトリックスは毎回フレームバッファに影響しますか?したがって、行列をプッシュするとフレームバッファが変更されますが、ポップバックするとフレームバッファは既に変更されていますので、私の行列としてのアイデンティティがあるかどうかは関係ありません。 – drjrm3

+0

@Laurbert: 'glPushMatrix'は何も変更しません。後で呼び出すことができるように、現在の行列のコピーを保存するだけです。ジオメトリをレンダリングすると、現在の行列が使用され、ピクセル値がフレームバッファ内で変更されます。後で何らかの理由でマトリックスが変更された場合、既に描画されているものには影響しません。 –

29

glPushMatrixはスタックの上にマトリックスを複製します(あなたは常に上位のものを扱っています)。あなたが行っている他の変換は、このトップマトリックス、複製されたものを変更します。 glPopMatrixを実行すると元のマトリックスに戻ります。

たとえば、車を描いたとします。あなたは車のボディを描くために行列を設定します、それをM1と呼ぶことにしましょう。今、あなたは1つの車輪を描きたいと思う。 M2 - ホイールが正しく表示されるために必要なマトリックスを計算するか、車輪が車のボディと相対的であるため(M3のようなM2 = M1 * M3の行列があります)、M1を修正します。しかし車には4つの車輪があります。M1のコピーを保管する必要があります。これを行うにはglPushMatrixを実行し、glPopMatrixを実行してコピーを取り戻します。あなたは、画面上で何かを描くと

glPushMatrix and glPopMatrix

、あなたはオブジェクト空間の座標を与えています。実際に何かを表示するには、それらの座標を変換する必要があります。そのためにいくつかの行列があります。

ホイールの例では、ホイールのジオメトリは1つだけですが、異なるマトリックスを使用しているため、4つのホイールが描画されます。 glPushMatrixglPopMatrixはマトリックスでのみ動作し、実際の頂点データはGPUに保持され、各glVertexはそこに別のデータを送り、削除することはできません。次の画像を参照して、マトリックスはオブジェクトのみを変換するために使用されているが(実際には、すべてのマトリックスをスタックに押し込むことができる)世界座標

multiple matrices

+0

ありがとう、私はglPushMatrix()とglPopMatrix()が今どのように動作するのかをよく理解していますが、私の質問は - 私たちが行列をポップした場合、ホイール(あなたの例では) M1を取得するには? 私のコードでは、私はプッシュ、翻訳、ポップ...しかし、以前のすべての翻訳が記録されています(ボックスが画面を横切って移動しているので)。私がプッシュ、翻訳、そしてポップしたら、元のマトリックスに戻ります(したがって、何も起こらなかったはずです)。 – drjrm3

+0

詳細情報を追加しました。 –

+0

@ Laurbert515時間が経過するにつれてボックス変換が常に増加するので、なぜ画面上を移動しないのですか?また、OpenGLはオブジェクトの何も知らないことに注意してください。これはdraw呼び出しを行う瞬間に頂点を描画します(あなたの場合は 'glVertex')。そしてそれらについて忘れてしまいます。ですから、行列の変換を変更して他のものを描くことができます。 –

6

OpenGLは、描画APIであるに配位。描画関数を呼び出すと、描画呼び出しを発行した瞬間に事実がフレームバッファに描画されます。実際には、OpenGLはすべてのコマンドを内部的にバッチして順番に処理します。しかし、OpenGLがそれらの描画呼び出しを処理しようとしているときには、バッチ内のこの特定の位置にある状態に設定された行列を使ってフレームバッファに描画します。

これをもう一度言い換えると、OpenGLはシーン管理を何もしません。フレームバッファに描画コマンドを発行する順序と方法で描画します。あなたは三角形を送ります:OpenGLは変換して描画します。内部にはシーンがありません。これを理解すると、マトリックススタックがその「魔法」をどのように果たすことができるかを理解することは自明になります。

+0

+1もう一度完全に明確な "それは描画APIです" - 返信です。あなたからの2番目の答えがこのようなものでなければならないのは残念です。たぶんこれらのチュートリアルや書籍は、これをより明確に述べるべきです。 –

関連する問題