PDA

View Full Version : Problem with glutIdleFunc



Mighty
04-20-2004, 10:12 AM
So I have a function (call it foo()) that moves my gameObjects. So when I call this function, I immediately glutIdleFunc(NULL), which originally pointed to my main function glutDisplay. The problem I'm having comes when I want to redraw after a move is made. I still want to make more moves though. Here's my algorithm in a nutshell


foo()
{
glutIdleFunc(NULL);
while(moreMovesToMake())
{
makeMove();
//update board to show move
glutDisplay();
}
glutIdleFunc(glutDisplay);
} Basically the board does not update while in this loop even when I call glutDisplay()
Anyone know why?

plasmonster
04-20-2004, 10:43 AM
Mighty, if you've never worked with an event driven system like windows, this might be a little confusing at first. Rather that calling glut functions directly, glut will let you know when something important happens. For example, when the world needs to be redrawn, glut will call your display() function so that you can draw; when the application is idle, glut will call your idle() function, and so on. You need only concern yourself with defining these basic functions to handle the various events, glut will do the rest!

Here's a glut typical setup in main:

int main( int argc, char** argv ) {

glutInit( &argc, argv );
glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL );
glutInitWindowSize( 640, 480 );
glutInitWindowPosition( 0, 0 );
glutCreateWindow( "MyWindowName" );
glutIdleFunc( myIdleFunc );
glutDisplayFunc( myDisplayFunc );
glutReshapeFunc( myReshapeFunc );
glutKeyboardFunc( myKeyboardFunc );
glutSpecialFunc( mySpecialFunc );
glutMouseFunc( myMouseFunc );
glutMotionFunc( myMotionFunc );

// ... there are others ...
// you don't need to define them all

// this begins the event (message) loop
glutMainLoop();

}

Overmind
04-20-2004, 11:25 AM
In addition to that, NEVER call your display function directly.

You need to register it with glutDisplayFunc, and then you should call glutPostRedisplay to tell glut that you want to redraw the scene.

Mighty
04-20-2004, 03:01 PM
Overmind and Portal, thank you for the replies.
Yes I am new to the event driven systems. I've been reading the red book and I'm getting a hang of it. Here's what I have in the message loop. (see listing below)
BTW Portal, I changed the glutDisplay calls to glutPostDisplay, so I'm assuming this will explicitly call the display func I registered with glut via glutDisplayFunc(glutDisplay);

Anyways I'm still having problems. It stil won't redraw the display between moves? It is important for this program to stall the drawing processes because its an AI system which relies on generating as many states as possible, basically I don't want the drawing to steal any clock cycles.

Any ideas on what I can do?
Thanks in advance
Mighty

Here again is what I'd like to do...

foo()
{
glutIdleFunc(NULL); //stop drawing
while(moveMakeMoves())
{
makeTheMove();
glutPostRedisplay(); //redraw window
}

}Here's what I have in main...

int main(int argc, char** argv)
{
/*
Glut's initialization code. Set window's size and type of display.
Window size is put half the 800x600 resolution as defined by above
constants. The windows is positioned at the top leftmost area of
the screen.
*/
glutInitDisplayMode( GLUT_DOUBLE | GLUT_DEPTH | GLUT_RGBA | GLUT_MULTISAMPLE );
glutInitWindowPosition( GL_WIN_INITIAL_X, GL_WIN_INITIAL_Y );
glutInitWindowSize( GL_WIN_WIDTH, GL_WIN_HEIGHT );
glutInit( &argc, argv );

glutCreateWindow("Checkers");

/*
The function below are called when the respective event
is triggered. Very simple, isn't it?
*/
glutReshapeFunc(glutResize); // called every time the screen is resized
glutDisplayFunc(glutDisplay); // called when window needs to be redisplayed
glutIdleFunc(glutDisplay); // called whenever the application is idle
glutKeyboardFunc(glutKeyboard); // called when the application receives a input from the keyboard
glutMouseFunc(glutMouse); // called when the application receives a input from the mouse
glutMotionFunc(glutMotion); // called when the mouse moves over the screen with one of this button pressed
glutSpecialFunc(glutSpecial); // called when a special key is pressed like SHIFT

/*
Do any lighting, material, alpha, etc initialization or
configuration here.
*/
InitializeOGL();

/*
Creates a menu attached to the mouses middle button
the menu here consists in two options, one to toggle
fullscreen mode and another for exiting the application.
*/
glutCreateMenu(glutMenu);
glutAddMenuEntry("Full Screen", 1);
glutAddMenuEntry("Exit", 2);
glutAttachMenu(GLUT_MIDDLE_BUTTON);

/*
Application's main loop. All the above functions
are called whe the respective events are triggered
*/
glutMainLoop();

return 0;
}

nexusone
04-20-2004, 04:39 PM
I know some examples use display as the glutidlefunc callback, but remember the main point of some examples is to show how a said function works. Does not mean the way the program is written is the best way to go about doing a full program.

Better that glutIdleFunc or glutTimerFunc point to it own routine.

glutIdleFunc( foo );
glutDisplayFunc( display );

// Now foo loop's and only updates the screen if there has been a event that causes a screen change.

void foo(void)
{

if (move_player) some_event = 1; // Update display because of player move.

if (move_AI) some_event = 1 // Update display because AI or computer move.
// Repeat for events needing a screen update.

if (some_event) glutPostRedisplay(); // Update display because of event. Note glutPostRedisplay is the correct way to call for a display update.

} // End event loop.

Mighty
04-20-2004, 05:36 PM
Interesting, so are you basically advising me to have function foo (called TeamTakeTurn in the program) as the glutIdleFunc? When does glut decide to call this function with the messageloop?

nexusone
04-21-2004, 04:37 AM
I know I used foo for the idle routine, maybe that through you off a bit.

Let's call our control loop, My_control_loop and not foo.

glutIdleFunc( My_control_loop ); // will be called when the glut main loop is idle. other option would be to use glutTimerFunc called after X time has past.

void My_control_loop( void )
{
// GLUT is going to call this loop over and over durring idle time to see if any event has happened.

// Now we have to say at what event should some action take place.

// example say the arrow key's are being pressed, our keyboard routine would set a state flag that we are moving.

if ( player_move )
{

// Do some processing here to update player data, like our foo routine.
foo();
// Note each loop we will call foo until the player has finnish his move, or any animation needs to be done of the object.
}
if( computer_move )
{
// Process move here
}

glutPostRedisplay(); // Update screen.
}

void foo(void)
{
if(moreMovesToMake())
{
makeMove();
}
}

Also it may help for you to write down what you want your program to do in steps.

example:

Start of program:
setup window
display title
Loop and wait for user input

start of game
zero score
setup play area
enter into game play loop
player dies routine
player win routine

Just a idea of where to start


Originally posted by Mighty:
Interesting, so are you basically advising me to have function foo (called TeamTakeTurn in the program) as the glutIdleFunc? When does glut decide to call this function with the messageloop?

Mighty
04-21-2004, 10:32 AM
Awesome nexusone, I appreciate the explanation, it helps out a lot.

Mighty

zeckensack
04-21-2004, 10:55 AM
Just to add my cents here ...

A natural place to trigger a world update (including a redraw) is the keyboard and mouse callbacks. If the "camera" or a player or whatnot moves, you need to redisplay. If your scene is otherwise static, this is the only place you really need to call glutRedisplay.

If you want an automatically playing animation, there's no special event that should trigger an update. In this case, you should call glutPostRedisplay from your idle callback.
If you add some logic to your idle callback that determines whether or not there's an animation running, you can avoid unnecessary screen updates here. Though most programs are quite contempt with drawing as fast as they can, even if nothing happens on screen, it doesn't mean everyone must do that.

This isn't immediately necessary, but it's something that will matter in the long run:
Always try to make your animation independent of rendering speed. Use a timer. Instead of moving an object by a fixed amount per frame, assign to it a velocity (which can be a vector), scale that with the time since last frame and add it to the old position.

Several options are available to get the time that passed since the last frame. On Win32 QueryPerformanceCounter is a reasonable option.
You can also try out GLUT's timer callback mechanism. It's quite easy to use, but it won't be as precise.