-1
#include <iostream>
#include <X11/Xlib.h>
#include <GL/glut.h>
#include <GL/glui.h>

using namespace std;

GLsizei wh = 500;
GLsizei ww = 500;

void MyInit();    
void DisplayLine(void);    
void DisplaySquare(void ); 

void MyInit()
{
    glClearColor( 1, 1, 1, 0 );
    glColor3f( 1, 0, 0 );
    glPointSize( 10 );
    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity(  );
    glOrtho( 0.0, ww, 0.0, wh, -1.0, 1.0 );
}

void DisplayLine()
{
    glClear( GL_COLOR_BUFFER_BIT );

    glBegin( GL_LINES );
        glVertex2i( 100, 100 );
        glVertex2i( 170, 170 );
        glVertex2i( 30, 370 );
        glVertex2i( 160, 50 );
    glEnd(  );

    glFlush(  );
}

void DisplaySquare()
{
    glClear( GL_COLOR_BUFFER_BIT );

    glBegin( GL_LINE_STRIP );
        glBegin( GL_POLYGON );
        glVertex2f( 150, 150 );
        glVertex2f( 350, 150 );
        glVertex2f( 350, 350 );
        glVertex2f( 150, 350 );
        glVertex2f( 150, 150 );
    glEnd(  );

    glFlush(  );
}

void DisplayRSquare()
{
    glClear( GL_COLOR_BUFFER_BIT );

#if 0
    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity(  );
    glBegin( GL_LINE_LOOP );
        glVertex2f( 50, 50 );
        glVertex2f( 250, 250 );
        glVertex2f( 50, 250 );
    glEnd(  );
#endif

    glBegin( GL_LINE_LOOP );
        glVertex2f( 0, 0 );
        glVertex2f( 500, 0 );
        glVertex2f( 500, 500 );
        glVertex2f( 0, 500 );
    glEnd(  );
    glTranslatef( 100, 0, 0 );

#if 0
    glRotatef( 20, 0, 0, 1 );
    glTranslatef( -50, -50, 0 );
    glColor3f( 0, 1, 0 );

    glBegin( GL_LINE_LOOP );
        glVertex2f( 0, 0 );
        glVertex2f( 500, 0 );
        glVertex2f( 500, 500 );
        glVertex2f( 0, 500 );
    glEnd(  );

    glBegin( GL_LINE_LOOP );
        glVertex2f( 50, 50 );
        glVertex2f( 250, 50 );
        glVertex2f( 250, 250 );
        glVertex2f( 50, 250 );
    glEnd(  );

    glRotatef( 12, 0, 0, 1 );
    glBegin( GL_LINE_LOOP );
        glVertex2f( 75, 75 );
        glVertex2f( 75, 550 );
        glVertex2f( 550, 550 );
        glVertex2f( 550, 75 );
    glEnd(  );

    glFlush(  );
    glBegin( GL_LINES );
        glVertex2f( 0, 0 );
        glVertex2f( 150, 150 );
    glEnd()
#endif

    glFlush(  );
}

void DisplayCube()
{
    glClear( GL_COLOR_BUFFER_BIT );
    glBegin( GL_LINE_STRIP );
    glBegin( GL_POLYGON );
    glVertex2i( 150, 150 );
    glVertex2i( 350, 150 );
    glVertex2i( 350, 350 );
    glVertex2i( 150, 350 );
    glVertex2i( 150, 150 );
    glEnd(  );
    glBegin( GL_LINE_STRIP );
    glBegin( GL_POLYGON );
    glVertex2i( 250, 250 );
    glVertex2i( 450, 250 );
    glVertex2i( 450, 450 );
    glVertex2i( 250, 450 );
    glVertex2i( 250, 250 );
    glEnd(  );
    glBegin( GL_LINE_STRIP );
    glBegin( GL_LINES );
    glVertex2i( 150, 150 );
    glVertex2i( 250, 250 );
    glVertex2i( 350, 150 );
    glVertex2i( 450, 250 );
    glVertex2i( 350, 350 );
    glVertex2i( 450, 450 );
    glVertex2i( 150, 350 );
    glVertex2i( 250, 450 );
    glEnd(  );
    glFlush(  );
}

void DisplayRotate()
{
    glClear( GL_COLOR_BUFFER_BIT );
    glColor3f( 0.0, 1.0, 0.0 );
    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity(  );
    for( int angle = 0; angle < 18; angle += 3 ) 
    {
        glRotatef( angle, 1, 0, 0 );
        if( angle > 8 ) 
            {
            glRotatef( angle * 2, 1, 0.0, 0 );
            glColor3f( 1.0, 0.0, 0.0 );
        }
        glBegin( GL_LINE_LOOP );
        glVertex2f( 150, 150 );
        glVertex2f( 350, 150 );
        glVertex2f( 350, 350 );
        glVertex2f( 150, 350 );
        glEnd(  );
    }
    glFlush(  );
}

void pressMouse(int button, int state, int x, int y )
{
    if( state == GLUT_DOWN )
    {
        glBegin( GL_POINTS );
        glPointSize( 50 );
        glVertex2i( x, wh - y );
        glEnd(  );
        glFlush(  );
    }
}

void holdMouse(int x, int y )
{
    glBegin( GL_POINTS );
        glPointSize( 50 );
        glVertex2i( x, wh - y );
    glEnd(  );
    glFlush(  );
}

void mouse(int btn, int state, int x, int y )
{
    if( state == GLUT_DOWN ) 
    {
        mouseState = state;
        mouseButton = btn;
        mouseX = x;
        mouseY = y;
    } 
    else 
    {
        mouseState = 0;
    }
}

void motion(int x,  int y )
{
    if( mouseState == GLUT_DOWN ) 
   {
        if( MouseButton == GLUT_LEFT_BUTTON ) 
            {
            yrotation -= ( mouseX - x );
            xrotation -= ( mouseY - y );
        }
    }
    mouseX = x;
    mouseY = y;
    glutPostRedisplay(  );
}

void DisplayFSquare()
{
    glClear( GL_COLOR_BUFFER_BIT );
    glColor3f( 0, 0, 1 );
    glBegin( GL_LINE_LOOP );
        glVertex2f( ( GLdouble ) 0.25, ( GLdouble ) 0.25 );
        glVertex2f( ( GLdouble ) 0.75, ( GLdouble ) 0.25 );
        glVertex2f( ( GLdouble ) 0.75, ( GLdouble ) .75 );
        glVertex2f( ( GLdouble ) 0.25, ( GLdouble ) 0.75 );
    glEnd(  );
    glFlush(  );
}

int main(int argc, char **argv )
{
    glutInit( &argc, argv );
    glutInitDisplayMode( GLUT_SINGLE | GLUT_RGB );
    glutInitWindowSize( ww, wh );
    glutInitWindowPosition( 150, 150 );
    glutCreateWindow( "Line" );
    MyInit(  );
    glutDisplayFunc( DisplayRSquare );
    glutMouseFunc( pressMouse );
    glutMotionFunc( holdMouse );
    glutMainLoop(  );
}

基本的な変換をテストするために、いくつかの簡単なモデルを作成しました。2 つの質問があります。

  1. DisplayRSquare : この関数では、ウィンドウ サイズで正方形を描画し、それを (100, 0) に移動したいのですが、(200, 0) に変換されました。それを (50, 0) に移動すると、(100, 0) に移動します。

さらに奇妙なことに、プログラムが機能する場合と機能しない場合があります。

  1. functionglVertex2f(0.3,0.7)の場合、ウィンドウの幅 0.3*、ウィンドウの高さ 0.7* の位置にポイントを見つける必要がありますね。しかし、私はそれを見つけることができません。座標を計算して実行する必要がありますglVertex2f(0.3*width,0.7*height)

私のコンパイルコマンドは g++ -o line Line.cpp -lGL -lGLU -lglut -lglui で、./line(ファイル名は Line.cpp) を実行するだけです。

4

1 に答える 1

3

「OpenGL はシーン グラフではありません。OpenGLはシーンを維持しません。描画コマンドを実行し、単一の点、線、三角形を一度に 1 つずつ描画するだけです。」

あなたのコードには、特定の基本的な手順がありません。最初に、適切な投影とモデル ビュー マトリックスを設定する必要があります。プログラムの最初に、モデルビュー マトリックスに射影マトリックス (オルソ) を配置します。そして、既知の(同一性)状態にリセットすることなく、モデルビューマトリックスで乗算、乗算、乗算、乗算するだけです。

各固定機能の OpenGL 表示プロセスの大まかな概要は次のとおりです。

  1. クリアカラーとデプスを設定してからクリア
  2. ビューポートと投影行列を設定する

    1. マトリックス モード投影
    2. ID を読み込む
    3. 乗算投影 (オルソまたはパースペクティブ)
  3. 初期ビュー マトリックスを設定する

    1. マトリックスモードのモデルビュー
    2. ID を読み込む
    3. セットアップ ビュー (lookat など)
  4. ジオメトリを描く

    1. オブジェクトごとに
    2. マトリックスモードのモデルビュー
    3. プッシュ マトリックス
    4. ローカル変換を適用
    5. 描画オブジェクト
    6. ポップマトリックス

更新 1

最初に、プログラムを書き直します。これは、予測可能な方法で動作し、最初に意図したことを実行します。

その後、質問への答えを見つけてください

#include <GL/glut.h>

void DrawRSquare(
    float sz,
    float tx,
    float ty )
{
    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();

    /* 
       Order of operations matters.
       Drawing commands use the current state
       of OpenGL, which includes the transformation
       matrix state. So this must be set before
       drawing.
    */
    glTranslatef(tx, ty, 0);

    glColor3f(1, 0, 0);
    glBegin( GL_LINE_LOOP );
    glVertex2f( 0, 0 );
    glVertex2f( sz, 0 );
    glVertex2f( sz, sz );
    glVertex2f( 0,  sz );
    glEnd();

    glPopMatrix();
}

void Display(void)
{
    glClearColor( 1, 1, 1, 0 );
    glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT );

    const int windim[2] = {
        glutGet(GLUT_WINDOW_WIDTH),
        glutGet(GLUT_WINDOW_HEIGHT)
    };

    glViewport(0, 0, windim[0], windim[1]);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(0.0, windim[0], 0.0, windim[1], -1, 1);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    DrawRSquare(50, 100, 0);
    DrawRSquare(50, 200, 100);

    glutSwapBuffers();
}

int main(
    int argc,
    char **argv )
{
    glutInit( &argc, argv );
    glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGB );
    glutCreateWindow( "" );
    glutDisplayFunc( Display );

   glutMainLoop(  );
}

実際には、プログラムは DisplayRSquare を実行しています。この関数では、作成したウィンドウと同じサイズの正方形を描画し、2 次元空間のベクトル (100,0) でそれをさらに拡大したいと考えていますが、実際には (200,0) に変換されています。ベクトルを (50,0) に変更すると (100,0) に移動します。

これは、Display 関数がおそらく 3 回呼び出された後、それ以上呼び出されないためです。DisplayRSquare の最初の呼び出しでは、ウィンドウが作成されたがまだ公開されていないときに、いくつかの線を描画した後に (100,0,0) の変換が適用されます。次に、ウィンドウが公開され、次の再描画で、既に設定されている変換に別の (100,0,0) が適用されます。しかし、それでもウィンドウは別の時間に公開され、今度は (100,0,0) + (100,0,0) が適用された正方形が再び描画されます。ウィンドウのサイズを変更すると、再描画のたびに正方形が見えなくなるまで移動します。

そのため、描画を開始する前に、OpenGL の状態を既知の状態にリセットする必要があります。

さらに配線されているのは、プログラムがうまく機能する場合があることです。時々そうではありません。私のコードは glTranslatef(100,0,0) です。同じプログラムの場合、100 を変換することもあれば、200 を変換することもあります...一種の有線...

何が起こるかというと、プログラムが受け取る再描画イベントの量はさまざまです。これは、他のウィンドウをその上に移動したり、アイコン化して元に戻したりすることなどによって行われます。

関数 glVertex2f(0.3,0.7) の場合、ウィンドウの幅 0.3*、ウィンドウの高さ 0.7* の位置にポイントを見つける必要があります。

これは、設定された射影とモデル ビュー マトリックスに完全に依存します。それらがどのように設定されているかを知らなければ、プログラムがそれらを明確に定義された状態に設定することはありません。

しかし、私はそれを見つけることができません。

おそらく、あなたの変換行列は、意図したものとはかけ離れているからです。

座標を計算して glVertex2f(0.3*width,0.7*height) を実行する必要がありますか?

いいえ、少なくともあなたの考えとは違います。


提案: 固定関数パイプラインと即時モードを使用しています。どちらも非常に時代遅れであり、推奨されていません。実際、それらは OpenGL の最近のバージョンから取り除かれているので、私はわざわざそれらを学ぶ気にもなりません。

最新の OpenGL を学習したい場合は、Nicol Bolas のチュートリアルを読んで作業することを強くお勧めします。

http://arcsynthesis.org/gltut

于 2012-06-25T09:04:25.297 に答える