GLUT supports simple cascading pop-up menus. They are designed to let a user select various modes within a program. The functionality is simple and minimalistic and is meant to be that way. Do not mistake GLUT's pop-up menu facility with an attempt to create a full-featured user interface. It is illegal to create or destroy menus, or change, add, or remove menu items while a menu (and any cascaded sub-menus) are in use (that is, popped up).
The popup menus can be arranged in a hierachy of menus, sub-menus, sub-sub-menus, and so on. Since a sub-menu identifier must be passed as an argument to the GLUT functions that create the parent menu, the menu must be created from the bottom up. For example, assume we want to create a main menu with entries Option A or Submenu1, where the sub-menu has entries of Options B, C, or Submenu2, where the sub-sub-menu has Options D and E.
Submenu identifiers must be declared for each of our menu entries. This is a unique integer value will be assigned as the menus are called by glutCreateMenu(). Start with the lowest level menu and pass as an argument the callback function, menuCB, which defines menu selection options. To create the lowest level menu and its entries:
Then go up one more level and do the same thing for Submenu1:
Finally, we need to go the same thing for the highest level menu:
These menu options can now be used in the callback function menuCB to process the users menu choice.
void menuCB(int item)
. . .
GLUT supports interaction with the computer mouse that is triggered when one of the three typical buttons is presses. A mouse callback fuction can be initiated when a given mouse button is pressed or released. The command glutMouseFunc() is used to specify the callback function to use when a specified button is is a given state at a certain location. This buttons are defined as either GL_LEFT_BUTTON, GL_RIGHT_BUTTON, or GL_MIDDLE_BUTTON and the states for that button are either GLUT_DOWN (when pressed) or GLUT_UP (when released). Finally, x and y callback parameters indicate the location (in window-relative coordinates) of the mouse at the time of the event.
Just as with the menu options above, the callback function can use a switch statement with multiple variations of mouse buttons, actions and locations to do some pretty niffy things. For example, we could use the mouse to cause an object within certain x and y ranges to rotate 90 degrees to the right with a click of the right button, to rotate 90 degrees to the left with a click of the left button, and to flip upside down with a click of the middle button.
This program will take mouse interaction input and will respond by rotating 90 degrees to the right for a right click, rotating 90 degrees to the left for a left click, and flipping upside-down for a click of the middle button.
GLUT interaction using keyboard inputs is handled very similarly to those with the mouse. The command glutKeyboardFunc() is used to run the callback function specified and pass as parameters, the ASCII code of the pressed key, and the x and y coordinates of the mouse curor at the time of the event.
Special keys can also be used as triggers. The key passed to the callback function, in this case, takes one of the following values (defined in glut.h).
As we have seen, the screen window will only be redrawn whenever the display callback function is involked. This occurs automatically when the window is resized or uncovered. You can explicitly force the display callback to be involked by issuing the command glutPostRedisplay(). To perform an animated simulation, we obviously want to continually update the window, however, we do not want to constantly issue a stream of glutPostRedisplay() calls. We need a mechanism for the window to be continually updated automatically.
There are two callback functions that are helpful in this regard: Idle Callback (glutIdleFunc()) and Timer Callback (glutTimerFunc()). The Idle Callback specifies a function that is involked whenever the system is not handling any other callbacks or events. While the Timer Callback specifies a function that is involked after a specified time period. When the Timer Callback function is involked, after a time interval, measured in milliseconds, an identifier is passed in as an argument.
Note that the Timer Callback function is only involked once, after the specified time interval in the call to glutTimerFunc(). To have the timer callback involked automatically after each successive time interval, place a second call to glutTimerFunc() inside the Timer Callback function - causing reiterative calls.
Most OpenGL implementations provide double-buffering - hardware or software that supplies two complete color buffers. One is displayed while the other is being drawn. When the drawing of a frame is complete, the two buffers are swapped, so the one that was being viewed is now used for drawing, and vice versa. With double-buffering, every frame is shown only when the drawing is complete; the viewer will never see a partially drawn frame. The code will specify a callback function to perform when idle. This should cause some kind of change of variable - usually a change in angle (angle = angle + 2.0), for example. It should also include the command glutPostRedisplay(). This will cause the display function to be involked again with the new variable. The display function should include a command to glutSwapBuffers() to cause the next buffer to be created, and subsequently redrawn due to the glutIdleFunc() command.
This program creates a crane-like object that has a ball swinging from the end of a rope.
Back to Top