首页 文章

OpenGL和Broken Lines问题中的无限循环绘图

提问于
浏览
2

无限循环问题

我想达到如图所示的效果:

enter image description here

我通过在 glutDisplayFunct 回调函数中包含一个无限循环来生成这个,这是不好的,因为我无法处理来自键盘的任何输入 . 我能想到的另一种方法是使用过剩的显式窗口刷新函数 .

我想知道如何插入无限循环并检查键盘输入 . 这是我所做的示例代码 . 它只是实现了DDA算法,并尝试通过生成随机坐标和颜色来绘制无限线 .

#include <stdio.h>
#include <GL/glut.h>

int width;
int height;

void dda (int x1, int y1, int x2, int y2)
{
  int del_x, del_y, sample_steps, i = 1;
  double x_incr, y_incr, x, y;

  del_x = x2 - x1;
  del_y = y2 - y1;
  sample_steps = (abs (del_x) > abs (del_y)) ? abs (del_x) : abs (del_y);

  x_incr = del_x / (double) sample_steps;
  y_incr = del_y / (double) sample_steps;

  x = x1;
  y = y1;


  glBegin (GL_POINTS);
  while (i<=sample_steps)
  {
    glVertex2f ((2.0 * x)/width, (2.0 * y)/height);
    x += x_incr;
    y += y_incr;
    i++;
  }
  glEnd ();

  glFlush ();
}

void keypress_handler (unsigned char key, int x, int y)
{
  if (key == 'q' || key == 'Q')
  {
    glutLeaveMainLoop ();
  }
}

void init_screen (void)
{
  glMatrixMode (GL_PROJECTION);
  glClearColor (0, 0, 0, 1);
  glClear (GL_COLOR_BUFFER_BIT);
  glLoadIdentity ();
  glMatrixMode (GL_MODELVIEW);
}

void test_dda (void)
{
  int x1, y1, x2, y2;
  float r, g, b;

  int i=1;

  glClear (GL_COLOR_BUFFER_BIT);
  srand (time(NULL));
  width = glutGet (GLUT_WINDOW_WIDTH);
  height = glutGet (GLUT_WINDOW_HEIGHT);

  while (i)
  {
    x1 = rand () % width  - (width  /2);  /* Global */
    y1 = rand () % height - (height /2); /* Global */
    x2 = rand () % width  - (width  /2);  /* Global */
    y2 = rand () % height - (height /2); /* Global */

    r = rand () / (float) RAND_MAX;
    g = rand () / (float) RAND_MAX;
    b = rand () / (float) RAND_MAX;

    glColor3f (r, g, b);
    dda (x1, y1, x2, y2);
    printf ("\r%d", i);
    i++;
  }

}

void reshape (int w, int h)
{
  glViewport (0, 0, w, h);
  glMatrixMode (GL_PROJECTION);
  glLoadIdentity ();
  gluOrtho2D (-1, 1, -1, 1);
  glMatrixMode (GL_MODELVIEW);
}

int main (int argc, char *argv[])
{
  glutInit (&argc, argv);
  glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
  init_screen ();
  glutCreateWindow ("DDA");
  glutDisplayFunc (test_dda);
  glutReshapeFunc (reshape);
  glutKeyboardFunc (keypress_handler);

  glutMainLoop ();

  printf ("\n");
  return 0;
}

首次绘制时断行

另外我还有一个问题,就像这样:

当我取消注释 test_dda 函数内的无限循环( while (i) )并以1280x960屏幕大小运行可执行文件时,每条绘制的线显示为虚线,它们看起来像虚线 . 但是,如果我没有在这个函数中无限循环并用其他方式绘制线条,比如强制OpenGL重绘,则显示应显示的线条 . 我注意到,第一次绘制时,线条显示已损坏 . 我正在谈论的断线如下所示:

enter image description here

要理解我在说什么,请执行以下操作以获得效果 . 将 while (i) 更改为 while (i<1000) . 这将在屏幕上绘制1000行 . 当我使用1280x960窗口大小进行此更改时,窗口被绘制2次 . 第一次绘制线条时显示与上图相同 . 绘制1000行的那一刻,窗口再次被清除,再次绘制它,但这次行显示应该是 . 为什么会这样 .

3 回答

  • 0

    你不必 . 无限循环已经在 glutMainLoop() 内发生 . 它将一遍又一遍地调用您的显示功能,直到程序关闭 . 要保持先前帧的输出(即绘制它们),请不要使用 glClear() 清除颜色缓冲区 .

    至于虚线:不要逐个像素地画线 . 虽然我没有仔细观察,但你很可能会因视角/投影矩阵而产生一些差异(即你用太多的间距绘制点) . 相反,使用OpenGL调用来绘制线条 .

    你在这里尝试做的主要是尝试在硬件加速渲染之上进行软件渲染,这很奇怪而且不是真的推荐 .

  • 3

    每次需要重绘窗口时,都会调用"display"函数(在您的情况下为 test_dda ) . 如果您在显示功能内部处于无限循环中,则GLUT中的事件处理代码不会更改运行 .

    而是使用计时器,并在计时器功能中绘制一行,然后调用一个函数强制GLUT重绘窗口,在那里“冲洗”GL管道 .

  • 1

    我认为你采用的起始解决方案在概念上是错误的 .

    别带我坏:)

    如果重点是反复绘制线条,一种可能的解决方案是以这种方式对流程进行分段:

    • FRAME 1第1步:在一个帧缓冲区上绘制线条,该帧缓冲区映射到包含工作纹理的四边形上的纹理

    • FRAME 1第2步:使用工作纹理绘制四边形

    • GLUT INPUT CALLBACK

    • FRAME 2第1步:在一个帧缓冲区上绘制线条,该帧缓冲区映射到包含工作纹理的四边形上的纹理

    • FRAME 1第2步:使用输出工作纹理绘制四边形

    • GLUT INPUT CALLBACK

    等等.....

相关问题