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

时间:2016-04-02 23:10:43

标签: c++ opengl glut

在大部分课程之后,他们在高年级为我们提供C ++课程。叹。所以我在水下试图学习它和OpenGL,后者是课堂的实际主题。

拜托,为什么这个东西会跑两次?这个作业已经上交和评分,但我找不到任何好的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();
}

1 个答案:

答案 0 :(得分:4)

每次需要再次渲染图形时,都会调用GLUT显示函数displayFunction。在真正的OpenGL应用程序上,它将被连续调用,由计时器控制。这里它在打开的窗口被调用一次。但是根据操作系统的不同,可能会多次调用它,例如,如果需要刷新窗口,因为它已被激活。

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

通常情况下,显示功能应该快速执行(并且永远不会阻止/等待),并且最后只调用glFlush()glutSwapBuffers()一次。

更好的实现方式是:动画的状态(即时钟图标的数量)存储在全局变量int state = 0中。 displayFunction()总是在不等待的情况下绘制该数量的时钟,然后退出。在启动主循环之前,计时器glutTimerFunc注册,其功能增加state,然后调用glutPostRedisplay()。这会调度GLUT以调用显示功能。然后,应用程序在动画期间也会保持响应,并可以通过关闭窗口退出。