无限循环问题
我想达到如图所示的效果:
我通过在 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重绘,则显示应显示的线条 . 我注意到,第一次绘制时,线条显示已损坏 . 我正在谈论的断线如下所示:
要理解我在说什么,请执行以下操作以获得效果 . 将 while (i)
更改为 while (i<1000)
. 这将在屏幕上绘制1000行 . 当我使用1280x960窗口大小进行此更改时,窗口被绘制2次 . 第一次绘制线条时显示与上图相同 . 绘制1000行的那一刻,窗口再次被清除,再次绘制它,但这次行显示应该是 . 为什么会这样 .
3 回答
你不必 . 无限循环已经在
glutMainLoop()
内发生 . 它将一遍又一遍地调用您的显示功能,直到程序关闭 . 要保持先前帧的输出(即绘制它们),请不要使用glClear()
清除颜色缓冲区 .至于虚线:不要逐个像素地画线 . 虽然我没有仔细观察,但你很可能会因视角/投影矩阵而产生一些差异(即你用太多的间距绘制点) . 相反,使用OpenGL调用来绘制线条 .
你在这里尝试做的主要是尝试在硬件加速渲染之上进行软件渲染,这很奇怪而且不是真的推荐 .
每次需要重绘窗口时,都会调用"display"函数(在您的情况下为
test_dda
) . 如果您在显示功能内部处于无限循环中,则GLUT中的事件处理代码不会更改运行 .而是使用计时器,并在计时器功能中绘制一行,然后调用一个函数强制GLUT重绘窗口,在那里“冲洗”GL管道 .
我认为你采用的起始解决方案在概念上是错误的 .
别带我坏:)
如果重点是反复绘制线条,一种可能的解决方案是以这种方式对流程进行分段:
FRAME 1第1步:在一个帧缓冲区上绘制线条,该帧缓冲区映射到包含工作纹理的四边形上的纹理
FRAME 1第2步:使用工作纹理绘制四边形
GLUT INPUT CALLBACK
FRAME 2第1步:在一个帧缓冲区上绘制线条,该帧缓冲区映射到包含工作纹理的四边形上的纹理
FRAME 1第2步:使用输出工作纹理绘制四边形
GLUT INPUT CALLBACK
等等.....