更新 window 显示 OpenGL/GLUT C++

Update window display OpenGL/GLUT C++

我有一个方法,我需要这个方法来使用 GLUT 显示网络中病毒的行为(这是我第一次使用图形库)。

我正在显示一些连接它们的点和线。该程序运行良好,它完美地显示了网络的初始状态,但我无法在调用方法模拟后设法找到更新显示的方法。

这些点根据计算机的状态改变颜色,所以我需要一种每 3 秒或类似时间更新一次显示(网络图)的方法。有任何想法吗?

我读过有关使用 glutPostRedisplay() 或以某种方式使用 glutIdleFunc() 的内容,但我不明白如何实现它。感谢您的帮助。

这是我的代码:(但这只显示了初始状态)

void Visualizador::visualizar(int cItr, int ios, double vsc, int vcf, double rc, double grc) {

glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(1280,720);
glutCreateWindow("Network initial state");
glutDisplayFunc(display); //display creates a number of points (computers) and lines (connections)
glutIdleFunc(display);
glutMainLoop();

for (int i = 0; i < cItr; i++) { //cItr: Number of times the state of the network will be updated
    ostringstream oss;
    oss << "State #" << i+1 << " of the network";
    string windowName = oss.str();
    const char* cstr = windowName.c_str();
    simulator.simulate(1, vsc, vcf, rc, grc); //this method can change which point is infected
    glutDisplayFunc(display);
    glutIdleFunc(display);
    glutSetWindowTitle(cstr);
    glutMainLoop();
    }
}

经过大量阅读,我发现完成我想做的事情的唯一方法是擦除代码并将我的模拟方法放在显示函数中。以下是代码最终的工作方式:

glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(1280,720);
glutCreateWindow("Network initial state");
glutDisplayFunc(display);
glutIdleFunc(display);
glutMainLoop();

如您所见,我只留下了代码的顶部。我这样做的原因是因为 glutIdleFunc(display) 将被连续调用,所以如果我每次 glutIdleFunc() 调用 display 时更改显示函数内的网络状态(调用模拟),网络将会改变。我还必须将 glutPostRedisplay() 放在 glutIdleFunc() 的底部。调用 glutPostRedisplay() 会导致程序引发一个标志,指示 window 需要重新绘制,换句话说,显示需要更新。

尽管存在未知变量,但我还是包含了显示代码,因为它可能对某人有帮助:

void Visualizador::display() {

if(v->displayCount <= Visualizador::cantIterac) 
{
    int contVertices = 0;

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    for (int i = 0; i < Visualizador::v->grafo.cntVrt*2; i += 2) {
        if (Visualizador::v->grafo.obtEst(contVertices) == Grafo::S) {
            glColor3f(0.0, 1.0, 0.0);
        }
        else {
            if (Visualizador::v->grafo.obtEst(contVertices) == Grafo::R) {
                glColor3f(0.5, 0.5, 0.5);
            }
            else {
                glColor3f(1.0, 0.0, 0.0); //red
            }
        }
        glPointSize(5.8);
        glBegin(GL_POINTS);
        glVertex2f(arrPos[i], arrPos[i + 1]);
        contVertices++;
    }
    glEnd();

    contVertices = 0;
    glLineWidth(1.6); //Ajusta el ancho de las lineas
    glColor3f(0.2, 1.0, 1.0); //Color blanco
    glBegin(GL_LINES); //empieza a dibujar lineas, cada dos llamadas a la funcion glVertex dibuja una sola linea
    for (int i = 0; i < Visualizador::v->grafo.cntVrt*2; i += 2) {
        int* adyVrt = Visualizador::v->grafo.obtAdy(contVertices);
        for (int j = 0; j < Visualizador::v->grafo.arrVrt[contVertices].lstAdy->obtCntAdy(); j++) {
            glVertex2f(arrPos[i], arrPos[i + 1]);
            glVertex2f(arrPos[adyVrt[j]*2], arrPos[(adyVrt[j]*2) + 1]);
        }
        contVertices++;
    }
    glEnd();
    glutSwapBuffers();

    if (v->displayCount < Visualizador::cantIterac)
    {
        Sleep(500);

        v->simulador.simular(1,Visualizador::virusSpreadC, Visualizador::virusCheckFrec, Visualizador::recoveryC, Visualizador::gainResistance);

        ostringstream oss;
        oss << "State #" << v->displayCount+1 << " of the network";
        string windowName = oss.str();
        const char* cstr = windowName.c_str();
        glutSetWindowTitle(cstr);
        glutPostRedisplay();
    }
    v->displayCount++;
}
else
{
   glutIdleFunc(NULL);
}
}