为什么这个 C++ / OpenGL 程序 运行 两次?

Why does this C++ / OpenGL program run twice?

完成大部分课程后,他们 spring 高年级学习 C++。叹。所以我在水下尝试学习它和 OpenGL,后者是 class.

的实际主题

请问,为什么这个东西运行两次?这个作业已经上交并评分了,所以我找不到任何好的 OpenGL 在线指南。感谢您的任何想法。

#ifdef __APPLE__
#include <GLUT/glut.h>
#include <OpenGL/gl.h>
#else
#include <GL/glut.h>
#endif

#include <stdlib.h>

int width = 800, height = 600;
float xmin = -(width / 2), ymin = -(height / 2), xmax = width / 2, ymax = height / 2;
GLubyte bitmap[72] = { 0x00, 0x00, 0x00,
0x40, 0x00, 0x02,
0x20, 0x00, 0x04,
0x10, 0x38, 0x08,
0x09, 0x63, 0x10,
0x06, 0x00, 0xA0,
0x08, 0x00, 0x20,
0x10, 0x00, 0x10,
0x10, 0x00, 0x10,
0x10, 0x00, 0x08,
0x20, 0x00, 0x08,
0x20, 0x10, 0x08,
0x20, 0x18, 0x08,
0x10, 0x14, 0x08,
0x10, 0x12, 0x10,
0x10, 0x11, 0x10,
0x08, 0x10, 0x20,
0x04, 0x10, 0x40,
0x01, 0x87, 0x00,
0x00, 0x78, 0x00,
0x00, 0x00, 0x00,
0x00, 0x00, 0x00,
0x00, 0x00, 0x00,
0x00, 0x00, 0x00
};

void init(void) {
    // Set display-window color to white.
    glClearColor(0.0, 0.0, 1.0, 0.0);
    // Set projection parameters.
    glMatrixMode(GL_PROJECTION);
    gluOrtho2D(xmin,xmax,ymin,ymax);
    // Clear display window.
    glClear(GL_COLOR_BUFFER_BIT);
    glutSwapBuffers();
}

// Windows redraw function
void winReshapeFcn(GLint newWidth, GLint newHeight) {
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(-(GLdouble)width / 2, (GLdouble)width / 2, -(GLdouble)height / 2, (GLdouble)height / 2);
    glClear(GL_COLOR_BUFFER_BIT);
}

void drawText() {
    int x = (int) xmin + 20, y = (int) ymax - 20, count = 0;
    char what [] = { 'R', 'e', 'c', 't', 'a', 'n', 'g', 'l', 'e', 's' };
    float color = 1.0;

    glRasterPos2i(x, y);
    do {
        glColor3f(color,color,color);
        color = color - 0.1;
        glutBitmapCharacter(GLUT_BITMAP_9_BY_15, what[count]);
        y = y - 20;
        glRasterPos2i(x, y);
        count = count + 1;
    } while (count <= 9);
}

void drawRectangles() {
    int h = (int) ymax, x1 = -h, y1 = h, x2 = h, y2 = -h, count = 0, delta, factor = 5;

    do {
        glBegin(GL_LINES);
            glVertex2i(x1,h);
            glVertex2i(h,y1);

            glVertex2i(h,y1);
            glVertex2i(x2,-h);

            glVertex2i(x2,-h);
            glVertex2i(-h,y2);

            glVertex2i(-h,y2);
            glVertex2i(x1,h);
        glEnd();
        h = h - factor; delta = factor * count;
        x1 = -h + delta; y1 = h - delta; x2 = h - delta; y2 = -h + delta;
        count = count + 1;
    } while (x1 < h);
}

void drawBitmaps() {
    int count = 0;
    GLfloat xorigin = xmin + (xmax - ymax) / 2.0;

    // Needed for reading from memory. 1 indicates byte alignment
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    // Center the bitmap image
    glRasterPos2i(0, 0);
    do {
        glBitmap(24.0, 24.0, xorigin, ymax, 0.0, 24.0, bitmap);
        count = count + 24;
        Sleep(150);
        glutSwapBuffers();
    } while ((count < width) && (count < height));
}

void displayFunction(void) {

    // Clear display window.
    glClear(GL_COLOR_BUFFER_BIT);
    // Set  graphic objects color to Red or change for your choice

    drawText();
    glColor3f(1.0, 1.0, 0.0);
    drawRectangles();
    drawBitmaps();

    // Execute OpenGL functions
    glFlush();
}

void main(int argc, char** argv) {
    // Initialize GLUT.
    glutInit(&argc, argv);
    // Set display mode.
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
    // Set top-left display-window position.
    glutInitWindowPosition((glutGet(GLUT_SCREEN_WIDTH) - width) / 2, (glutGet(GLUT_SCREEN_HEIGHT) - height) / 2);
    // Set display-window width and height.
    glutInitWindowSize(width, height);
    // Create display window.
    glutCreateWindow("Michael Powers - Homework 2");
    // Execute initialization procedure.
    init();
    // Send graphics to display window.
    glutDisplayFunc(displayFunction);
    // Window reshape call
    glutReshapeFunc(winReshapeFcn);
    // Display everything and wait.
    glutMainLoop();
}

每次需要再次渲染图形时,都会调用 GLUT 显示函数 displayFunction。在真正的 OpenGL 应用程序中,它将被持续调用,由计时器控制。这里它在 window 打开时被调用一次。但是根据 OS,它可能会被调用多次,例如,如果 window 因为它被激活而需要刷新。

在代码中,动画在 displayFunction() 执行期间由 Sleep(150)glutSwapBuffers() 控制。因此应用程序在动画期间阻塞,但由于 glutSwapBuffers() 次调用,图形仍然显示。

通常显示函数应该快速执行(永远不要 block/wait),最后只调用一次 glFlush()glutSwapBuffers()

更好的实现方式是:动画的状态(即时钟图标的数量)存储在全局变量 int state = 0 中。 displayFunction() 总是不等待地绘制那个数量的时钟,然后退出。在开始主循环之前,timer 被注册到 glutTimerFunc,具有递增 state 的函数,然后调用 glutPostRedisplay()。这会安排 GLUT 调用显示功能。然后应用程序在动画期间也保持响应,并且可以通过关闭 window.

退出