-1

I am trying to make some shapes rotate every .5 secs while displaying it the entire time, while using a loop, however, it only displays the end result. How can I make it display the changing image constantly?

Here is what I have:

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();


}
Aracthor
  • 5,757
  • 6
  • 31
  • 59
mr nooby noob
  • 1,860
  • 5
  • 33
  • 56
  • You multiply the difference by a fraction until the value is correct. What you are doing does exactly what it says it does: sleeps for 500 milliseconds. Nothing happens in those 500 milliseconds. – RamblingMad Sep 25 '15 at 04:13
  • 3
    Maybe take advantage of your toolkit event loop – Basile Starynkevitch Sep 25 '15 at 04:58
  • 1
    GLUT already provides the event loops for you. So basically you're trying to reinvent the wheel on top of an existing wheel and it's not working. You can use the Timer/Idle function to set the time between each frame. – aslg Sep 25 '15 at 08:20

3 Answers3

4

You were already given 3 answers. And each of them did completely miss the actual problem (I added the same comment on each of those answers):

The problem you have is that 'glutPostRedisplay` is not actively displaying anything. All it does is setting some flag, that upon the next iteration of the event loop, the display function call be called. I.e. like this:

bool do_display = false;

void glutPostRedisplay()
{
    do_display = true;
}

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

Setting that do_display flag, will of course not do anything in a loop, other than reduantly setting it.

What you have to do is treating the idle function itself as the loop body and incrementing the loop variable there. I.e.

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;
}

Also you should not sleep there, so that the program stays interactive. Instead measure the time between iterations and adjust the increment by the time internval passed.

datenwolf
  • 159,371
  • 13
  • 185
  • 298
0

I'm not an OpenGL programmer, but I would guess that having

glutPostRedisplay();

after

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

could be the source of problem, from my experience with ncurses and window refreshing.

Also, I've always used nanosleep for delays

#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;   
}   
destrovel
  • 75
  • 1
  • 10
  • The problem is the glutPostRedisplay in the loop: glutPostRedisplay merely sets a flag i.e. conceptually do_display = true – calling it in a loop with not cause multiple redraws. – datenwolf Sep 25 '15 at 08:08
0

To do what you said (not basing anything on your example) I would write something like this:

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();
}

No use of sleep, just a busy loop.

Also, using float for a for loop counter is usually frowned upon. And for good reasons.

RamblingMad
  • 5,332
  • 2
  • 24
  • 48
  • An active loop without any sleep like this is strongly not recommended. You are making the CPU working at the maximum of its capacity for nothing. Why to monopolize computer resources when you can avoid it? – Aracthor Sep 25 '15 at 05:24
  • You can yield the CPU inside the idle-loop. However, for a wait of hundreds of milliseconds that doesn't need to be precise, the OP probably wants a timer in the event loop. – Davislor Sep 25 '15 at 05:37
  • The problem is the glutPostRedisplay in the loop: glutPostRedisplay merely sets a flag i.e. conceptually do_display = true – calling it in a loop with not cause multiple redraws. – datenwolf Sep 25 '15 at 08:08