c++ - opengl/glut 中的 renderDisplayFunc 不止一次调用 myfunc

标签 c++ opengl glut

#include "GL/glut.h"
#include "GL/gl.h"
#include <iostream>
#include <stdlib.h>

using namespace std;

#define XWidth 700  // Clipping window size 700*700
#define YHeight 700 

void renderFunction() {

/*Clear Information from last draw
Sets the current clearing color for use in clearing
color buffers in RGBA mode.
*/
    glClearColor(0.0, 0.0, 0.0, 0.0);
    glClear(GL_COLOR_BUFFER_BIT);

    //Set line width
    glLineWidth(1);

    //(x,y) coordinates as in pixels
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(0, XWidth, 0, YHeight, -1, 1);


    //Set line color
    glColor3f(1.0, 0.0, 0.0);

    //random num generated
    for(int i=0;i<4;i++){
    int r1 = rand() % 1000;
    int r2 = rand() % 1000;
    int r3 = rand() % 1000;
    int r4 = rand() % 1000;

    //Begin LINE coordinates
    glBegin(GL_LINES);
        glVertex2d(r1, r2);
        glVertex2d(r3,r4);
    //End LINE coordinate
    glEnd();
    cout<<r1<<" "<<r2<<" "<<r3<<" "<<r4<<" i is "<<i<<endl;}

    //Forces previously issued OpenGL commands to begin execution
    glFlush();
}

// Driver program to test above functions
int main(int argc, char** argv) {

    //Initialize GLUT
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE);

    //Set Output Window Size
    glutInitWindowSize(XWidth,YHeight);

    //Set the position of Output window corresponding to Screen
    glutInitWindowPosition(100,100);

    //Create the Window
    glutCreateWindow("OpenGL - Classify line among three classes");

    //Set handler functions for drawing
    glutDisplayFunc(renderFunction);

    //Start the main loop
    glutMainLoop();
    return 0;
}

当我执行上面的程序时,它工作正常。但问题是,当我打印随机生成的变量值 r1 r2 r3 r4 时,它们正在打印 8 次或有时 12 次。这意味着 glutDisplayFunc(renderFunction); 多次调用 renderFunction,这不是必需的。

如何控制这种行为。我希望只调用一次 renderFunction

更新:我想创建 4 条线,正好形成 4 条线,但是当我打印坐标时,它们显示出我上面提到的意外行为。

最佳答案

我在这里看到了几个问题。

较小的一个是您在 renderFunction 中对 for 循环的缩进有点误导。该循环总是恰好有 4 次迭代,每次都打印一次随机变量。

第二个是您似乎误解了 glutDisplayFunc(renderFunction); 的含义。正如解释的那样 here ,这只会将 renderFunction 注册为过剩的默认“显示”回调,并且:

GLUT determines when the display callback should be triggered based on the window's redisplay state.

glutMainLoop将调用已注册的回调,直到程序完成。请注意,glutMainLoop 永远不会返回。程序被未处理的信号或主窗口关闭中断。这意味着如果您最小化并恢复窗口,glut 将要重新绘制其内容并再次调用显示回调 (renderFunction)。

由于在 glut 调用 display 函数时您无法轻易控制,或者不应尝试控制,因此我建议您确保 display 函数只会绘制到屏幕上。您可以在 main 函数中生成(并打印)随机值,并将随机变量设置为全局变量,以便从 renderFunction 轻松访问它们。或者,通过在第一次执行时修改标志的条件语句来保护采样和打印的执行:

// at global scope (before renderFunction)
generated = false
declare random variables
...
// inside renderFunction 
if (generated = false) {
  generate RV
  print RV
  generated = true
}
display lines

无论哪种情况,您都需要存储所有 16 个随机变量,因为您生成了 4 个随机值 4 次(并且您将它们全部用于绘图/打印)。我建议将它们存储在 int r[4][4];

这是我喜欢的版本:

#include "GL/glut.h"
#include "GL/gl.h"
#include <iostream>
#include <stdlib.h>

using namespace std;

#define XWidth 700  // Clipping window size 700*700
#define YHeight 700 

int r[4][4];

void renderFunction() {

  /*Clear Information from last draw
    Sets the current clearing color for use in clearing
    color buffers in RGBA mode.
   */
  glClearColor(0.0, 0.0, 0.0, 0.0);
  glClear(GL_COLOR_BUFFER_BIT);

  //Set line width
  glLineWidth(1);

  //(x,y) coordinates as in pixels
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glOrtho(0, XWidth, 0, YHeight, -1, 1);

  //Set line color
  glColor3f(1.0, 0.0, 0.0);

  //random num generated
  for(int i=0;i<4;i++){
    //Begin LINE coordinates
    glBegin(GL_LINES);
    glVertex2d(r[i][0], r[i][1]);
    glVertex2d(r[i][2], r[i][3]);
    //End LINE coordinate
    glEnd();
  }

  //Forces previously issued OpenGL commands to begin execution
  glFlush();
}

// Driver program to test above functions
int main(int argc, char** argv) {

  //Initialize GLUT
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_SINGLE);

  //Set Output Window Size
  glutInitWindowSize(XWidth,YHeight);

  //Set the position of Output window corresponding to Screen
  glutInitWindowPosition(100,100);

  //Create the Window
  glutCreateWindow("OpenGL - Classify line among three classes");

  //Set handler functions for drawing
  glutDisplayFunc(renderFunction);

  //random num generated
  for(int i=0;i<4;i++) {
    r[i][0] = rand() % 1000;
    r[i][1] = rand() % 1000;
    r[i][2] = rand() % 1000;
    r[i][3] = rand() % 1000;

    cout<<r[i][0] << " " << r[i][1]<<" "<<r[i][2]<<" "<<r[i][3]<<" i is "<<i<<endl;
  }

  //Start the main loop
  glutMainLoop();
  return 0;
}

编辑 原始发帖人在评论部分提出了一个有趣的问题转折。我将在这里解释一下:

If you require a large (10000+) number of lines and memory is a huge concern, can we still get the originally desired behavior:random values printed only once and lines not changing position every time the screen gets repainted.

答案是:是的!保持您最初拥有的非常低的内存占用的一种方法是使用“if”保护技巧的组合,每次通过 re-seeding the random number generator 打印和生成(相同的)随机值。 .

#include "GL/glut.h"
#include "GL/gl.h"
#include <iostream>
#include <stdlib.h>

using namespace std;

#define XWidth 700  // Clipping window size 700*700
#define YHeight 700

bool printed;
int random_seed;

void renderFunction() {

  /*Clear Information from last draw
    Sets the current clearing color for use in clearing
    color buffers in RGBA mode.
   */
  glClearColor(0.0, 0.0, 0.0, 0.0);
  glClear(GL_COLOR_BUFFER_BIT);

  //Set line width
  glLineWidth(1);

  //(x,y) coordinates as in pixels
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glOrtho(0, XWidth, 0, YHeight, -1, 1);


  //Set line color
  glColor3f(1.0, 0.0, 0.0);


  // =============================================
  // set the seed of your random number generator
  // ---------------------------------------------
  srand(random_seed);
  // =============================================

  //random num generated
  for(int i=0;i<4;i++) {
    int r1 = rand() % 1000;
    int r2 = rand() % 1000;
    int r3 = rand() % 1000;
    int r4 = rand() % 1000;

    //Begin LINE coordinates
    glBegin(GL_LINES);
    glVertex2d(r1, r2);
    glVertex2d(r3,r4);
    //End LINE coordinate
    glEnd();

    // ***********************************************
    // make sure the values are only printed the first
    // time around
    // ***********************************************
    if (!printed) {
      cout<<r1<<" "<<r2<<" "<<r3<<" "<<r4<<" i is "<<i<<endl;
    }
  }

  printed = true;

  //Forces previously issued OpenGL commands to begin execution
  glFlush();
}

// Driver program to test above functions
int main(int argc, char** argv) {

  //Initialize GLUT
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_SINGLE);

  //Set Output Window Size
  glutInitWindowSize(XWidth,YHeight);

  //Set the position of Output window corresponding to Screen
  glutInitWindowPosition(100,100);

  //Create the Window
  glutCreateWindow("OpenGL - Classify line among three classes");

  //Set handler functions for drawing
  glutDisplayFunc(renderFunction);


  // =======================================
  // generate a random seed for the lines
  // ---------------------------------------
  srand(time(0));
  random_seed = rand();
  // =======================================

  // ==========================================
  // initialize the printing guard to "false",
  // i.e. "did not print the random values yet"
  // ------------------------------------------
  printed = false;
  // ==========================================


  //Start the main loop
  glutMainLoop();
  return 0;
}

请注意,此方法与原始问题中的代码非常相似,添加的代码使用注释明确分隔。好的一面是,无论您要绘制多少行,它都使用恒定的内存量。不利的一面是调用 rand() 有点昂贵,因此您通常需要在高速(前一个版本)和低内存消耗(后一个版本)之间进行权衡。

关于c++ - opengl/glut 中的 renderDisplayFunc 不止一次调用 myfunc,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18485690/

相关文章:

c++ - 为什么我的 or 语句不起作用,C++?

c++ - 如何将基类指针数组转换为派生类

c++ - 如何将多个 vtkprop 或 vtkactor 组合成一个更大的 actor 或 prop?

c++ - 使用 GLUT_DOUBLE 模式绘制形状

C++ 从头文件中调用函数

c++ - snprintf 变量列表不会将枚举转换为 char*

c++ - 为 OpenGL Gouraud 着色提供带有三角带和扇形的法线

c++ - glm::lookat,OpenGL 中的透视澄清

opengl - 在 GLUT 中截图

c++ - glutStrokeCharacter 绘制一个 int 变量