This article describes in detail how to create your first GLUI window with some basic controls inside it, and provides you with a template for your OpenGL applications.
This article can be used in the following ways:
GLUT and GLUI events. GLUI library GLUI library created specifically for graphical manipulation, such as the rotation and translation controls. Make sure you read the GLUT Window Template article as a prerequisite to this article. One important thing to note is that GLUI is a C++ library, which means that your code must be written in files with CPP extension rather than C, otherwise the linker will complain.
GLUI is a C++ GUI library, built entirely on top of GLUT, to provide GUI controls such as buttons, checkboxes, radio buttons, labels, panels, text fields and spinners to OpenGL applications. It is window-system independent, relying on GLUT to handle all system-dependent issues, such as window, keyboard, joystick and mouse management. The GLUI API is very simple, allowing us to create new GLUI windows and add controls inside them with a single line of code. To add to its simplicity, GLUI automatically positions and sizes controls when placed on their window.
Here's an example GLUI window taken from the GLUI Manual, showing the different controls. This window is rendered entirely in OpenGL. It therefore looks the same on PCs, Macs, SGIs, and other UNIXes, using either SGI's implementation of OpenGL, Microsoft's, or Mesa's.
In addition to the above controls, GLUI has seen some additional controls after its new 2.35 version release in July 2006. You can see below the new scroll bar, text area, file browser, tree, tree panel and list.
When OpenGL applications get more complex, we need something more than a GLUT mouse, keyboard, and/or popup menus to interact with our OpenGL objects drawn on the window. GLUI gives us more flexibility by allowing us to add GUI components to interact with our OpenGL objects, such as buttons, check boxes, radio buttons, spinners, list boxes, lists, trees, file browsers, text fields, text areas, and the special controls: rotation and translation.
To avoid having to write the same code every time you want to create an OpenGL graphical application with GUI components, this program code can be used as a template to get you directly started.
In order to run the program, three dynamic link libraries (DLLs) are required: opengl32.dll, glu32.dll, glut32.dll. The opengl32.dll and glu32.dll already come with your Windows OS and are found in the system folder. To run the executable, you have to download the glut32.dll and copy it into your system folder. You can find all the DLL files in the attached zip file GLUI_Window_Template_dll.zip under Visual C++\dll.
In order to write a C++ OpenGL application with GLUI using Microsoft Visual Studio on a Windows platform, you need the following files:
You can find all the header files and lib files in the attached zip file GLUI_Window_Template_dll.zip under Visual C++\include\GL and Visual C++\lib respectively.
To use the code under a Visual C++ 6.0 environment, perform the following steps:
| Files | Description | Source Folder (Attached) | Target Folder |
| GL.H, GLU.H, GLUT.H, GLUI.H | Header Files | Visual C++/include/GL | C:\Program Files\Microsoft Visual Studio\VC98\Include\GL |
| OPENGL32.LIB, GLU32.LIB, GLUT32.LIB, GLUI32.LIB | Lib Files | Visual C++/lib | C:\Program Files\Microsoft Visual Studio\VC98\Lib |
| OPENGL32.DLL, GLU32.DLL, GLUT32.DLL | DLL Files | Visual C++/dll | C:\WINDOWS\system32 |
GLUI, GLUT, GLU, OpenGL.
To avoid having to set the link settings in every Visual C++ 6.0 project you create, you may want to include the following code segment in your code, which would basically do the same thing as above.
// Link the lib files to the program. This is not necessary
// if you have added the lib names using Project/Settings/Link
#pragma comment (lib, "glui32.lib")
#pragma comment (lib, "glut32.lib")
#pragma comment (lib, "glu32.lib")
#pragma comment (lib, "opengl32.lib")
#pragma comment( linker,
"/subsystem:\"windows\" /entry:\"mainCRTStartup\"" )
The source code is intended to be used as a template for your OpenGL applications. To use it in your new application, you can simply rename the CPP file and add it to your Visual Studio project.
Please note that GLUI is a C++ library, and thus doesn't work with C. So if you're obtaining linkage errors while trying to build a GLUI program, just check that all file extensions are CPP and not C.
Knowing that GLUI is built on top of GLUT, it requires very little change to integrate GLUI components with an existing GLUT application. Thus, we will start with the GLUT Window Template and apply changes to it until we create our GLUI Window Template.
First, we start by including the header file for GLUI using the following include directive:
#include <GL/glui.h>
There is no need to include <GL/gl.h>, <GL/glu.h>, or <GL/glut.h> since <GL/glui.h> already includes them.
After creating our GLUT window, we need to make sure that we keep track of the window id so that GLUI can interact with it and send it redisplay events.
main_window = glutCreateWindow (window_title);
GLUT 'callback' functions are registered as usual, except for the Idle function.
// Set the callback functions
glutDisplayFunc (display);
glutReshapeFunc (reshape);
glutMouseFunc (mouse);
glutMotionFunc (motion);
glutPassiveMotionFunc (pmotion);
glutKeyboardFunc (keyboard);
glutSpecialFunc (special);
glutEntryFunc (entry);
An idle callback function is called whenever an idle state is reached. An idle state is a state where no system events are received for processing as callbacks. The glutIdleFunc sets the idle callback function, which is continuously called as long as there are no events received. This means that we should minimize the amount of computation and rendering in the idle function to have a more interactive application. Passing NULL to glutIdleFunc disables the generation of the idle callback.
In a normal GLUT application, the idle function is registered as follows:
glutIdleFunc (idle);
However, when GLUI is used, the idle callback function is registered through the GLUI global object, GLUI_Master. The reason for this is that GLUI makes extensive use of idle events. Logically, it does so in order to keep refreshing the GLUI controls and to listen to user's interactions with them.
GLUI_Master.set_glutIdleFunc (idle);
If there is no Idle callback to be used, NULL is passed:
GLUI_Master.set_glutIdleFunc (NULL);
GLUT idle function, we need to explicitly set the current window before posting a redisplay event. Otherwise, the redisplay may be accidentally sent to the GLUI window rather than the GLUT window. void idle ( )
{
glutSetWindow(main_window);
glutPostRedisplay();
}
GLUI takes an inordinate amount of the CPU time even when the application is idle. The reason for this is that the GLUI window with all the controls inside it are being refreshed continuously. In order to avoid having a 100% CPU usage whenever we run a GLUI window, we need to call the Windows system function, Sleep, which would help us avoid continuously calling the idle function.
Even if no idle function is specified, the GLUI application would consume most of the CPU time and cause your system to run slowly.
When we call the Sleep function as shown below, the CPU usage by the GLUI application reduces to almost 0%.
#include <windows.h>
void idle ()
{
glutSetWindow (main_window);
glutPostRedisplay ();
Sleep (100);
}
The GLUI window is created as follows:
// pointer to a GLUI window
GLUI * glui_window;
// Create GLUI window
glui_window = GLUI_Master.create_glui ("Options");
Here is the create_glui function definition, as described in the GLUI manual:
GLUI *GLUI_Master_Object::create_glui(char *name, int flags=0, int x=-1,
int y=-1);
| Attribute | Description |
name |
Name of new GLUI window |
flags |
Initialization flags. No flags are defined in the current version |
x,y |
Initial location of window. Note that no initial size can be specified, because GLUI automatically resizes Windows to fit all controls |
Note that flags, x, and y are optional arguments. If they are not specified, default values will be used. GLUI provides default values for arguments whenever possible. The function returns a pointer to a new GLUI window.
In addition to the function that creates the window, GLUI also supports functions to enable, disable, hide, show, or close a window. Below is the prototype and description of each of these functions, as shown in the GLUI manual:
| Name | Prototype | Description |
get_glut_window_id |
int GLUI::get_glut_window_id( void ); |
Returns the standard GLUT window ID of a GLUI window |
enable, disable |
void GLUI::enable( void );void GLUI::disable( void ); |
Enables or disables (grays out) a GLUI window. No controls are active when a GLUI window is disabled |
hide |
void GLUI::hide( void ); |
Hides a GLUI window or subwindow. A hidden window or subwindow cannot receive any user input |
show |
void GLUI::show( void ); |
Unhides a previously-hidden GLUI window or subwindow |
close |
void GLUI::close( void ); |
Cleanly destroys a GLUI window or subwindow |
close_all |
void GLUI_Master_Object::close_all( void ); |
Cleanly destroys all GLUI windows and subwindows. This function is called by the following example code: GLUI_Master.close_all(); |
GLUI can associate live variables with most types of controls. Live variables are simply C variables that are automatically updated when the user interacts with a GLUI control. If the user directly updates a live variable from the code without using the set method of the control, then we need to call the sync_live () function in order to synchronize the control with the value of the live variable.
For example, let's say we have a checkbox associated with a live variable as follows:
int draw = 0;
glui_window->add_checkbox ( "Draw", &draw );
When the program starts, the Draw checkbox will be un-checked since the value of the draw live variable is 0. If the value of draw was 1, then the Draw checkbox would have appeared as checked. Let's say that after the program loads, the user clicks on the checkbox to make it checked as follows:
When that happens, GLUI automatically updates the value of the draw live variable to 1.
Also, let's assume that somewhere in the code, the programmer updates the value of the draw value back to 0. Doing this will not affect the control, and thus the control and the live variable will become un-synchronized.
draw = 0;
In order to avoid this, we can call the sync_live() method of the current window to update the user interface:
glui_window->sync_live();
In case there are multiple windows, we can use the sync_live_all() function of the GLUI Master Object to synchronize live variables and controls in all GLUI windows:
GLUI_Master.sync_live_all();
Otherwise, we should not apply any direct changes to live variables. We can avoid that by directly using the set method(s) of the control:
draw_checkbox.set_int_val ( 0 );
In addition to having live variables to track the values of controls, GLUI can also generate callbacks whenever the value of a control changes. When a control is first created, the user may optionally specify the callback function that will be called whenever the control's value changes, along with an integer ID to identify the calling control. This would mean that multiple controls may call the same callback function, and still be identified through their different IDs passed to the function.
glui_window->add_checkbox ( "Draw", &draw, ID,
callback_func );
Here is the list of supported control types, their GLUI name, description, accessor functions, live variables and callbacks, as copied from the GLUI Manual:
| Control Type | Class Name | Used for... | Set/Get values |
Live var? | Callback? |
| Panel | GLUI_Panel |
grouping controls into boxes |
-
|
-
|
N
|
| Column | GLUI_Column |
grouping controls into columns |
-
|
-
|
N
|
| Rollout | GLUI_Rollout |
grouping controls into collapsible boxes |
-
|
-
|
N
|
| Button | GLUI_Button |
invoking user actions |
-
|
-
|
Y
|
| Checkbox | GLUI_Checkbox |
handling booleans |
get_int_valset_int_val |
int |
Y
|
| Radio Group, Radio Button |
GLUI_RadioGroup, GLUI_RadioButton |
handling mutually-exclusive options |
get_int_valset_int_val |
int |
Y
|
| Static Text | GLUI_StaticText |
plain text labels |
set_text |
-
|
N
|
| Editable Text | GLUI_EditText |
text that can be edited and optionally interpreted as integers or floats. Upper and lower bounds can be placed on integers and floats |
|
intfloattext |
Y
|
| Rotation | GLUI_Rotation |
Inputting rotation values via an arcball |
get_float_array_val |
float [16] |
Y
|
| Translation | GLUI_Translation |
Inputting X, Y, and Z values |
get_xget_yget_z |
float [1] OR [2] |
Y
|
| Listbox | GLUI_Listbox |
Choosing from a list of items |
get_int_val |
int |
Y
|
| Spinner | GLUI_Spinner |
interactively manipulating numeric values. Supports single clicks, click-hold, and click-drag. Upper and lower bounds can be specified |
get_int_valset_int_valget_float_valset_float_val |
intfloat |
Y
|
| Separator | GLUI_Separator |
separating controls with simple horizontal lines |
-
|
-
|
N
|
Knowing that GLUI is implemented through Object Oriented C++, all the GLUI controls inherit from the base class GLUI_Control. There are two functions to create a control: add_control () and add_control_to_panel (), where control is replaced by the type of the control. For example, we can create a checkbox using any of the following two functions:
This function adds a checkbox at the top level of the window.
GLUI_Checkbox *GLUI::add_checkbox( char *name, int *live_var=NULL, int id=-1,
GLUI_Update_CB callback=NULL);
This function nests the checkbox within a panel.
GLUI_Checkbox *GLUI::add_checkbox_to_panel( GLUI_Panel *panel, char *name,
int *live_var=NULL, int id=-1, GLUI_Update_CB callback=NULL);
In addition to the common method for creating controls, there are common functions that can be used on most of the controls and are all inherited from the GLUI_Control base class. Here is the list of those methods, copied from the GLUI manual:
| Name | Prototype | Description |
set_name |
|
Sets the label on a button, checkbox, etc. |
set_w, set_h |
|
Sets new minimum width/height for a control. set_w() is especially useful to increase the size of the editable text area in an editable text control or spinner. |
get, set |
int GLUI_Control::get_int_val( void ); |
Gets or sets the value of a control. Refer to the individual control descriptions below to see which values can be read and set for each control. |
disable, enable |
void GLUI_Control::enable( void ); |
Disables (grays out) or enables an individual control. A disabled control cannot be activated or used. Disabling a radio group disables all radio buttons within it, and disabling a panel disables all controls within it (including other panels). Enabling behaves similarly. |
set_alignment |
|
Sets the alignment of a control to left-aligned, right-aligned, or centered. |
After describing live variables, callbacks, list of controls, and common functions, now it's time to see how controls are added and how they would interact with our OpenGL application. Below is the list of GLUI function prototypes for every control. For more details about each of the following functions, please check the GLUI manual.
| Control | add_control \ add_control_to_panel \ Other |
| Panels |
|
| Rollouts |
|
| Columns |
|
| Buttons |
|
| Checkboxes |
|
| Radio Buttons |
|
| Static Text |
|
| Editable Text Boxes |
|
| Spinners |
|
| Separators |
|
| Rotation Controls |
|
| Translation Controls |
|
| Listboxes |
|
GLUI window. A "panel" is used to group controls together. Panels can be nested, and thus one can say add_panel_to_panel (). // Add the 'Object Properties' Panel to the GLUI window
GLUI_Panel *op_panel = glui_window->add_panel (
"Object Properties");
Draw checkbox to the panel.// Draw Check Box Live Variable
int draw = 1;
// Add the Draw Check box to the 'Object Properties' Panel
glui_window->add_checkbox_to_panel (op_panel, "Draw", &draw );
When the Draw checkbox is checked or unchecked, it affects whether the object is displayed on the window. This is done by placing the following code segment in the display function:
if (draw)
{
// Draw Object...
}
Wireframe checkbox.// Wireframe checkbox Live Variable
int wireframe = 1;
// Add the Wireframe checkbox to the 'Object Properties' Panel
glui_window->add_checkbox_to_panel (op_panel, "Wireframe",
&wireframe );
When the Wireframe checkbox is checked or unchecked, it affects whether the object is displayed in solid or wireframe. This is done by placing the following code segment in the display function:
if (wireframe)
{
drawWireObject ();
}
else
{
drawSolidObject ();
}
// Add a separator
glui_window->add_separator_to_panel (op_panel);
Color listbox. The add_listbox_to_panel takes the following arguments: the panel to which the listbox is to be added, the name of the listbox, the live variable which will be updated with the id of the selected item, the listbox control id that will be passed to the callback function, and the callback function. After creating the listbox, an item is added to it by calling the add_item function, which takes the item id and item name as arguments. After creating the listbox, we set the default item in the listbox by calling the set_int_val () function.// Id of the selected item in the list box (List Box Live Variable)
int listbox_item_id = 12;
// Add the Color listbox to the 'Object Properties' Panel
GLUI_Listbox *color_listbox = glui_window->add_listbox_to_panel (
op_panel, "Color", &listbox_item_id, COLOR_LISTBOX, glui_callback);
// Add the items to the listbox
color_listbox->add_item (1, "Black");
color_listbox->add_item (2, "Blue");
color_listbox->add_item (3, "Cyan");
color_listbox->add_item (4, "Dark Grey");
color_listbox->add_item (5, "Grey");
color_listbox->add_item (6, "Green");
color_listbox->add_item (7, "Light Grey");
color_listbox->add_item (8, "Magenta");
color_listbox->add_item (9, "Orange");
color_listbox->add_item (10, "Pink");
color_listbox->add_item (11, "Red");
color_listbox->add_item (12, "White");
color_listbox->add_item (13, "Yellow");
// Select the White Color by default
color_listbox->set_int_val (12);
Whenever a user selects a color from the listbox, the glui_callback function is called and the COLOR_LISTBOX id is passed to it. Based on the item selected, the color array will be filled with the appropriate RGB components. For example, when the user selects the Grey color, the following code is executed in the glui_callback function:
switch (control_id)
{
// Color Listbox item changed
case COLOR_LISTBOX:
switch (listbox_item_id)
{
// Select grey color
case 5:
color[0] = 128/255.0;
color[1] = 128/255.0;
color[2] = 128/255.0;
break;
}
break;
}
After a GLUI callback, GLUI automatically posts a redisplay event, and the display function is called. In order to reflect the changes in the color of the object, the following code fragment is placed in the display function before the object is drawn:
// Set the color
glColor3fv (color);
// Draw object
drawObject ();
![]() Rollout Panel |
Collapsed Rollout Panel |
GLUI window. A rollout is a collapsible panel. // Add the 'Object Type' Rollout Panel to the GLUI window
GLUI_Rollout *ot_rollout = glui_window->add_rollout (
"Object Type");
// Id of the selected radio button
int radiogroup_item_id = 0;
// Create radio button group
GLUI_RadioGroup *ot_group = glui_window->add_radiogroup_to_panel (ot_panel,
&radiogroup_item_id, OBJECTYPE_RADIOGROUP, glui_callback);
GLUI_RadioGroup::get_int_val(), or set with GLUI_RadioGroup::set_int_val(). // Add the radio buttons to the radio group
glui_window->add_radiobutton_to_group( ot_group, "Cube" );
glui_window->add_radiobutton_to_group( ot_group, "Sphere" );
glui_window->add_radiobutton_to_group( ot_group, "Cone" );
glui_window->add_radiobutton_to_group( ot_group, "Torus" );
glui_window->add_radiobutton_to_group( ot_group, "Dodecahedron" );
glui_window->add_radiobutton_to_group( ot_group, "Octahedron" );
glui_window->add_radiobutton_to_group( ot_group, "Tetrahedron" );
glui_window->add_radiobutton_to_group( ot_group, "Icosahedron" );
glui_window->add_radiobutton_to_group( ot_group, "Teapot" );
Based on the radio button selected and the wireframe checkbox state, we need to display the right GLUT geometric shape.
// The different GLUT shapes
enum GLUT_SHAPES
{
GLUT_WIRE_CUBE = 0,
GLUT_SOLID_CUBE,
GLUT_WIRE_SPHERE,
GLUT_SOLID_SPHERE,
GLUT_WIRE_CONE,
GLUT_SOLID_CONE,
GLUT_WIRE_TORUS,
GLUT_SOLID_TORUS,
GLUT_WIRE_DODECAHEDRON,
GLUT_SOLID_DODECAHEDRON,
GLUT_WIRE_OCTAHEDRON,
GLUT_SOLID_OCTAHEDRON,
GLUT_WIRE_TETRAHEDRON,
GLUT_SOLID_TETRAHEDRON,
GLUT_WIRE_ICOSAHEDRON,
GLUT_SOLID_ICOSAHEDRON,
GLUT_WIRE_TEAPOT,
GLUT_SOLID_TEAPOT
};
// Get the id of the selected object
int selected_object = (radiogroup_item_id * 2) + 1 - wireframe;
switch (selected_object)
{
// draw glut wire cube
case GLUT_WIRE_CUBE:
glutWireCube (0.5);
break;
// draw glut solid cube
case GLUT_SOLID_CUBE:
glutSolidCube (0.5);
break;
// draw glut wire sphere
case GLUT_WIRE_SPHERE:
glutWireSphere (0.5, 50, 50);
break;
// draw glut solid sphere
case GLUT_SOLID_SPHERE:
glutSolidSphere (0.5, 50, 50);
break;
// and so on...
}
For example, let's say that the wireframe checkbox is checked and the Teapot radio button is clicked. Then, the wireframe live variable would be 1 since the checkbox is checked. The radiogroup_item_id value would be 8, which is the id of the Teapot radio button. Thus, the selected object would be calculated as follows:
selected_object = (8 * 2) + 1 - 1 = 16.
where 16 is the same as GLUT_WIRE_TEAPOT, and thus the following code segment would be executed to draw the GLUT wire teapot.
glutWireTeapot (0.5);
For more information about the GLUT geometric shapes, you may check the GLUT Geometric Shapes article.
GLUI window. // Add the 'Transformation' Panel to the GLUI window
GLUI_Panel *transformation_panel = glui_window->add_panel (
"Transformation");
// Create transformation panel 1 that will contain the Translation
// controls
GLUI_Panel *transformation_panel1 = glui_window->add_panel_to_panel (
transformation_panel, "");
![]() |
![]() |
![]() |
![]() |
GLUI_TRANSLATION_XY |
GLUI_TRANSLATION_X |
GLUI_TRANSLATION_Y |
GLUI_TRANSLATION_Z |
In order to add the XY translation control, we execute the following code segment:
// Translation XY Live Variable
float translate_xy[2] = {0, 0};
// Add the xy translation control
GLUI_Translation *translation_xy = glui_window->add_translation_to_panel(
transformation_panel1, "Translation XY",
GLUI_TRANSLATION_XY, translate_xy,
TRANSLATION_XY, glui_callback );
// Set the translation speed
translation_xy->set_speed( 0.005 );
The first parameter of the add_translation_to_panel is the panel to which we want to add the translation control. The second parameter is the name of the translation control. The third parameter represents the type of the translation, which could be any of GLUI_TRANSLATION_XY, GLUI_TRANSLATION_X, GLUI_TRANSLATION_Y, or GLUI_TRANSLATION_Z. The fourth parameter is the live variable used to track the x, y, or z coordinates being changed. The fifth parameter represents the ID of the control as it gets passed to the callback function, which is specified in the sixth parameter.
The set_speed method allows us to adjust the speed of the translation control in response to user mouse movements.
// Add column, but don't draw it
glui_window->add_column_to_panel (transformation_panel1, false);
// Translation Z Live Variable
float translate_z = 0;
// Add the z translation control
GLUI_Translation *translation_z = glui_window->add_translation_to_panel (
transformation_panel1, "Translation Z",
GLUI_TRANSLATION_Z, &translate_z,
TRANSLATION_Z, glui_callback );
// Set the translation speed
translation_z->set_speed( 0.005 );
In order to have our objects translated whenever the user moves with the translation control, we need to apply the translation to the matrix on top of the model stack before we display our object. This is done using the glTranslate OpenGL function as follows:
// Apply the translation
glTranslatef (translate_xy[0], translate_xy[1], -translate_z);
// Create transformation panel 2 that will contain the rotation and
// spinner controls
GLUI_Panel *transformation_panel2 = glui_window->add_panel_to_panel (
transformation_panel, "");
// Rotation Matrix Live Variable Array (Initialize as Identity Matrix)
float rotation_matrix[16] = { 1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0 };
// Add the rotation control
glui_window->add_rotation_to_panel (transformation_panel2,
"Rotation", rotation_matrix, ROTATION, glui_callback);
The ROTATION is a constant representing the id of the rotation control, which will be sent to the callback function whenever the user rotates the archball. The rotation_matrix is the live variable for the rotation control and is automatically updated whenever the archball is rotated. The rotation_matrix represents the matrix that will cause rotation when multiplied to the current matrix at the top of our model view stack. To cause our object to rotate, we must multiply the rotation_matrix by the current matrix before our object gets displayed. This is done as follows:
// Apply the rotation matrix
glMultMatrixf (rotation_matrix);
The rotation control can be constrained to horizontal-only movement by holding the CTRL key, or to vertical rotation by holding the ALT key.
// Add separator
glui_window->add_separator_to_panel (transformation_panel2);
spinner to allow for scaling our object. The spinner is added to transformation panel 2, and it is named Scale.// Add the scale spinner
GLUI_Spinner *spinner = glui_window->add_spinner_to_panel (
transformation_panel2, "Scale", GLUI_SPINNER_FLOAT,
&scale, SCALE_SPINNER, glui_callback);
// Set the limits for the spinner
spinner->set_float_limits ( -4.0, 4.0 );
The spinner is an integer or floating point editable textbox with two attached arrows, which increases or decreases the current value of the control. The rate at which the spinner changes can be controlled using the set_speed function. Also, one can hold SHIFT while initially clicking an arrow to increase the step amount by a factor of 100, or CONTROL to decrease the step amount to 1/100th its usual value. The data type of the spinner can be either GLUI_SPINNER_INT or GLUI_SPINNER_FLOAT, and it is passed as the third parameter to the add_spinner_to_panel method. The live variable could be a float or int data type, based on the selected data type of the control. The SCALE_SPINNER is the ID of the spinner control, which would be passed to the glui_callback function whenever the user manipulates the spinner control.
We can use the set_float_limits and set_int_limits methods to set the upper and lower limits on the integer or float values that an editable text box can accept.
In order for our value in the spinner to affect the scaling of our object, we need to use the OpenGL glScalef function to apply the scaling on the object before it gets drawn:
// Apply the scaling
glScalef (scale, scale, scale);
Finally, after adding all of the above controls, we add the Quit button as follows:
// Add the Quit Button
glui_window->add_button ("Quit", QUIT_BUTTON, glui_callback);
When the Quit button is clicked, the glui_callback function is executed with QUIT_BUTTON ID as its parameter and causes the program to exit:
// Quit Button clicked
case QUIT_BUTTON:
printf ("Quit Button clicked... Exit!\n");
exit (1);
break;
After creating the GLUI window and adding controls to it, we need to associate it with the "main graphics window" as follows:
glui_window->set_main_gfx_window (main_window);
When a control in the GLUI window changes value, a redisplay request will be sent to this main graphics window.
Invoke the standard GLUT main "event loop":
glutMainLoop();
I think this article can significantly help in creating an OpenGL application with graphical user controls, and at the same time, the template can be used to save lots of copy and paste from old projects or the Internet.
In case you find this template useful or have suggestions, please let me know.
GLUI and GLUT events by placing GLUT or GLUI in front of a message at the command prompt | You must Sign In to use this message board. | |||||
|
|||||
|
|||||