没有获得 OpenGL 的输出以使用鼠标单击打印行

Not getting an output for OpenGL to print line using mouse click

我的目标是用鼠标点击画一条线。当您单击第一次单击时,它会读取坐标,然后当进行嵌套单击时,它将使用 GL_LINES 和第一个点和第二个点绘制线。

int first, x1, yi, x2, yj, ww = 600, wh = 400;
void drawl()
{
    glClear(GL_COLOR_BUFFER_BIT);  
    glLineWidth(5.00);
    glColor3f(0,1,0);
    glBegin(GL_LINES);
        glVertex2i(x1,yi);
        glVertex2i(x2,yj);
    glEnd();
    glFlush();
}

void Display()
{
    glClearColor(0.5, 0.5, 0.5, 1.0);  
    glColor3f(0.7, 0.4, 0.0);  
    glClear(GL_COLOR_BUFFER_BIT);  
    glFlush();  
}

void mouse(int button, int state, int x, int y)
{
    if(button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
    {
        if(first == 0)
        {       
            first++;
            x1 = x;
            yi = wh - y;
        }
        else
        {
            x2 = x;
            yj = wh - y;
            drawl();
            printf("%d,%d,%d,%d\n",x1,yi,x2,yj);
            first--;
        }   

    }
}

void main(int argc, char **argv)
{
    first = 0;
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
    glutInitWindowSize(800,500);
    glutInitWindowPosition(0,0);
    glutCreateWindow("Mouse");
    gluOrtho2D(0,800,0,500);
    glutDisplayFunc(Display);
    glutMouseFunc(mouse);
    glutMainLoop();
} 

我得到的输出如下。它没有划清界限。我应该包含 myinit() 函数吗?为什么?

首先,您实际上并没有绘制任何东西 - 函数 drawl 仅在您每隔两次单击时才会被调用。要绘制一条线(或任何东西),需要在每一帧调用绘图例程,例如调用 Display 函数。

其次,mouse 回调函数中给出的位置不适合在 3D 中定义点。必须将它们转换到适当的坐标(通常范围从 -1 到 1)才能将它们用作绘图数据。否则 GL 会尝试在视图之外绘制一些线,这意味着什么都不会绘制。

我会稍微重新组织应用程序结构 - 当您收到 mouse 调用而不是每隔一次调用 drawl 时,存储 mouse 函数提供的正确翻译的位置你在一些全局变量中并在 Display 例程中进行绘图。另外 gluOrtho2D 通常也应该在每一帧都被调用。在您调用它时您的参数有误 - 请参阅 reference page 了解详细信息。

为了这个答案,我将我对问题 的答案从 C++ 移植到了 C。


你必须把鼠标事件和绘图函数分开。

在鼠标 (void mouse(int button, int state, int x, int y)) 事件中,您应该只收集输入。

  • 如果按下鼠标左键,以下函数将鼠标位置的 X 坐标添加到数组 ptListX 并将 Y 坐标添加到数组 ptListY.

  • 如果按下右键,多边形将被标记为闭合。如果再次按下左键,多边形将被清除并重新开始。

int wndSizwX = 800, wndSizeY = 500; // size of the window
int mouseX = 0, mouseY = 0;         // current mouse position

#define MAX_PTS 100
int ptListX[MAX_PTS]; // X coordinate ot the input points 
int ptListY[MAX_PTS]; // Y coordinate of the input points
int noOfPts = 0;      // number of input points
int closed = 0;       // marke polygon "closed"

void mouse(int button, int state, int x, int y)
{
    mouseX = x;
    mouseY = y;

    if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
    {
        if (closed || noOfPts >= MAX_PTS - 1)
            noOfPts = 0; // restart the polygon
        closed = 0;
        ptListX[noOfPts] = mouseX; 
        ptListY[noOfPts] = mouseY;
        noOfPts ++;
    }
    if ( button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN )
        closed = 1;
}

在鼠标移动事件函数中,可以跟踪当前鼠标位置:

void mouse_move(int x, int y)
{
    mouseX = x;
    mouseY = y;
    glutPostRedisplay();
}

在主循环中(Display函数),将当前的点列表连成线并连续绘制。如果设置了 cloesd 标志,则多边形被关闭。否则绘制从列表中的最后一个点到当前鼠标位置的线。

void Display()
{
    glClearColor(0.5f, 0.5f, 0.5f, 1.0f);  
    glClear(GL_COLOR_BUFFER_BIT);  

    if (noOfPts)
    {
        glLineWidth(5.0);
        glColor3f(0.0f,1.0f,0.0f);
        glBegin(GL_LINE_STRIP);
        for (int i=0; i<noOfPts; ++i )
            glVertex2f( (float)ptListX[i], (float)ptListY[i] );
        if ( closed )
            glVertex2f( (float)ptListX[0], (float)ptListY[0] );
        else
            glVertex2f( (float)mouseX, (float)mouseY );
        glEnd();
    }

    glFlush();  
}

鼠标移动事件的注册需要在主程序中glutPassiveMotionFunc添加。
此外,必须翻转正交投影的 Y 轴,以使视图 space 与鼠标坐标相匹配:

void main(int argc, char **argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
    glutInitWindowSize(wndSizwX,wndSizeY);
    glutInitWindowPosition(0,0);
    glutCreateWindow("Mouse");

    gluOrtho2D(0, wndSizwX, wndSizeY, 0); // flip Y 

    glutDisplayFunc(Display);
    glutMouseFunc(mouse);
    glutPassiveMotionFunc(mouse_move);
    glutMainLoop();
}

查看预览: