关于C#:在OpenGL中先后暂停

Pausing in OpenGL successively

1
2
3
4
5
6
7
8
9
10
11
12
void keyPress(unsigned char key,int x,int y){
    int i;
    switch(key){
    case 'f':
        i = 3;
        while(i--){
            x_pos += 3;
            sleep(100);
            glutPostRedisplay();
        }
    }
}

  • 以上是在 Windows 7 中使用 GLUT 库用 C 语言编写的代码片段。

  • 此函数采用字符键和鼠标坐标 x,y 并在按 f 字符时分 3 个连续步骤沿 x 方向执行平移。在每一步之间,程序应该hibernate 100 毫秒。

  • 我们要移动一个机器人,并在他前进的时候连续停顿。

  • 我们在使程序在 3 个步骤之间hibernate时遇到了问题。上面的代码片段有什么问题?


我相信你的代码的问题是你的睡眠弄乱了 glut 的主循环。调用堆栈可能看起来像这样

1
2
3
4
main() -> glutMainLoop() -> keyPress() -> sleep()

#but can't get to this...
main() -> glutMainLoop() -> display()

直到 keyPress() 返回,glut 的主循环不能继续渲染下一帧。它正在等待函数返回。 glutPostRedisplay() 所做的只是说"嘿,有些东西发生了变化,所以图像已经过时了,我们需要在下一次主循环迭代时重绘"。它实际上并没有调用 display().

您必须对代码进行结构化,以使主循环可以正常继续,但在绘图之间仍存在延迟。例如:

  • keyPress() 中,设置一个 moving = true 状态。让函数返回。
  • idle() 函数中,如果移动或者如果您上次移动过,则调用 sleep() (实际上,您可能想考虑计算经过的时间并自己进行计时,这样您就不会阻塞整个程序)
  • 再次在 idle() 中增加 x_pos 并减少你的移动计数,让函数返回,过剩将绘制,然后再次调用空闲,你可以再次睡眠/移动。

免责声明:jozxyqk 的答案对我来说似乎更好。这个答案以一种肮脏的方式解决了这个问题。

您正在滥用 glutPostRedisplay,如本答案所述。问题是, glutPostRedisplay 将当前窗口标记为需要重新显示,但只有在您再次进入 glutMainLoop 时才会这样做。这确实只发生一次,因此似乎只有一次睡眠有效。

事实上所有三个睡眠都可以工作,但是在 300 毫秒后你只能重绘一次。

要解决这个问题,你必须找到另一种重绘场景的方法。

1
2
3
4
5
while(i--){
    x_pos += 3;
    sleep(100);
    yourDrawFunction();
}

假设您在 UNIX 系统上工作。

sleep for 100 ms

1
sleep(100);

这里的问题是,您正在睡眠 100 秒,因为您可能正在使用 <unistd.h> 标头的睡眠功能,它将 sleep() 定义为:

1
extern unsigned int sleep (unsigned int __seconds);

你想要的可能类似于

1
usleep(100000); //sleeps for 100000 microseconds == 100 ms