Search Contact information
University of Cambridge Home Department of Engineering
University of Cambridge >  Engineering Department >  computing help

Using GLUI

GLUI is a GLUT-based C++ library that provides buttons, spinners, etc for OpenGL applications. It can run on any machine where OpenGL is available (i.e. just about anywhere) and it's free. It's easy to use, though control over color, fonts, etc is limited.

GLUT routines deal display the graphics, so you need to know how to use them first. These issues are covered on our using GLUT page.

The first example below spins a shape in 3D. A separate window has controls to make the shape a wireframe and to change the number of line segments used. Most of the code (shown in full later) involves setting up windows and using GLUT routines to draw into them. Adding the controls takes about a dozen lines of code. The GLUI routines take advantage of C++'s way of assigning default values to trailing parameters, so you can often get away with supplying just one or 2 parameters to functions. The GLUI concepts used here are screen dump
Here's the full code

Example 1

/****************************************************************************

  A simple GLUT program using the GLUI User Interface Library

  This program sets up a checkbox and a spinner, both with live variables.
  No callbacks are used.

  -----------------------------------------------------------------------

  9/9/98 Paul Rademacher (rademach@cs.unc.edu)

****************************************************************************/

#include <string.h>
#include <glut.h>
#include "glui.h"

/** These are the live variables passed into GLUI ***/
int   wireframe = 0;
int   segments = 8;
int   main_window;


/***************************************** myGlutIdle() ***********/

void myGlutIdle( void )
{
  /* According to the GLUT specification, the current window is
     undefined during an idle callback.  So we need to explicitly change
     it if necessary */
  if ( glutGetWindow() != main_window )
    glutSetWindow(main_window);

  glutPostRedisplay();
}

/**************************************** myGlutReshape() *************/

void myGlutReshape( int x, int y )
{
  float xy_aspect;

  xy_aspect = (float)x / (float)y;
  glViewport( 0, 0, x, y );

  glMatrixMode( GL_PROJECTION );
  glLoadIdentity();
  glFrustum( -xy_aspect*.08, xy_aspect*.08, -.08, .08, .1, 15.0 );

  glutPostRedisplay();
}

/***************************************** myGlutDisplay() *****************/

void myGlutDisplay( void )
{
  static float rotationX = 0.0, rotationY = 0.0;

  glClearColor( .9f, .9f, .9f, 1.0f );
  glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

  /*** Rotate the object ***/
  rotationX += 3.3f;
  rotationY += 4.7f;

  glMatrixMode( GL_MODELVIEW );
  glLoadIdentity();
  glTranslatef( 0.0, 0.0, -1.0 );
  glRotatef( rotationY, 0.0, 1.0, 0.0 );
  glRotatef( rotationX, 1.0, 0.0, 0.0 );

  /*** Now we render object, using the variables 'segments' and
    'wireframe'.  These are _live_ variables, which are transparently
    updated by GLUI ***/

  if ( wireframe )
    glutWireTorus( .2,.5,16,segments );
  else
    glutSolidTorus( .2,.5,16,segments );

  glutSwapBuffers();
}

/**************************************** main() ********************/

int main(int argc, char* argv[])
{
  /****************************************/
  /*   Initialize GLUT and create window  */
  /****************************************/

  glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH );
  glutInitWindowPosition( 50, 50 );
  glutInitWindowSize( 300, 300 );

  main_window = glutCreateWindow( "GLUI Example 1" );
  glutDisplayFunc( myGlutDisplay );
  glutReshapeFunc( myGlutReshape );

  /****************************************/
  /*       Set up OpenGL lights           */
  /****************************************/

  GLfloat light0_ambient[] =  {0.1f, 0.1f, 0.3f, 1.0f};
  GLfloat light0_diffuse[] =  {.6f, .6f, 1.0f, 1.0f};
  GLfloat light0_position[] = {1.0f, 1.0f, 1.0f, 0.0f};

  glEnable(GL_LIGHTING);
  glEnable(GL_LIGHT0);
  glLightfv(GL_LIGHT0, GL_AMBIENT, light0_ambient);
  glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse);
  glLightfv(GL_LIGHT0, GL_POSITION, light0_position);

  /****************************************/
  /*          Enable z-buffering          */
  /****************************************/

  glEnable(GL_DEPTH_TEST);

  /****************************************/
  /*         Here's the GLUI code         */
  /****************************************/

  GLUI *glui = GLUI_Master.create_glui( "GLUI" );
  glui->add_checkbox( "Wireframe", &wireframe );
  GLUI_Spinner *segment_spinner =
    glui->add_spinner( "Segments:", GLUI_SPINNER_INT, &segments );
  segment_spinner->set_int_limits( 3, 60 );

  glui->set_main_gfx_window( main_window );

  /* We register the idle callback with GLUI, *not* with GLUT */
  GLUI_Master.set_glutIdleFunc( myGlutIdle );

  glutMainLoop();
}
If you call this file simple.cc then it can be compiled using g++ -I/usr/include/GL -o simple simple.cc -lglui -lglut -lGLU -lGL
The compile line is long, but on Unix you can use Makefiles or Shell scripts to save on typing.

Controls inside the main graphics window

If you want your controls to be in the same window as the main graphics, more work is required so that graphical events get handled by GLUI rather than GLUT There's an example later

More controls

A few more of the available options are introduced here. As with the previous components, they can be created with a single line of code, and their positioning is managed automatically
  • Panels and separators - these are ways to group and visually organise controls. Panels are rectangles, and separators are horizontal lines. You can also create columns of controls, but they're not used here.
  • Text - static and editable text is available
  • Buttons - clicking on them runs a callback routine
  • Arcballs - a rollerball: useful to control rotation of an object in the main graphical window
  • Listbox - a menu where only the selected item is shown
  • Radiobutton - a menu where all items are shown, but only one can be selected
screen dump

Example 2

This builds on the earlier example, adding recently introduced components inside a GLUT window.
/****
  Adapted from a program by 
  9/9/98 Paul Rademacher (rademach@cs.unc.edu)

****************************************************************************/

#include <string.h>
#include <glut.h>
#include "glui.h"

/** These are the live variables passed into GLUI ***/
int   wireframe = 0;
int   segments = 8;
int   main_window;

/***************************************** myGlutIdle() ***********/

void myGlutIdle( void )
{
  /* According to the GLUT specification, the current window is
     undefined during an idle callback.  So we need to explicitly change
     it if necessary */
  if ( glutGetWindow() != main_window )
    glutSetWindow(main_window);

  glutPostRedisplay();
}

/**************************************** myGlutReshape() *************/

void myGlutReshape( int x, int y )
{
  float xy_aspect;

  xy_aspect = (float)x / (float)y;
  GLUI_Master.auto_set_viewport();

  glMatrixMode( GL_PROJECTION );
  glLoadIdentity();
  glFrustum( -xy_aspect*.08, xy_aspect*.08, -.08, .08, .1, 15.0 );

  glutPostRedisplay();
}

/***************************************** myGlutDisplay() *****************/

void myGlutDisplay( void )
{
  static float rotationX = 0.0, rotationY = 0.0;

  glClearColor( .9f, .9f, .9f, 1.0f );
  glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

  /*** Rotate the object ***/
  rotationX += 3.3f;
  rotationY += 4.7f;

  glMatrixMode( GL_MODELVIEW );
  glLoadIdentity();
  glTranslatef( 0.0, 0.0, -1.0 );
  glRotatef( rotationY, 0.0, 1.0, 0.0 );
  glRotatef( rotationX, 1.0, 0.0, 0.0 );

  /*** Now we render object, using the variables 'segments' and
    'wireframe'.  These are _live_ variables, which are transparently
    updated by GLUI ***/

  if ( wireframe )
    glutWireTorus( .2,.5,16,segments );
  else
    glutSolidTorus( .2,.5,16,segments );

  glutSwapBuffers();
}

/**************************************** main() ********************/

int main(int argc, char* argv[])
{
  /****************************************/
  /*   Initialize GLUT and create window  */
  /****************************************/

  glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH );
  glutInitWindowPosition( 50, 50 );
  glutInitWindowSize( 300, 300 );

  main_window = glutCreateWindow( "GLUI Example 1" );
  glutDisplayFunc( myGlutDisplay );
  glutReshapeFunc( myGlutReshape );

  /****************************************/
  /*       Set up OpenGL lights           */
  /****************************************/

  GLfloat light0_ambient[] =  {0.1f, 0.1f, 0.3f, 1.0f};
  GLfloat light0_diffuse[] =  {.6f, .6f, 1.0f, 1.0f};
  GLfloat light0_position[] = {1.0f, 1.0f, 1.0f, 0.0f};

  glEnable(GL_LIGHTING);
  glEnable(GL_LIGHT0);
  glLightfv(GL_LIGHT0, GL_AMBIENT, light0_ambient);
  glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse);
  glLightfv(GL_LIGHT0, GL_POSITION, light0_position);

  /****************************************/
  /*          Enable z-buffering          */
  /****************************************/

  glEnable(GL_DEPTH_TEST);

  /****************************************/
  /*         Here's the GLUI code         */
  /****************************************/

  GLUI *glui = GLUI_Master.create_glui_subwindow(main_window,
                     GLUI_SUBWINDOW_TOP);

  glui->add_checkbox( "Wireframe", &wireframe );
  GLUI_Spinner *segment_spinner =
    glui->add_spinner( "Segments:", GLUI_SPINNER_INT, &segments );
  segment_spinner->set_int_limits( 3, 60 );

  glui->set_main_gfx_window( main_window );
  GLUI_Listbox *listbox = glui->add_listbox("A listbox");
  listbox->add_item(1,"Red");
  listbox->add_item(2,"Green");
  listbox->add_item(3,"Blue");

  glui->add_statictext("Example 2");
  glui->add_separator();
  GLUI_Panel *obj_panel = glui->add_panel ("Test Panel");
  glui->add_button("Quit",0,(GLUI_Update_CB)exit);
  GLUI_RadioGroup *group1 = glui->add_radiogroup_to_panel(obj_panel);
  glui->add_radiobutton_to_group(group1,"Option 1");
  glui->add_radiobutton_to_group(group1,"Option 2");
  GLUI_Rotation *arcball = glui->add_rotation("ball (doesn't do anything)");
  
  /* We register the idle callback with GLUI, *not* with GLUT */
  GLUI_Master.set_glutIdleFunc( myGlutIdle );
  GLUI_Master.set_glutReshapeFunc( myGlutReshape );
  glutMainLoop();
}

References

© Cambridge University Engineering Dept
Information provided by Tim Love (tpl)
Last updated: May 2006