【问题标题】:How to make your code execute slowly by using sleep() or something else?如何通过使用 sleep() 或其他方式使您的代码执行缓慢?
【发布时间】:2015-09-25 04:00:57
【问题描述】:

我试图让一些形状每 0.5 秒旋转一次,同时一直显示它,但使用循环时,它只显示最终结果。如何让它不断显示变化的图像?

这是我所拥有的:

for (float i = 190.0; i <= 200; i+= 2.0){
    viewMatrix = glm::lookAt(
        glm::vec3(i, 70.0f, 200.0f),  // eye position
        glm::vec3(0),                   // look at position
        glm::vec3(0.0f, 1.0f, 0.0f)); // up vect0r

    std::this_thread::sleep_for(std::chrono::milliseconds(500));//problem here
    glutPostRedisplay();


}

【问题讨论】:

  • 您将差值乘以一个分数,直到值正确为止。你所做的正是它所说的:睡眠 500 毫秒。在这 500 毫秒内什么都没有发生。
  • 也许可以利用你的工具包事件循环
  • GLUT 已经为您提供了事件循环。所以基本上你试图在现有轮子上重新发明轮子,但它不起作用。您可以使用 Timer/Idle 功能来设置每帧之间的时间。

标签: c++ opengl glut freeglut


【解决方案1】:

您已经得到了 3 个答案。他们每个人都完全错过了实际问题(我对每个答案都添加了相同的评论):

您遇到的问题是“glutPostRedisplay”没有主动显示任何内容。它所做的只是设置一些标志,在事件循环的下一次迭代中,调用 display 函数。 IE。像这样:

bool do_display = false;

void glutPostRedisplay()
{
    do_display = true;
}

void glutMainLoop()
{
    while(running) {
    ...
    if( do_display ) call_display_callback();
    do_display = false; 
    ...
    }
} 

设置 do_display 标志,当然不会在循环中做任何事情,除了重复设置它。

您需要做的是将idle 函数本身视为循环体,并在那里增加循环变量。即

float i = 190.0;
void anim_idle()
{
    if( i >= 200 ) { glutIdleFunc(NULL); }
    viewMatrix = glm::lookAt(
        glm::vec3(i, 70.0f, 200.0f),  // eye position
        glm::vec3(0),                   // look at position
        glm::vec3(0.0f, 1.0f, 0.0f)); // up vect0r

    glutPostRedisplay();

    i += 0.02;
}

此外,您不应该在那里睡觉,以便程序保持互动。而是测量迭代之间的时间,并通过时间间隔调整增量。

【讨论】:

    【解决方案2】:

    我不是 OpenGL 程序员,但我猜有

    glutPostRedisplay();
    

    之后

    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    

    根据我在 ncurses 和窗口刷新方面的经验,可能是问题的根源。

    另外,我一直使用 nanosleep 来延迟

    #include <time.h>
    int msleep(unsigned long milisec)   
    {   
        struct timespec req={0};   
        time_t sec=(int)(milisec/1000);   
        milisec=milisec-(sec*1000);   
        req.tv_sec=sec;   
        req.tv_nsec=milisec*1000000L;   
        while(nanosleep(&req,&req)==-1)   
            continue;   
        return 1;   
    }   
    

    【讨论】:

    • 问题是循环中的 glutPostRedisplay:glutPostRedisplay 只是设置了一个标志,即概念上 do_display = true - 在循环中调用它不会导致多次重绘。
    【解决方案3】:

    按照你说的做(不是基于你的例子)我会写这样的东西:

    int main(){
        init();
    
        using Clock = std::chrono::high_resolution_clock;
        using std::chrono::duration_cast;
        using std::chrono::milliseconds;
    
        auto start = Clock::now();
        while(1){
            auto now = Clock::now();
            if(duration_cast<milliseconds>(now - start).count() >= 500){
                // do animation
                start = now;
            }
    
            swap_buffers();
        }
    
        finish();
    }
    

    没有使用睡眠,只是一个忙碌的循环。

    此外,将float 用于for 循环计数器通常是不受欢迎的。并且有充分的理由。

    【讨论】:

    • 强烈不推荐这样的没有任何睡眠的活动循环。您正在使 CPU 以最大的容量工作,而这一切都是徒劳的。可以避免的情况下,为什么还要垄断计算机资源?
    • 您可以在空闲循环中让出 CPU。但是,对于不需要精确的数百毫秒的等待,OP 可能需要事件循环中的计时器。
    • 问题是循环中的 glutPostRedisplay:glutPostRedisplay 只是设置了一个标志,即概念上 do_display = true - 在循环中调用它不会导致多次重绘。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多