INT32GP Graphics Programming

Note - updated 18th August 06

glutTimerFunc

To work out how to use the glutTimerFunc, examine the code in timer01.c

  1. Double buffering is implemented in the following two lines. Locate them.
        glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
    
        glutSwapBuffers();
    Which takes the place of glFlush?
  2. Nothing happens for 5 seconds. A global variable is defined as follows - specifies 5 seconds.
    /*
    ** manage animation
    */
    int timer_milliseconds = 5000;
    
    The GLUT callback is registered as follows. It specifies how long to wait until the function timer is called (with an id number of 1).

    glutTimerFunc(timer_milliseconds, timer, 1);

  3. The code for timer is placed above setUpGLUT.
    void timer(int id){
       static count = 0;
       switch(id){
          case 1:
             glClearColor(0.7, 0.9, 0.7, 0.0);
             rotateSquare();
             glutTimerFunc(50, timer, 2);
             break;
          case 2:
             count++;
             rotateSquare();
             if(count < 300)
                glutTimerFunc(50, timer, 2);
             else{
                angleIncrement = -0.5;
                glutTimerFunc(50, timer, 3);
             }
             break;
          case 3:
             glClearColor(0.9, 0.9, 0.7, 0.0);
             rotateSquare();
             glutTimerFunc(50, timer, 3);
             break;
       }
       glutPostRedisplay();
    }
    
    The following global variables are important.
    /*
    ** manage transforms
    */
    GLdouble ra = 0;
    GLdouble angleIncrement = 0.5;
    
  4. Rotation is applied to the square in display
       glPushMatrix();
          glRotated(ra, 0, 0, 1);
          render(square,NUM_VERTICES_FOR_SQUARE,GL_POLYGON);
       glPopMatrix();
    
  5. The angle of rotation is changed in rotateSquare.
    void rotateSquare(void){
       ra += angleIncrement;
       if(ra >= 360.0)
          ra = 0.0;
    }
    
    This function is also called from keyboard. Pressing 'r' causes the rotation t speed up. Also try pressing 'r' before the animation begins.
  6. Add another case to the timer function to render a smaller (scaled) stationary black square in the middle of the orange square.
    NOTE: All rendering code must be called from display. Therefore, tackle this problem using a GLboolean originally set to false. When it is true, the black square will be rendered.

glutIdleFunc

Examine the code in idle01.c.

  1. A glutMouseFunc, called mouse is registered with GLUT.
    void mouse(int button, int state, int xMouse, int yMouse){
       static int idling = GL_FALSE;
       if(button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
          if(idling){
             glutIdleFunc(NULL);
             idling = GL_FALSE;
          }
          else{
             glutIdleFunc(idle);
             idling = GL_TRUE;
          }
       else if(button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN){
          printf("xMouse=%d yMouse=%d\n", xMouse, yMouse);
       }
    }
    
    When the left mouse button is pressed the first time glutIdleFunc, called idle, is reqistered with GLUT. It is deregistered the next time it is pressed. Each consecutive press of the left button toggles the registration on and off.

    When the right mouse button is clicked, the position of the mouse is printed out.

  2. The idle function calls rotateSquare.
    void idle(void){
       rotateSquare();
       glutPostRedisplay();
    }
    
  3. Note that the glutTimerFunc, timer, is also used in this program. It causes the background colour to change and, after a certain time, it closes the program automatically. How long will the program run for?

Control Timing

The glutIdleFunc is called whenever the program is doing nothing else. We need a way to control how often the image is updated. We can do this by introducing a delay into the idle function.

Control timing - use glutGet(GLUT_ELAPSED_TIME)

GLUT has a function that returns the number of milliseconds from the time glutInit() was called.

  1. Write a function to introduce a delay.
    void delay(int milliseconds){
       int oldTime = glutGet(GLUT_ELAPSED_TIME);
       int newTime = glutGet(GLUT_ELAPSED_TIME);
       int difference = newTime - oldTime;
       while(difference < milliseconds){
          newTime = glutGet(GLUT_ELAPSED_TIME);
          difference = newTime - oldTime;
       }
    }
    
  2. Call delay from idle.
    void idle(void){
       rotateSquare();
       delay(100);
       glutPostRedisplay();
    }
    

Example Programs
idling1.c
clock10.c counting seconds
complement05.c. Stare at the cross in the centre. Start the animation by pressing the left mouse button. The colour of the "circling" point is an illusion. It appears to be the complementary colour of magenta. What colour is this? Enhance the code to try other complementary colours by pressing a key.

Control Timing - use glutTimerFunc

We can use glutTimerFunc to count milliseconds and idle. It is a little tricky to use because you cannot cancel it - but you can switch to different functions.

Example Program using mouse control of glutTimerFunc
clock02.c counting half seconds

Add C code to control timing.

NOTE: The following works with Borland C under Windows, not with gcc under Linux.

Enhance the code in idle01.c.

  1. Control the time between each call to rotateSquare by calling a function, delay and passing to it the number of milliseconds to delay.
    void idle(void){
       delay(100);
       rotateSquare();
       glutPostRedisplay();
    }
    
  2. To write delay, we need to use C time functions. In the includes section at the top of the program, add the following line of code.
    #include <time.h>
    
  3. Write the delay function. Note that it uses a data type called clock_t. It gets the current time from the system clock.
    void delay(int milliseconds){
       clock_t oldTick;
       clock_t newTick;
       double difference = 0;
       int i;
       oldTick = clock();
       while(difference < milliseconds){
          newTick = clock();
          difference = (double) (newTick - oldTick);
       }
       printf("difference=%f\n", difference);
       printf("newTick=%f\n", (double) newTick);
       printf("oldTick=%f\n\n", (double) oldTick);
    }
    
    The print statements at the end are there to help you understand how the function works. Write comments to explain how the function works and then remove the print statements (these slow down execution).
  4. How long is the actual delay? How would you program a one second delay?
  5. Links to explanation of what is available in time.h
    C guide       time.h
  6. You may also be able to use a system call sleep(numSecond), which causes processes to go to sleep for a number of seconds. Try this for Linux.

NOTE: Although it is easy enough to count seconds using Cs time.h, it is not so easy to count milliseconds.

Example Programs using clock(), which returns the processor time used by the program not the current time.
clock01.c counting seconds
complement01.c. Stare at the cross in the centre. Start the animation by pressing the left mouse button. The colour of the "circling" point is an illusion. It appears to be the complementary colour of magenta. What colour is this? Enhance the code to try other complementary colours by pressing a key.

Copyright © 2006 Fran Soddell
last updated 18 August 2006 F.Soddell@latrobe.edu.au