Department of Engineering

IT Services

GLUE

Introduction

glue GLUE is a Graphics Library for Undergraduate Education which is designed for use by students learning C++.

When you write a graphical program, you need to cope with the user resizing or uncovering the window at any moment. In practise it means that graphical programs will be structured differently to non-graphical ones, ready to react to the user's actions. With GLUE all you need to do is to define which function to run in these circumstances - GLUE will call it for you at the right time. GLUE offers you the chance to respond to key-presses and mouse-clicks too. Here's a simple example - the code on the left and the program on the right.

// Compile using
// g++ -I/usr/local/include -I/usr/include/GL -L/usr/local/lib 
//     ... -lglue -lglui -lglut -lGLU -lGL
#include "glue.h"

void mygraphics(int w, int h) {
  color(BLUE);
  text("hello", 150,h/2);
}

int main() {
  glueWindow();  
  graphicsfunction (mygraphics);
  glueGo();
}
  • glueWindow() creates a window of default size and color. The default background colour is WHITE and the default foreground colour is BLACK
  • graphicsfunction defines which routine (in this case mygraphics) will be used to draw in the window. This routine will be called when the window first appears, when it's resized, and when it's unobscured or de-iconified. Note that the graphics routine is always given the window's current width and height. In this example the text is drawn half-way down the window.
  • glueGo() starts the graphics. The window won't appear until this routine is called. The routine won't end until the graphics window is closed (whereupon it will make the program quit), so it's often the last command in the main routine. By default there's a floating "Quit" button that can be used to quit the program.

Coordinates

  • The initial window is positioned using screen coordinates (pixels) - (0,0) is bottom-left.
  • For routines that draw into the window, all coordinate are in pixels by default, (0,0) being bottom-left of the window rather than the screen.
  • Once some axes have been drawn, you can have the coordinates interpreted as relative to the axes (using the coordinate system defined by labello and labelhi when the axes were drawn) or use the window-pixel-based coordinate system. For example, if your x and y axes run from 0 to 1, drawing a line from (0,0) to (1,1) will draw a diagonal line to fill the axes area as long as you've chosen AXES as your coordinate system. PIXELS is the default.

A note about C++ parameter default values

In C++ you don't always need to supply all the parameters to a function. The routines below use this facility to help make your programs shorter. Any parameter mentioned below with a = sign after it can be left out as long as there are no more following parameters. The omitted parameters are given the stated default values. So glueWindow(500,500) is legal, setting the window's width and height to 500, but using the default values for the other parameters.

Routines

  • void glueWindow(int width=640,int height=480,int xpos=50,int ypos=50, int backgroundcolor=WHITE, bool quitbutton=true);
    Create a window. The background color can be one of BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE. The final parameter specifies whether a Quit button appears.
  • void glueGo();
    Activates the graphics. This routine doesn't return until the graphics window is closed.
  • void keyboardfunction(void (*func)( unsigned char, int x, int y));
    Use the routine called func to process keyboard presses. The routine has to accept 3 arguments. The first gives the ASCII value of the key pressed, the other 2 give the mouse pointer coordinates.
  • void mousefunction(void (*func)(int button, int state, int x, int y));
    Use the routine called func to process mouse button presses. The routine has to accept 4 arguments. The first contains the mouse button pressed (GLUE_LEFT_BUTTON, GLUE_MIDDLE_BUTTON, or GLUE_RIGHT_BUTTON), the 2nd holds information on whether the button was pressed or released (GLUE_UP or GLUE_DOWN), the last 2 give the mouse pointer coordinates.
  • void graphicsfunction(void (* func)(int w, int h));
    Use the routine called func to produce graphics. The 2 parameters given to the routine by GLUE provide the window's current width and height.
  • void move(double x, double y, int coords=PIXELS);
    Set the "current position" to (x,y) but don't draw anything. By default, the PIXEL coordinate system is used. The alternative is to use the AXES coordinate system.
  • void draw(double x, double y, int coords=PIXELS);
    Draw a line from the "current position" (i.e. where the last "move" or "draw" command finished. This is undefined if neither move nor draw have previously been used) to (x,y), and set the "current position" to (x,y). By default, the PIXEL coordinate system is used. The alternative is to use the AXES coordinate system.
  • void text(string txt, int x, int y, void* font=TIMES13) ;
    Display the txt at position (x,y). Possible fonts are TIMES10, TIMES13, TIMES24, HELVETICA10, HELVETICA12, HELVETICA24
  • void color(int);
    Set the color to one of BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE.
  • void color(float red,float green, float blue);
    Set the color to an RGB value, the components being in the range 0 to 1.
  • void filledrectangle(int x, int y, int w, int h);
    Fill a rectangle with the current color
  • void filledcircle(int x, int y, int r, int num_lines=100);
    Fill a circle of radius r centred on (x,y) with the current color. The circle is drawn as a regular polygon with 100 sides by default.
  • void xaxis(float xlo, float xhi, int nxticks, float y, float ticksize, string title, float labello, float labelhi, int decplaces=2);
    Draw an x-axis from (xlo,y) to (xhi,y) (where the coordinate system is in pixels and (0,0) is the bottom-left of the window). Put nxticks tickmarks along the axis, the marks being ticksize pixels long. ticksize can be negative, in which case they point up rather than down. Print labello near (xlo,y), labelhi near (xhi,y), and a label by each tickmark. Use title as the X axis title. The final parameter shows how many decimal places are shown in the tickmark labels
  • void yaxis(float ylo, float yhi, int nyticks, float x, float ticksize, string title, float labello, float labelhi, int decplaces=2);
    Draw a y-axis from (x,ylo) to (x,yhi) (where the coordinate system is in pixels and (0,0) is the bottom-left of the window). Put nyticks tickmarks along the axis, the marks being ticksize pixels long. ticksize can be negative, in which case they point right rather than left. Print labello near (x,ylo), labelhi near (x,yhi), and a label by each tickmark. Use title as the Y axis title. The final parameter shows how many decimal places are shown in the tickmark labels

Example 2

example2This longer example uses more of the graphics routines and shows how to respond to keypresses (pressing 'q' will quit the program). The lines on the graph use the AXES coordinate system. The other objects use the default PIXEL coordinate system.

// Compile using
// g++ -I/usr/local/include -I/usr/include/GL -L/usr/local/lib 
//      ... -lglue -lglui -lglut -lGLU -lGL
#include <iostream>
#include <iostream>
#include <cmath>

using namespace std;

#include "glue.h"
 int number=61;
 float xlo=0.0, xhi = number - 1, ylo = 0.0, yhi=0.1;   

void keyboard(unsigned char key, int x, int y ) {
switch ( key ) 
  {
  case 'q':
      exit ( 0 );
      break;
  default:
      break;
  }
}

void mygraphics(int w, int h) {

 int nxticks = 7, nyticks = 6;
  color(BLACK);  
  xaxis(50,300, nxticks, 50, 5, "Outcome", 0, 60,0);

  color(GREEN);
  yaxis(50,300, nyticks, 50, -10, "Frequency", 0, 0.1,3);

  filledcircle(200,250,50);
  color(RED);

  filledrectangle(250,270,80,10);
   // Plot data as discrete distribution

   float data[61], mean=35.0, deviation=6;
   float t1, t2;
   for(int i=0; i< number; i++)
   {
     t1 = (i -  mean)/deviation;
     t2 = -0.5*t1*t1;
     data[i] = exp(t2)/(deviation*sqrt(2*M_PI));
   }
    for(int i=0; i<number; i++)
     {
       move(i,0,AXES);
       draw(i,data[i],AXES);
     }
}

int main() {
  glueWindow(500, 500);  
  graphicsfunction (mygraphics);
  keyboardfunction (keyboard);
  glueGo();
}

Additions

GLUE uses GLUI and GLUT behind the scenes, which can both do a lot more than GLUE. Each uses OpenGL. GLUE is designed so that direct access to these other libraries of routines is available without you needing to change the basic structure of your code. The following code uses some openGL primitives. It resets the coordinate system so that (0,0) is in the center of the window and y goes down the window rather than up. Then it rotates the coordinate system when you press the 'r' button.

#include <iostream>
#include <iostream>
#include <cmath>

using namespace std;

#include "glue.h"
int myw, myh;
int  angle=15;

void mygraphics(int w, int h) {
myw=w;
myh=h;
  glViewport(0, 0, w, h);       /* Establish viewing area to cover entire window. */
  glMatrixMode(GL_PROJECTION);  /* Start modifying the projection matrix. */
  glLoadIdentity();             /* Reset project matrix. */
  glOrtho(0, w, 0, h, -1, 1);   /* Map abstract coords directly to window coords. */
  glScalef(1, -1, 1);           /* Invert Y axis so increasing Y goes down. */
  glTranslatef(w/2, -h/2, 0);   /* Shift origin */
  glRotated(angle, 0, 0, 1);
  angle=angle+15;
  color(BLUE);
  text("press the r key", 0,0);
  glBegin(GL_TRIANGLES);
    glColor3f(0.0, 0.0, 1.0);  /* blue */
    glVertex2i(0, h/3);
    glColor3f(0.0, 1.0, 0.0);  /* green */
    glVertex2i(h/3, h/3);
    glColor3f(1.0, 0.0, 0.0);  /* red */
    glVertex2i(0, 0);
  glEnd();
  glFlush();  /* Single buffered, so needs a flush. */
}

void keyboard(unsigned char key, int x, int y ) {
  static int angle=15;
switch ( key ) 
  {
  case 'r':
      mygraphics(myw, myh); 
      angle=angle+15;
      break;
  default:
      break;
  }
}

int main() {
  glueWindow();  
  graphicsfunction (mygraphics);
  keyboardfunction (keyboard);
  glueGo();
}

See Also