Problem with stopping glutPostRedisplay

I finally got the glutIdleFunc to work to my favor but the only problem is that I can’t get it to stop. I have tried:
[ol]

[li] Using bool and turning it to false when it displays once.[/li]
[li] Placing the display code in the Mouse Func.[/li]
[li] Some other stuff that got me nowhere.[/li][/ol]

I want to know the best way to display something then keep it on the screen without it flashing. Some specifics on my code:
[list=A]

[li] I’m using Double Buffering, I have glutSwapBuffers(); in both the display function on everywhere else that I have glutPostDisplay();[/li]
[li]Code for IdleFunc:[/li]bool Redisplay = false;
void redisplay()
{
if(Redisplay)
{
glutPostRedisplay();
Redisplay = false;
}
}

[li] Here is the MouseFunc:[/li]GLfloat card_x1[3] = { 0.0, 0.2, 0.4 };
GLfloat card_x2[3] = { 0.4, 0.6, 0.8 };
int card_num = 0;
void mouse(int button, int state, int x, int y)
{
if(state == GLUT_DOWN && button == GLUT_LEFT_BUTTON)
exit(0);
if(state == GLUT_DOWN && button == GLUT_RIGHT_BUTTON)
{
glColor3f(0.0, 0.0, 1.0);
glRectf(card_x1[card_num], 0.2, card_x2[card_num], 0.8);
glRectf(card_x1[card_num], -0.2, card_x2[card_num], -0.8);
card_num++;
glutSwapBuffers();
glutPostRedisplay();
Redisplay = true;
}
}

Thanks in advanced. Any other comments are welcome. I’m a complete beginner using GLUT.

Hi !

If you turn on doublebuffering it will not flash.

Mikael

Trash the idle function. If you only want to redisplay after mouse action, then you want a glutPostRedisplay in your mouse event handler.

Display code should never be anywhere else but in the display callback. This ensures it gets called upon window creation, for starters.

If you need animation, this again requires an idle callback with glutPostRedisplay, so this won’t work.
Note that you can ‘hook’ the idle function when an animation starts and ‘unhook’ it (glutIdleFunc(NULL); ) when the animation has finished. The idle callback can unhook itself, if required.

I’m using Double Buffering, I have glutSwapBuffers(); in both the display function on everywhere else that I have glutPostDisplay();

No, no, no. You should only have the glutSwapBuffers in the display function. glutPostDisplay only puts a WM_PAINT message in the windows message queue. It will NOT call Display at that point, and even if it did, you have glutSwapBuffers in your display function, so why would you want to swap again? You’d be swapping back to a back buffer that hasn’t been drawn to!

Originally posted by Deiussum:
No, no, no. You should only have the glutSwapBuffers in the display function. glutPostDisplay only puts a WM_PAINT message in the windows message queue. It will NOT call Display at that point, and even if it did, you have glutSwapBuffers in your display function, so why would you want to swap again? You’d be swapping back to a back buffer that hasn’t been drawn to!

Hmm, that is good to know. I don’t know much about GLUT and OpenGL and rely only on what I can get from my books. Through, it may be that I haven’t seen the function except in the Display Function. I thought that somehow it would help.

I have tried displaying the image using just the mouse function but it never before worked like it should. I was told that only the Idle Function will actually display the image and everything that calls the glutPostRedisplay() is put in a sort of queue for the Idle Function to pick up and display.

What seems like a simple task is causing me a lot of confusion and time. I will try to do without the Idle Function and just keep everything in the mouse or Keyboard function but what do I do when it doesn’t work and I have to go back to Idle Function. I don’t konw enough about OpenGL to not use GLUT.

Thanks, I’m learning a lot from experience and this forum.

Originally posted by zeckensack:
[b]Trash the idle function. If you only want to redisplay after mouse action, then you want a glutPostRedisplay in your mouse event handler.

Display code should never be anywhere else but in the display callback. This ensures it gets called upon window creation, for starters.

If you need animation, this again requires an idle callback with glutPostRedisplay, so this won’t work.
Note that you can ‘hook’ the idle function when an animation starts and ‘unhook’ it (glutIdleFunc(NULL); ) when the animation has finished. The idle callback can unhook itself, if required.[/b]

So how would I use glutIdleFunc(NULL)? Or where do I put it in the code to where it will work. I have tried something like this in the Idle Function but it didn’t display anything at all. It was at the very last line in the function. If I could get this working then I can understand some of what I have to do to complete the rest of the program.

Let’s fix your code snippet first

GLfloat card_x1[3] = { 0.0, 0.2, 0.4 };
GLfloat card_x2[3] = { 0.4, 0.6, 0.8 };
int card_num = 0;

void redisplay()
{
glColor3f(0.0, 0.0, 1.0);
glRectf(card_x1[card_num], 0.2, card_x2[card_num], 0.8);
glRectf(card_x1[card_num], -0.2, card_x2[card_num], -0.8);
card_num++;
glutSwapBuffers();
}

void idle()
{
//do nothing
}

void mouse(int button, int state, int x, int y)
{
if(state == GLUT_DOWN && button == GLUT_LEFT_BUTTON)
exit(0);
if(state == GLUT_DOWN && button == GLUT_RIGHT_BUTTON)
{
glutPostRedisplay();
}
}

What I meant with animation above was that you might want to play some animation over a number of frames without user interaction. Eg the user clicks somewhere and a pig flys across the screen for the next 100 frames

That would look something like

bool flying_pig=false;
float flying_pig_position=0.0f;
float flying_pig_speed=0.0f;

void
display()
{
//render_static_stuff
.
.
.
if (flying_pig)
{
flying_pig_position+=flying_pig_speed;
//draw the pig at its new position
.
.
.
if (flying_pig_position>100.0f) //pig left the screen
//turn off the animation
flying_pig=false;
}
glutSwapBuffers();
}

void
idle()
{
glutPostRedisplay();
//we can unhook the idle function if nothing needs to be animated
if (!flying_pig) glutIdleFunc(NULL);
}

void
keyboard(<…> )
{
if (<user_pressed_p> )
{
flying_pig=true; //signal that an animation is running
//set pig to its starting position and give it some speed
flying_pig_position=0.0f;
flying_pig_speed=1.0f;
//activate the idle callback to keep the animation running
glutIdleFunc(idle);
}
}

Originally posted by zeckensack:
[b][quote]

bool flying_pig=false;
float flying_pig_position=0.0f;
float flying_pig_speed=0.0f;

void
display()
{
//render_static_stuff
.
.
.
if (flying_pig)
{
flying_pig_position+=flying_pig_speed;
//draw the pig at its new position
.
.
.
if (flying_pig_position>100.0f) //pig left the screen
//turn off the animation
flying_pig=false;
}
glutSwapBuffers();
}

void
idle()
{
glutPostRedisplay();
//we can unhook the idle function if nothing needs to be animated
if (!flying_pig) glutIdleFunc(NULL);
}

void
keyboard(<…> )
{
if (<user_pressed_p> )
{
flying_pig=true; //signal that an animation is running
//set pig to its starting position and give it some speed
flying_pig_position=0.0f;
flying_pig_speed=1.0f;
//activate the idle callback to keep the animation running
glutIdleFunc(idle);
}
}

[/b][/QUOTE]

I will try to do this with my code. Well, is there any way to not have the change code in the display function. I have no problem with it, if it works then it works and I will be happy. Anything is better than what I have now. Through, the reason why I would want to split the code in to functions is somewhat misplaced. I can’t wait to try it out.

To understand how glut works, you need to understand how Win32 programming in general works. Windows programming is an event-driven system. With the base Win32 API, you basically register a callback function that gets called for all events, then you check for those events. Glut does this as well, but hides the details from you and lets you register for individual events.

One of the events is the WM_PAINT message, which signals that the scene needs to be redisplayed. (The window may have been minimized and restored, resized, uncovered from another window, or any other number of things that cause an area to need to be redrawn.) To register to receive WM_PAINT messages, you use glutDisplayFunc. (Note: I believe glut REQUIRES this one.)

Another event is a resize event, which you have glut inform you of by using glutReshapeFunc. Then there are the keyboard, mouse events, etc. etc.

glutIdleFunc is a special callback because it is called for every time the “message pump” looks for events but doesn’t find any. That’s why it is a good place to do updates for animation, etc.

glutPostRedisplay, basically just adds a WM_PAINT event to your message Q so that after your callback function exits, and glut checks for another event underneath, it will know to call the function registered with glutDisplayFunc.

Hope that helps…

Originally posted by Deiussum:
To understand how glut works, you need to understand how Win32 programming in general works. Windows programming is an event-driven system.

So, what you are saying is: no. The example seems like a really good one. I thought that only the IdleFunc can create new drawings but maybe I misunderstood what I was reading.
Is this why people take classes for this stuff?

I’m just doing Console C++ programming right now and technically, I shouldn’t really be working with OpenGL since I am still a novice with C++. Through, it is not C++ that is hard, it is working with the API and libraries that makes it hard. Well, technically, C++ can get really, really hard but I’m not interested in creating professional programs yet or creating APIs.

Nope. Read what I said about the Display function and Idle functions again. The display function is called when you need to display, the Idle function is called when there are no other events. If you want to continuously update, you use the idle function to post display events, which then causes the display function to get called…

Originally posted by Deiussum:
Nope. Read what I said about the Display function and Idle functions again. The display function is called when you need to display, the Idle function is called when there are no other events. If you want to continuously update, you use the idle function to post display events, which then causes the display function to get called…

I think I understand now, I will need to use Idle function no matter what animation I want to do, even if it is to just display something and keep it there. Thanks a lot!

I seemed to have done what I wanted. I need to run some more tests to make sure it is correct. It will be a different problem through.