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

我刚刚创建了几个简单的模型来测试基本转换。我有两个问题:

  1. DisplayRSquare:在这个函数中,我用窗口大小绘制了一个正方形,并希望将其移动到 (100, 0),但它转换为 (200, 0)。如果我将它移动到 (50, 0),它将移动到 (100, 0)。

更奇怪的是,该程序有时有效,有时无效。

  1. 对于函数glVertex2f(0.3,0.7),我们应该在 0.3*widthofthewindow,0.7*height 的位置找到一个点,对吧?但我找不到它。我必须计算坐标并运行glVertex2f(0.3*width,0.7*height)

我的编译命令是 g++ -o line Line.cpp -lGL -lGLU -lglut -lglui 然后运行 ​​./line(File name is Line.cpp)

4

1 回答 1

3

请跟我说话:“OpenGL 不是场景图!——它不维护场景,它所做的只是执行绘图命令,一次绘制一个点、线和三角形。”

您的代码缺少某些基本步骤。首先,您需要设置适当的投影和模型视图矩阵。您在程序开头的模型视图矩阵中放置了一个投影矩阵(正交)。然后您只需在模型视图矩阵上进行乘法、乘法和乘法,而无需将其重置为已知(身份)状态。

每个固定函数OpenGL显示过程的粗略轮廓大致如下:

  1. 设置清除颜色和深度,然后清除
  2. 设置视口和投影矩阵

    1. 矩阵模式投影
    2. 加载标识
    3. 乘投影(正交或透视)
  3. 设置初始视图矩阵

    1. 矩阵模式模型视图
    2. 加载标识
    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,在这个函数中,我绘制了一个与我们创建的窗口相同大小的正方形,并希望在二维空间中使用向量 (100,0) 来增加它,但实际上它是平移的 (200,0)。如果将向量更改为 (50,0),它将移动 (100,0)。

这样做的原因是,您的 Display 函数可能被调用了三次,然后就不再调用了。在 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*widthofthewindow,0.7*height 的位置找到一个点,对吧?

这完全取决于设置的投影和模型视图矩阵。如果不知道它们是如何设置的,并且您的程序永远不会将它们设置为明确定义的状态,我们不知道。

但我找不到它。

很可能,因为您的转换矩阵将与您缩进的内容相去甚远。

我必须计算坐标并运行 glVertex2f(0.3*width,0.7*height)?

不。好吧,至少不是你想的那样。


一个建议:您正在使用固定功能管道和立即模式。两者都严重过时和弃用。事实上,它们已从最新版本的 OpenGL 中删除,所以我什至懒得去学习它们。

如果您想学习现代 OpenGL,我强烈建议您阅读并完成 Nicol Bolas 的教程,恕我直言,这是您目前能找到的最好的教程之一:

http://arcsynthesis.org/gltut

于 2012-06-25T09:04:25.297 回答